import { Injectable } from '@angular/core'; import { Store, Action } from '@ngrx/store'; import { Effect, Actions,ofType } from '@ngrx/effects'; import { Observable , of } from 'rxjs'; import { withLatestFrom, switchMap, map, catchError, mergeMap } from 'rxjs/operators'; import {GeoJSON,WKT} from 'ol/format'; import {Feature} from 'ol'; import { getCenter } from 'ol/extent'; import {Point} from 'ol/geom' import * as mapActions from '../actions/map.actions'; import * as mapReducers from '../reducers/map.reducer'; import {commonReducers} from '@farmmaps/common'; import {commonActions} from '@farmmaps/common'; import { IItem } from '@farmmaps/common'; import { FolderService, ItemService } from '@farmmaps/common'; import { tassign } from 'tassign'; import {FeatureIconService} from '../services/feature-icon.service'; import * as style from 'ol/style'; import { ItemTypeService } from '@farmmaps/common'; @Injectable() export class MapEffects { private _geojsonFormat: GeoJSON; private _wktFormat: WKT; private toPointFeature(updateEvent:commonActions.DeviceUpdateEvent): Feature { var f = this._wktFormat.readFeature(updateEvent.attributes["geometry"],{ dataProjection: 'EPSG:4326', featureProjection: 'EPSG:3857' }); f.setId(updateEvent.itemCode); var centroid = getCenter(f.getGeometry().getExtent()); f.setGeometry(new Point(centroid)); return f; } @Effect() init$: Observable = this.actions$.pipe( ofType(mapActions.INIT), withLatestFrom(this.store$.select(commonReducers.selectGetRootItems)), switchMap(([action, rootItems]) => { let actions=[]; for (let rootItem of rootItems) { if (rootItem.itemType == "UPLOADS_FOLDER") actions.push(new mapActions.SetParent(rootItem.code)); } // initialize default feature styles actions.push(new mapActions.SetStyle('file',new style.Style({ image: new style.Icon({ anchor: [0.5, 1], scale: 0.05, src: this.featureIconService$.getIconImageDataUrl("fa fa-file-o") }), stroke: new style.Stroke({ color: 'red', width: 1 }), fill: new style.Fill({ color: 'rgba(0, 0, 255, 0.1)' }) }))); actions.push(new mapActions.SetStyle('selected',new style.Style({ image: new style.Icon({ anchor: [0.5, 1], scale: 0.08, src: this.featureIconService$.getIconImageDataUrl(null) }), stroke: new style.Stroke({ color: 'red', width: 3 }), fill: new style.Fill({ color: 'rgba(0, 0, 255, 0.1)' }) }))); return actions; } )); @Effect() initBaseLayers$: Observable = this.actions$.pipe( ofType(mapActions.INIT), withLatestFrom(this.store$.select(mapReducers.selectGetProjection)), map(([action, projection]) => new mapActions.LoadBaseLayers(projection))); @Effect() loadBaseLayers$: Observable = this.actions$.pipe( ofType(mapActions.LOADBASELAYERS), switchMap((action: mapActions.LoadBaseLayers) => { return this.itemService$.getItemList("vnd.farmmaps.itemtype.layer", { "isBaseLayer": true }).pipe( map((items: IItem[]) => new mapActions.LoadBaseLayersSuccess(items)), catchError(error => of(new commonActions.Fail(error)))); })); @Effect() initRootItems$: Observable = this.actions$.pipe( ofType(commonActions.INITROOTSUCCESS), map((action) => new mapActions.Init() )); @Effect() startSearch$: Observable = this.actions$.pipe( ofType(mapActions.STARTSEARCH), switchMap((action: mapActions.StartSearch) => { var startDate = action.queryState.startDate; var endDate = action.queryState.endDate; var newAction:Observable; if (action.queryState.itemCode || action.queryState.parentCode || action.queryState.itemType || action.queryState.query || action.queryState.tags) { newAction= this.itemService$.getFeatures(action.queryState.bbox, "EPSG:3857", action.queryState.query, action.queryState.tags, startDate, endDate, action.queryState.itemType, action.queryState.parentCode).pipe( switchMap((features: any) => { for (let f of features.features) { if (f.properties && f.properties["code"]) { f.id = f.properties["code"]; } } return of(new mapActions.StartSearchSuccess(this._geojsonFormat.readFeatures(features), action.queryState)); } ), catchError(error => of(new commonActions.Fail(error)))); } else { return []; } return newAction; })); @Effect() startSearchSucces$: Observable = this.actions$.pipe( ofType(mapActions.STARTSEARCHSUCCESS), mergeMap((action: mapActions.StartSearchSuccess) => { return [new commonActions.SetMenuVisible(false)]; })); @Effect() selectItem$: Observable = this.actions$.pipe( ofType(mapActions.SELECTITEM), withLatestFrom(this.store$.select(mapReducers.selectGetSelectedItem)), withLatestFrom(this.store$.select(mapReducers.getSetStateCount)), switchMap(([[action, selectedItem],setStateCount]) => { let a = action as mapActions.SelectItem; let itemCode = selectedItem ? selectedItem.code : ""; if (a.itemCode != itemCode || setStateCount == 1) { return this.itemService$.getItem(a.itemCode).pipe( map((item: IItem) => new mapActions.SelectItemSuccess(item)), catchError(error => of(new commonActions.Fail(error)))) } else { return []; } } )); @Effect() selectItemSuccess$: Observable = this.actions$.pipe( ofType(mapActions.SELECTITEMSUCCESS), switchMap((action:mapActions.SelectItemSuccess) => { return this.itemService$.getFeature(action.item.code, "EPSG:3857").pipe( map((feature: any) => { let f = this._geojsonFormat.readFeature(feature); f.setId(action.item.code); return new mapActions.AddFeatureSuccess(f ); }), catchError(error => of(new commonActions.Fail(error)))); } )); @Effect() selectItemSuccessTemporal$: Observable = this.actions$.pipe( ofType(mapActions.SELECTITEMSUCCESS), switchMap((action:mapActions.SelectItemSuccess) => { if(action.item.itemType == "vnd.farmmaps.itemtype.temporal") { return this.itemService$.getChildItemList(action.item.code,null).pipe( map(items => new mapActions.SelectTemporalItemsSuccess( items.sort((a, b) => -(b.dataDate.getTime() - a.dataDate.getTime()) ) )), catchError(error => of(new commonActions.Fail(error)))); } else { return []; } } )); @Effect() uploadedItemClick$: Observable = this.actions$.pipe( ofType(commonActions.UPLOADEDFILECLICK), switchMap((action: commonActions.UploadedFileClick) => of(new mapActions.DoQuery(tassign(mapReducers.initialState.query, {itemCode:action.itemCode}))) )); //@Effect() //itemAdded$: Observable = this.actions$.pipe( // ofType(commonActions.ITEMADDEDEVENT), // withLatestFrom(this.store$.select(mapReducers.selectGetParentCode)), // mergeMap(([action, parentCode]) => { // let itemAddedAction = action as commonActions.ItemAddedEvent; // if (parentCode && itemAddedAction.attributes["parentCode"] == parentCode) { // return this.itemService$.getFeature(itemAddedAction.itemCode,"EPSG:3857").pipe( // map((feature: Feature) => new mapActions.AddFeatureSuccess(this.toPointFeature(feature))), // catchError(error => of(new commonActions.Fail(error)))) // } else // return [ // ]; // })); @Effect() featureUpdate$: Observable = this.actions$.pipe( ofType(commonActions.DEVICEUPDATEEVENT), withLatestFrom(this.store$.select(mapReducers.selectGetFeatures)), mergeMap(([action, features]) => { let deviceUpdateEventAction = action as commonActions.DeviceUpdateEvent; var feature: Feature = null; for (let f of features) { if (f.getId() == deviceUpdateEventAction.itemCode) { feature = f; break; } } if (feature) { return of(new mapActions.UpdateFeatureSuccess(this.toPointFeature(deviceUpdateEventAction))); } else { return []; } })); @Effect() itemUpdate$: Observable = this.actions$.pipe( ofType(commonActions.ITEMCHANGEDEVENT), withLatestFrom(this.store$.select(mapReducers.selectGetSelectedItem)), mergeMap(([action, selectedItem]) => { let itemChangedAction = action as commonActions.ItemChangedEvent; if (selectedItem && selectedItem.code == itemChangedAction.itemCode) { return this.itemService$.getItem(itemChangedAction.itemCode).pipe( map((item: IItem) => new mapActions.SelectItemSuccess(item)), catchError(error => of(new commonActions.Fail(error)))); } else { return []; } })); @Effect() setQueryState$: Observable = this.actions$.pipe( ofType(mapActions.SETQUERYSTATE), withLatestFrom(this.store$.select(mapReducers.selectGetInSearch)), switchMap(([action,inSearch]) => { if(!inSearch) { let a = action as mapActions.SetQueryState; var newAction:Action; if (a.queryState.itemCode && a.queryState.itemCode != "") { newAction= new mapActions.SelectItem(a.queryState.itemCode); } else { newAction= new mapActions.StartSearch(a.queryState); } return of(newAction); } else { return []; } })); @Effect() setState$: Observable = this.actions$.pipe( ofType(mapActions.SETSTATE), withLatestFrom(this.store$.select(mapReducers.selectGetInSearch)), switchMap(([action,inSearch]) => { if(!inSearch) { let a = action as mapActions.SetQueryState; var newAction:Action; if (a.queryState.itemCode && a.queryState.itemCode != "") { newAction= new mapActions.SelectItem(a.queryState.itemCode); } else { newAction= new mapActions.StartSearch(a.queryState); } return of(newAction); } else { return []; } })); constructor(private actions$: Actions, private store$: Store, private folderService$: FolderService, private itemService$: ItemService,private featureIconService$:FeatureIconService,private itemTypeService$:ItemTypeService) { this._geojsonFormat = new GeoJSON(); this._wktFormat = new WKT(); } }