Add router-outlet to map component to make it more reusable
FarmMaps.Develop/FarmMapsLib/pipeline/head This commit looks good Details

2022.01
Willem Dantuma 2020-12-11 12:08:15 +01:00
parent e873f5af5b
commit 7266c98a10
4 changed files with 52 additions and 30 deletions

View File

@ -8,6 +8,10 @@ const routes = [
path: '', path: '',
component: MapComponent component: MapComponent
}, },
{
path: ':xCenter/:yCenter/:zoom/:rotation/:baseLayer',
component: MapComponent
},
{ {
path: ':xCenter/:yCenter/:zoom/:rotation/:baseLayer/:queryState', path: ':xCenter/:yCenter/:zoom/:rotation/:baseLayer/:queryState',
component: MapComponent component: MapComponent

View File

@ -19,9 +19,10 @@
period:period$|async, period:period$|async,
compassHeading:compassHeading$|async, compassHeading:compassHeading$|async,
styles:styles$|async, styles:styles$|async,
selectedFeature:selectedFeature$|async selectedFeature:selectedFeature$|async,
fullscreen:fullscreen$|async
} as state"> } as state">
<aol-map #map (moveEnd)="handleOnMoveEnd($event)" (click)="handleOnMouseDown($event)" [ngClass]="{'panel-visible':state.panelVisible}" class="map"> <aol-map #map (moveEnd)="handleOnMoveEnd($event)" (click)="handleOnMouseDown($event)" [ngClass]="{'panel-visible':state.panelVisible,'fullscreen':state.fullscreen}" class="map">
<div> <div>
</div> </div>
@ -38,7 +39,7 @@
<fm-map-item-source-vector [styles]="state.styles" [features]="state.features" (onFeatureSelected)="handleFeatureClick($event)" (onFeatureHover)="handleFeatureHover($event)" [selectedFeature]="state.selectedFeature" [selectedItem]="state.selectedItem"></fm-map-item-source-vector> <fm-map-item-source-vector [styles]="state.styles" [features]="state.features" (onFeatureSelected)="handleFeatureClick($event)" (onFeatureHover)="handleFeatureHover($event)" [selectedFeature]="state.selectedFeature" [selectedItem]="state.selectedItem"></fm-map-item-source-vector>
</aol-layer-vector> </aol-layer-vector>
<!-- <fm-map-gps-location [position]="state.position" [headingTolerance]="20" [showHeading]="true" [heading]="state.compassHeading"></fm-map-gps-location> --> <!-- <fm-map-gps-location [position]="state.position" [headingTolerance]="20" [showHeading]="true" [heading]="state.compassHeading"></fm-map-gps-location> -->
<div class="control-container"> <div class="control-container" >
<router-outlet name="map-controls"></router-outlet> <router-outlet name="map-controls"></router-outlet>
<fm-map-layer-switcher></fm-map-layer-switcher> <fm-map-layer-switcher></fm-map-layer-switcher>
<fm-map-pan-to-location [position]="state.position" [mapState]="state.mapState" [animate]="true"></fm-map-pan-to-location> <fm-map-pan-to-location [position]="state.position" [mapState]="state.mapState" [animate]="true"></fm-map-pan-to-location>
@ -46,9 +47,11 @@
</div> </div>
<fm-map-file-drop-target [parentCode]="state.parentCode" (onFileDropped)="handleFileDropped($event)"></fm-map-file-drop-target> <fm-map-file-drop-target [parentCode]="state.parentCode" (onFileDropped)="handleFileDropped($event)"></fm-map-file-drop-target>
</aol-map> </aol-map>
<fm-map-map-search #mapSearch [openedModalName]="state.openedModalName" (onOpenModal)="handleOpenModal($event)" (onCloseModal)="handleCloseModal()" [ngClass]="{'menuVisible':state.menuVisible}" (onToggleMenu)="handleToggleMenu($event)" (onSearchCollapse)="handleSearchCollapse($event)" (onSearchExpand)="handleSearchExpand($event)" [collapsed]="state.searchCollapsed" [searchMinified]="state.searchMinified" (onSearch)="handleSearch($event)" (onClear)="handleClearSearch($event)" [filterOptions]="state.queryState" [clearEnabled]="state.clearEnabled" [period]="state.period"></fm-map-map-search> <div *ngIf="noContent">
<fm-side-panel [resizeable]="true" [visible]="state.panelVisible" [collapsed]="state.panelCollapsed" [collapsable]="false"> <fm-map-map-search #mapSearch [openedModalName]="state.openedModalName" (onOpenModal)="handleOpenModal($event)" (onCloseModal)="handleCloseModal()" [ngClass]="{'menuVisible':state.menuVisible}" (onToggleMenu)="handleToggleMenu($event)" (onSearchCollapse)="handleSearchCollapse($event)" (onSearchExpand)="handleSearchExpand($event)" [collapsed]="state.searchCollapsed" [searchMinified]="state.searchMinified" (onSearch)="handleSearch($event)" (onClear)="handleClearSearch($event)" [filterOptions]="state.queryState" [clearEnabled]="state.clearEnabled" [period]="state.period"></fm-map-map-search>
<div class="panel-wrapper"> </div>
<fm-side-panel [resizeable]="true" [visible]="state.panelVisible && noContent" [collapsed]="state.panelCollapsed" [collapsable]="false">
<div class="panel-wrapper" *ngIf="noContent">
<div class="panel-top bg-secondary" *ngIf="!(state.searchMinified)"> <div class="panel-top bg-secondary" *ngIf="!(state.searchMinified)">
</div> </div>
<div class="panel-bottom"> <div class="panel-bottom">
@ -65,7 +68,10 @@
<div *ngIf="state.queryState?.tags">Cannot find tag <span>{{state.queryState?.tags}}</span></div> <div *ngIf="state.queryState?.tags">Cannot find tag <span>{{state.queryState?.tags}}</span></div>
</div> </div>
</div> </div>
</div> </div>
</fm-side-panel>
<fm-side-panel [resizeable]="true" [visible]="!noContent">
<router-outlet></router-outlet>
</fm-side-panel> </fm-side-panel>
</ng-container> </ng-container>

View File

@ -49,6 +49,10 @@ aol-map { position:absolute;width:100%;height:calc(100vh + 4rem);}
.control-container { .control-container {
position: absolute; position: absolute;
right: 1em; right: 1em;
bottom: 8.1em;
}
.fullscreen .control-container {
bottom: 5em; bottom: 5em;
} }

View File

@ -1,4 +1,4 @@
import { Component, OnInit, OnDestroy, HostListener, ViewChild, AfterViewInit,NgZone } from '@angular/core'; import { Component, OnInit, OnDestroy, HostListener, ViewChild, AfterViewInit,NgZone,ElementRef } from '@angular/core';
import { Location } from '@angular/common'; import { Location } from '@angular/common';
import { Observable, Subject, Subscription, from,of ,EMPTY } from 'rxjs'; import { Observable, Subject, Subscription, from,of ,EMPTY } from 'rxjs';
import { withLatestFrom, switchMap,skip } from 'rxjs/operators'; import { withLatestFrom, switchMap,skip } from 'rxjs/operators';
@ -79,10 +79,13 @@ export class MapComponent implements OnInit, OnDestroy,AfterViewInit {
public overlayLayersCollapsed: boolean = true; public overlayLayersCollapsed: boolean = true;
public extent$: Observable<Extent> = this.store.select(mapReducers.selectGetExtent); public extent$: Observable<Extent> = this.store.select(mapReducers.selectGetExtent);
public styles$:Observable<IStyles> = this.store.select(mapReducers.selectGetStyles); public styles$:Observable<IStyles> = this.store.select(mapReducers.selectGetStyles);
public fullscreen$: Observable<boolean> = this.store.select(commonReducers.selectGetFullScreen);
private lastUrl = ""; private lastUrl = "";
private initialized: boolean = false; private initialized: boolean = false;
public noContent: boolean = false;
@ViewChild('map') map; @ViewChild('map') map;
@ViewChild('contentDiv') contentDiv: ElementRef;
constructor(private store: Store<mapReducers.State | commonReducers.State>, constructor(private store: Store<mapReducers.State | commonReducers.State>,
private route: ActivatedRoute, private route: ActivatedRoute,
@ -162,7 +165,7 @@ export class MapComponent implements OnInit, OnDestroy,AfterViewInit {
this.store.dispatch(new mapActions.DoQuery(queryState)); this.store.dispatch(new mapActions.DoQuery(queryState));
} }
ngOnInit() { ngOnInit() {
this.initialized = false; this.initialized = false;
console.debug("Init"); console.debug("Init");
this.store.dispatch(new mapActions.Clear()); this.store.dispatch(new mapActions.Clear());
@ -237,23 +240,27 @@ export class MapComponent implements OnInit, OnDestroy,AfterViewInit {
ngAfterViewInit() { ngAfterViewInit() {
console.debug("View init"); console.debug("View init");
if(this.route.children.length == 0) {
this.noContent=true;
}
this.initCustomStyles(); this.initCustomStyles();
// url to state // url to state
let urlMapState = this.getMapStateFromUrl(this.route.snapshot.paramMap); let urlMapState = this.getMapStateFromUrl(this.route.snapshot.paramMap);
let urlQueryState = this.getQueryStateFromUrl(this.route.snapshot.paramMap); let urlQueryState = this.getQueryStateFromUrl(this.route.snapshot.paramMap);
if(urlQueryState && urlMapState) { if(urlQueryState && urlMapState && this.noContent) {
this.store.dispatch(new mapActions.SetState(urlMapState,urlQueryState)); this.store.dispatch(new mapActions.SetState(urlMapState,urlQueryState));
window.localStorage.setItem("FarmMapsCommonMap_mapState",this.serializeMapState(urlMapState)); window.localStorage.setItem("FarmMapsCommonMap_mapState",this.serializeMapState(urlMapState));
} else if(urlQueryState) { } else if(urlQueryState && this.noContent) {
this.store.dispatch(new mapActions.SetQueryState(urlQueryState)); this.store.dispatch(new mapActions.SetQueryState(urlQueryState));
} else { } else {
this.store.dispatch(new mapActions.SetReplaceUrl(true)); this.store.dispatch(new mapActions.SetReplaceUrl(true));
} }
this.paramSub = this.route.paramMap.pipe(withLatestFrom(this.state$),switchMap(([params,state]) => { this.paramSub = this.route.paramMap.pipe(withLatestFrom(this.state$),switchMap(([params,state]) => {
if(this.initialized) { if(this.initialized && this.noContent) {
let urlQueryState = this.getQueryStateFromUrl(params); let urlQueryState = this.getQueryStateFromUrl(params);
if( this.serializeService.serialize(state.queryState) != this.serializeService.serialize(urlQueryState)) { if( this.serializeService.serialize(state.queryState) != this.serializeService.serialize(urlQueryState)) {
return of(new mapActions.SetState(state.mapState,urlQueryState)); return of(new mapActions.SetState(state.mapState,urlQueryState));
@ -318,24 +325,25 @@ export class MapComponent implements OnInit, OnDestroy,AfterViewInit {
} }
replaceUrl(mapState: IMapState, queryState: IQueryState, replace: boolean = true) { replaceUrl(mapState: IMapState, queryState: IQueryState, replace: boolean = true) {
if(this.noContent) {
let newMapState = this.serializeMapState(mapState); let newMapState = this.serializeMapState(mapState);
let newQueryState = this.serializeService.serialize(queryState); let newQueryState = this.serializeService.serialize(queryState);
let currentMapState = this.serializeMapState(this.getMapStateFromUrl(this.route.snapshot.paramMap)); let currentMapState = this.serializeMapState(this.getMapStateFromUrl(this.route.snapshot.paramMap));
let urlQueryState = this.getQueryStateFromUrl(this.route.snapshot.paramMap); let urlQueryState = this.getQueryStateFromUrl(this.route.snapshot.paramMap);
let currentQueryState = urlQueryState==null?"":this.serializeService.serialize(urlQueryState); let currentQueryState = urlQueryState==null?"":this.serializeService.serialize(urlQueryState);
if(mapState.baseLayerCode!="" && ((newMapState!= currentMapState) || (newQueryState!=currentQueryState))) { if(mapState.baseLayerCode!="" && ((newMapState!= currentMapState) || (newQueryState!=currentQueryState))) {
let parts =["."]; let parts =["."];
parts.push(mapState.xCenter.toFixed(5)); parts.push(mapState.xCenter.toFixed(5));
parts.push(mapState.yCenter.toFixed(5)); parts.push(mapState.yCenter.toFixed(5));
parts.push( mapState.zoom.toFixed(0)); parts.push( mapState.zoom.toFixed(0));
parts.push( mapState.rotation.toFixed(2)); parts.push( mapState.rotation.toFixed(2));
parts.push(mapState.baseLayerCode); parts.push(mapState.baseLayerCode);
parts.push( this.serializeService.serialize(queryState)); parts.push( this.serializeService.serialize(queryState));
console.debug("Replace url",parts); console.debug("Replace url",parts);
this.router.navigate(parts, { replaceUrl: replace,relativeTo:this.route.parent }); this.router.navigate(parts, { replaceUrl: replace,relativeTo:this.route.parent });
} }
}
} }
handleOnMoveEnd(event) { handleOnMoveEnd(event) {