import { tassign } from 'tassign'; import { IItem,Item } from '@farmmaps/common'; import { IItemLayer,ItemLayer,TemporalItemLayer} from '../models/item.layer'; import { IMapState} from '../models/map.state'; import { IQueryState} from '@farmmaps/common'; import { IPeriodState} from '../models/period.state'; import { IStyles} from '../models/style.cache'; import * as mapActions from '../actions/map.actions'; import {commonActions} from '@farmmaps/common'; import { createSelector, createFeatureSelector } from '@ngrx/store'; import {Feature} from 'ol'; import { createEmpty, extend} from 'ol/extent'; import { ROUTER_NAVIGATION, RouterNavigationAction } from '@ngrx/router-store'; import { MODULE_NAME } from '../module-name'; const startDate:Date = new Date(new Date(Date.now()).getFullYear(), new Date(Date.now()).getMonth() - 3, 1); const endDate:Date = new Date(Date.now()); export const initialQueryState: IQueryState = { itemCode: null, parentCode: null, level: 1, itemType: null, bboxFilter: false, query: null, tags: null, endDate: null, startDate: null, bbox: [] }; export interface State { period:IPeriodState, mapState: IMapState, viewExtent: number[], queryState: IQueryState, query:IQueryState, parentCode: string, features: Array, panelVisible: boolean, panelCollapsed: boolean, selectedFeature: Feature, selectedItem:IItem, clearEnabled: boolean, searchCollapsed: boolean, searchMinified: boolean, extent: number[], baseLayers: Array overlayLayers: Array, selectedItemLayer: IItemLayer, projection: string, selectedBaseLayer: IItemLayer, selectedOverlayLayer: IItemLayer, styles:IStyles, showLayerSwitcher:boolean, setStateCount:number } export const initialState: State = { period: { startDate: startDate, endDate: endDate }, mapState: { zoom: 8, rotation: 0, xCenter: 5.377554, yCenter: 52.162422, baseLayerCode: "" }, viewExtent:[], queryState: tassign(initialQueryState), query: tassign(initialQueryState), parentCode: null, features: [], panelVisible: false, panelCollapsed: false, selectedFeature: null, selectedItem: null, clearEnabled: false, searchCollapsed: true, searchMinified:false, extent: null, baseLayers: [], overlayLayers: [], projection: "EPSG:3857", selectedBaseLayer: null, selectedOverlayLayer: null, selectedItemLayer: null, styles: {}, showLayerSwitcher: false, setStateCount: 0 } export function reducer(state = initialState, action: mapActions.Actions | commonActions.Actions | RouterNavigationAction): State { switch (action.type) { case ROUTER_NAVIGATION: { let a = action as RouterNavigationAction; return tassign(state); } case mapActions.SETMAPSTATE: { let a = action as mapActions.SetMapState; return tassign(state, { mapState: a.mapState,setStateCount: state.setStateCount+1 }); } case mapActions.SETQUERYSTATE: { let a = action as mapActions.SetQueryState; return tassign(state, { queryState: tassign(a.queryState ),setStateCount: state.setStateCount+1}); } case mapActions.SETSTATE: { let a = action as mapActions.SetState; return tassign(state, { mapState: tassign(a.mapState), queryState: tassign(a.queryState),setStateCount: state.setStateCount+1}); } case mapActions.SETVIEWEXTENT: { let a = action as mapActions.SetViewExtent; return tassign(state, { viewExtent: a.extent }); } case mapActions.SETPARENT: { let a = action as mapActions.SetParent; return tassign(state, { parentCode : a.parentCode }); } case mapActions.STARTSEARCHSUCCESS: { let a = action as mapActions.StartSearchSuccess; let extent = state.extent; if (!action.query.bboxFilter) { console.debug("Set extent"); extent = createEmpty(); if (extent) { for (let f of action.features) { extend(extent, (f as Feature).getGeometry().getExtent()); } } } return tassign(state, { panelVisible: true, clearEnabled: true, searchMinified: true, features: a.features, extent:extent }); } case mapActions.SELECTFEATURE: { let a = action as mapActions.SelectFeature; return tassign(state, { selectedFeature: state.selectedItem?state.selectedFeature: a.feature }); } case mapActions.SELECTITEM: { return tassign(state, { selectedItem: null, searchMinified:false, selectedItemLayer: null, features:[] }); } case mapActions.SELECTITEMSUCCESS: { let a = action as mapActions.SelectItemSuccess; var itemLayer = null; if (a.item && "vnd.farmmaps.itemtype.layer,vnd.farmmaps.itemtype.shape.processed,vnd.farmmaps.itemtype.geotiff.processed".indexOf(a.item.itemType) >=0 ) { itemLayer = new ItemLayer(a.item); } else if (a.item && a.item.itemType == "vnd.farmmaps.itemtype.temporal") { itemLayer = new TemporalItemLayer(a.item); } return tassign(state, { selectedItem: a.item, selectedItemLayer: itemLayer, panelVisible: a.item != null, clearEnabled: a.item != null, searchCollapsed: false, searchMinified: true, queryState: tassign(state.queryState, {itemCode:a.item ? a.item.code:null}) }); } case mapActions.STARTSEARCH: { let a = action as mapActions.StartSearch; return tassign(state, { selectedItem: null, selectedItemLayer:null, queryState: tassign(a.queryState), searchCollapsed: false, searchMinified: true }); } case mapActions.DOQUERY: { let a = action as mapActions.DoQuery; return tassign(state, { query: tassign(a.query, { bbox: a.query.bboxFilter ? state.viewExtent : [] })}); } case mapActions.ADDFEATURESUCCESS: { let a = action as mapActions.AddFeatureSuccess; let features = state.features.slice(); features.push(a.feature); return tassign(state, { panelVisible: true, selectedFeature: a.feature, extent: a.feature.getGeometry().getExtent(), searchCollapsed: false, clearEnabled:true, features:features }); } case mapActions.UPDATEFEATURESUCCESS: { let a = action as mapActions.UpdateFeatureSuccess; let features: any[] = []; var index = -1; for (var i = 0; i < state.features.length; i++) { if (state.features[i].getId() == a.feature.getId()) { features.push(a.feature); } else { features.push(state.features[i]); } } return tassign(state, { features: features }); } case mapActions.EXPANDSEARCH: { return tassign(state, { searchCollapsed: false }); } case mapActions.COLLAPSESEARCH: { return tassign(state, { searchCollapsed: state.panelVisible ? false: true}); } case mapActions.SETEXTENT: { console.debug("Set extent 2"); let a = action as mapActions.SetExtent; return tassign(state, { extent: a.extent }); } case mapActions.ADDLAYER: { let a = action as mapActions.AddLayer; let itemLayers = state.overlayLayers.slice(0); let itemLayer = new ItemLayer(a.item); itemLayer.layerIndex = a.layerIndex == -1 ? 0 : a.layerIndex; itemLayers.push(itemLayer); return tassign(state, { overlayLayers: itemLayers, selectedOverlayLayer: itemLayer }); } case mapActions.REMOVELAYER: { let a = action as mapActions.RemoveLayer; let newLayers = state.overlayLayers.slice(0); let i = state.overlayLayers.indexOf(a.itemLayer); var selectedOverlayLayer: IItemLayer = null; if (i>0 && state.overlayLayers.length > 1) selectedOverlayLayer = state.overlayLayers[i - 1]; else if (i == 0 && state.overlayLayers.length > 1) selectedOverlayLayer = state.overlayLayers[i + 1]; newLayers.splice(i, 1); return tassign(state, { overlayLayers: newLayers, selectedOverlayLayer: selectedOverlayLayer }); } case mapActions.SETVISIBILITY: { let a = action as mapActions.SetVisibility; let newLayers = state.overlayLayers.slice(0); let i = state.overlayLayers.indexOf(a.itemLayer); newLayers[i].visible = a.visibility; return tassign(state, { overlayLayers: newLayers }); } case mapActions.SETOPACITY: { let a = action as mapActions.SetOpacity; let newLayers = state.overlayLayers.slice(0); let i = state.overlayLayers.indexOf(a.itemLayer); newLayers[i].opacity = a.opacity; return tassign(state, { overlayLayers: newLayers }); } case mapActions.SETLAYERINDEX: { let a = action as mapActions.SetLayerIndex; if (a.itemLayer == null) { var newItemlayer = new ItemLayer(state.selectedItemLayer.item); newItemlayer.layerIndex = a.layerIndex; return tassign(state, { selectedItemLayer: newItemlayer}) } else { let newLayers = state.overlayLayers.slice(0); let i = state.overlayLayers.indexOf(a.itemLayer); newLayers[i].layerIndex = a.layerIndex; return tassign(state, { overlayLayers: newLayers }); } } case mapActions.LOADBASELAYERSSUCCESS: { let a =action as mapActions.LoadBaseLayersSuccess; let baseLayers:ItemLayer[] = []; for (let item of a.items) { var l = new ItemLayer(item); l.visible = false; baseLayers.push(l); } var selectedBaseLayer: IItemLayer = null; var mapState = tassign(state.mapState); console.debug(`Base layerload: ${mapState.baseLayerCode}`) if (baseLayers.length > 0 && mapState.baseLayerCode != "") { selectedBaseLayer = baseLayers.filter(layer => layer.item.code === mapState.baseLayerCode)[0]; selectedBaseLayer.visible = true; } else if (baseLayers.length > 0) { selectedBaseLayer = baseLayers[0]; selectedBaseLayer.visible = true; mapState.baseLayerCode = selectedBaseLayer.item.code; } return tassign(state, { mapState:mapState, baseLayers: baseLayers, selectedBaseLayer: selectedBaseLayer }); } case mapActions.SELECTBASELAYER: { let a = action as mapActions.SelectBaseLayer; let baseLayers = state.baseLayers.slice(0); baseLayers.forEach((l) => l.visible = false); let i = state.baseLayers.indexOf(a.itemLayer); baseLayers[i].visible = true; var mapState = tassign(state.mapState); mapState.baseLayerCode = a.itemLayer.item.code; return tassign(state, {mapState:mapState, baseLayers:baseLayers,selectedBaseLayer:a.itemLayer }); } case mapActions.SELECTOVERLAYLAYER: { let a = action as mapActions.SelectOverlayLayer; return tassign(state, { selectedOverlayLayer: a.itemLayer }); } case commonActions.ESCAPE: { let a = action as commonActions.Escape; let newQueryState = tassign(state.queryState, { query: null, tags: null, itemCode: null, parentCode: null, itemType: null }); if (a.escapeKey) { return tassign(state, { panelVisible: false, panelCollapsed:false, selectedItem: null, selectedItemLayer: null, selectedFeature: null, queryState: newQueryState, clearEnabled: false, searchCollapsed: true, searchMinified: false, features: [], query:initialState.query, showLayerSwitcher: false }); } else { return tassign(state, {}); } } case mapActions.SETSTYLE:{ let a = action as mapActions.SetStyle; let styles = tassign(state.styles); styles[a.itemType] = a.style; return tassign(state,{styles:styles}); } case mapActions.SHOWLAYERSWITCHER:{ let a = action as mapActions.ShowLayerSwitcher; return tassign(state,{showLayerSwitcher:a.show}); } case mapActions.INIT:{ return tassign(state,{setStateCount:0}); } default: { return state; } } } export const getMapState = (state: State) => state.mapState; export const getParentCode = (state: State) => state.parentCode; export const getFeatures = (state: State) => state.features; export const getPanelVisible = (state: State) => state.panelVisible; export const getPanelCollapsed = (state: State) => state.panelCollapsed; export const getSelectedFeature = (state: State) => state.selectedFeature; export const getSelectedItem = (state: State) => state.selectedItem; export const getQueryState = (state: State) => state.queryState; export const getClearEnabled = (state: State) => state.clearEnabled; export const getSearchCollapsed = (state: State) => state.searchCollapsed; export const getSearchMinified = (state: State) => state.searchMinified; export const getExtent = (state: State) => state.extent; export const getOverlayLayers = (state: State) => state.overlayLayers; export const getBaseLayers = (state: State) => state.baseLayers; export const getProjection = (state: State) => state.projection; export const getSelectedBaseLayer = (state: State) => state.selectedBaseLayer; export const getSelectedOverlayLayer = (state: State) => state.selectedOverlayLayer; export const getQuery = (state: State) => state.query; export const getSelectedItemLayer = (state: State) => state.selectedItemLayer; export const getPeriod = (state:State) => state.period; export const getStyles = (state:State) => state.styles; export const getShowLayerSwitcher = (state:State) => state.showLayerSwitcher; export const getSetStateCount = (state:State) => state.setStateCount; export const selectMapState = createFeatureSelector(MODULE_NAME); export const selectGetMapState= createSelector(selectMapState, getMapState); export const selectGetParentCode = createSelector(selectMapState, getParentCode); export const selectGetFeatures = createSelector(selectMapState, getFeatures); export const selectGetPanelVisible = createSelector(selectMapState, getPanelVisible); export const selectGetPanelCollapsed = createSelector(selectMapState, getPanelCollapsed); export const selectGetSelectedFeature = createSelector(selectMapState, getSelectedFeature); export const selectGetSelectedItem = createSelector(selectMapState, getSelectedItem); export const selectGetQueryState = createSelector(selectMapState, getQueryState); export const selectGetClearEnabled = createSelector(selectMapState, getClearEnabled); export const selectGetSearchCollapsed = createSelector(selectMapState, getSearchCollapsed); export const selectGetSearchMinified = createSelector(selectMapState, getSearchMinified); export const selectGetExtent = createSelector(selectMapState, getExtent); export const selectGetOverlayLayers = createSelector(selectMapState, getOverlayLayers); export const selectGetBaseLayers = createSelector(selectMapState, getBaseLayers); export const selectGetProjection = createSelector(selectMapState, getProjection); export const selectGetSelectedBaseLayer = createSelector(selectMapState, getSelectedBaseLayer); export const selectGetSelectedOverlayLayer = createSelector(selectMapState, getSelectedOverlayLayer); export const selectGetQuery = createSelector(selectMapState, getQuery); export const selectGetSelectedItemLayer = createSelector(selectMapState, getSelectedItemLayer); export const selectGetPeriod = createSelector(selectMapState, getPeriod); export const selectGetStyles = createSelector(selectMapState, getStyles); export const selectGetShowLayerSwitcher = createSelector(selectMapState,getShowLayerSwitcher); export const selectgetSetStateCount = createSelector(selectMapState,getSetStateCount);