From d3782323f51d7eec1974b2b291da9995be41a0e5 Mon Sep 17 00:00:00 2001 From: Willem Dantuma Date: Fri, 1 Nov 2019 16:53:24 +0100 Subject: [PATCH] First functional version --- .../common-map/src/lib/common-map.module.ts | 43 --- .../item-widget-list.component.ts | 20 +- .../src/lib/components/map/map.component.html | 15 +- .../src/lib/components/map/map.component.ts | 12 +- projects/common-map/src/lib/map.component.ts | 297 ------------------ src/app/app.component.scss | 6 + 6 files changed, 33 insertions(+), 360 deletions(-) delete mode 100644 projects/common-map/src/lib/map.component.ts diff --git a/projects/common-map/src/lib/common-map.module.ts b/projects/common-map/src/lib/common-map.module.ts index f6d4bab..ca9815b 100644 --- a/projects/common-map/src/lib/common-map.module.ts +++ b/projects/common-map/src/lib/common-map.module.ts @@ -53,14 +53,7 @@ import { LayerVectorImageComponent } from './components/aol/layer-vector-image/l import { StateSerializerService } from './services/state-serializer.service'; import { GeolocationService } from './services/geolocation.service'; import { localStorageSync } from 'ngrx-store-localstorage'; -import { ItemWidgetWeatherComponent } from './components/item-widget-weather/item-widget-weather.component'; -import { ItemListItemTemporalComponent } from './components/item-list-item-temporal/item-list-item-temporal.component'; -import { ItemListItemHeightComponent } from './components/item-list-item-height/item-list-item-height.component'; -import { ItemListItemTipstarComponent } from './components/item-list-item-tipstar/item-list-item-tipstar.component'; -import { ItemListItemWatBalComponent } from './components/item-list-item-watbal/item-list-item-watbal.component'; import { WidgetStatusComponent } from './components/widget-status/widget-status.component'; -import { ItemListItemShadowComponent } from './components/item-list-item-shadow/item-list-item-shadow.component'; -import { ItemListItemBofekComponent } from './components/item-list-item-bofek/item-list-item-bofek.component'; export { @@ -96,16 +89,9 @@ export { ItemListItemComponent, ItemListItemContainerComponent, ItemListComponent, - ItemWidgetWeatherComponent, - ItemListItemTemporalComponent, ItemWidgetListComponent, - ItemListItemHeightComponent, - ItemListItemTipstarComponent, - ItemListItemWatBalComponent, - ItemListItemShadowComponent, WidgetStatusComponent, GpsLocation, - ItemListItemBofekComponent, AbstractFeatureListComponent, AbstractFeatureListFeatureComponent, AbstractSelectedItemComponent, @@ -159,17 +145,9 @@ export { ItemListItemComponent, ItemListItemContainerComponent, ItemListComponent, - ItemWidgetWeatherComponent, - ItemListItemTemporalComponent, ItemWidgetListComponent, - ItemListItemHeightComponent, - ItemListItemTipstarComponent, - ItemListItemWatBalComponent, - ItemListItemShadowComponent, WidgetStatusComponent, GpsLocation, - ItemListItemBofekComponent - // Switch2D3DComponent ], entryComponents: [ FeatureListComponent, @@ -184,13 +162,6 @@ export { SelectedItemShapeComponent, ItemListComponent, ItemListItemComponent, - ItemWidgetWeatherComponent, - ItemListItemTemporalComponent, - ItemListItemHeightComponent, - ItemListItemTipstarComponent, - ItemListItemWatBalComponent, - ItemListItemShadowComponent, - ItemListItemBofekComponent, ], exports: [ ItemVectorSourceComponent, @@ -211,15 +182,8 @@ export { ItemListItemComponent, ItemListItemContainerComponent, ItemListComponent, - ItemWidgetWeatherComponent, - ItemListItemTemporalComponent, ItemWidgetListComponent, - ItemListItemHeightComponent, - ItemListItemTipstarComponent, - ItemListItemWatBalComponent, - ItemListItemShadowComponent, WidgetStatusComponent, - ItemListItemBofekComponent, RotationResetComponent, MapSearchComponent, SelectPeriodModalComponent, @@ -253,13 +217,6 @@ export class AppCommonMapModule { { provide: AbstractSelectedItemComponent, useClass: SelectedItemGeotiffComponent, multi: true }, { provide: AbstractSelectedItemComponent, useClass: SelectedItemShapeComponent, multi: true }, { provide: AbstractItemListItemComponent, useClass: ItemListItemComponent, multi: true }, - { provide: AbstractItemWidgetComponent, useClass: ItemWidgetWeatherComponent, multi: true }, - { provide: AbstractItemListItemComponent, useClass: ItemListItemTemporalComponent, multi: true }, - { provide: AbstractItemListItemComponent, useClass: ItemListItemHeightComponent, multi: true }, - { provide: AbstractItemListItemComponent, useClass: ItemListItemTipstarComponent, multi: true }, - { provide: AbstractItemListItemComponent, useClass: ItemListItemWatBalComponent, multi: true }, - { provide: AbstractItemListItemComponent, useClass: ItemListItemShadowComponent, multi: true }, - { provide: AbstractItemListItemComponent, useClass: ItemListItemBofekComponent, multi: true }, { provide: AbstractItemListComponent, useClass: ItemListComponent, multi: true } ] }; diff --git a/projects/common-map/src/lib/components/item-widget-list/item-widget-list.component.ts b/projects/common-map/src/lib/components/item-widget-list/item-widget-list.component.ts index 67e09b3..01ef171 100644 --- a/projects/common-map/src/lib/components/item-widget-list/item-widget-list.component.ts +++ b/projects/common-map/src/lib/components/item-widget-list/item-widget-list.component.ts @@ -1,4 +1,4 @@ -import { Component, Input, Injectable, Inject, ComponentFactoryResolver, ViewContainerRef, QueryList, ComponentFactory, ViewChildren,AfterViewInit } from '@angular/core'; +import { Component, Input, Injectable, Inject, Optional,ComponentFactoryResolver, ViewContainerRef, QueryList, ComponentFactory, ViewChildren,AfterViewInit } from '@angular/core'; import { Location } from '@angular/common'; import { Store } from '@ngrx/store'; import * as mapReducers from '../../reducers/map.reducer'; @@ -18,19 +18,21 @@ export class ItemWidgetListComponent implements AfterViewInit { public widgets: AbstractItemWidgetComponent[]; @ViewChildren('widgetTemplate', { read: ViewContainerRef }) private widgetTargets: QueryList; - constructor(public store: Store, public itemTypeService: ItemTypeService, public location: Location, private componentFactoryResolver: ComponentFactoryResolver, @Inject(AbstractItemWidgetComponent) itemWidgetComponentList: AbstractItemWidgetComponent[]) { + constructor(public store: Store, public itemTypeService: ItemTypeService, public location: Location, private componentFactoryResolver: ComponentFactoryResolver, @Optional() @Inject(AbstractItemWidgetComponent) itemWidgetComponentList: AbstractItemWidgetComponent[]) { this.widgets = itemWidgetComponentList; //todo filter this list on widgets available for user } ngAfterViewInit() { let targets = this.widgetTargets.toArray(); - for (var i = 0; i < this.widgets.length; i++) { - var componentFactory: ComponentFactory = this.componentFactoryResolver.resolveComponentFactory(this.widgets[i]['constructor'] as any); - const viewContainerRef = targets[i]; - viewContainerRef.clear(); - - const componentRef = viewContainerRef.createComponent(componentFactory); - (componentRef.instance).item = this.item; + if(this.widgets) { + for (var i = 0; i < this.widgets.length; i++) { + var componentFactory: ComponentFactory = this.componentFactoryResolver.resolveComponentFactory(this.widgets[i]['constructor'] as any); + const viewContainerRef = targets[i]; + viewContainerRef.clear(); + + const componentRef = viewContainerRef.createComponent(componentFactory); + (componentRef.instance).item = this.item; + } } } } diff --git a/projects/common-map/src/lib/components/map/map.component.html b/projects/common-map/src/lib/components/map/map.component.html index d72ddc4..2a0e68b 100644 --- a/projects/common-map/src/lib/components/map/map.component.html +++ b/projects/common-map/src/lib/components/map/map.component.html @@ -1,8 +1,13 @@ - - - - - + +
+ +
+ + + + + + diff --git a/projects/common-map/src/lib/components/map/map.component.ts b/projects/common-map/src/lib/components/map/map.component.ts index 5df667f..34eb53b 100644 --- a/projects/common-map/src/lib/components/map/map.component.ts +++ b/projects/common-map/src/lib/components/map/map.component.ts @@ -38,7 +38,7 @@ export class MapComponent implements OnInit, OnDestroy,AfterViewInit { title: string = 'Map'; public openedModalName: Observable; public itemTypes: Observable<{ [id: string]: IItemType }>; - public mapState: Observable; + public mapState$: Observable; public features: Observable>; public overlayLayers: Observable>; public selectedOverlayLayer: Observable; @@ -67,7 +67,7 @@ export class MapComponent implements OnInit, OnDestroy,AfterViewInit { public position: Observable; public baseLayersCollapsed:boolean = true; public overlayLayersCollapsed: boolean = true; - public extent: Observable; + public extent$: Observable; @ViewChild('map') map; constructor(private store: Store, private route: ActivatedRoute, private router: Router, private uploadService: ResumableFileUploadService, private serializeService: StateSerializerService, public itemTypeService: ItemTypeService, private location: Location, private geolocationService: GeolocationService ) { @@ -107,7 +107,7 @@ export class MapComponent implements OnInit, OnDestroy,AfterViewInit { ngOnInit() { this.store.dispatch(new mapActions.Init()); this.selectedFeatures.next({x:0,y:0,features:[]}); - this.mapState = this.store.select(mapReducers.selectGetMapState); + this.mapState$ = this.store.select(mapReducers.selectGetMapState); this.parentCode = this.store.select(mapReducers.selectGetParentCode); this.features = this.store.select(mapReducers.selectGetFeatures); this.overlayLayers = this.store.select(mapReducers.selectGetOverlayLayers); @@ -126,16 +126,16 @@ export class MapComponent implements OnInit, OnDestroy,AfterViewInit { this.menuVisible = this.store.select(mapReducers.selectGetMenuVisible); this.openedModalName = this.store.select(commonReducers.selectOpenedModalName); this.query = this.store.select(mapReducers.selectGetQuery); - this.extent = this.store.select(mapReducers.selectGetExtent); + this.extent$ = this.store.select(mapReducers.selectGetExtent); this.selectedFeatures.next(null); this.selectedItemLayer = this.store.select(mapReducers.selectGetSelectedItemLayer); this.period = this.store.select(mapReducers.selectGetPeriod); this.position = this.geolocationService.getCurrentPosition(); - this.mapState.pipe(withLatestFrom(this.queryState)).subscribe((state) => { + this.mapState$.pipe(withLatestFrom(this.queryState)).subscribe((state) => { this.replaceUrl(state[0], state[1], true); }); - this.query.pipe(withLatestFrom(this.mapState)).subscribe((state) => { + this.query.pipe(withLatestFrom(this.mapState$)).subscribe((state) => { this.replaceUrl(state[1], state[0],false); }); } diff --git a/projects/common-map/src/lib/map.component.ts b/projects/common-map/src/lib/map.component.ts deleted file mode 100644 index 7b9ba15..0000000 --- a/projects/common-map/src/lib/map.component.ts +++ /dev/null @@ -1,297 +0,0 @@ -import { Component, OnInit, OnDestroy, HostListener, Inject, ViewChild, AfterViewInit } from '@angular/core'; -import { Location } from '@angular/common'; -import { Observable, Subject, Subscription,combineLatest, from } from 'rxjs'; -import { debounce, withLatestFrom, first, combineAll } from 'rxjs/operators'; -import { Router, ActivatedRoute, ParamMap, Event } from '@angular/router'; -import { Store } from '@ngrx/store'; -//import { proj,Map } from 'openlayers'; - -// Map -import * as mapReducers from './reducers/map.reducer'; -import * as mapActions from './actions/map.actions'; -import { IMapState,ISelectedFeatures,IItemLayer, ItemLayer,IQueryState,IPeriodState } from './models'; -import { IDroppedFile } from './components/aol/file-drop-target/file-drop-target.component'; -import { IMetaData } from './components/meta-data-modal/meta-data-modal.component'; -import { StateSerializerService } from './services/state-serializer.service'; -import { GeolocationService} from './services/geolocation.service'; - -// AppCommon -import { ResumableFileUploadService, ItemTypeService } from '@farmmaps/common'; -import { IItemType, IItem } from '@farmmaps/common'; -import {commonReducers} from '@farmmaps/common'; -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'; - - -@Component({ - selector: 'map', - templateUrl: './map.component.html', - styleUrls: ['./map.component.scss'] -}) - -export class MapComponent implements OnInit, OnDestroy,AfterViewInit { - title: string = 'Map'; - public openedModalName: Observable; - public itemTypes: Observable<{ [id: string]: IItemType }>; - public mapState: Observable; - public features: Observable>; - public overlayLayers: Observable>; - public selectedOverlayLayer: Observable; - public selectedItemLayer: Observable; - public baseLayers: Observable>; - public selectedBaseLayer: Observable; - public projection: Observable; - public selectedFeatures: Subject = new Subject(); - public droppedFile: Subject = new Subject(); - private paramSub: Subscription; - private itemTypeSub: Subscription; - private mapStateSub: Subscription; - private queryStateSub: Subscription; - public parentCode: Observable; - public panelVisible: Observable; - public panelCollapsed: Observable; - public selectedFeature: Observable; - public selectedItem: Observable; - public queryState: Observable; - public period: Observable; - public clearEnabled: Observable; - public searchCollapsed: Observable; - public searchMinified: Observable; - public menuVisible: Observable; - public query: Observable; - public position: Observable; - public baseLayersCollapsed:boolean = true; - public overlayLayersCollapsed: boolean = true; - public extent: Observable; - @ViewChild('map') map; - - constructor(private store: Store, private route: ActivatedRoute, private router: Router, private uploadService: ResumableFileUploadService, private serializeService: StateSerializerService, public itemTypeService: ItemTypeService, private location: Location, private geolocationService: GeolocationService ) { - } - - @HostListener('document:keyup', ['$event']) - escapeClose(event: KeyboardEvent) { - let x = event.keyCode; - if (x === 27) { - this.handleCloseModal() - } - } - - handleOpenModal(modalName: string) { - this.store.dispatch(new commonActions.OpenModal(modalName)); - } - - handleCloseModal() { - this.store.dispatch(new commonActions.CloseModal()); - } - - handleFileDropped(droppedFile: IDroppedFile) { - this.uploadService.addFiles(droppedFile.files, droppedFile.event, { parentCode:droppedFile.parentCode, geometry:droppedFile.geometry }); - } - - handleFeaturesSelected(feature: Feature) { - if (feature) { - let newQuery = tassign(mapReducers.initialQueryState, { itemCode: feature.get('code') }); - this.store.dispatch(new mapActions.DoQuery(newQuery)); - } - } - - handleSearch(queryState: IQueryState) { - this.store.dispatch(new mapActions.DoQuery(queryState)); - } - - ngOnInit() { - this.store.dispatch(new mapActions.Init()); - this.selectedFeatures.next({x:0,y:0,features:[]}); - this.mapState = this.store.select(mapReducers.selectGetMapState); - this.parentCode = this.store.select(mapReducers.selectGetParentCode); - this.features = this.store.select(mapReducers.selectGetFeatures); - this.overlayLayers = this.store.select(mapReducers.selectGetOverlayLayers); - this.selectedOverlayLayer = this.store.select(mapReducers.selectGetSelectedOverlayLayer); - this.baseLayers = this.store.select(mapReducers.selectGetBaseLayers); - this.projection = this.store.select(mapReducers.selectGetProjection); - this.selectedBaseLayer = this.store.select(mapReducers.selectGetSelectedBaseLayer); - this.panelVisible = this.store.select(mapReducers.selectGetPanelVisible); - this.panelCollapsed = this.store.select(mapReducers.selectGetPanelCollapsed); - this.selectedFeature = this.store.select(mapReducers.selectGetSelectedFeature); - this.selectedItem = this.store.select(mapReducers.selectGetSelectedItem); - this.queryState = this.store.select(mapReducers.selectGetQueryState); - this.clearEnabled = this.store.select(mapReducers.selectGetClearEnabled); - this.searchCollapsed = this.store.select(mapReducers.selectGetSearchCollapsed); - this.searchMinified = this.store.select(mapReducers.selectGetSearchMinified); - this.menuVisible = this.store.select(mapReducers.selectGetMenuVisible); - this.openedModalName = this.store.select(commonReducers.selectOpenedModalName); - this.query = this.store.select(mapReducers.selectGetQuery); - this.extent = this.store.select(mapReducers.selectGetExtent); - this.selectedFeatures.next(null); - this.selectedItemLayer = this.store.select(mapReducers.selectGetSelectedItemLayer); - this.period = this.store.select(mapReducers.selectGetPeriod); - this.position = this.geolocationService.getCurrentPosition(); - - this.mapState.pipe(withLatestFrom(this.queryState)).subscribe((state) => { - this.replaceUrl(state[0], state[1], true); - }); - this.query.pipe(withLatestFrom(this.mapState)).subscribe((state) => { - this.replaceUrl(state[1], state[0],false); - }); - } - - private stateSetCount: number = 0; - private lastQueryState: string = this.serializeService.serialize(mapReducers.initialQueryState); - private lastMapState: string = ""; - ngAfterViewInit() { - this.paramSub = this.route.paramMap.subscribe((params: ParamMap) => { - //console.log("Param sub"); - var newMapState: IMapState = null; - var newQueryState: IQueryState = null; - var mapStateChanged = false; - var queryStateChanged = false; - if (params.has("xCenter") && params.has("yCenter")) { - 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"); - newMapState = { xCenter: xCenter, yCenter: yCenter, zoom: zoom, rotation: rotation, baseLayerCode: baseLayer } - mapStateChanged = this.lastMapState != JSON.stringify(newMapState) && this.stateSetCount == 0; - this.lastMapState = JSON.stringify(newMapState); - //console.log(`Base layer: ${newMapState.baseLayerCode}`) - } - if (params.has("queryState")) { - let queryState = params.get("queryState"); - newQueryState = tassign(mapReducers.initialQueryState); - if (queryState != "") { - newQueryState = this.serializeService.deserialize(queryState); - } - queryStateChanged = this.lastQueryState != queryState; - this.lastQueryState = queryState; - } - - if (mapStateChanged && queryStateChanged) { - //console.log("Both states"); - this.store.dispatch(new mapActions.SetState(newMapState, newQueryState)); - } else if (mapStateChanged) { - //console.log("Map state"); - this.store.dispatch(new mapActions.SetMapState(newMapState)); - } else if (queryStateChanged) { - //console.log("Query state"); - this.store.dispatch(new mapActions.SetQueryState(newQueryState)); - } - this.stateSetCount += 1; - }); - setTimeout(() => { - this.map.instance.updateSize(); - }, 500); - } - - handleSearchCollapse(event) { - this.store.dispatch(new mapActions.CollapseSearch()); - } - - handleSearchExpand(event) { - this.store.dispatch(new mapActions.ExpandSearch()); - } - - handleToggleMenu(event) { - this.store.dispatch(new mapActions.ToggleMenu()); - } - - handleToggleBaseLayers(event:MouseEvent) { - this.baseLayersCollapsed = !this.baseLayersCollapsed; - event.preventDefault(); - } - - handleToggleOverlayLayers(event: MouseEvent) { - this.overlayLayersCollapsed = !this.overlayLayersCollapsed; - event.preventDefault(); - } - - handlePredefinedQuery(event: MouseEvent, query: any) { - event.preventDefault(); - var queryState = tassign(mapReducers.initialQueryState, query); - this.store.dispatch(new mapActions.DoQuery(queryState)); - } - - handleTrijntjeClick(event: MouseEvent, query: any) { - event.preventDefault(); - var queryState = tassign(mapReducers.initialQueryState, query); - var mapState = JSON.parse(this.lastMapState); - this.router.navigate(["app","trijntje" , mapState.xCenter.toFixed(5), mapState.yCenter.toFixed(5), mapState.zoom, mapState.rotation.toFixed(2), mapState.baseLayerCode, this.serializeService.serialize(queryState)], { replaceUrl: false }); - } - - replaceUrl(mapState: IMapState, queryState: IQueryState, replace: boolean = true) { - //console.log(`Replace url :${mapState.baseLayerCode}`) - this.router.navigate([".", mapState.xCenter.toFixed(5), mapState.yCenter.toFixed(5), mapState.zoom, mapState.rotation.toFixed(2), mapState.baseLayerCode, this.serializeService.serialize(queryState)], { replaceUrl: replace,relativeTo:this.route.parent.parent }); - } - - handleOnMoveEnd(event) { - var map = event.map; - var view = map.getView(); - var rotation = view.getRotation(); - var zoom = view.getZoom(); - var center = transform(view.getCenter(), view.getProjection(), "EPSG:4326"); - var extent = view.calculateExtent(this.map.instance.getSize()); - let mapState: IMapState = { xCenter: center[0], yCenter: center[1], zoom: zoom, rotation: rotation, baseLayerCode: null }; - let state = { mapState: mapState, extent: extent }; - let source = from([state]); - source.pipe(withLatestFrom(this.selectedBaseLayer), withLatestFrom(this.queryState)).subscribe(([[state, baselayer], queryState]) => { - if (mapState && baselayer && queryState) { - let newMapState = tassign(state.mapState, { baseLayerCode: baselayer.item.code }); - this.replaceUrl(newMapState, tassign(queryState, { bbox: queryState.bboxFilter ? state.extent : queryState.bbox })); - this.store.dispatch(new mapActions.SetViewExtent(state.extent)); - } - }); - } - - handleOnMouseDown(event: MouseEvent) { - this.store.dispatch(new mapActions.CollapseSearch()); - } - - - - handleOnDownload(event) { - - } - - handleClearSearch(event) { - this.store.dispatch(new commonActions.Escape(true, false)); - } - - handleOnDelete(itemLayer: IItemLayer) { - this.store.dispatch(new mapActions.RemoveLayer(itemLayer)); - } - - handleOnToggleVisibility(itemLayer: IItemLayer) { - this.store.dispatch(new mapActions.SetVisibility(itemLayer,!itemLayer.visible)); - } - - handleOnSetOpacity(event:{ layer: IItemLayer,opacity:number }) { - this.store.dispatch(new mapActions.SetOpacity(event.layer, event.opacity)); - } - - handleZoomToExtent(itemLayer: IItemLayer) { - var extent = createEmpty(); - extend(extent, itemLayer.layer.getExtent()); - if (extent) { - this.store.dispatch(new mapActions.SetExtent(extent)); - } - } - - handleSelectBaseLayer(itemLayer: IItemLayer) { - this.store.dispatch(new mapActions.SelectBaseLayer(itemLayer)); - } - - handleSelectOverlayLayer(itemLayer: IItemLayer) { - this.store.dispatch(new mapActions.SelectOverlayLayer(itemLayer)); - } - - ngOnDestroy() { - this.paramSub.unsubscribe(); - if (this.itemTypeSub) this.itemTypeSub.unsubscribe(); - if (this.mapStateSub) this.mapStateSub.unsubscribe(); - if (this.queryStateSub) this.queryStateSub.unsubscribe(); } -} diff --git a/src/app/app.component.scss b/src/app/app.component.scss index 4394fdc..30b5b91 100644 --- a/src/app/app.component.scss +++ b/src/app/app.component.scss @@ -17,5 +17,11 @@ $fa-font-path: "~font-awesome/fonts"; border-color: $input-border-color; } +:host ::ng-deep body { + background: #f1f1f1; + line-height: 18px; + user-select:none; +} +