Compare commits
No commits in common. "ef81b04f4e0bed0423ed2402dcba4d1423bafee2" and "c6d7f6b0cbc606243d3ab7addccdac5fe011f0e3" have entirely different histories.
ef81b04f4e
...
c6d7f6b0cb
@ -28,7 +28,7 @@ export abstract class AbstractFeatureListComponent {
|
||||
}
|
||||
|
||||
getAction(feature:Feature):Action {
|
||||
var newQuery: any = tassign(mapReducers.initialState.queryState);
|
||||
var newQuery: any = tassign(mapReducers.initialState.query);
|
||||
newQuery.parentCode = feature.get('parentCode');
|
||||
newQuery.itemCode = feature.get('code');
|
||||
newQuery.itemType = feature.get('itemType');
|
||||
|
@ -1,8 +1,8 @@
|
||||
import { Component, OnInit, OnDestroy, HostListener, ViewChild, AfterViewInit,NgZone } from '@angular/core';
|
||||
import { Component, OnInit, OnDestroy, HostListener, Inject, ViewChild, AfterViewInit,ChangeDetectorRef,NgZone } from '@angular/core';
|
||||
import { Location } from '@angular/common';
|
||||
import { Observable, Subject, Subscription, from,of } from 'rxjs';
|
||||
import { withLatestFrom, switchMap } from 'rxjs/operators';
|
||||
import { Router, ActivatedRoute, ParamMap } from '@angular/router';
|
||||
import { Observable, Subject, Subscription,combineLatest, from,interval } from 'rxjs';
|
||||
import { debounce, withLatestFrom, first, combineAll,throttle } from 'rxjs/operators';
|
||||
import { Router, ActivatedRoute, ParamMap, Event } from '@angular/router';
|
||||
import { Store } from '@ngrx/store';
|
||||
//import { proj,Map } from 'openlayers';
|
||||
|
||||
@ -16,6 +16,7 @@ import { IQueryState } from '@farmmaps/common';
|
||||
import { IPeriodState } from '../../models/period.state';
|
||||
import {IStyles} from '../../models/style.cache';
|
||||
import { IDroppedFile } from '../aol/file-drop-target/file-drop-target.component';
|
||||
import { IMetaData } from '../meta-data-modal/meta-data-modal.component';
|
||||
import { StateSerializerService } from '@farmmaps/common';
|
||||
import { GeolocationService} from '../../services/geolocation.service';
|
||||
import {DeviceOrientationService} from '../../services/device-orientation.service';
|
||||
@ -29,6 +30,7 @@ import {commonActions} from '@farmmaps/common';
|
||||
import {Feature} from 'ol';
|
||||
import {Extent,createEmpty,extend } from 'ol/extent';
|
||||
import {transform} from 'ol/proj';
|
||||
import { query } from '@angular/animations';
|
||||
import { tassign } from 'tassign';
|
||||
import * as style from 'ol/style';
|
||||
|
||||
@ -55,7 +57,7 @@ export class MapComponent implements OnInit, OnDestroy,AfterViewInit {
|
||||
public droppedFile$: Subject<IDroppedFile> = new Subject<IDroppedFile>();
|
||||
private paramSub: Subscription;
|
||||
private itemTypeSub: Subscription;
|
||||
private stateSub: Subscription;
|
||||
private mapStateSub: Subscription;
|
||||
private queryStateSub: Subscription;
|
||||
private querySub: Subscription;
|
||||
public parentCode$: Observable<string> =this.store.select(mapReducers.selectGetParentCode);
|
||||
@ -65,7 +67,6 @@ export class MapComponent implements OnInit, OnDestroy,AfterViewInit {
|
||||
public clickedFeature: Subject<Feature> = new Subject<Feature>();
|
||||
public selectedItem$: Observable<IItem> = this.store.select(mapReducers.selectGetSelectedItem);
|
||||
public queryState$: Observable<IQueryState> = this.store.select(mapReducers.selectGetQueryState);
|
||||
public state$:Observable<{mapState:IMapState,queryState:IQueryState,setStateCount:number}> = this.store.select(mapReducers.selectGetState);
|
||||
public period$: Observable<IPeriodState> = this.store.select(mapReducers.selectGetPeriod);
|
||||
public clearEnabled$: Observable<boolean> = this.store.select(mapReducers.selectGetClearEnabled);
|
||||
public searchCollapsed$: Observable<boolean> = this.store.select(mapReducers.selectGetSearchCollapsed);
|
||||
@ -79,7 +80,6 @@ export class MapComponent implements OnInit, OnDestroy,AfterViewInit {
|
||||
public extent$: Observable<Extent> = this.store.select(mapReducers.selectGetExtent);
|
||||
public styles$:Observable<IStyles> = this.store.select(mapReducers.selectGetStyles);
|
||||
private setStateCount$:Observable<number> = this.store.select(mapReducers.selectgetSetStateCount);
|
||||
private lastUrl = "";
|
||||
|
||||
@ViewChild('map') map;
|
||||
|
||||
@ -121,7 +121,19 @@ export class MapComponent implements OnInit, OnDestroy,AfterViewInit {
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
this.mapStateSub = this.mapState$.pipe(withLatestFrom(this.queryState$),withLatestFrom(this.setStateCount$)).subscribe(([[mapState,queryState],setStateCount]) =>{
|
||||
if(setStateCount>0) {
|
||||
console.debug(`Mapstate ${setStateCount}`);
|
||||
this.replaceUrl(mapState,queryState,true);
|
||||
}
|
||||
});
|
||||
this.queryStateSub = this.queryState$.pipe(withLatestFrom(this.mapState$),withLatestFrom(this.setStateCount$)).subscribe(([[queryState,mapState],setStateCount]) =>{
|
||||
if(setStateCount>0) {
|
||||
console.debug(`Querystate ${setStateCount}`);
|
||||
this.replaceUrl(mapState,queryState,true);
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@HostListener('document:keyup', ['$event'])
|
||||
@ -160,7 +172,8 @@ export class MapComponent implements OnInit, OnDestroy,AfterViewInit {
|
||||
console.debug("Init");
|
||||
this.store.dispatch(new mapActions.Clear());
|
||||
this.selectedFeatures$.next({x:0,y:0,features:[]});
|
||||
this.selectedFeatures$.next(null);
|
||||
this.selectedFeatures$.next(null);
|
||||
|
||||
}
|
||||
|
||||
initCustomStyles() {
|
||||
@ -182,107 +195,47 @@ export class MapComponent implements OnInit, OnDestroy,AfterViewInit {
|
||||
})));
|
||||
}
|
||||
|
||||
round(value:number,decimals:number):number {
|
||||
let d = Math.pow(10, decimals);
|
||||
return Math.round((value + Number.EPSILON)*d)/d;
|
||||
}
|
||||
|
||||
getMapStateFromUrl(params:ParamMap):IMapState {
|
||||
var hasUrlmapState = params.has("xCenter") && params.has("yCenter");
|
||||
if (hasUrlmapState) {
|
||||
let xCenter = parseFloat(params.get("xCenter"));
|
||||
let yCenter = parseFloat(params.get("yCenter"));
|
||||
let zoom = parseFloat(params.get("zoom"));
|
||||
let rotation = parseFloat(params.get("rotation"));
|
||||
let baseLayer = params.get("baseLayer")?params.get("baseLayer"):"";
|
||||
var newMapState = {zoom: zoom, rotation: rotation, xCenter: xCenter, yCenter: yCenter, baseLayerCode: baseLayer };
|
||||
return newMapState;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
normalizeMapState(mapState:IMapState):IMapState {
|
||||
if(!mapState) return null;
|
||||
return {zoom: this.round(mapState.zoom,0),
|
||||
rotation: this.round(mapState.rotation,2),
|
||||
xCenter: this.round(mapState.xCenter,5),
|
||||
yCenter: this.round(mapState.yCenter,5),
|
||||
baseLayerCode: mapState.baseLayerCode };
|
||||
}
|
||||
|
||||
serializeMapState(mapState:IMapState):string {
|
||||
return JSON.stringify(this.normalizeMapState(mapState));
|
||||
}
|
||||
|
||||
getQueryStateFromUrl(params:ParamMap):IQueryState {
|
||||
if (params.has("queryState")) {
|
||||
let queryState = params.get("queryState");
|
||||
var newQueryState = tassign(mapReducers.initialQueryState);
|
||||
if (queryState != "") {
|
||||
newQueryState = this.serializeService.deserialize(queryState);
|
||||
}
|
||||
return newQueryState;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
ngAfterViewInit() {
|
||||
console.debug("View init");
|
||||
this.initCustomStyles();
|
||||
|
||||
// url to state
|
||||
|
||||
this.paramSub = this.route.paramMap.pipe(withLatestFrom(this.state$),switchMap(([params,state]) => {
|
||||
var newMapState: IMapState = state.mapState;
|
||||
var newQueryState: IQueryState = state.queryState;
|
||||
|
||||
this.paramSub = this.route.paramMap.pipe(withLatestFrom(this.setStateCount$),withLatestFrom(this.queryState$),withLatestFrom(this.mapState$)).subscribe( ([[[params,setStateCount],lastQueryState],lastMapState]) => {
|
||||
console.debug(`Url change ${setStateCount}`);
|
||||
var newMapState: IMapState = lastMapState;
|
||||
var newQueryState: IQueryState = lastQueryState;
|
||||
var hasUrlmapState = params.has("xCenter") && params.has("yCenter");
|
||||
var queryStateChanged = false;
|
||||
var mapStateChanged = false;
|
||||
let urlMapState = this.getMapStateFromUrl(params);
|
||||
if(urlMapState) {
|
||||
newMapState = urlMapState;
|
||||
mapStateChanged = this.serializeMapState(state.mapState) != this.serializeMapState(newMapState);
|
||||
if (hasUrlmapState) {
|
||||
let xCenter = parseFloat(params.get("xCenter"));
|
||||
let yCenter = parseFloat(params.get("yCenter"));
|
||||
let zoom = parseFloat(params.get("zoom"));
|
||||
let rotation = parseFloat(params.get("rotation"));
|
||||
let baseLayer = params.get("baseLayer")?params.get("baseLayer"):"";
|
||||
newMapState = { xCenter: xCenter, yCenter: yCenter, zoom: zoom, rotation: rotation, baseLayerCode: baseLayer }
|
||||
window.localStorage.setItem("FarmMapsCommonMap_mapState",JSON.stringify(newMapState));
|
||||
}
|
||||
|
||||
let urlQueryState = this.getQueryStateFromUrl(params);
|
||||
if(urlQueryState) {
|
||||
newQueryState = urlQueryState;
|
||||
queryStateChanged = this.serializeService.serialize(state.queryState) != this.serializeService.serialize(urlQueryState);
|
||||
}
|
||||
|
||||
if(queryStateChanged && mapStateChanged && state.setStateCount ==0) {
|
||||
return of(new mapActions.SetState(newMapState,newQueryState));
|
||||
window.localStorage.setItem("FarmMapsCommonMap_mapState",this.serializeMapState(newMapState));
|
||||
} else if(queryStateChanged) {
|
||||
return of(new mapActions.SetQueryState(newQueryState));
|
||||
} return of(null)
|
||||
})).subscribe((action) => {
|
||||
if(action) {
|
||||
console.debug("Url to state");
|
||||
this.store.dispatch(action);
|
||||
}
|
||||
});
|
||||
|
||||
// state to url
|
||||
|
||||
this.stateSub = this.state$.pipe(withLatestFrom(this.route.paramMap),switchMap(([state,params]) => {
|
||||
let newUrl = this.serializeMapState(state.mapState) + "_" + this.serializeService.serialize(state.queryState);
|
||||
if(this.lastUrl!=newUrl && state.setStateCount>0) {
|
||||
this.lastUrl=newUrl;
|
||||
return of(state);
|
||||
}
|
||||
else {
|
||||
return of(null);
|
||||
}
|
||||
})).subscribe((newUrlState) =>{
|
||||
if(newUrlState) {
|
||||
console.debug(`State to url ${newUrlState.setStateCount}`);
|
||||
this.replaceUrl(newUrlState.mapState,newUrlState.queryState,true);
|
||||
if (params.has("queryState")) {
|
||||
let queryState = params.get("queryState");
|
||||
newQueryState = tassign(mapReducers.initialQueryState);
|
||||
if (queryState != "") {
|
||||
newQueryState = this.serializeService.deserialize(queryState);
|
||||
queryState = this.serializeService.serialize(newQueryState);
|
||||
}
|
||||
});
|
||||
|
||||
queryStateChanged = this.serializeService.serialize(lastQueryState) != queryState;
|
||||
}
|
||||
console.debug(newQueryState);
|
||||
console.debug(queryStateChanged?"Changed":"");
|
||||
let t =0;
|
||||
if(setStateCount==0) t=600;
|
||||
setTimeout(() => {
|
||||
this.zone.run(()=> {
|
||||
if (setStateCount ==0) {
|
||||
this.store.dispatch(new mapActions.SetState(newMapState,newQueryState));
|
||||
} else if(queryStateChanged) {
|
||||
this.store.dispatch(new mapActions.SetQueryState(newQueryState));
|
||||
}
|
||||
})
|
||||
},t);
|
||||
});
|
||||
setTimeout(() => {
|
||||
this.map.instance.updateSize();
|
||||
}, 500);
|
||||
@ -325,7 +278,7 @@ export class MapComponent implements OnInit, OnDestroy,AfterViewInit {
|
||||
if(mapState.baseLayerCode!="") {
|
||||
parts.push(mapState.baseLayerCode);
|
||||
parts.push( this.serializeService.serialize(queryState));
|
||||
console.debug("Replace url",parts);
|
||||
console.debug("Replace url",mapState,queryState,replace);
|
||||
this.router.navigate(parts, { replaceUrl: replace,relativeTo:this.route.parent });
|
||||
}
|
||||
}
|
||||
@ -343,7 +296,7 @@ export class MapComponent implements OnInit, OnDestroy,AfterViewInit {
|
||||
let state = { mapState: mapState, extent: extent };
|
||||
let source = from([state]);
|
||||
source.pipe(withLatestFrom(this.selectedBaseLayer$),withLatestFrom(this.setStateCount$)).subscribe(([[state, baselayer],setStateCount]) => {
|
||||
if (mapState && baselayer) { // do not react on first move
|
||||
if (mapState && baselayer && setStateCount > 0) { // do not react on first move
|
||||
let newMapState = tassign(state.mapState, { baseLayerCode: baselayer.item.code });
|
||||
this.store.dispatch(new mapActions.SetMapState(newMapState));
|
||||
this.store.dispatch(new mapActions.SetViewExtent(state.extent));
|
||||
@ -353,7 +306,6 @@ export class MapComponent implements OnInit, OnDestroy,AfterViewInit {
|
||||
}
|
||||
|
||||
handleOnMouseDown(event: MouseEvent) {
|
||||
event.stopPropagation();
|
||||
this.zone.run(() =>{
|
||||
this.store.dispatch(new mapActions.CollapseSearch());
|
||||
});
|
||||
@ -398,7 +350,7 @@ export class MapComponent implements OnInit, OnDestroy,AfterViewInit {
|
||||
ngOnDestroy() {
|
||||
if (this.paramSub) this.paramSub.unsubscribe();
|
||||
if (this.itemTypeSub) this.itemTypeSub.unsubscribe();
|
||||
if (this.stateSub) this.stateSub.unsubscribe();
|
||||
if (this.mapStateSub) this.mapStateSub.unsubscribe();
|
||||
if (this.queryStateSub) this.queryStateSub.unsubscribe();
|
||||
if (this.querySub) this.querySub.unsubscribe();
|
||||
}
|
||||
|
@ -4,11 +4,11 @@ import { Store, Action } from '@ngrx/store';
|
||||
import { Effect, Actions,ofType } from '@ngrx/effects';
|
||||
|
||||
import { Observable , of } from 'rxjs';
|
||||
import { withLatestFrom, switchMap, map, catchError, mergeMap,delay } from 'rxjs/operators';
|
||||
import { withLatestFrom, switchMap, map, catchError, mergeMap } from 'rxjs/operators';
|
||||
|
||||
import {GeoJSON,WKT} from 'ol/format';
|
||||
import {Feature} from 'ol';
|
||||
import { getCenter,createEmpty,extend } from 'ol/extent';
|
||||
import { getCenter } from 'ol/extent';
|
||||
import {Point} from 'ol/geom'
|
||||
|
||||
|
||||
@ -27,7 +27,6 @@ import {FeatureIconService} from '../services/feature-icon.service';
|
||||
import * as style from 'ol/style';
|
||||
|
||||
import { ItemTypeService } from '@farmmaps/common';
|
||||
import { IQueryState } from 'dist/common/public-api';
|
||||
|
||||
|
||||
@Injectable()
|
||||
@ -137,29 +136,10 @@ export class MapEffects {
|
||||
|
||||
|
||||
@Effect()
|
||||
zoomToExtent$: Observable<Action> = this.actions$.pipe(
|
||||
ofType(mapActions.STARTSEARCHSUCCESS),
|
||||
delay(500),
|
||||
mergeMap((action: mapActions.StartSearchSuccess) => {
|
||||
let actions =[];
|
||||
actions.push(new commonActions.SetMenuVisible(false));
|
||||
let extent = createEmpty();
|
||||
if (!action.query.bboxFilter) {
|
||||
if (extent) {
|
||||
for (let f of action.features) {
|
||||
extend(extent, (f as Feature).getGeometry().getExtent());
|
||||
}
|
||||
}
|
||||
actions.push(new mapActions.SetExtent(extent));
|
||||
}
|
||||
return actions;
|
||||
}));
|
||||
|
||||
@Effect()
|
||||
hideMenu$: Observable<Action> = this.actions$.pipe(
|
||||
startSearchSucces$: Observable<Action> = this.actions$.pipe(
|
||||
ofType(mapActions.STARTSEARCHSUCCESS),
|
||||
mergeMap((action: mapActions.StartSearchSuccess) => {
|
||||
return of(new commonActions.SetMenuVisible(false));
|
||||
return [new commonActions.SetMenuVisible(false)];
|
||||
}));
|
||||
|
||||
@Effect()
|
||||
@ -268,27 +248,23 @@ export class MapEffects {
|
||||
}
|
||||
}));
|
||||
|
||||
getActionFromQueryState(queryState:IQueryState, inSearch:boolean):Observable<Action>|[] {
|
||||
if(!inSearch && (queryState.itemType || queryState.parentCode || queryState.itemCode)) {
|
||||
var newAction:Action;
|
||||
if (queryState.itemCode && queryState.itemCode != "") {
|
||||
newAction= new mapActions.SelectItem(queryState.itemCode);
|
||||
} else {
|
||||
newAction= new mapActions.StartSearch(queryState);
|
||||
}
|
||||
return of(newAction);
|
||||
} else {
|
||||
return of(new commonActions.Escape(true,false));
|
||||
}
|
||||
}
|
||||
|
||||
@Effect()
|
||||
setQueryState$: Observable<Action> = this.actions$.pipe(
|
||||
ofType(mapActions.SETQUERYSTATE),
|
||||
withLatestFrom(this.store$.select(mapReducers.selectGetInSearch)),
|
||||
switchMap(([action,inSearch]) => {
|
||||
let a = action as mapActions.SetQueryState;
|
||||
return this.getActionFromQueryState(a.queryState,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()
|
||||
@ -296,8 +272,18 @@ export class MapEffects {
|
||||
ofType(mapActions.SETSTATE),
|
||||
withLatestFrom(this.store$.select(mapReducers.selectGetInSearch)),
|
||||
switchMap(([action,inSearch]) => {
|
||||
let a = action as mapActions.SetState;
|
||||
return this.getActionFromQueryState(a.queryState,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<mapReducers.State>, private folderService$: FolderService, private itemService$: ItemService,private featureIconService$:FeatureIconService,private itemTypeService$:ItemTypeService) {
|
||||
|
@ -10,7 +10,7 @@ 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';
|
||||
|
||||
@ -129,8 +129,18 @@ export function reducer(state = initialState, action: mapActions.Actions | commo
|
||||
}
|
||||
case mapActions.STARTSEARCHSUCCESS: {
|
||||
let a = action as mapActions.StartSearchSuccess;
|
||||
let extent = state.extent;
|
||||
if (!action.query.bboxFilter) {
|
||||
extent = createEmpty();
|
||||
if (extent) {
|
||||
for (let f of action.features) {
|
||||
extend(extent, (f as Feature).getGeometry().getExtent());
|
||||
}
|
||||
}
|
||||
}
|
||||
return tassign(state, {
|
||||
features: a.features,
|
||||
extent:extent,
|
||||
inSearch:false
|
||||
});
|
||||
}
|
||||
@ -456,7 +466,11 @@ export function reducer(state = initialState, action: mapActions.Actions | commo
|
||||
case mapActions.SHOWLAYERSWITCHER:{
|
||||
let a = action as mapActions.ShowLayerSwitcher;
|
||||
return tassign(state,{showLayerSwitcher:a.show});
|
||||
}
|
||||
}
|
||||
|
||||
case commonActions.INITUSER: {
|
||||
return tassign(state,{setStateCount:0,features:[],selectedFeature:null,selectedItem:null});
|
||||
}
|
||||
default: {
|
||||
return state;
|
||||
}
|
||||
@ -487,7 +501,6 @@ export const getStyles = (state:State) => state.styles;
|
||||
export const getShowLayerSwitcher = (state:State) => state.showLayerSwitcher;
|
||||
export const getSetStateCount = (state:State) => state.setStateCount;
|
||||
export const getInSearch = (state:State) => state.inSearch;
|
||||
export const getState = (state:State) => {return {mapState:state.mapState,queryState:state.queryState,setStateCount:state.setStateCount};}
|
||||
|
||||
export const selectMapState = createFeatureSelector<State>(MODULE_NAME);
|
||||
export const selectGetMapState= createSelector(selectMapState, getMapState);
|
||||
@ -514,6 +527,5 @@ export const selectGetStyles = createSelector(selectMapState, getStyles);
|
||||
export const selectGetShowLayerSwitcher = createSelector(selectMapState,getShowLayerSwitcher);
|
||||
export const selectgetSetStateCount = createSelector(selectMapState,getSetStateCount);
|
||||
export const selectGetInSearch = createSelector(selectMapState,getInSearch);
|
||||
export const selectGetState = createSelector(selectMapState,getState);
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user