Compare commits
	
		
			140 Commits
		
	
	
		
			3db760dd96
			...
			develop
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | 9b86927e2c | ||
|  | e224b80995 | ||
|  | 88f3d9ef1a | ||
| 6737029a61 | |||
|  | d4786564bd | ||
| 6fd69d7999 | |||
|  | 4ec75b3d5a | ||
| 04e3f1e71f | |||
|  | df77631299 | ||
| a8d0f05c81 | |||
|  | c79637be77 | ||
|  | b5e11da9a8 | ||
|  | 9d45c25a95 | ||
|  | 2ffce50c47 | ||
|  | f50ff878e0 | ||
| 09c74448a8 | |||
| 205b73b30e | |||
|  | 313cc59fe7 | ||
| c3fb42c65f | |||
|  | 6b73fb0d55 | ||
| ea641caf38 | |||
| ac15b2018d | |||
|  | fe73f615ad | ||
|  | 3e1b3ee78e | ||
|  | 58391b7828 | ||
|  | b2b2a1e8be | ||
|  | 0d96a1be4f | ||
| d599430cb0 | |||
|  | e17911b339 | ||
|  | 9d6cbffb3d | ||
|  | a11eb81e73 | ||
|  | 4fc3ad933c | ||
|  | e6d90c9e61 | ||
| 250b3841fe | |||
| 51291cd86f | |||
|  | e9e3b719a4 | ||
|  | 1c0ad57b0a | ||
|  | 8684ba25c8 | ||
| 78ca3044cf | |||
| 2e55b5a70e | |||
|  | af0a3dca2d | ||
| f039898c26 | |||
|  | ab19b1c2ce | ||
| a2641f8ea5 | |||
|  | d6841c8f83 | ||
| 187b24ab97 | |||
| b80ddf7854 | |||
|  | 79bc3d9082 | ||
| 1c92ad4c28 | |||
|  | 61e6de0052 | ||
| fb25b92349 | |||
|  | e78f2893ae | ||
| 51170b45e9 | |||
|  | 7365bea145 | ||
| dc096065b4 | |||
|  | b9850311ea | ||
| ee9c050db3 | |||
|  | 95200d9920 | ||
|  | ee1ce21cca | ||
|  | 467f7447bf | ||
|  | 1df4496058 | ||
|  | 2137f3f07e | ||
| a46e8040b2 | |||
|  | 2ca9730735 | ||
| 3d2ca8fb9f | |||
| 6810da8b79 | |||
|  | 4866a6f22d | ||
| 84a1004977 | |||
| 39c619a837 | |||
|  | 758613aa12 | ||
| 6914a61bc4 | |||
| 9f43287433 | |||
|  | 10df983ae3 | ||
| 78249811ab | |||
| df14427d60 | |||
|  | c7c131d437 | ||
| b2fe8f3bd7 | |||
|  | 3027c69fa8 | ||
| 5995d205a4 | |||
|  | fd479c92d8 | ||
| e9880d6eb2 | |||
|  | a4438d8a90 | ||
| 89061774de | |||
|  | 362e6c8534 | ||
| 64a0e58238 | |||
|  | a3d4dfbd59 | ||
| 4c106ebff3 | |||
|  | 5c8fd64521 | ||
| 72ba8eca81 | |||
|  | f89f741265 | ||
| 50af55acb2 | |||
|  | cc879b85e5 | ||
| b4a0a4584d | |||
| 8ab1611f39 | |||
|  | 475c522039 | ||
| 068396ac9a | |||
|  | 4a30707ec6 | ||
| 852b1db895 | |||
|  | fcbd68eca0 | ||
| 3a42f9114e | |||
| 3f664b472c | |||
|  | 57811f3f2e | ||
| 5e1bc6d705 | |||
| d4a230f96d | |||
|  | ed1e1478b2 | ||
| afe013a59a | |||
| db3734f8a3 | |||
|  | 86f75c7f78 | ||
| a7abb4072b | |||
|  | 61d6446d75 | ||
| 392008ae4b | |||
| 093c26c7f3 | |||
|  | a8e1ba6c02 | ||
| e64fbfd014 | |||
| 8cd7b85de2 | |||
|  | ddc7f97e27 | ||
| 24e3765c28 | |||
|  | 86f3ddb34b | ||
| d6c55ef82b | |||
| d977ddfb7b | |||
|  | 0e8bd5343d | ||
| ceeaa89ba3 | |||
|  | c3dbf85eb6 | ||
| ad5fe95b55 | |||
|  | 6b95fb7f77 | ||
| da7e193219 | |||
| 31f9b48bd7 | |||
|  | 1d6b30edff | ||
| 349a76395b | |||
|  | 32b3b98f76 | ||
| 010ed6e010 | |||
| a8675f5c49 | |||
|  | f76ef44dee | ||
| 2387a0e39e | |||
| 98980fc857 | |||
|  | 6f7d8fe248 | ||
| 03a1ccd597 | |||
|  | 9c866e500f | ||
| 3b692359c6 | |||
| 3d4042e8c6 | 
							
								
								
									
										54
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										54
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							| @@ -1,22 +1,22 @@ | ||||
| { | ||||
|   "name": "farmmaps-lib-app", | ||||
|   "version": "4.10.0", | ||||
|   "version": "4.19.0", | ||||
|   "lockfileVersion": 3, | ||||
|   "requires": true, | ||||
|   "packages": { | ||||
|     "": { | ||||
|       "name": "farmmaps-lib-app", | ||||
|       "version": "4.10.0", | ||||
|       "version": "4.19.0", | ||||
|       "dependencies": { | ||||
|         "@angular-eslint/eslint-plugin": "^18.2.0", | ||||
|         "@angular/animations": "^18.2.3", | ||||
|         "@angular/common": "^18.2.3", | ||||
|         "@angular/compiler": "^18.2.3", | ||||
|         "@angular/core": "^18.2.3", | ||||
|         "@angular/forms": "^18.2.3", | ||||
|         "@angular/platform-browser": "^18.2.3", | ||||
|         "@angular/platform-browser-dynamic": "^18.2.3", | ||||
|         "@angular/router": "^18.2.3", | ||||
|         "@angular/animations": "18.2.3", | ||||
|         "@angular/common": "18.2.3", | ||||
|         "@angular/compiler": "18.2.3", | ||||
|         "@angular/core": "18.2.3", | ||||
|         "@angular/forms": "18.2.3", | ||||
|         "@angular/platform-browser": "18.2.3", | ||||
|         "@angular/platform-browser-dynamic": "18.2.3", | ||||
|         "@angular/router": "18.2.3", | ||||
|         "@farmmaps/common": "file:dist/common", | ||||
|         "@farmmaps/common-map": "file:dist/common-map", | ||||
|         "@farmmaps/common-map3d": "file:dist/common-map3d", | ||||
| @@ -55,11 +55,11 @@ | ||||
|       }, | ||||
|       "devDependencies": { | ||||
|         "@angular-builders/custom-webpack": "^18.0.0", | ||||
|         "@angular-devkit/build-angular": "^18.2.3", | ||||
|         "@angular/cli": "^18.2.3", | ||||
|         "@angular/compiler-cli": "^18.2.3", | ||||
|         "@angular/language-service": "^18.2.3", | ||||
|         "@angular/localize": "^18.2.3", | ||||
|         "@angular-devkit/build-angular": "18.2.3", | ||||
|         "@angular/cli": "18.2.3", | ||||
|         "@angular/compiler-cli": "18.2.3", | ||||
|         "@angular/language-service": "18.2.3", | ||||
|         "@angular/localize": "18.2.3", | ||||
|         "@types/arcgis-rest-api": "^10.4.5", | ||||
|         "@types/jasmine": "~2.8.8", | ||||
|         "@types/jasminewd2": "^2.0.9", | ||||
| @@ -90,14 +90,14 @@ | ||||
|     }, | ||||
|     "dist/common": { | ||||
|       "name": "@farmmaps/common", | ||||
|       "version": "4.10.0-prerelease.2511", | ||||
|       "version": "4.19.0-prerelease.2582", | ||||
|       "dependencies": { | ||||
|         "tslib": "^2.3.0" | ||||
|       }, | ||||
|       "peerDependencies": { | ||||
|         "@angular/common": "^18.2.3", | ||||
|         "@angular/core": "^18.2.3", | ||||
|         "@angular/forms": "^18.2.3", | ||||
|         "@angular/common": "18.2.3", | ||||
|         "@angular/core": "18.2.3", | ||||
|         "@angular/forms": "18.2.3", | ||||
|         "@microsoft/signalr": "^3.1.16", | ||||
|         "@ng-bootstrap/ng-bootstrap": "^17.0.1", | ||||
|         "@ngrx/effects": "^18.0.2", | ||||
| @@ -115,12 +115,12 @@ | ||||
|     }, | ||||
|     "dist/common-map": { | ||||
|       "name": "@farmmaps/common-map", | ||||
|       "version": "4.10.0-prerelease.2511", | ||||
|       "version": "4.19.0-prerelease.2582", | ||||
|       "dependencies": { | ||||
|         "tslib": "^2.0.0" | ||||
|       }, | ||||
|       "peerDependencies": { | ||||
|         "@angular/core": "^18.2.3", | ||||
|         "@angular/core": "18.2.3", | ||||
|         "@ngrx/effects": "^18.0.2", | ||||
|         "@ngrx/router-store": "^18.0.2", | ||||
|         "@ngrx/store": "^18.0.2", | ||||
| @@ -130,27 +130,27 @@ | ||||
|     }, | ||||
|     "dist/common-map3d": { | ||||
|       "name": "@farmmaps/common-map3d", | ||||
|       "version": "4.10.0-prerelease.2511", | ||||
|       "version": "4.19.0-prerelease.2582", | ||||
|       "dependencies": { | ||||
|         "tslib": "^2.0.0" | ||||
|       }, | ||||
|       "peerDependencies": { | ||||
|         "@angular/common": "^18.2.3", | ||||
|         "@angular/core": "^18.2.3", | ||||
|         "@angular/common": "18.2.3", | ||||
|         "@angular/core": "18.2.3", | ||||
|         "cesium": "^1.97.0", | ||||
|         "ol-cesium": ">=2.13.0" | ||||
|       } | ||||
|     }, | ||||
|     "dist/ng-openlayers": { | ||||
|       "name": "@farmmaps/ng-openlayers", | ||||
|       "version": "4.10.0-prerelease.2511", | ||||
|       "version": "4.19.0-prerelease.2582", | ||||
|       "license": "MPL-2.0", | ||||
|       "dependencies": { | ||||
|         "tslib": "^2.3.0" | ||||
|       }, | ||||
|       "peerDependencies": { | ||||
|         "@angular/common": "^18.2.3", | ||||
|         "@angular/core": "^18.2.3", | ||||
|         "@angular/common": "18.2.3", | ||||
|         "@angular/core": "18.2.3", | ||||
|         "ol": "^8.2.0" | ||||
|       } | ||||
|     }, | ||||
|   | ||||
							
								
								
									
										38
									
								
								package.json
									
									
									
									
									
								
							
							
						
						
									
										38
									
								
								package.json
									
									
									
									
									
								
							| @@ -1,7 +1,7 @@ | ||||
| { | ||||
|   "name": "farmmaps-lib-app", | ||||
|   "version": "4.10.0", | ||||
|   "scripts": { | ||||
|   "version": "4.19.0", | ||||
|   "scripts":   { | ||||
|     "ng": "ng", | ||||
|     "start": "ng serve", | ||||
|     "build": "ng build", | ||||
| @@ -10,16 +10,16 @@ | ||||
|     "e2e": "ng e2e" | ||||
|   }, | ||||
|   "private": true, | ||||
|   "dependencies": { | ||||
|   "dependencies":   { | ||||
|     "@angular-eslint/eslint-plugin": "^18.2.0", | ||||
|     "@angular/animations": "^18.2.3", | ||||
|     "@angular/common": "^18.2.3", | ||||
|     "@angular/compiler": "^18.2.3", | ||||
|     "@angular/core": "^18.2.3", | ||||
|     "@angular/forms": "^18.2.3", | ||||
|     "@angular/platform-browser": "^18.2.3", | ||||
|     "@angular/platform-browser-dynamic": "^18.2.3", | ||||
|     "@angular/router": "^18.2.3", | ||||
|     "@angular/animations": "18.2.3", | ||||
|     "@angular/common": "18.2.3", | ||||
|     "@angular/compiler": "18.2.3", | ||||
|     "@angular/core": "18.2.3", | ||||
|     "@angular/forms": "18.2.3", | ||||
|     "@angular/platform-browser": "18.2.3", | ||||
|     "@angular/platform-browser-dynamic": "18.2.3", | ||||
|     "@angular/router": "18.2.3", | ||||
|     "@farmmaps/common": "file:dist/common", | ||||
|     "@farmmaps/common-map": "file:dist/common-map", | ||||
|     "@farmmaps/common-map3d": "file:dist/common-map3d", | ||||
| @@ -56,17 +56,17 @@ | ||||
|     "util": "^0.12.4", | ||||
|     "zone.js": "~0.14.10" | ||||
|   }, | ||||
|   "optionalDependencies": { | ||||
|   "optionalDependencies":   { | ||||
|     "@lmdb/lmdb-linux-x64": "^3.1.0", | ||||
|     "@rollup/rollup-linux-x64-gnu": "^4.21.2" | ||||
|   }, | ||||
|   "devDependencies": { | ||||
|   "devDependencies":   { | ||||
|     "@angular-builders/custom-webpack": "^18.0.0", | ||||
|     "@angular-devkit/build-angular": "^18.2.3", | ||||
|     "@angular/cli": "^18.2.3", | ||||
|     "@angular/compiler-cli": "^18.2.3", | ||||
|     "@angular/language-service": "^18.2.3", | ||||
|     "@angular/localize": "^18.2.3", | ||||
|     "@angular-devkit/build-angular": "18.2.3", | ||||
|     "@angular/cli": "18.2.3", | ||||
|     "@angular/compiler-cli": "18.2.3", | ||||
|     "@angular/language-service": "18.2.3", | ||||
|     "@angular/localize": "18.2.3", | ||||
|     "@types/arcgis-rest-api": "^10.4.5", | ||||
|     "@types/jasmine": "~2.8.8", | ||||
|     "@types/jasminewd2": "^2.0.9", | ||||
| @@ -90,4 +90,4 @@ | ||||
|     "ts-node": "^8.8.1", | ||||
|     "typescript": "~5.4.4" | ||||
|   } | ||||
| } | ||||
| } | ||||
| @@ -8,7 +8,7 @@ | ||||
|     "tslib": "^2.0.0" | ||||
|   }, | ||||
|   "peerDependencies": { | ||||
|     "@angular/core": "^18.2.3", | ||||
|     "@angular/core": "18.2.3", | ||||
|     "ngrx-store-localstorage": "^18.0.0", | ||||
|     "@ngrx/effects": "^18.0.2", | ||||
|     "@ngrx/router-store": "^18.0.2", | ||||
|   | ||||
| @@ -59,6 +59,8 @@ export const TOGGLESHOWDATALAYERSLIDE = '[Map] ToggleShowDataLayerSlide' | ||||
| export const SETVIEWSTATE = '[Map] SetViewState' | ||||
| export const CLEARFEATURES = '[Map] ClearFeatures'; | ||||
| export const SETPANELEXTRAWIDE = '[Map] SetPanelExtraWide'; | ||||
| export const BACKUPFEATURES = '[Map] BackupFeatures'; | ||||
| export const RESTOREFEATURES = '[Map] RestoreFeatures'; | ||||
|  | ||||
| export class Clear implements Action { | ||||
|   readonly type = CLEAR; | ||||
| @@ -347,6 +349,16 @@ export class SetPanelExtraWide implements Action { | ||||
|   constructor(public panelExtraWide:boolean) {} | ||||
| } | ||||
|  | ||||
| export class BackupFeatures implements Action { | ||||
|   readonly type = BACKUPFEATURES; | ||||
|   constructor() {} | ||||
| } | ||||
|  | ||||
| export class RestoreFeatures implements Action { | ||||
|   readonly type = RESTOREFEATURES; | ||||
|   constructor() {} | ||||
| } | ||||
|  | ||||
| export type Actions = SetMapState | ||||
|   | Init | ||||
|   | Clear | ||||
| @@ -395,5 +407,7 @@ export type Actions = SetMapState | ||||
|   | ToggleShowDataLayerSlide | ||||
|   | SetViewState | ||||
|   | ClearFeatures | ||||
|   | SetPanelExtraWide; | ||||
|   | SetPanelExtraWide | ||||
|   | BackupFeatures | ||||
|   | RestoreFeatures; | ||||
|  | ||||
|   | ||||
| @@ -36,6 +36,7 @@ import { RotationResetComponent } from './components/aol/rotation-reset/rotation | ||||
| import { ZoomToExtentComponent } from './components/aol/zoom-to-extent/zoom-to-extent.component'; | ||||
| import { FeatureListContainerComponent } from './components/feature-list-container/feature-list-container.component'; | ||||
| import { FeatureListCropfieldComponent } from './components/feature-list-cropfield/feature-list-cropfield.component'; | ||||
| import { FeatureListObservationComponent } from './components/feature-list-observation/feature-list-observation.component'; | ||||
| import { FeatureListCroppingschemeComponent } from './components/feature-list-croppingscheme/feature-list-croppingscheme.component'; | ||||
| import { FeatureListFeatureContainerComponent } from './components/feature-list-feature-container/feature-list-feature-container.component'; | ||||
| import { FeatureListFeatureCropfieldComponent } from './components/feature-list-feature-cropfield/feature-list-feature-cropfield.component'; | ||||
| @@ -105,7 +106,7 @@ const metaReducers: Array<MetaReducer<any, any>> = [LocalStorageSync]; | ||||
|  | ||||
| export { | ||||
|   AbstractFeatureListComponent, | ||||
|   AbstractFeatureListFeatureComponent, AbstractItemListComponent, AbstractItemListItemComponent, AbstractItemWidgetComponent, AbstractSelectedItemComponent, DeviceOrientationService, FeatureIconService, FeatureListComponent, FeatureListContainerComponent, FeatureListCropfieldComponent, FeatureListCroppingschemeComponent, FeatureListFeatureComponent, FeatureListFeatureContainerComponent, FeatureListFeatureCropfieldComponent, FeatureListFeatureCroppingschemeComponent, FileDropTargetComponent, ForChild, | ||||
|   AbstractFeatureListFeatureComponent, AbstractItemListComponent, AbstractItemListItemComponent, AbstractItemWidgetComponent, AbstractSelectedItemComponent, DeviceOrientationService, FeatureIconService, FeatureListComponent, FeatureListContainerComponent, FeatureListCropfieldComponent, FeatureListObservationComponent, FeatureListCroppingschemeComponent, FeatureListFeatureComponent, FeatureListFeatureContainerComponent, FeatureListFeatureCropfieldComponent, FeatureListFeatureCroppingschemeComponent, FileDropTargetComponent, ForChild, | ||||
|   ForItemType, ForPackage, ForSourceTask, GeolocationService, GeometryThumbnailComponent, GpsLocation, IClickedFeature, ifZoomToShowDirective, IItemLayer, IMapState, IPeriodState, ISelectedFeatures, ItemLayer, ItemLayersComponent, ItemListComponent, ItemListItemComponent, | ||||
|   ItemListItemContainerComponent, ITemporalItemLayer, ItemVectorSourceComponent, ItemWidgetListComponent, LayerListComponent, LayerSwitcher, LayerVectorImageComponent, LegendComponent, mapActions, MapComponent, mapEffects, | ||||
|   mapReducers, MapSearchComponent, MetaDataModalComponent, PanToLocation, RotationResetComponent, SelectedItemComponent, SelectedItemContainerComponent, SelectedItemCropfieldComponent, | ||||
| @@ -142,6 +143,7 @@ export { | ||||
|         FeatureListContainerComponent, | ||||
|         FeatureListCroppingschemeComponent, | ||||
|         FeatureListCropfieldComponent, | ||||
|         FeatureListObservationComponent, | ||||
|         FeatureListFeatureContainerComponent, | ||||
|         FeatureListFeatureComponent, | ||||
|         FeatureListFeatureCroppingschemeComponent, | ||||
| @@ -201,6 +203,7 @@ export { | ||||
|         FeatureListContainerComponent, | ||||
|         FeatureListCroppingschemeComponent, | ||||
|         FeatureListCropfieldComponent, | ||||
|         FeatureListObservationComponent, | ||||
|         FeatureListFeatureContainerComponent, | ||||
|         ZoomToExtentComponent, | ||||
|         ifZoomToShowDirective, | ||||
| @@ -214,9 +217,10 @@ export { | ||||
|         TemporalService, | ||||
|         { provide: AbstractFeatureListComponent, useClass: FeatureListCroppingschemeComponent, multi: true }, | ||||
|         { provide: AbstractFeatureListComponent, useClass: FeatureListCropfieldComponent, multi: true }, | ||||
|         { provide: AbstractFeatureListComponent, useClass: FeatureListObservationComponent, multi: true },         | ||||
|         { provide: AbstractFeatureListFeatureComponent, useClass: FeatureListFeatureComponent, multi: true }, | ||||
|         { provide: AbstractFeatureListFeatureComponent, useClass: FeatureListFeatureCroppingschemeComponent, multi: true }, | ||||
|         { provide: AbstractFeatureListFeatureComponent, useClass: FeatureListFeatureCropfieldComponent, multi: true }, | ||||
|         { provide: AbstractFeatureListFeatureComponent, useClass: FeatureListFeatureCropfieldComponent, multi: true },        | ||||
|         { provide: AbstractSelectedItemComponent, useClass: SelectedItemComponent, multi: true }, | ||||
|         { provide: AbstractSelectedItemComponent, useClass: SelectedItemCropfieldComponent, multi: true }, | ||||
|         { provide: AbstractSelectedItemComponent, useClass: SelectedItemGeotiffComponent, multi: true }, | ||||
|   | ||||
| @@ -0,0 +1,14 @@ | ||||
| <div class="card border-0"> | ||||
|   <div class="card-body" *ngIf="(schemeItem|async);let schemeItem"> | ||||
|     <fm-back-button></fm-back-button> | ||||
|     <h4 i18n>Farm</h4> | ||||
|     <h3>{{schemeItem.name}}</h3> | ||||
|     <div *ngIf="features;let features"> | ||||
|         <div class="cropfields"> | ||||
|           <div class="row m-0 ps-3 pe-3" *ngFor="let feature of features" [ngClass]="{'selected':isFeatureSelected(feature)}" (click)="handleFeatureClick(feature)" (mouseenter)="handleFeatureMouseEnter(feature)" (mouseleave)="handleFeatureMouseLeave(feature)"> | ||||
|           <fm-map-feature-list-feature-container [feature]="feature"></fm-map-feature-list-feature-container> | ||||
|         </div> | ||||
|       </div> | ||||
|     </div> | ||||
|   </div> | ||||
| </div> | ||||
| @@ -0,0 +1,20 @@ | ||||
| fm-map-feature-list-feature-container { | ||||
|   width:100%; | ||||
|   pointer-events:none; | ||||
| } | ||||
|  | ||||
| .row { | ||||
|   border-bottom: 1px solid var(--bs-gray-500); | ||||
|   user-select: none; | ||||
|   padding-left:1.5rem; | ||||
| } | ||||
|  | ||||
| .row.selected { | ||||
|   background-color: var(--bs-gray-100); | ||||
| } | ||||
|  | ||||
| .cropfields { | ||||
|   border-top: 1px solid var(--bs-gray-500); | ||||
|   margin-left: -1.25rem; | ||||
|   margin-right: -1.25rem; | ||||
| } | ||||
| @@ -0,0 +1,30 @@ | ||||
| import { Component, Injectable,AfterViewInit, OnInit,SimpleChanges, ChangeDetectorRef} from '@angular/core'; | ||||
| import { Location } from '@angular/common'; | ||||
| import { AbstractFeatureListComponent } from '../feature-list/feature-list.component'; | ||||
| import {ForItemType } from '../for-item/for-itemtype.decorator'; | ||||
| import {ForChild } from '../for-item/for-child.decorator'; | ||||
| import { Store } from '@ngrx/store'; | ||||
| import * as mapReducers from '../../reducers/map.reducer'; | ||||
| import { commonReducers, ItemTypeService, IItem,ItemService } from '@farmmaps/common'; | ||||
| import { Observable } from 'rxjs'; | ||||
|  | ||||
| @ForChild() | ||||
| @ForItemType("vnd.farmmaps.itemtype.observation") | ||||
| @Injectable() | ||||
| @Component({ | ||||
|   selector: 'fm-map-feature-list-observation', | ||||
|     templateUrl: './feature-list-observation.component.html', | ||||
|     styleUrls: ['./feature-list-observation.component.scss'] | ||||
| }) | ||||
| export class FeatureListObservationComponent extends AbstractFeatureListComponent implements OnInit { | ||||
|  | ||||
|   constructor(store: Store<mapReducers.State | commonReducers.State>, itemTypeService: ItemTypeService, location: Location, private itemService: ItemService) { | ||||
|     super(store, itemTypeService,location); | ||||
|   } | ||||
|  | ||||
|   public schemeItem: Observable<IItem> | ||||
|  | ||||
|   ngOnInit() { | ||||
|     this.schemeItem = this.itemService.getItem(this.queryState.parentCode); | ||||
|   }  | ||||
| } | ||||
| @@ -10,7 +10,7 @@ | ||||
|         <li class="nav-item py-0"> | ||||
|           <span><i class="fal fa-layer-group" aria-hidden="true"></i> <span i18n>Base maps</span></span> | ||||
|           <div  class="mb-4"> | ||||
|             <fm-map-layer-list [baseLayers]="true" [itemLayers]="baseLayers|async" [selectedLayer]="selectedBaseLayer|async" (onSelectLayer)="handleSelectBaseLayer($event)"></fm-map-layer-list> | ||||
|             <fm-map-layer-list [baseLayers]="true" [itemLayers]="baseMaps|async" [selectedLayer]="selectedBaseLayer|async" (onSelectLayer)="handleSelectBaseLayer($event)"></fm-map-layer-list> | ||||
|           </div> | ||||
|         </li> | ||||
|         <li class="nav-item py-0"> | ||||
| @@ -20,12 +20,17 @@ | ||||
|           </div> | ||||
|         </li> | ||||
|         <li class="nav-item py-0" *ngIf="selectedItemLayer$ | async as selectedItemLayer"> | ||||
|           <span><i class="fal fa-layer-group" aria-hidden="true"></i> <span i18n>Data</span><span class="slideButton"><a href="#" title="Compare" class="btn btn-light btn-sm" (click)="handleToggleShowDatalayerSlide($event)"><i class="fal fa-sliders-h-square"></i></a></span></span> | ||||
|           <span><i class="fal fa-layer-group" aria-hidden="true"></i> <span i18n>Overlay slider</span><span class="slideButton"><a href="#" title="Compare" class="btn btn-light btn-sm" (click)="handleToggleShowDatalayerSlide($event)"><i class="fal fa-sliders-h-square"></i></a></span></span> | ||||
|           <div class="mb-4"> | ||||
|             <fm-map-layer-list [dataLayers]="true" [itemLayers]="[selectedItemLayer]" [selectedLayer]="selectedItemLayer" (onToggleVisibility)="handleOnToggleVisibility($event)" (onSetOpacity)="handleOnSetOpacity($event)" (onZoomToExtent)="handleZoomToExtent($event)" (onSelectLayer)="handleSelectOverlayLayer($event)"></fm-map-layer-list> | ||||
|           </div> | ||||
|         </li> | ||||
|  | ||||
|         <li class="nav-item py-0"> | ||||
|           <span><i class="fal fa-layer-group" aria-hidden="true"></i> <span i18n>Aerial photos</span></span> | ||||
|           <div  class="mb-4"> | ||||
|             <fm-map-layer-list [baseLayers]="true" [itemLayers]="aerialMaps|async" [selectedLayer]="selectedBaseLayer|async" (onSelectLayer)="handleSelectBaseLayer($event)"></fm-map-layer-list> | ||||
|           </div> | ||||
|         </li> | ||||
|       </ul> | ||||
|   </div> | ||||
|   </div> | ||||
|   | ||||
| @@ -4,7 +4,7 @@ import { Store } from '@ngrx/store'; | ||||
| import * as mapReducers from '../../reducers/map.reducer'; | ||||
| import * as mapActions from '../../actions/map.actions'; | ||||
| import {createEmpty,extend } from 'ol/extent'; | ||||
| import { Observable } from 'rxjs'; | ||||
| import { filter, map, Observable } from 'rxjs'; | ||||
|  | ||||
| @Component({ | ||||
|   selector: 'fm-map-layer-switcher', | ||||
| @@ -17,7 +17,8 @@ export class LayerSwitcher  implements OnInit,OnChanges{ | ||||
|   public overlayLayers: Observable<Array<IItemLayer>>; | ||||
|   public selectedOverlayLayer: Observable<IItemLayer>; | ||||
|   public selectedItemLayer$: Observable<IItemLayer>; | ||||
|   public baseLayers: Observable<Array<IItemLayer>>; | ||||
|   public baseMaps: Observable<Array<IItemLayer>>; | ||||
|   public aerialMaps: Observable<Array<IItemLayer>>; | ||||
|   public selectedBaseLayer: Observable<IItemLayer>; | ||||
|  | ||||
|   constructor( private store: Store<mapReducers.State>) { | ||||
| @@ -26,7 +27,8 @@ export class LayerSwitcher  implements OnInit,OnChanges{ | ||||
|   ngOnInit() {  | ||||
|     this.overlayLayers = this.store.select(mapReducers.selectGetOverlayLayers); | ||||
|     this.selectedOverlayLayer = this.store.select(mapReducers.selectGetSelectedOverlayLayer); | ||||
|     this.baseLayers = this.store.select(mapReducers.selectGetBaseLayers); | ||||
|     this.baseMaps = this.store.select(mapReducers.selectGetBaseMaps); | ||||
|     this.aerialMaps = this.store.select(mapReducers.selectGetArealMaps); | ||||
|     this.selectedBaseLayer = this.store.select(mapReducers.selectGetSelectedBaseLayer); | ||||
|     this.selectedItemLayer$ = this.store.select(mapReducers.selectGetSelectedItemLayer) | ||||
|     this.showLayerSwitcher = this.store.select(mapReducers.selectGetShowLayerSwitcher); | ||||
| @@ -83,3 +85,4 @@ export class LayerSwitcher  implements OnInit,OnChanges{ | ||||
|     event.preventDefault(); | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -52,11 +52,20 @@ aol-map { position:absolute;width:100%;height:calc( 100vh );} | ||||
|   pointer-events: none; | ||||
| } | ||||
|  | ||||
| @media screen and (max-width: 768px) { | ||||
|   .control-container { | ||||
|     margin-left: 1em; | ||||
|     margin-right: 1em; | ||||
|     pointer-events: all; | ||||
|   } | ||||
| } | ||||
|  | ||||
| .control-container { | ||||
|   float:right; | ||||
|   margin-right: 1em; | ||||
|   pointer-events: all; | ||||
| @media screen and (min-width: 768px) { | ||||
|   .control-container {     | ||||
|     float: right; | ||||
|     margin-right: 1em; | ||||
|     pointer-events: all; | ||||
|   } | ||||
| } | ||||
|  | ||||
| .fullscreen .viewport-container { | ||||
|   | ||||
| @@ -1,39 +1,39 @@ | ||||
| import { Component, OnInit, OnDestroy, HostListener, ViewChild, AfterViewInit,NgZone,ElementRef } from '@angular/core'; | ||||
| import { Component, OnInit, OnDestroy, HostListener, ViewChild, AfterViewInit, NgZone, ElementRef } from '@angular/core'; | ||||
| import { Location } from '@angular/common'; | ||||
| import { Observable, Subject, Subscription, from,of ,EMPTY } from 'rxjs'; | ||||
| import { withLatestFrom, switchMap,skip  } from 'rxjs/operators'; | ||||
| import { Observable, Subject, Subscription, from, of, EMPTY } from 'rxjs'; | ||||
| import { withLatestFrom, switchMap, skip } from 'rxjs/operators'; | ||||
| import { Router, ActivatedRoute, ParamMap } from '@angular/router'; | ||||
| import { Store } from '@ngrx/store'; | ||||
| import { DeviceService } from '@farmmaps/common'; | ||||
| import {getRenderPixel} from 'ol/render'; | ||||
| import { getRenderPixel } from 'ol/render'; | ||||
|  | ||||
| // Map | ||||
| import * as mapReducers from '../../reducers/map.reducer'; | ||||
| import * as mapActions from '../../actions/map.actions'; | ||||
| import { IMapState} from '../../models/map.state'; | ||||
| import { IClickedFeature} from '../../models/clicked.feature'; | ||||
| import { IMapState } from '../../models/map.state'; | ||||
| import { IClickedFeature } from '../../models/clicked.feature'; | ||||
| import { IQuery } from '../../reducers/map.reducer' | ||||
| import { ISelectedFeatures } from '../../models/selected.features'; | ||||
| import { IItemLayer } from '../../models/item.layer'; | ||||
| import { IListItem, IQueryState } from '@farmmaps/common'; | ||||
| import { IPeriodState } from '../../models/period.state'; | ||||
| import {IStyles} from '../../models/style.cache'; | ||||
| import { IStyles } from '../../models/style.cache'; | ||||
| import { IDroppedFile } from '../aol/file-drop-target/file-drop-target.component'; | ||||
| import { StateSerializerService } from '@farmmaps/common'; | ||||
| import { GeolocationService} from '../../services/geolocation.service'; | ||||
| import { GeolocationService } from '../../services/geolocation.service'; | ||||
| import { GeolocatorService } from '@farmmaps/common'; | ||||
| import {DeviceOrientationService} from '../../services/device-orientation.service'; | ||||
| import { DeviceOrientationService } from '../../services/device-orientation.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 { commonReducers } from '@farmmaps/common'; | ||||
| import { commonActions } from '@farmmaps/common'; | ||||
|  | ||||
| import {Feature} from 'ol'; | ||||
| import {Geometry,Point,Circle} from 'ol/geom'; | ||||
| import {Extent,createEmpty,extend } from 'ol/extent'; | ||||
| import {transform} from 'ol/proj'; | ||||
| import { Feature } from 'ol'; | ||||
| import { Geometry, Point, Circle } from 'ol/geom'; | ||||
| import { Extent, createEmpty, extend } from 'ol/extent'; | ||||
| import { transform } from 'ol/proj'; | ||||
| import { tassign } from 'tassign'; | ||||
| import * as style from 'ol/style'; | ||||
|  | ||||
| @@ -44,7 +44,7 @@ import * as style from 'ol/style'; | ||||
|   styleUrls: ['./map.component.scss'] | ||||
| }) | ||||
|  | ||||
| export class MapComponent implements OnInit, OnDestroy,AfterViewInit { | ||||
| export class MapComponent implements OnInit, OnDestroy, AfterViewInit { | ||||
|   title = 'Map'; | ||||
|   public openedModalName$: Observable<string> = this.store.select(commonReducers.selectOpenedModalName); | ||||
|   public itemTypes$: Observable<{ [id: string]: IItemType }>; | ||||
| @@ -54,49 +54,51 @@ export class MapComponent implements OnInit, OnDestroy,AfterViewInit { | ||||
|   public selectedOverlayLayer$: Observable<IItemLayer> = this.store.select(mapReducers.selectGetSelectedOverlayLayer); | ||||
|   public selectedItemLayer$: Observable<IItemLayer> = this.store.select(mapReducers.selectGetSelectedItemLayer); | ||||
|   public baseLayers$: Observable<Array<IItemLayer>> = this.store.select(mapReducers.selectGetBaseLayers); | ||||
|   public selectedBaseLayer$: Observable<IItemLayer> =  this.store.select(mapReducers.selectGetSelectedBaseLayer); | ||||
|   public selectedBaseLayer$: Observable<IItemLayer> = this.store.select(mapReducers.selectGetSelectedBaseLayer); | ||||
|   public projection$: Observable<string> = this.store.select(mapReducers.selectGetProjection); | ||||
|   public selectedFeatures$: Subject<ISelectedFeatures> = new Subject<ISelectedFeatures>(); | ||||
|   public droppedFile$: Subject<IDroppedFile>  = new Subject<IDroppedFile>(); | ||||
|   public droppedFile$: Subject<IDroppedFile> = new Subject<IDroppedFile>(); | ||||
|   private paramSub: Subscription; | ||||
|   private itemTypeSub: Subscription; | ||||
|   private stateSub: Subscription; | ||||
|   private queryStateSub: Subscription; | ||||
|   private querySub: Subscription; | ||||
|   public parentCode$: Observable<string> =this.store.select(mapReducers.selectGetParentCode); | ||||
|   public parentCode$: Observable<string> = this.store.select(mapReducers.selectGetParentCode); | ||||
|   public panelVisible$: Observable<boolean> = this.store.select(mapReducers.selectGetPanelVisible); | ||||
|   public panelCollapsed$: Observable<boolean> = this.store.select(mapReducers.selectGetPanelCollapsed); | ||||
|   public panelExtraWide$: Observable<boolean> = this.store.select(mapReducers.selectGetPanelExtraWide); | ||||
|   public selectedFeature$: Observable<Feature<Geometry>> = this.store.select(mapReducers.selectGetSelectedFeature); | ||||
|   public clickedFeature: Subject<Feature<Geometry>> = new Subject<Feature<Geometry>>(); | ||||
|   public selectedItem$: Observable<IItem> = this.store.select(mapReducers.selectGetSelectedItem); | ||||
|   public parentItem$: Observable<IItem> =this.store.select(mapReducers.selectGetParentItem); | ||||
|   public parentItem$: Observable<IItem> = this.store.select(mapReducers.selectGetParentItem); | ||||
|   public queryState$: Observable<IQueryState> = this.store.select(mapReducers.selectGetQueryState); | ||||
|   public state$:Observable<{mapState:IMapState,queryState:IQueryState}> = this.store.select(mapReducers.selectGetState); | ||||
|   public state$: Observable<{ mapState: IMapState, queryState: IQueryState }> = 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); | ||||
|   public searchMinified$: Observable<boolean> = this.store.select(mapReducers.selectGetSearchMinified); | ||||
|   public showDataLayerSlide$: Observable<boolean> = this.store.select(mapReducers.selectGetShowdataLayerSlide); | ||||
|   public menuVisible$: Observable<boolean>; | ||||
|   public query$: Observable<IQuery> =  this.store.select(mapReducers.selectGetQuery); | ||||
|   public query$: Observable<IQuery> = this.store.select(mapReducers.selectGetQuery); | ||||
|   public position$: Observable<GeolocationPosition> = this.geolocationService.getCurrentPosition(); | ||||
|   public compassHeading$: Observable<number> = this.deviceorientationService.getCurrentCompassHeading(); | ||||
|   public baseLayersCollapsed = true; | ||||
|   public overlayLayersCollapsed = true; | ||||
|   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 initialized = false; | ||||
|   public noContent = false; | ||||
|   public overrideSelectedItemLayer = false; | ||||
|   public overrideOverlayLayers = false; | ||||
|   public hideShowLayerValues = false; | ||||
|   public const | ||||
|   public dataLayerSlideValue = 50; | ||||
|   public dataLayerSlideEnabled = false; | ||||
|   private visibleAreaBottom = 0; | ||||
|   private viewEnabled = true; | ||||
|    | ||||
|  | ||||
|   @ViewChild('map') map; | ||||
|   @ViewChild('contentDiv') contentDiv: ElementRef; | ||||
|  | ||||
| @@ -110,47 +112,48 @@ export class MapComponent implements OnInit, OnDestroy,AfterViewInit { | ||||
|     private geolocationService: GeolocationService, | ||||
|     private geolocaterService: GeolocatorService, | ||||
|     private zone: NgZone, | ||||
|     private deviceorientationService:DeviceOrientationService, | ||||
|     public devicesService:DeviceService) { | ||||
|       if(route && route.snapshot && route.snapshot.data && route.snapshot.data["fm-map-map"]) { | ||||
|         const params = route.snapshot.data["fm-map-map"]; | ||||
|         this.overrideSelectedItemLayer = params["overrideSelectedItemlayer"] ? params["overrideSelectedItemlayer"] : false; | ||||
|         this.overrideOverlayLayers = params["overrideOverlayLayers"] ? params["overrideOverlayLayers"] : false; | ||||
|       } | ||||
|       this.querySub = this.query$.pipe(skip(1), withLatestFrom(this.mapState$)).subscribe(([query,mapState]) =>{ | ||||
|         if(query && query.querystate) { | ||||
|           let newQueryState = tassign(mapReducers.initialQueryState); | ||||
|           //console.debug(`Do Query`); | ||||
|           const urlparts=[]; | ||||
|           if (query.querystate.itemCode && query.querystate.itemCode != "") { | ||||
|             if(query.querystate.itemType && query.querystate.itemType!= "") { | ||||
|               const itemType = this.itemTypeService.itemTypes[query.querystate.itemType]; | ||||
|               if (itemType && itemType.viewer && itemType.viewer == "edit_in_editor" && itemType.editor) { | ||||
|                 urlparts.push('/editor'); | ||||
|                 urlparts.push(itemType.editor); | ||||
|                 urlparts.push('item'); | ||||
|                 urlparts.push(query.querystate.itemCode); | ||||
|               } | ||||
|     private deviceorientationService: DeviceOrientationService, | ||||
|     public devicesService: DeviceService) { | ||||
|     if (route && route.snapshot && route.snapshot.data && route.snapshot.data["fm-map-map"]) { | ||||
|       const params = route.snapshot.data["fm-map-map"]; | ||||
|       this.overrideSelectedItemLayer = params["overrideSelectedItemlayer"] ? params["overrideSelectedItemlayer"] : false; | ||||
|       this.overrideOverlayLayers = params["overrideOverlayLayers"] ? params["overrideOverlayLayers"] : false; | ||||
|       this.hideShowLayerValues = params["hideShowLayerValues"] ? params["hideShowLayerValues"] : false; | ||||
|     } | ||||
|     this.querySub = this.query$.pipe(skip(1), withLatestFrom(this.mapState$)).subscribe(([query, mapState]) => { | ||||
|       if (query && query.querystate) { | ||||
|         let newQueryState = tassign(mapReducers.initialQueryState); | ||||
|         //console.debug(`Do Query`); | ||||
|         const urlparts = []; | ||||
|         if (query.querystate.itemCode && query.querystate.itemCode != "") { | ||||
|           if (query.querystate.itemType && query.querystate.itemType != "") { | ||||
|             const itemType = this.itemTypeService.itemTypes[query.querystate.itemType]; | ||||
|             if (itemType && itemType.viewer && itemType.viewer == "edit_in_editor" && itemType.editor) { | ||||
|               urlparts.push('/editor'); | ||||
|               urlparts.push(itemType.editor); | ||||
|               urlparts.push('item'); | ||||
|               urlparts.push(query.querystate.itemCode); | ||||
|             } | ||||
|           } else { | ||||
|             newQueryState= query.querystate; | ||||
|           } | ||||
|           if(urlparts.length==0 ) { | ||||
|             newQueryState.itemCode = query.querystate.itemCode; | ||||
|             this.zone.run(() => { | ||||
|               this.replaceUrl(mapState,newQueryState,query.replace);              | ||||
|             }) | ||||
|           } else { | ||||
|             this.router.navigate(urlparts); | ||||
|           } | ||||
|         } else { | ||||
|           newQueryState = query.querystate; | ||||
|         } | ||||
|       }); | ||||
|       this.store.dispatch(new mapActions.Init()); | ||||
|       // this.store.select(commonReducers.getRootItems).subscribe((l) => { | ||||
|       //    if(l && l.length>0) { | ||||
|       //      this.store.dispatch(new mapActions.Init()); | ||||
|       //    } | ||||
|       // }); | ||||
|         if (urlparts.length == 0) { | ||||
|           newQueryState.itemCode = query.querystate.itemCode; | ||||
|           this.zone.run(() => { | ||||
|             this.replaceUrl(mapState, newQueryState, query.replace); | ||||
|           }) | ||||
|         } else { | ||||
|           this.router.navigate(urlparts); | ||||
|         } | ||||
|       } | ||||
|     }); | ||||
|     this.store.dispatch(new mapActions.Init()); | ||||
|     // this.store.select(commonReducers.getRootItems).subscribe((l) => { | ||||
|     //    if(l && l.length>0) { | ||||
|     //      this.store.dispatch(new mapActions.Init()); | ||||
|     //    } | ||||
|     // }); | ||||
|   } | ||||
|  | ||||
|   @HostListener('document:keyup', ['$event']) | ||||
| @@ -161,27 +164,27 @@ export class MapComponent implements OnInit, OnDestroy,AfterViewInit { | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   handlePanelResize(resizeTop:number) { | ||||
|     if(resizeTop==100 || !this.devicesService.IsMobile() ) { | ||||
|       this.visibleAreaBottom=0; | ||||
|   handlePanelResize(resizeTop: number) { | ||||
|     if (resizeTop == 100 || !this.devicesService.IsMobile()) { | ||||
|       this.visibleAreaBottom = 0; | ||||
|     } else { | ||||
|       this.visibleAreaBottom=100-resizeTop; | ||||
|       if(this.visibleAreaBottom>60) { | ||||
|         this.visibleAreaBottom=60; | ||||
|       this.visibleAreaBottom = 100 - resizeTop; | ||||
|       if (this.visibleAreaBottom > 60) { | ||||
|         this.visibleAreaBottom = 60; | ||||
|       } | ||||
|     }       | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   bottom(panelVisible:boolean) { | ||||
|     if(panelVisible) { | ||||
|       return this.visibleAreaBottom + '%';      | ||||
|   bottom(panelVisible: boolean) { | ||||
|     if (panelVisible) { | ||||
|       return this.visibleAreaBottom + '%'; | ||||
|     } else { | ||||
|       return "0%"; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   handleOpenModal(modalName: string) { | ||||
|     this.store.dispatch(new  commonActions.OpenModal(modalName)); | ||||
|     this.store.dispatch(new commonActions.OpenModal(modalName)); | ||||
|   } | ||||
|  | ||||
|   handleCloseModal() { | ||||
| @@ -189,7 +192,7 @@ export class MapComponent implements OnInit, OnDestroy,AfterViewInit { | ||||
|   } | ||||
|  | ||||
|   handleFileDropped(droppedFile: IDroppedFile) { | ||||
|     this.uploadService.addFiles(droppedFile.files, droppedFile.event, { parentCode:droppedFile.parentCode, geometry:droppedFile.geometry }); | ||||
|     this.uploadService.addFiles(droppedFile.files, droppedFile.event, { parentCode: droppedFile.parentCode, geometry: droppedFile.geometry }); | ||||
|   } | ||||
|  | ||||
|   handleFeatureClick(feature: Feature<Geometry>) { | ||||
| @@ -205,26 +208,26 @@ export class MapComponent implements OnInit, OnDestroy,AfterViewInit { | ||||
|     this.store.dispatch(new mapActions.DoQuery(queryState)); | ||||
|   } | ||||
|  | ||||
|   handleSidepaneloutletActivate(component:any) { | ||||
|    if(component && component.hasOwnProperty('clickedFeature')) { | ||||
|      (component as IClickedFeature).clickedFeature = this.clickedFeature; | ||||
|    } | ||||
|    if(component && component.hasOwnProperty('extrawide')) { | ||||
|     this.store.dispatch(new mapActions.SetPanelExtraWide(true)); | ||||
|   handleSidepaneloutletActivate(component: any) { | ||||
|     if (component && component.hasOwnProperty('clickedFeature')) { | ||||
|       (component as IClickedFeature).clickedFeature = this.clickedFeature; | ||||
|     } | ||||
|     if (component && component.hasOwnProperty('extrawide')) { | ||||
|       this.store.dispatch(new mapActions.SetPanelExtraWide(true)); | ||||
|     } | ||||
|   } | ||||
|  } | ||||
|  | ||||
|   handleSidepaneloutletDeactivate(component:any) { | ||||
|     if(component && component.hasOwnProperty('clickedFeature')) { | ||||
|   handleSidepaneloutletDeactivate(component: any) { | ||||
|     if (component && component.hasOwnProperty('clickedFeature')) { | ||||
|       (component as IClickedFeature).clickedFeature = null; | ||||
|     } | ||||
|     if(component && component.hasOwnProperty('extrawide')) { | ||||
|     if (component && component.hasOwnProperty('extrawide')) { | ||||
|       this.store.dispatch(new mapActions.SetPanelExtraWide(false)); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   handlePrerender(event:any) { | ||||
|     if(!this.dataLayerSlideEnabled) return; | ||||
|   handlePrerender(event: any) { | ||||
|     if (!this.dataLayerSlideEnabled) return; | ||||
|     const ctx = event.context; | ||||
|     const mapSize = this.map.instance.getSize(); | ||||
|     const width = mapSize[0] * (this.dataLayerSlideValue / 100); | ||||
| @@ -243,72 +246,74 @@ export class MapComponent implements OnInit, OnDestroy,AfterViewInit { | ||||
|     ctx.clip(); | ||||
|   } | ||||
|  | ||||
|   handleSlideChange(event:any) { | ||||
|      this.dataLayerSlideValue = event.target.value; | ||||
|      this.map.instance.render(); | ||||
|   handleSlideChange(event: any) { | ||||
|     this.dataLayerSlideValue = event.target.value; | ||||
|     this.map.instance.render(); | ||||
|   } | ||||
|  | ||||
|   ngOnInit() {     | ||||
|   ngOnInit() { | ||||
|     this.initialized = false; | ||||
|     //console.debug("Init"); | ||||
|     this.store.dispatch(new mapActions.Clear()); | ||||
|     this.selectedFeatures$.next({x:0,y:0,features:[]}); | ||||
|     this.selectedFeatures$.next({ x: 0, y: 0, features: [] }); | ||||
|     this.selectedFeatures$.next(null); | ||||
|   } | ||||
|  | ||||
|   initCustomStyles() { | ||||
|     this.store.dispatch(new mapActions.SetStyle('vnd.farmmaps.itemtype.layer',new style.Style({ | ||||
|     this.store.dispatch(new mapActions.SetStyle('vnd.farmmaps.itemtype.layer', new style.Style({ | ||||
|       stroke: new style.Stroke({ | ||||
|         color: 'red', | ||||
|         lineDash: [ 5,5], | ||||
|         lineDash: [5, 5], | ||||
|         width: 1 | ||||
|       }), | ||||
|       geometry:(feature) =>feature.getGeometry() | ||||
|       geometry: (feature) => feature.getGeometry() | ||||
|     }))); | ||||
|     this.store.dispatch(new mapActions.SetStyle('vnd.farmmaps.itemtype.layer_selected',new style.Style({ | ||||
|     this.store.dispatch(new mapActions.SetStyle('vnd.farmmaps.itemtype.layer_selected', new style.Style({ | ||||
|       stroke: new style.Stroke({ | ||||
|         color: 'red', | ||||
|         lineDash: [ 5,5], | ||||
|         lineDash: [5, 5], | ||||
|         width: 3 | ||||
|       }), | ||||
|       geometry:(feature) =>feature.getGeometry() | ||||
|       geometry: (feature) => feature.getGeometry() | ||||
|     }))); | ||||
|   } | ||||
|  | ||||
|   round(value:number,decimals:number):number { | ||||
|   round(value: number, decimals: number): number { | ||||
|     const d = Math.pow(10, decimals); | ||||
|     return Math.round((value + Number.EPSILON)*d)/d; | ||||
|     return Math.round((value + Number.EPSILON) * d) / d; | ||||
|   } | ||||
|  | ||||
|   getMapStateFromUrl(params:ParamMap):IMapState { | ||||
|   getMapStateFromUrl(params: ParamMap): IMapState { | ||||
|     const hasUrlmapState = params.has("xCenter") && params.has("yCenter"); | ||||
|     if (hasUrlmapState) { | ||||
|       const xCenter = parseFloat(params.get("xCenter")); | ||||
|       const yCenter = parseFloat(params.get("yCenter")); | ||||
|       const zoom = parseFloat(params.get("zoom")); | ||||
|       const rotation = parseFloat(params.get("rotation")); | ||||
|       const baseLayer = params.get("baseLayer")?params.get("baseLayer"):""; | ||||
|       const newMapState = {zoom: zoom, rotation: rotation, xCenter: xCenter, yCenter: yCenter, baseLayerCode: baseLayer }; | ||||
|       const baseLayer = params.get("baseLayer") ? params.get("baseLayer") : ""; | ||||
|       const 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 }; | ||||
|   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 { | ||||
|   serializeMapState(mapState: IMapState): string { | ||||
|     return JSON.stringify(this.normalizeMapState(mapState)); | ||||
|   } | ||||
|  | ||||
|   getQueryStateFromUrl(params:ParamMap):IQueryState { | ||||
|   getQueryStateFromUrl(params: ParamMap): IQueryState { | ||||
|     if (params.has("queryState")) { | ||||
|       const queryState = params.get("queryState"); | ||||
|       let newQueryState = tassign(mapReducers.initialQueryState); | ||||
| @@ -323,65 +328,65 @@ export class MapComponent implements OnInit, OnDestroy,AfterViewInit { | ||||
|  | ||||
|   ngAfterViewInit() { | ||||
|     //console.debug("View init"); | ||||
|     this.noContent=true; | ||||
|     this.noContent = true; | ||||
|     this.route.children.forEach((entry) => { | ||||
|       if(entry.outlet=="primary") { | ||||
|         this.noContent=false; | ||||
|       if (entry.outlet == "primary") { | ||||
|         this.noContent = false; | ||||
|       } | ||||
|     }); | ||||
|        | ||||
|  | ||||
|     this.initCustomStyles(); | ||||
|  | ||||
|     // url to state | ||||
|  | ||||
|       const urlMapState = this.getMapStateFromUrl(this.route.snapshot.paramMap); | ||||
|       const urlQueryState = this.getQueryStateFromUrl(this.route.snapshot.paramMap); | ||||
|       if(urlQueryState && urlMapState && this.noContent) { | ||||
|         this.store.dispatch(new mapActions.SetState(urlMapState,urlQueryState)); | ||||
|         window.localStorage.setItem("FarmMapsCommonMap_mapState",this.serializeMapState(urlMapState)); | ||||
|       } else if(urlQueryState && this.noContent) { | ||||
|         this.store.dispatch(new mapActions.SetQueryState(urlQueryState)); | ||||
|       }  else { | ||||
|         this.store.dispatch(new mapActions.SetReplaceUrl(true)); | ||||
|       } | ||||
|     const urlMapState = this.getMapStateFromUrl(this.route.snapshot.paramMap); | ||||
|     const urlQueryState = this.getQueryStateFromUrl(this.route.snapshot.paramMap); | ||||
|     if (urlQueryState && urlMapState && this.noContent) { | ||||
|       this.store.dispatch(new mapActions.SetState(urlMapState, urlQueryState)); | ||||
|       window.localStorage.setItem("FarmMapsCommonMap_mapState", this.serializeMapState(urlMapState)); | ||||
|     } else if (urlQueryState && this.noContent) { | ||||
|       this.store.dispatch(new mapActions.SetQueryState(urlQueryState)); | ||||
|     } else { | ||||
|       this.store.dispatch(new mapActions.SetReplaceUrl(true)); | ||||
|     } | ||||
|  | ||||
|       this.paramSub = this.route.paramMap.pipe(withLatestFrom(this.state$),switchMap(([params,state]) => { | ||||
|          if(this.initialized && this.noContent) { | ||||
|           const urlQueryState = this.getQueryStateFromUrl(params); | ||||
|           if( this.serializeService.serialize(state.queryState) != this.serializeService.serialize(urlQueryState)) { | ||||
|             return of(new mapActions.SetState(state.mapState,urlQueryState)); | ||||
|           }           | ||||
|          }  | ||||
|          return EMPTY;         | ||||
|       })).subscribe((action) => { | ||||
|         if(action) { | ||||
|           this.zone.run(() => { | ||||
|             //console.debug("Url to state"); | ||||
|             this.store.dispatch(action); | ||||
|           }); | ||||
|     this.paramSub = this.route.paramMap.pipe(withLatestFrom(this.state$), switchMap(([params, state]) => { | ||||
|       if (this.initialized && this.noContent) { | ||||
|         const urlQueryState = this.getQueryStateFromUrl(params); | ||||
|         if (this.serializeService.serialize(state.queryState) != this.serializeService.serialize(urlQueryState)) { | ||||
|           return of(new mapActions.SetState(state.mapState, urlQueryState)); | ||||
|         } | ||||
|       }); | ||||
|       } | ||||
|       return EMPTY; | ||||
|     })).subscribe((action) => { | ||||
|       if (action) { | ||||
|         this.zone.run(() => { | ||||
|           //console.debug("Url to state"); | ||||
|           this.store.dispatch(action); | ||||
|         }); | ||||
|       } | ||||
|     }); | ||||
|  | ||||
|     // state to url | ||||
|  | ||||
|     this.stateSub = this.state$.pipe(switchMap((state) => { | ||||
|       const newUrl = this.serializeMapState(state.mapState) + "_" + this.serializeService.serialize(state.queryState); | ||||
|       if(this.lastUrl!=newUrl) { | ||||
|         this.lastUrl=newUrl; | ||||
|       if (this.lastUrl != newUrl) { | ||||
|         this.lastUrl = newUrl; | ||||
|         return of(state); | ||||
|       } | ||||
|       else { | ||||
|         return of(null); | ||||
|       } | ||||
|     })).subscribe((newUrlState: any) => { | ||||
|         if(newUrlState) { | ||||
|           //console.debug(`State to url`); | ||||
|           this.replaceUrl(newUrlState.mapState,newUrlState.queryState,newUrlState.replaceUrl); | ||||
|         } | ||||
|       }); | ||||
|     this.initialized = true;    | ||||
|       if (newUrlState) { | ||||
|         //console.debug(`State to url`); | ||||
|         this.replaceUrl(newUrlState.mapState, newUrlState.queryState, newUrlState.replaceUrl); | ||||
|       } | ||||
|     }); | ||||
|     this.initialized = true; | ||||
|     this.showDataLayerSlide$.subscribe((v) => { | ||||
|       this.dataLayerSlideEnabled=v; | ||||
|       this.dataLayerSlideEnabled = v; | ||||
|       this.map.instance.render(); | ||||
|     }); | ||||
|     this.store.select(mapReducers.selectGetViewEnabled).subscribe((v) => { | ||||
| @@ -401,7 +406,7 @@ export class MapComponent implements OnInit, OnDestroy,AfterViewInit { | ||||
|     this.store.dispatch(new commonActions.ToggleMenu()); | ||||
|   } | ||||
|  | ||||
|   handleToggleBaseLayers(event:MouseEvent) { | ||||
|   handleToggleBaseLayers(event: MouseEvent) { | ||||
|     this.baseLayersCollapsed = !this.baseLayersCollapsed; | ||||
|     event.preventDefault(); | ||||
|   } | ||||
| @@ -418,30 +423,30 @@ export class MapComponent implements OnInit, OnDestroy,AfterViewInit { | ||||
|   } | ||||
|  | ||||
|   replaceUrl(mapState: IMapState, queryState: IQueryState, replace = true) { | ||||
|       if(this.noContent) { | ||||
|         const newMapState = this.serializeMapState(mapState); | ||||
|         const newQueryState = this.serializeService.serialize(queryState); | ||||
|         const currentMapState = this.serializeMapState(this.getMapStateFromUrl(this.route.snapshot.paramMap)); | ||||
|         const urlQueryState = this.getQueryStateFromUrl(this.route.snapshot.paramMap); | ||||
|         const currentQueryState = urlQueryState==null?"":this.serializeService.serialize(urlQueryState); | ||||
|         if(mapState.baseLayerCode!="" && ((newMapState!= currentMapState)  || (newQueryState!=currentQueryState))) { | ||||
|           const parts =["."]; | ||||
|           parts.push(mapState.xCenter.toFixed(5)); | ||||
|           parts.push(mapState.yCenter.toFixed(5)); | ||||
|           parts.push( mapState.zoom.toFixed(0)); | ||||
|           parts.push( mapState.rotation.toFixed(2));         | ||||
|           parts.push(mapState.baseLayerCode); | ||||
|           parts.push( this.serializeService.serialize(queryState)); | ||||
|            | ||||
|           //console.debug("Replace url",parts); | ||||
|           this.router.navigate(parts, { replaceUrl: replace,relativeTo:this.route.parent }); | ||||
|         }   | ||||
|       }      | ||||
|     if (this.noContent) { | ||||
|       const newMapState = this.serializeMapState(mapState); | ||||
|       const newQueryState = this.serializeService.serialize(queryState); | ||||
|       const currentMapState = this.serializeMapState(this.getMapStateFromUrl(this.route.snapshot.paramMap)); | ||||
|       const urlQueryState = this.getQueryStateFromUrl(this.route.snapshot.paramMap); | ||||
|       const currentQueryState = urlQueryState == null ? "" : this.serializeService.serialize(urlQueryState); | ||||
|       if (mapState.baseLayerCode != "" && ((newMapState != currentMapState) || (newQueryState != currentQueryState))) { | ||||
|         const parts = ["."]; | ||||
|         parts.push(mapState.xCenter.toFixed(5)); | ||||
|         parts.push(mapState.yCenter.toFixed(5)); | ||||
|         parts.push(mapState.zoom.toFixed(0)); | ||||
|         parts.push(mapState.rotation.toFixed(2)); | ||||
|         parts.push(mapState.baseLayerCode); | ||||
|         parts.push(this.serializeService.serialize(queryState)); | ||||
|  | ||||
|         //console.debug("Replace url",parts); | ||||
|         this.router.navigate(parts, { replaceUrl: replace, relativeTo: this.route.parent }); | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   handleOnMoveEnd(event) {     | ||||
|     if(this.initialized && this.viewEnabled) { | ||||
|       this.zone.run(() =>{ | ||||
|   handleOnMoveEnd(event) { | ||||
|     if (this.initialized && this.viewEnabled) { | ||||
|       this.zone.run(() => { | ||||
|         //console.debug("Move end"); | ||||
|         const map = event.map; | ||||
|         const view = map.getView(); | ||||
| @@ -461,21 +466,23 @@ export class MapComponent implements OnInit, OnDestroy,AfterViewInit { | ||||
|           } | ||||
|         }); | ||||
|       }); | ||||
|     }    | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   handleOnMouseDown(event: MouseEvent) { | ||||
|     event.stopPropagation(); | ||||
|     this.zone.run(() =>{ | ||||
|     this.zone.run(() => { | ||||
|       this.store.dispatch(new commonActions.CloseAll()); | ||||
|     }); | ||||
|   } | ||||
|  | ||||
|   handleShowLayerValues(event: MouseEvent) { | ||||
|     event.stopPropagation(); | ||||
|     this.zone.run(() =>{ | ||||
|       this.store.dispatch(new mapActions.ToggleLayerValuesEnabled()); | ||||
|     }); | ||||
|     if (!this.hideShowLayerValues) { | ||||
|       event.stopPropagation(); | ||||
|       this.zone.run(() => { | ||||
|         this.store.dispatch(new mapActions.ToggleLayerValuesEnabled()); | ||||
|       }); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   handleOnDownload(event) { | ||||
| @@ -491,15 +498,15 @@ export class MapComponent implements OnInit, OnDestroy,AfterViewInit { | ||||
|   } | ||||
|  | ||||
|   handleOnToggleVisibility(itemLayer: IItemLayer) { | ||||
|     this.store.dispatch(new mapActions.SetVisibility(itemLayer,!itemLayer.visible)); | ||||
|     this.store.dispatch(new mapActions.SetVisibility(itemLayer, !itemLayer.visible)); | ||||
|   } | ||||
|  | ||||
|   handleOnSetOpacity(event:{ layer: IItemLayer,opacity:number }) { | ||||
|   handleOnSetOpacity(event: { layer: IItemLayer, opacity: number }) { | ||||
|     this.store.dispatch(new mapActions.SetOpacity(event.layer, event.opacity)); | ||||
|   } | ||||
|  | ||||
|   handleZoomToExtent(itemLayer: IItemLayer) { | ||||
|     const extent =  createEmpty(); | ||||
|     const extent = createEmpty(); | ||||
|     extend(extent, itemLayer.layer.getExtent()); | ||||
|     if (extent) { | ||||
|       this.store.dispatch(new mapActions.SetExtent(extent)); | ||||
| @@ -514,21 +521,21 @@ export class MapComponent implements OnInit, OnDestroy,AfterViewInit { | ||||
|     this.store.dispatch(new mapActions.SelectOverlayLayer(itemLayer)); | ||||
|   } | ||||
|  | ||||
|   handlePeriodChange(period:IPeriodState) { | ||||
|   handlePeriodChange(period: IPeriodState) { | ||||
|     this.store.dispatch(new mapActions.SetPeriod(period)); | ||||
|   } | ||||
|  | ||||
|   handleCitySearch(location:string) { | ||||
|   handleCitySearch(location: string) { | ||||
|     this.geolocaterService.geocode(location).subscribe(locations => { | ||||
|       if( locations.length > 0) { | ||||
|         const point = new  Point([locations[0].coordinates.lon,locations[0].coordinates.lat]); | ||||
|       if (locations.length > 0) { | ||||
|         const point = new Point([locations[0].coordinates.lon, locations[0].coordinates.lat]); | ||||
|         point.transform('EPSG:4326', 'EPSG:3857'); | ||||
|         const circle = new Circle(point.getCoordinates(),5000);//  | ||||
|         const circle = new Circle(point.getCoordinates(), 5000);//  | ||||
|         const extent = createEmpty(); | ||||
|         extend(extent, circle.getExtent()); | ||||
|         this.store.dispatch(new mapActions.SetExtent(extent)) | ||||
|       } | ||||
|      }); | ||||
|     }); | ||||
|   } | ||||
|  | ||||
|   ngOnDestroy() { | ||||
|   | ||||
| @@ -25,7 +25,7 @@ export class SelectedItemCropfieldComponent extends AbstractSelectedItemComponen | ||||
|   public items: Observable<IListItem[]>; | ||||
|  | ||||
|   constructor(store: Store<mapReducers.State | commonReducers.State>, itemTypeService: ItemTypeService, location: Location, router: Router, private itemService$: ItemService,private folderService$: FolderService) { | ||||
|     super(store, itemTypeService,location,router); | ||||
|     super(store, itemTypeService, itemService$, location,router); | ||||
|   } | ||||
|  | ||||
|   areaInHa(item:IItem):number { | ||||
|   | ||||
| @@ -7,28 +7,31 @@ | ||||
|         <h2 *ngIf="parentOfItemType('vnd.farmmaps.itemtype.cropfield')">{{parentItem.name}}</h2> | ||||
|         <h1>{{item.name}}</h1> | ||||
|       </div> | ||||
|       <div class="legend-container" *ngIf="item?.data.layers;let layers"> | ||||
|         <div class="card menu-card"> | ||||
|           <div *ngIf="layers.length>1"> | ||||
|             <select (change)="onLayerChanged($event.target.value)"> | ||||
|               <option *ngFor="let l of layers;" [value]="l.index"  [selected]="itemLayer.layerIndex == l.index">{{l.name}}</option> | ||||
|             </select> | ||||
|       <ng-container *ngIf="item?.data.layers;let layers"> | ||||
|         <div class="legend-container"> | ||||
|           <div class="card menu-card"> | ||||
|             <div *ngIf="layers.length>1"> | ||||
|               <select (change)="onLayerChanged($event.target.value)"> | ||||
|                 <option *ngFor="let l of layers;" [value]="l.index"  [selected]="itemLayer.layerIndex == l.index">{{l.name}}</option> | ||||
|               </select> | ||||
|             </div> | ||||
|             <fm-map-layer-legend [showTitle]="layers.length == 1" | ||||
|               [layer]="layer(layers,itemLayer.layerIndex)" [histogramenabled]="true"></fm-map-layer-legend> | ||||
|           </div> | ||||
|           <fm-map-layer-legend [showTitle]="layers.length == 1" | ||||
|             [layer]="layer(layers,itemLayer.layerIndex)" [histogramenabled]="true"></fm-map-layer-legend> | ||||
|         </div> | ||||
|       </div> | ||||
|       <div class="card menu-card"> | ||||
|         <ul class="p-0 mt-2"> | ||||
|           <li *ngIf="item.isEditable"><a href="#" class="ms-1 me-1" (click)="handleOnEdit(item)"><i class="fal fa-pencil" aria-hidden="true" i18n-title title="Edit"></i> <span i18n>Edit</span></a></li> | ||||
|           <ng-container *ngIf="itemTypeService.isLayer(item)"> | ||||
|             <li *ngIf="!getItemLayer(item,itemLayer.layerIndex)"><a   href="#" (click)="handleAddAsLayer(item,itemLayer.layerIndex)"><i class="fas fa-layer-plus" aria-hidden="true" i18n-title title="Add as layer"></i> <span i18n>Add as overlay</span></a></li> | ||||
|             <li *ngIf="getItemLayer(item,itemLayer.layerIndex)"><a  href="#" (click)="handleRemoveLayer(item,itemLayer.layerIndex)"><i class="fas fa-layer-minus" aria-hidden="true" i18n-title title="Remove overlay"></i> <span i18n>Remove overlay</span></a></li> | ||||
|           </ng-container> | ||||
|           <li><fm-item-link class="text-primary p-0" [itemCode]="item.code" pathSuffix="data" [showText]="true"></fm-item-link></li> | ||||
|         </ul> | ||||
|       </div> | ||||
|       <fm-map-zoom-to-show-alert [layer]="itemLayer?.layer"></fm-map-zoom-to-show-alert> | ||||
|         <div class="card menu-card"> | ||||
|           <ul class="p-0 mt-2"> | ||||
|             <li *ngIf="item.isEditable"><a href="#" class="ms-1 me-1" (click)="handleOnEdit(item)"><i class="fal fa-pencil" aria-hidden="true" i18n-title title="Edit"></i> <span i18n>Edit</span></a></li> | ||||
|             <ng-container *ngIf="itemTypeService.isLayer(item)"> | ||||
|               <li *ngIf="!getItemLayer(item,itemLayer.layerIndex)"><a   href="#" (click)="handleAddAsLayer(item,itemLayer.layerIndex)"><i class="fas fa-layer-plus" aria-hidden="true" i18n-title title="Add as layer"></i> <span i18n>Add as overlay</span></a></li> | ||||
|               <li *ngIf="getItemLayer(item,itemLayer.layerIndex)"><a  href="#" (click)="handleRemoveLayer(item,itemLayer.layerIndex)"><i class="fas fa-layer-minus" aria-hidden="true" i18n-title title="Remove overlay"></i> <span i18n>Remove overlay</span></a></li> | ||||
|             </ng-container> | ||||
|             <li><fm-item-link class="text-primary p-0" [itemCode]="item.code" pathSuffix="data" [showText]="true"></fm-item-link></li> | ||||
|             <li><a href="#" (click)="download($event,item,layers,itemLayer.layerIndex)"><i class="fal fa-download" aria-hidden="true" i18n-title title="Download"></i> <span i18n>Download</span></a></li> | ||||
|           </ul> | ||||
|         </div> | ||||
|         <fm-map-zoom-to-show-alert [layer]="itemLayer?.layer"></fm-map-zoom-to-show-alert> | ||||
|       </ng-container> | ||||
|     </div> | ||||
|   </div> | ||||
| </div> | ||||
|   | ||||
| @@ -1,12 +1,13 @@ | ||||
| import { Component, Injectable } from '@angular/core'; | ||||
| import { Location } from '@angular/common'; | ||||
| import { Store } from '@ngrx/store'; | ||||
| import * as mapReducers from '../../reducers/map.reducer'; | ||||
| import { commonReducers, ItemTypeService, ItemService, FolderService } from '@farmmaps/common'; | ||||
| import { Component, Injectable, OnDestroy } from '@angular/core'; | ||||
| import { Router } from '@angular/router'; | ||||
| import { commonReducers, FolderService, IItem, IItemLinkType, ItemService, ItemTypeService, IUrlType } from '@farmmaps/common'; | ||||
| import { Store } from '@ngrx/store'; | ||||
| import { Subscription } from 'rxjs'; | ||||
| import * as mapActions from '../../actions/map.actions'; | ||||
| import * as mapReducers from '../../reducers/map.reducer'; | ||||
| import { ForItemType } from '../for-item/for-itemtype.decorator'; | ||||
| import { AbstractSelectedItemComponent } from '../selected-item/selected-item.component'; | ||||
| import * as mapActions from '../../actions/map.actions'; | ||||
|  | ||||
|  | ||||
| @ForItemType("vnd.farmmaps.itemtype.geotiff.processed") | ||||
| @@ -16,10 +17,15 @@ import * as mapActions from '../../actions/map.actions'; | ||||
|   templateUrl: './selected-item-geotiff.component.html', | ||||
|   styleUrls: ['./selected-item-geotiff.component.scss'] | ||||
| }) | ||||
| export class SelectedItemGeotiffComponent extends AbstractSelectedItemComponent { | ||||
| export class SelectedItemGeotiffComponent extends AbstractSelectedItemComponent implements OnDestroy { | ||||
|   sub: Subscription; | ||||
|  | ||||
|   constructor(store: Store<mapReducers.State | commonReducers.State>, itemTypeService: ItemTypeService, location: Location, router: Router, private itemService$: ItemService,private folderService$: FolderService) { | ||||
|     super(store, itemTypeService,location,router); | ||||
|   constructor(store: Store<mapReducers.State | commonReducers.State>, public itemService: ItemService, itemTypeService: ItemTypeService, location: Location, router: Router, private itemService$: ItemService,private folderService$: FolderService) { | ||||
|     super(store, itemTypeService,itemService,location,router); | ||||
|   } | ||||
|  | ||||
|   ngOnDestroy(): void { | ||||
|     if (this.sub) this.sub.unsubscribe(); | ||||
|   } | ||||
|  | ||||
|   onLayerChanged(layerIndex: number) { | ||||
| @@ -29,4 +35,13 @@ export class SelectedItemGeotiffComponent extends AbstractSelectedItemComponent | ||||
|   layer(layers:any,layerIndex:number) { | ||||
|     return layers.find(l => l.index == layerIndex); | ||||
|   } | ||||
|    | ||||
|   download(event:MouseEvent,item:IItem,layers:any,layerIndex:number) { | ||||
|     event.stopPropagation(); | ||||
|     event.preventDefault(); | ||||
|     const itemLink : IItemLinkType = {itemcode:item.code,query:`layer=${this.layer(layers,layerIndex).name}`,pathsuffix:"download", validminutes:10} | ||||
|     this.sub = this.itemService.getItemLink(itemLink).subscribe((itemLinkUrl:IUrlType) => {   | ||||
|         window.location.href = itemLinkUrl.url;      | ||||
|     }) | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -7,25 +7,28 @@ | ||||
|         <h2 *ngIf="parentOfItemType('vnd.farmmaps.itemtype.cropfield')">{{parentItem.name}}</h2> | ||||
|         <h1>{{item.name}}</h1> | ||||
|       </div> | ||||
|       <div class="legend-container" *ngIf="item?.data.layers;let layers"> | ||||
|         <div class="card menu-card"> | ||||
|           <div *ngIf="layers.length>1"> | ||||
|             <select (change)="onLayerChanged($event.target.value)"> | ||||
|               <option *ngFor="let l of layers;" [value]="l.index" [selected]="itemLayer.layerIndex == l.index">{{l.name}}</option> | ||||
|             </select> | ||||
|       <ng-container *ngIf="item?.data.layers;let layers"> | ||||
|         <div class="legend-container"> | ||||
|           <div class="card menu-card"> | ||||
|             <div *ngIf="layers.length>1"> | ||||
|               <select (change)="onLayerChanged($event.target.value)"> | ||||
|                 <option *ngFor="let l of layers;" [value]="l.index" [selected]="itemLayer.layerIndex == l.index">{{l.name}}</option> | ||||
|               </select> | ||||
|             </div> | ||||
|             <fm-map-layer-legend [showTitle]="layers.length==1" [layer]="layer(layers,itemLayer.layerIndex)" [histogramenabled]="true"></fm-map-layer-legend> | ||||
|           </div> | ||||
|           <fm-map-layer-legend [showTitle]="layers.length==1" [layer]="layer(layers,itemLayer.layerIndex)" [histogramenabled]="true"></fm-map-layer-legend> | ||||
|         </div> | ||||
|       </div> | ||||
|       <div class="card menu-card"> | ||||
|         <ul class="p-0 mt-2"> | ||||
|           <li *ngIf="item.isEditable"><a href="#" class="mt-1 me-1" (click)="handleOnEdit(item)" ><i class="fal fa-pencil" aria-hidden="true" i18n-title title="Edit"></i> <span i18n>Edit</span></a></li> | ||||
|           <ng-container *ngIf="itemTypeService.isLayer(item)"> | ||||
|             <li *ngIf="!getItemLayer(item,itemLayer.layerIndex)"><a   href="#" (click)="handleAddAsLayer(item,itemLayer.layerIndex)" ><i class="fas fa-layer-olus" aria-hidden="true" i18n-title title="Add as layer"></i> <span i18n>Add as overlay</span></a></li> | ||||
|             <li *ngIf="getItemLayer(item,itemLayer.layerIndex)"><a  href="#" (click)="handleRemoveLayer(item,itemLayer.layerIndex)" ><i class="fas fa-layer-minus" aria-hidden="true" i18n-title title="Remove overlay"></i> <span i18n>Remove overlay</span></a></li> | ||||
|           </ng-container> | ||||
|         </ul> | ||||
|       </div> | ||||
|         <div class="card menu-card"> | ||||
|           <ul class="p-0 mt-2"> | ||||
|             <li *ngIf="item.isEditable"><a href="#" class="mt-1 me-1" (click)="handleOnEdit(item)" ><i class="fal fa-pencil" aria-hidden="true" i18n-title title="Edit"></i> <span i18n>Edit</span></a></li> | ||||
|             <ng-container *ngIf="itemTypeService.isLayer(item)"> | ||||
|               <li *ngIf="!getItemLayer(item,itemLayer.layerIndex)"><a   href="#" (click)="handleAddAsLayer(item,itemLayer.layerIndex)" ><i class="fas fa-layer-olus" aria-hidden="true" i18n-title title="Add as layer"></i> <span i18n>Add as overlay</span></a></li> | ||||
|               <li *ngIf="getItemLayer(item,itemLayer.layerIndex)"><a  href="#" (click)="handleRemoveLayer(item,itemLayer.layerIndex)" ><i class="fas fa-layer-minus" aria-hidden="true" i18n-title title="Remove overlay"></i> <span i18n>Remove overlay</span></a></li> | ||||
|             </ng-container> | ||||
|             <li><a href="#" (click)="download($event,item,layers,itemLayer.layerIndex)"><i class="fal fa-download" aria-hidden="true" i18n-title title="Download"></i> <span i18n>Download</span></a></li> | ||||
|           </ul> | ||||
|         </div> | ||||
|       </ng-container> | ||||
|       <fm-map-zoom-to-show-alert [layer]="itemLayer?.layer"></fm-map-zoom-to-show-alert> | ||||
|     </div> | ||||
|   </div> | ||||
|   | ||||
| @@ -1,14 +1,13 @@ | ||||
| import { Component, Input, Injectable, OnInit } from '@angular/core'; | ||||
| import { Location } from '@angular/common'; | ||||
| import { Feature } from 'ol'; | ||||
| import { Component, Injectable, OnDestroy } from '@angular/core'; | ||||
| import { Router } from '@angular/router'; | ||||
| import { commonReducers, FolderService, IItem, IItemLinkType, ItemService, ItemTypeService, IUrlType } from '@farmmaps/common'; | ||||
| import { Store } from '@ngrx/store'; | ||||
| import * as mapReducers from '../../reducers/map.reducer'; | ||||
| import { commonReducers, ItemTypeService, IItem, Item, ItemService, FolderService, IListItem} from '@farmmaps/common'; | ||||
| import * as mapActions from '../../actions/map.actions'; | ||||
| import { Router, ActivatedRoute, ParamMap, Event } from '@angular/router'; | ||||
| import * as mapReducers from '../../reducers/map.reducer'; | ||||
| import { ForItemType } from '../for-item/for-itemtype.decorator'; | ||||
| import { AbstractSelectedItemComponent } from '../selected-item/selected-item.component'; | ||||
| import { Observable } from 'rxjs'; | ||||
| import { Subscription } from 'rxjs'; | ||||
|  | ||||
|  | ||||
| @ForItemType("vnd.farmmaps.itemtype.shape.processed") | ||||
| @@ -18,13 +17,18 @@ import { Observable } from 'rxjs'; | ||||
|   templateUrl: './selected-item-shape.component.html', | ||||
|   styleUrls: ['./selected-item-shape.component.scss'] | ||||
| }) | ||||
| export class SelectedItemShapeComponent extends AbstractSelectedItemComponent { | ||||
|  | ||||
|   constructor(store: Store<mapReducers.State | commonReducers.State>, itemTypeService: ItemTypeService, location: Location, router: Router, private itemService$: ItemService,private folderService$: FolderService) { | ||||
|     super(store, itemTypeService,location,router); | ||||
|   } | ||||
| export class SelectedItemShapeComponent extends AbstractSelectedItemComponent implements OnDestroy { | ||||
|   public selectedLayer = 0; | ||||
|    | ||||
|   sub: Subscription; | ||||
|  | ||||
|   constructor(store: Store<mapReducers.State | commonReducers.State>, public itemService: ItemService, itemTypeService: ItemTypeService, location: Location, router: Router, private itemService$: ItemService,private folderService$: FolderService) { | ||||
|     super(store, itemTypeService,itemService,location,router); | ||||
|   } | ||||
|  | ||||
|   ngOnDestroy(): void { | ||||
|     if (this.sub) this.sub.unsubscribe(); | ||||
|   } | ||||
|  | ||||
|   onLayerChanged(layerIndex: number) { | ||||
|     this.store.dispatch(new mapActions.SetLayerIndex(layerIndex)); | ||||
|   } | ||||
| @@ -32,4 +36,13 @@ export class SelectedItemShapeComponent extends AbstractSelectedItemComponent { | ||||
|   layer(layers:any,layerIndex:number) { | ||||
|     return layers.find(l => l.index == layerIndex); | ||||
|   } | ||||
|      | ||||
|   download(event:MouseEvent,item:IItem,layers:any,layerIndex:number) { | ||||
|     event.stopPropagation(); | ||||
|     event.preventDefault(); | ||||
|     const itemLink : IItemLinkType = {itemcode:item.code,query:`layer=${this.layer(layers,layerIndex).name}`,pathsuffix:"download", validminutes:10} | ||||
|     this.sub = this.itemService.getItemLink(itemLink).subscribe((itemLinkUrl:IUrlType) => {   | ||||
|         window.location.href = itemLinkUrl.url;      | ||||
|     }) | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -7,43 +7,46 @@ | ||||
|         <h2 *ngIf="parentOfItemType('vnd.farmmaps.itemtype.cropfield')">{{parentItem.name}}</h2> | ||||
|         <h1>{{item.name}}</h1> | ||||
|       </div> | ||||
|       <div class="legend-container" *ngIf="item?.data.layers;let layers"> | ||||
|       <ng-container *ngIf="item?.data.layers;let layers"> | ||||
|         <div class="legend-container"> | ||||
|           <div class="card menu-card"> | ||||
|             <h5><span i18n>Date</span>: {{temporalService.selectedDate(itemLayer)}}</h5> | ||||
|             <div class="d-flex justify-content-between"> | ||||
|               <div> | ||||
|                 <button  *ngIf="temporalService.hasPrevious(itemLayer)" type="button" class="btn btn-link p-0" (click)="handlePreviousTemporal($event)"> | ||||
|                   <i class="fal fa-arrow-circle-left" aria-hidden="true" i18n-title title="Previous"></i> {{ temporalService.previousDate(itemLayer) }} | ||||
|                 </button> | ||||
|               </div> | ||||
|               <div> | ||||
|                 <button  *ngIf="temporalService.hasNext(itemLayer)" type="button" class="btn btn-link p-0" (click)="handleNextTemporal($event)"> | ||||
|                   {{ temporalService.nextDate(itemLayer)}} <i class="fal fa-arrow-circle-right" aria-hidden="true" i18n-title title="Next"></i> | ||||
|                 </button> | ||||
|               </div> | ||||
|             </div> | ||||
|             <fm-map-zoom-to-show-alert [layer]="currentItemLayer()?.layer"></fm-map-zoom-to-show-alert> | ||||
|           </div> | ||||
|           <div class="card menu-card pt-2"> | ||||
|             <div *ngIf="layers.length>1"> | ||||
|               <select (change)="onLayerChanged($event.target.value)"> | ||||
|                 <option *ngFor="let l of layers;" [value]="l.index"  [selected]="itemLayer.layerIndex == l.index">{{l.name}}</option> | ||||
|               </select> | ||||
|             </div> | ||||
|             <fm-map-layer-legend [showTitle]="layers.length == 1" | ||||
|               [layer]="layer(layers,itemLayer.layerIndex)" [histogramenabled]="true"></fm-map-layer-legend> | ||||
|           </div> | ||||
|         </div> | ||||
|         <div class="card menu-card"> | ||||
|           <h5><span i18n>Date</span>: {{temporalService.selectedDate(itemLayer)}}</h5> | ||||
|           <div class="d-flex justify-content-between"> | ||||
|             <div> | ||||
|               <button  *ngIf="temporalService.hasPrevious(itemLayer)" type="button" class="btn btn-link p-0" (click)="handlePreviousTemporal($event)"> | ||||
|                 <i class="fal fa-arrow-circle-left" aria-hidden="true" i18n-title title="Previous"></i> {{ temporalService.previousDate(itemLayer) }} | ||||
|               </button> | ||||
|             </div> | ||||
|             <div> | ||||
|               <button  *ngIf="temporalService.hasNext(itemLayer)" type="button" class="btn btn-link p-0" (click)="handleNextTemporal($event)"> | ||||
|                 {{ temporalService.nextDate(itemLayer)}} <i class="fal fa-arrow-circle-right" aria-hidden="true" i18n-title title="Next"></i> | ||||
|               </button> | ||||
|             </div> | ||||
|           </div> | ||||
|           <fm-map-zoom-to-show-alert [layer]="currentItemLayer()?.layer"></fm-map-zoom-to-show-alert> | ||||
|           <ul class="p-0 mt-2"> | ||||
|             <li *ngIf="item.isEditable"><a href="#" class="mt-1 me-1" (click)="handleOnEdit(item)"><i class="fal fa-pencil" aria-hidden="true" i18n-title title="Edit"></i> <span i18n>Edit</span></a></li> | ||||
|             <ng-container *ngIf="itemTypeService.isLayer(item)"> | ||||
|               <li *ngIf="!getItemLayer(item,itemLayer.layerIndex)"><a   href="#" (click)="handleAddAsLayer(item,itemLayer.layerIndex)"><i class="fas fa-layer-plus" aria-hidden="true" i18n-title title="Add as layer"></i> <span i18n>Add as overlay</span></a></li> | ||||
|               <li *ngIf="getItemLayer(item,itemLayer.layerIndex)"><a  href="#" (click)="handleRemoveLayer(item,itemLayer.layerIndex)"><i class="fas fa-layer-minus" aria-hidden="true" i18n-title title="Remove overlay"></i> <span i18n>Remove overlay</span></a></li> | ||||
|             </ng-container> | ||||
|             <li><a href="#" (click)="handleGoToChart(item)"><i class="fal fa-line-chart" aria-hidden="true" i18m-title title="Show chart"></i> <span i18n>Show chart</span></a></li> | ||||
|             <li><a href="#" (click)="download($event,item,layers,itemLayer.layerIndex)"><i class="fal fa-download" aria-hidden="true" i18n-title title="Download"></i> <span i18n>Download</span></a></li> | ||||
|           </ul> | ||||
|         </div> | ||||
|         <div class="card menu-card pt-2"> | ||||
|           <div *ngIf="layers.length>1"> | ||||
|             <select (change)="onLayerChanged($event.target.value)"> | ||||
|               <option *ngFor="let l of layers;" [value]="l.index"  [selected]="itemLayer.layerIndex == l.index">{{l.name}}</option> | ||||
|             </select> | ||||
|           </div> | ||||
|           <fm-map-layer-legend [showTitle]="layers.length == 1" | ||||
|             [layer]="layer(layers,itemLayer.layerIndex)" [histogramenabled]="true"></fm-map-layer-legend> | ||||
|         </div> | ||||
|       </div> | ||||
|       <div class="card menu-card"> | ||||
|         <ul class="p-0 mt-2"> | ||||
|           <li *ngIf="item.isEditable"><a href="#" class="mt-1 me-1" (click)="handleOnEdit(item)"><i class="fal fa-pencil" aria-hidden="true" i18n-title title="Edit"></i> <span i18n>Edit</span></a></li> | ||||
|           <ng-container *ngIf="itemTypeService.isLayer(item)"> | ||||
|             <li *ngIf="!getItemLayer(item,itemLayer.layerIndex)"><a   href="#" (click)="handleAddAsLayer(item,itemLayer.layerIndex)"><i class="fas fa-layer-plus" aria-hidden="true" i18n-title title="Add as layer"></i> <span i18n>Add as overlay</span></a></li> | ||||
|             <li *ngIf="getItemLayer(item,itemLayer.layerIndex)"><a  href="#" (click)="handleRemoveLayer(item,itemLayer.layerIndex)"><i class="fas fa-layer-minus" aria-hidden="true" i18n-title title="Remove overlay"></i> <span i18n>Remove overlay</span></a></li> | ||||
|           </ng-container> | ||||
|           <li><a href="#" (click)="handleGoToChart(item)"><i class="fal fa-line-chart" aria-hidden="true" i18m-title title="Show chart"></i> <span i18n>Show chart</span></a></li> | ||||
|         </ul> | ||||
|       </div> | ||||
|       </ng-container> | ||||
|     </div> | ||||
|   </div> | ||||
| </div> | ||||
|   | ||||
| @@ -1,16 +1,15 @@ | ||||
| import { Component, Injectable } from '@angular/core'; | ||||
| import { Location } from '@angular/common'; | ||||
| import { Store } from '@ngrx/store'; | ||||
| import * as mapReducers from '../../reducers/map.reducer'; | ||||
| import { commonReducers, ItemTypeService, IItem } from '@farmmaps/common'; | ||||
| import { Component, Injectable, OnDestroy } from '@angular/core'; | ||||
| import { Router } from '@angular/router'; | ||||
| import { commonReducers, IItem, IItemLinkType, ItemService, ItemTypeService, IUrlType } from '@farmmaps/common'; | ||||
| import { Store } from '@ngrx/store'; | ||||
| import { Subscription } from 'rxjs'; | ||||
| import * as mapActions from '../../actions/map.actions'; | ||||
| import { IItemLayer, ITemporalItemLayer } from '../../models/item.layer'; | ||||
| import * as mapReducers from '../../reducers/map.reducer'; | ||||
| import { TemporalService } from '../../services/temporal.service'; | ||||
| import { ForItemType } from '../for-item/for-itemtype.decorator'; | ||||
| import { AbstractSelectedItemComponent } from '../selected-item/selected-item.component'; | ||||
| import { ITemporalItemLayer} from '../../models/item.layer'; | ||||
| import * as mapActions from '../../actions/map.actions'; | ||||
| import { IItemLayer } from '../../models/item.layer'; | ||||
| import {TemporalService} from '../../services/temporal.service'; | ||||
|  | ||||
|  | ||||
| @ForItemType("vnd.farmmaps.itemtype.temporal") | ||||
| @Injectable() | ||||
| @@ -19,10 +18,15 @@ import {TemporalService} from '../../services/temporal.service'; | ||||
|   templateUrl: './selected-item-temporal.component.html', | ||||
|   styleUrls: ['./selected-item-temporal.component.scss'] | ||||
| }) | ||||
| export class SelectedItemTemporalComponent extends AbstractSelectedItemComponent { | ||||
| export class SelectedItemTemporalComponent extends AbstractSelectedItemComponent implements OnDestroy { | ||||
|   sub: Subscription; | ||||
|  | ||||
|   constructor(store: Store<mapReducers.State | commonReducers.State>, itemTypeService: ItemTypeService, location: Location, router: Router,public temporalService:TemporalService) { | ||||
|     super(store, itemTypeService,location,router); | ||||
|   constructor(store: Store<mapReducers.State | commonReducers.State>, public itemService: ItemService, itemTypeService: ItemTypeService, location: Location, router: Router,public temporalService:TemporalService) { | ||||
|     super(store, itemTypeService,itemService,location,router); | ||||
|   } | ||||
|    | ||||
|   ngOnDestroy(): void { | ||||
|     if (this.sub) this.sub.unsubscribe(); | ||||
|   } | ||||
|  | ||||
|   onLayerChanged(layerIndex: number) { | ||||
| @@ -33,8 +37,6 @@ export class SelectedItemTemporalComponent extends AbstractSelectedItemComponent | ||||
|     return  (this.itemLayer as ITemporalItemLayer)?.selectedItemLayer | ||||
|   } | ||||
|  | ||||
|    | ||||
|  | ||||
|   handleNextTemporal(event:MouseEvent) { | ||||
|     this.store.dispatch(new mapActions.NextTemporal()); | ||||
|     event.preventDefault();     | ||||
| @@ -61,4 +63,13 @@ export class SelectedItemTemporalComponent extends AbstractSelectedItemComponent | ||||
|     this.router.navigate(['/viewer', 'temporal', 'item', item.parentCode, new Date(Date.parse(item.dataDate)).getUTCFullYear()]); | ||||
|     return false; | ||||
|   } | ||||
|    | ||||
|   download(event:MouseEvent,item:IItem,layers:any,layerIndex:number) { | ||||
|     event.stopPropagation(); | ||||
|     event.preventDefault(); | ||||
|     const itemLink : IItemLinkType = {itemcode:item.code,query:`layer=${this.layer(layers,layerIndex).name}`,pathsuffix:"download", validminutes:10} | ||||
|     this.sub = this.itemService.getItemLink(itemLink).subscribe((itemLinkUrl:IUrlType) => {   | ||||
|        window.location.href = itemLinkUrl.url;        | ||||
|     }) | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -2,7 +2,7 @@ import {Component, Injectable, Input, Directive} from '@angular/core'; | ||||
| import {Location} from '@angular/common'; | ||||
| import {Store} from '@ngrx/store'; | ||||
| import * as mapReducers from '../../reducers/map.reducer'; | ||||
| import {AppConfig, commonReducers, IItem, ItemTypeService} from '@farmmaps/common'; | ||||
| import {AppConfig, commonReducers, IItem, ItemService, ItemTypeService} from '@farmmaps/common'; | ||||
| import * as mapActions from '../../actions/map.actions'; | ||||
| import {Router} from '@angular/router'; | ||||
| import { IItemLayer } from '../../models/item.layer'; | ||||
| @@ -15,7 +15,7 @@ export abstract class AbstractSelectedItemComponent { | ||||
|   @Input() parentItem: IItem; | ||||
|   @Input() itemLayer: IItemLayer; | ||||
|   @Input() overlayLayers: Array<IItemLayer>; | ||||
|   constructor(public store: Store<mapReducers.State | commonReducers.State>, public itemTypeService: ItemTypeService, private location: Location, public router: Router) { | ||||
|   constructor(public store: Store<mapReducers.State | commonReducers.State>, public itemTypeService: ItemTypeService, public itemService: ItemService, private location: Location, public router: Router) { | ||||
|   } | ||||
|  | ||||
|   handleOnView(item: IItem) { | ||||
| @@ -37,6 +37,11 @@ export abstract class AbstractSelectedItemComponent { | ||||
|     return false; | ||||
|   } | ||||
|  | ||||
|   handleOnDelete(item: IItem) { | ||||
|     this.itemService.deleteItem(item.code); | ||||
|     return false; | ||||
|   } | ||||
|  | ||||
|   handleAddAsLayer(item: IItem,layerIndex = -1) { | ||||
|     this.store.dispatch(new mapActions.AddLayer(item,layerIndex)); | ||||
|     return false; | ||||
| @@ -76,8 +81,8 @@ export abstract class AbstractSelectedItemComponent { | ||||
| }) | ||||
| export class SelectedItemComponent extends AbstractSelectedItemComponent { | ||||
|  | ||||
|   constructor(store: Store<mapReducers.State | commonReducers.State>, itemTypeService: ItemTypeService, location: Location, router: Router, public config:AppConfig) { | ||||
|     super(store, itemTypeService,location,router); | ||||
|   constructor(store: Store<mapReducers.State | commonReducers.State>, itemTypeService: ItemTypeService, itemService: ItemService, location: Location, router: Router, public config:AppConfig) { | ||||
|     super(store, itemTypeService,itemService,location,router); | ||||
|   } | ||||
|  | ||||
|   getThumbnailUrl(item:IItem):string { | ||||
|   | ||||
| @@ -9,6 +9,7 @@ import { ILayervalue } from '../models/layer.value'; | ||||
| import * as mapActions from '../actions/map.actions'; | ||||
| import {commonActions} from '@farmmaps/common'; | ||||
| import { createSelector, createFeatureSelector } from '@ngrx/store'; | ||||
| import * as _ from 'lodash'; | ||||
|  | ||||
| import {Feature} from 'ol'; | ||||
| import {Geometry} from 'ol/geom'; | ||||
| @@ -47,6 +48,7 @@ export interface State { | ||||
|   query:IQuery, | ||||
|   parentCode: string, | ||||
|   features: Array<Feature<Geometry>>, | ||||
|   featuresBackup: Array<Feature<Geometry>>, | ||||
|   panelVisible: boolean, | ||||
|   panelCollapsed: boolean, | ||||
|   panelExtraWide: boolean, | ||||
| @@ -93,6 +95,7 @@ export const initialState: State = { | ||||
|   query: null, | ||||
|   parentCode: null, | ||||
|   features: [], | ||||
|   featuresBackup: [], | ||||
|   panelVisible: false, | ||||
|   panelCollapsed: false, | ||||
|   panelExtraWide: false, | ||||
| @@ -156,13 +159,15 @@ export function reducer(state = initialState, action: mapActions.Actions | commo | ||||
|       const a = action as mapActions.StartSearchSuccess; | ||||
|       return tassign(state, { | ||||
|         features: a.features, | ||||
|         featuresBackup: [], | ||||
|         inSearch:false | ||||
|       }); | ||||
|     } | ||||
|     case mapActions.SETFEATURES: { | ||||
|       const a = action as mapActions.SetFeatures; | ||||
|       return tassign(state, { | ||||
|         features: a.features | ||||
|         features: a.features, | ||||
|         featuresBackup: [] | ||||
|       }); | ||||
|     } | ||||
|     case mapActions.SELECTFEATURE: { | ||||
| @@ -180,6 +185,7 @@ export function reducer(state = initialState, action: mapActions.Actions | commo | ||||
|         selectedItemLayer: null, | ||||
|         showDataLayerSlide: false, | ||||
|         features:[], | ||||
|         featuresBackup: [], | ||||
|         inSearch:inSearch | ||||
|       }); | ||||
|     } | ||||
| @@ -296,6 +302,7 @@ export function reducer(state = initialState, action: mapActions.Actions | commo | ||||
|       return tassign(state, { | ||||
|         selectedItem: null, | ||||
|         features:[], | ||||
|         featuresBackup: [], | ||||
|         selectedItemLayer:null, | ||||
|         searchCollapsed: !panelVisible, | ||||
|         panelVisible: panelVisible, | ||||
| @@ -332,7 +339,8 @@ export function reducer(state = initialState, action: mapActions.Actions | commo | ||||
|         extent: a.feature.getGeometry().getExtent(), | ||||
|         searchCollapsed: false, | ||||
|         clearEnabled:true, | ||||
|         features:features | ||||
|         features:features, | ||||
|         featuresBackup:[] | ||||
|       }); | ||||
|     } | ||||
|     case mapActions.UPDATEFEATURESUCCESS: { | ||||
| @@ -346,7 +354,7 @@ export function reducer(state = initialState, action: mapActions.Actions | commo | ||||
|           features.push(state.features[i]); | ||||
|         } | ||||
|       } | ||||
|       return tassign(state, { features: features }); | ||||
|       return tassign(state, { features: features, featuresBackup: [] }); | ||||
|     } | ||||
|     case mapActions.EXPANDSEARCH: { | ||||
|       return tassign(state, { searchCollapsed: false }); | ||||
| @@ -391,7 +399,7 @@ export function reducer(state = initialState, action: mapActions.Actions | commo | ||||
|       return tassign(state, {overlayLayers: [], selectedOverlayLayer: null}); | ||||
|     } | ||||
|     case mapActions.CLEARFEATURES: { | ||||
|       return tassign(state, {features: [], selectedFeature: null}); | ||||
|       return tassign(state, {features: [], featuresBackup: [], selectedFeature: null}); | ||||
|     } | ||||
|     case mapActions.SETVISIBILITY: { | ||||
|       const a = action as mapActions.SetVisibility; | ||||
| @@ -509,6 +517,7 @@ export function reducer(state = initialState, action: mapActions.Actions | commo | ||||
|         searchCollapsed: true, | ||||
|         searchMinified: false, | ||||
|         features: [], | ||||
|         featuresBackup: [], | ||||
|         query:initialState.query, | ||||
|         showLayerSwitcher: false, | ||||
|         extent: null, | ||||
| @@ -556,7 +565,8 @@ export function reducer(state = initialState, action: mapActions.Actions | commo | ||||
|           selectedItem: null, | ||||
|           selectedItemLayer: null, | ||||
|           showDataLayerSlide: false, | ||||
|           features:[] | ||||
|           features:[], | ||||
|           featuresBackup:[] | ||||
|          }); | ||||
|       } | ||||
|       if(state.features.length>0)  { | ||||
| @@ -569,7 +579,7 @@ export function reducer(state = initialState, action: mapActions.Actions | commo | ||||
|         if(index>=0) { | ||||
|           const newFeatures = state.features.slice(0); | ||||
|           newFeatures.splice(index,1); | ||||
|           return tassign(state,{features:newFeatures}); | ||||
|           return tassign(state,{features:newFeatures, featuresBackup:[]}); | ||||
|         } | ||||
|       } | ||||
|       return state; | ||||
| @@ -578,6 +588,17 @@ export function reducer(state = initialState, action: mapActions.Actions | commo | ||||
|       const a= action as mapActions.SetPanelExtraWide; | ||||
|       return tassign(state,{panelExtraWide:a.panelExtraWide}); | ||||
|     } | ||||
|     case mapActions.BACKUPFEATURES: { | ||||
|       return tassign(state, { | ||||
|         featuresBackup: _.cloneDeep(state.features) | ||||
|       }); | ||||
|     } | ||||
|     case mapActions.RESTOREFEATURES: { | ||||
|       return tassign(state, { | ||||
|         features: _.cloneDeep(state.featuresBackup), | ||||
|         featuresBackup: [] | ||||
|       }); | ||||
|     } | ||||
|     default: { | ||||
|       return state; | ||||
|     } | ||||
| @@ -637,6 +658,8 @@ export const selectGetExtent = createSelector(selectMapState, getExtent); | ||||
| export const selectGetViewExtent = createSelector(selectMapState, getViewExtent); | ||||
| export const selectGetOverlayLayers = createSelector(selectMapState, getOverlayLayers); | ||||
| export const selectGetBaseLayers = createSelector(selectMapState, getBaseLayers); | ||||
| export const selectGetBaseMaps = createSelector(selectGetBaseLayers, (layers) => layers.filter(layer => layer.item.data.category === "baseMap")); | ||||
| export const selectGetArealMaps = createSelector(selectGetBaseLayers, (layers) => layers.filter(layer => layer.item.data.category === "aerialPhoto").sort((a, b) => a.item.dataDate <= b.item.dataDate ? 1 : -1)); | ||||
| export const selectGetProjection = createSelector(selectMapState, getProjection); | ||||
| export const selectGetSelectedBaseLayer = createSelector(selectMapState, getSelectedBaseLayer); | ||||
| export const selectGetSelectedOverlayLayer = createSelector(selectMapState, getSelectedOverlayLayer); | ||||
|   | ||||
| @@ -8,8 +8,8 @@ | ||||
|     "tslib": "^2.0.0" | ||||
|   }, | ||||
|   "peerDependencies": { | ||||
|     "@angular/common": "^18.2.3", | ||||
|     "@angular/core":  "^18.2.3", | ||||
|     "@angular/common": "18.2.3", | ||||
|     "@angular/core":  "18.2.3", | ||||
|     "cesium": "^1.97.0", | ||||
|     "ol-cesium": ">=2.13.0" | ||||
|   } | ||||
|   | ||||
| @@ -6,9 +6,9 @@ | ||||
|   }, | ||||
|   "peerDependencies": { | ||||
|     "@ng-bootstrap/ng-bootstrap": "^17.0.1", | ||||
|     "@angular/common": "^18.2.3", | ||||
|     "@angular/core": "^18.2.3", | ||||
|     "@angular/forms": "^18.2.3", | ||||
|     "@angular/common": "18.2.3", | ||||
|     "@angular/core": "18.2.3", | ||||
|     "@angular/forms": "18.2.3", | ||||
|     "@ngrx/effects": "^18.0.2", | ||||
|     "@ngrx/router-store": "^18.0.2", | ||||
|     "@ngrx/store": "^18.0.2", | ||||
|   | ||||
| @@ -71,6 +71,8 @@ export const TOGGLENOTIFICATIONMENU = '[AppCommon] ToggleNotificationMenu'; | ||||
|  | ||||
| export const TOGGLEHELPMENU = '[AppCommon] ToggleHelpMenu'; | ||||
|  | ||||
| export const TOGGLESETTINGMENU = '[AppCommon] ToggleSettingMenu'; | ||||
|  | ||||
| export const SETMENUVISIBLE = '[AppCommon] SetMenuVisible'; | ||||
|  | ||||
| export const ONLINE = '[AppCommon] Online'; | ||||
| @@ -81,6 +83,11 @@ export const SETPAGEMODE = '[AppCommon] SetPageMode'; | ||||
|  | ||||
| export const SETUNREADNOTIFICATIONS = '[AppCommon] SetUnreadNotifications'; | ||||
|  | ||||
| export const SWITCHLANGUAGE = '[AppCommon] SwitchLanguage'; | ||||
|  | ||||
| export const SETSETTINGMENUBACKGROUNDCOLOR = '[AppCommon] SetSettingMenuBackgroundColor'; | ||||
|  | ||||
|  | ||||
| export class InitUser implements Action { | ||||
|   readonly type = INITUSER; | ||||
|  | ||||
| @@ -332,6 +339,12 @@ export class ToggleHelpMenu implements Action { | ||||
|   constructor() { } | ||||
| } | ||||
|  | ||||
| export class ToggleSettingMenu implements Action { | ||||
|   readonly type = TOGGLESETTINGMENU; | ||||
|  | ||||
|   constructor() { } | ||||
| } | ||||
|  | ||||
| export class SetMenuVisible implements Action { | ||||
|   readonly type = SETMENUVISIBLE; | ||||
|  | ||||
| @@ -363,6 +376,17 @@ export class SetUnreadNotifications implements Action { | ||||
|  | ||||
| } | ||||
|    | ||||
| export class SwitchLanguage implements Action { | ||||
|   readonly type = SWITCHLANGUAGE; | ||||
|  | ||||
|   constructor(public locale:string) { } | ||||
| } | ||||
|  | ||||
| export class SetSettingMenuBackgroundColor implements Action { | ||||
|   readonly type = SETSETTINGMENUBACKGROUNDCOLOR; | ||||
|  | ||||
|   constructor(public color:string) { } | ||||
| } | ||||
|  | ||||
| export type Actions = OpenModal | ||||
|   | InitRoot | ||||
| @@ -408,7 +432,10 @@ export type Actions = OpenModal | ||||
|   | ToggleAppMenu | ||||
|   | ToggleNotificationMenu | ||||
|   | ToggleHelpMenu | ||||
|   | ToggleSettingMenu | ||||
|   | NotificationEvent | ||||
|   | SetUnreadNotifications; | ||||
|   | SetUnreadNotifications | ||||
|   | SwitchLanguage | ||||
|   | SetSettingMenuBackgroundColor; | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -13,6 +13,7 @@ import { SchemaService } from './services/schema.service'; | ||||
| import { FolderService } from './services/folder.service'; | ||||
| import { TimespanService } from './services/timespan.service'; | ||||
| import { ItemService } from './services/item.service'; | ||||
| import { TaskService } from './services/task.service'; | ||||
| import { AdminService } from './services/admin.service'; | ||||
| import { EventService } from './services/event.service'; | ||||
| import { TypeaheadService } from './services/typeahead.service'; | ||||
| @@ -44,6 +45,7 @@ export { | ||||
|   ItemTypeService, | ||||
|   TimespanService, | ||||
|   ItemService, | ||||
|   TaskService, | ||||
|   AdminService, | ||||
|   EventService, | ||||
|   TypeaheadService, | ||||
|   | ||||
| @@ -34,6 +34,7 @@ import { HasClaimDirective } from './components/has-claim/has-claim.directive'; | ||||
| import { HasPackageDirective } from './components/has-package/has-package.directive'; | ||||
| import { HasRoleDirective } from './components/has-role/has-role.directive'; | ||||
| import { HelpMenuComponent } from './components/help-menu/help-menu.component'; | ||||
| import { SettingMenuComponent } from './components/setting-menu/setting-menu.component'; | ||||
| import { ItemLinkComponent } from './components/item-link/item-link.component'; | ||||
| import { MenuBackgroundComponent } from './components/menu-background/menu-background.component'; | ||||
| import { NotFoundComponent } from './components/not-found/not-found.component'; | ||||
| @@ -104,6 +105,7 @@ export { | ||||
|         AppMenuComponent, | ||||
|         NotificationMenuComponent, | ||||
|         HelpMenuComponent, | ||||
|         SettingMenuComponent, | ||||
|         BackButtonComponent, | ||||
|         ThumbnailComponent, | ||||
|         EditImageModalComponent, | ||||
|   | ||||
| @@ -33,6 +33,7 @@ | ||||
|     <fm-resumable-file-upload></fm-resumable-file-upload> | ||||
|   </ng-container>   | ||||
|   <div class="user-menu apponly"> | ||||
|     <fm-setting-menu [user]="user|async" [showMenu]="settingMenuVisible|async" [backgroundColor]="settingMenuBackgroundColor|async"></fm-setting-menu> | ||||
|     <fm-help-menu [user]="user|async" [showMenu]="helpMenuVisible|async"></fm-help-menu> | ||||
|     <fm-notification-menu [user]="user|async" [unread]="unreadNotifications|async" [showMenu]="notificationMenuVisible|async"></fm-notification-menu> | ||||
|     <fm-app-menu [user]="user|async" [showMenu]="appMenuVisible|async"></fm-app-menu> | ||||
|   | ||||
| @@ -119,7 +119,7 @@ body { background: #f1f1f1; line-height: 18px; user-select:none;font-family: Lat | ||||
|   max-height:0em; | ||||
| } | ||||
|  | ||||
| fm-help-menu,fm-app-menu,fm-user-menu,fm-notification-menu { | ||||
| fm-help-menu,fm-app-menu,fm-user-menu,fm-notification-menu,fm-setting-menu { | ||||
|   display: inline-block; | ||||
|   margin-left: 1rem; | ||||
| } | ||||
|   | ||||
| @@ -45,10 +45,12 @@ export class AppComponent implements OnInit, OnDestroy { | ||||
|   public accountMenuVisible: Observable<boolean> = this.store$.select(appReducers.SelectGetAccountMenuVisible); | ||||
|   public appMenuVisible: Observable<boolean> = this.store$.select(appReducers.SelectGetAppMenuVisible); | ||||
|   public notificationMenuVisible: Observable<boolean> = this.store$.select(appReducers.SelectGetNotificationMenuVisible); | ||||
|   public settingMenuVisible: Observable<boolean> = this.store$.select(appReducers.SelectGetSettingMenuVisible); | ||||
|   public helpMenuVisible: Observable<boolean> = this.store$.select(appReducers.SelectGetHelpMenuVisible); | ||||
|   public unreadNotifications: Observable<number> = this.store$.select(appReducers.SelectgetUnreadNotifications); | ||||
|   public user: Observable<IUser> = this.store$.select(appReducers.SelectGetUser); | ||||
|   public isPageMode: Observable<boolean> = this.store$.select(appReducers.SelectGetIsPageMode); | ||||
|   public settingMenuBackgroundColor: Observable<string> = this.store$.select(appReducers.SelectGetSettingMenuBackgroundColor); | ||||
|   @Input() showUploadProgress = true; | ||||
|  | ||||
|   constructor( | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| import {Component, HostListener} from '@angular/core'; | ||||
| import {Location} from "@angular/common"; | ||||
| import { DeviceService} from '../../services/device.service'; | ||||
| import { Location } from "@angular/common"; | ||||
| import { Component, EventEmitter, HostListener, Output } from '@angular/core'; | ||||
| import { DeviceService } from '../../services/device.service'; | ||||
|  | ||||
| @Component({ | ||||
|   selector: 'fm-back-button', | ||||
| @@ -8,16 +8,18 @@ import { DeviceService} from '../../services/device.service'; | ||||
|   styleUrls: ['./back-button.component.scss'] | ||||
| }) | ||||
| export class BackButtonComponent { | ||||
|   @Output() beforeLocationBack = new EventEmitter(); | ||||
|  | ||||
|   @HostListener('click') | ||||
|   onBackClicked() { | ||||
|     this.beforeLocationBack.emit(); | ||||
|     this.location.back(); | ||||
|   } | ||||
|  | ||||
|   constructor(private location: Location,private deviceService:DeviceService) { } | ||||
|   constructor(private location: Location,private deviceService:DeviceService) {     | ||||
|   } | ||||
|  | ||||
|   public show() { | ||||
|     return !this.deviceService.IsMobile(); | ||||
|   } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -11,7 +11,7 @@ | ||||
|         <i class="fal fa-image"></i> | ||||
|         <div i18n>No image selected</div> | ||||
|       </div> | ||||
|       <image-cropper #imageCropper | ||||
|       <image-cropper #imageCropper output="base64"  | ||||
|       [imageChangedEvent]="imageChangedEvent" | ||||
|       [maintainAspectRatio]="true" | ||||
|       [format]="imageType" | ||||
|   | ||||
| @@ -4,6 +4,7 @@ div.resumable-file-upload { | ||||
|   bottom: 0px; | ||||
|   width: 300px; | ||||
|   max-height: 250px; | ||||
|   z-index: 1; | ||||
|   /*z-index:2000 !important;*/ | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -0,0 +1,8 @@ | ||||
| <div> | ||||
|     <div (click)="toggle($event)" class="rounded-circle menu-button hidden" [style.background-color]="backgroundColor" [ngClass]="{'hidden':!user || noContent}"> | ||||
|         <span i18n-title title="Settings"><i class="fas fa-gear" aria-hidden="true"></i></span> | ||||
|         <div class="menu hidden" [ngClass]="{'hidden':!showMenu}">                                      | ||||
|             <router-outlet name="setting-menu" (activate)="activateRoute()" (deactivate)="deActivateRoute()"></router-outlet>             | ||||
|        </div> | ||||
|     </div> | ||||
| </div> | ||||
| @@ -0,0 +1,80 @@ | ||||
| .menu-button { | ||||
|     background-color: gray;   | ||||
|     display: inline-block; | ||||
|     width: 2.5em; | ||||
|     height: 2.5em; | ||||
|     line-height: 2.5em; | ||||
|     text-align: center; | ||||
|     font-size: 1rem; | ||||
|     position: relative; | ||||
| } | ||||
|  | ||||
| div.menu-button > span { | ||||
|     color:white; | ||||
| } | ||||
|  | ||||
| .menu { | ||||
|     max-height: calc( 100vh - 4rem); | ||||
|     //transition: max-height 0.2s; | ||||
|     overflow: hidden; | ||||
|     box-shadow: 0 0 20px rgba(0,0,0,.3); | ||||
|     position: fixed; | ||||
|     top: 3.4rem; | ||||
|     right:0.5rem; | ||||
|     left:0.5rem; | ||||
|     background-color: #fff; | ||||
|     border-radius: 0.25rem; | ||||
|     padding: 0.5rem; | ||||
|     z-index: 3; | ||||
| } | ||||
|  | ||||
| :host-context(.fullscreen)  .menu  { | ||||
|     top:4em; | ||||
| } | ||||
|  | ||||
| .card {       | ||||
|     padding:0.5rem; | ||||
|     min-width: 10rem;           | ||||
| } | ||||
|  | ||||
| .card-body { | ||||
|     text-align: left; | ||||
| } | ||||
|  | ||||
| .hidden { | ||||
|     max-height: 0;    | ||||
| } | ||||
|  | ||||
| .menu.hidden { | ||||
|     padding: 0; | ||||
| } | ||||
|  | ||||
| .menu-button.hidden { | ||||
|     overflow: hidden; | ||||
| } | ||||
|  | ||||
|  | ||||
| @media screen and (min-width: 44rem)  { | ||||
|     .menu { | ||||
|         position: absolute; | ||||
|         top: 3rem; | ||||
|         right:0; | ||||
|         left: unset; | ||||
|         max-width: 30em; | ||||
|     } | ||||
|  | ||||
|     :host-context(.fullscreen)  .menu  { | ||||
|         top: 3rem; | ||||
|     } | ||||
| }     | ||||
|  | ||||
| .unread { | ||||
|     display: block; | ||||
|     position: absolute; | ||||
|     top:-0.5em; | ||||
|     right: -0.5em; | ||||
| } | ||||
|  | ||||
| .unread.hidden { | ||||
|     display: none; | ||||
| } | ||||
| @@ -0,0 +1,38 @@ | ||||
| import { Input } from '@angular/core'; | ||||
| import { Component, OnInit } from '@angular/core'; | ||||
|  | ||||
| import { IUser } from '../../models/user'; | ||||
| import {Store} from '@ngrx/store'; | ||||
| import * as appReducers from '../../reducers/app-common.reducer'; | ||||
| import * as appActions from '../../actions/app-common.actions'; | ||||
|  | ||||
| @Component({ | ||||
|   selector: 'fm-setting-menu', | ||||
|   templateUrl: './setting-menu.component.html', | ||||
|   styleUrls: ['./setting-menu.component.scss'] | ||||
| }) | ||||
| export class SettingMenuComponent implements OnInit { | ||||
|    | ||||
|   @Input() user:IUser; | ||||
|   @Input() showMenu:boolean; | ||||
|   @Input() backgroundColor:string; | ||||
|   public noContent = true; | ||||
|  | ||||
|   constructor(private store: Store<appReducers.State>) { } | ||||
|  | ||||
|   ngOnInit(): void { | ||||
|   } | ||||
|  | ||||
|   toggle(event:MouseEvent) { | ||||
|     event.stopPropagation(); | ||||
|     this.store.dispatch(new appActions.ToggleSettingMenu()); | ||||
|   }  | ||||
|  | ||||
|   activateRoute() { | ||||
|     this.noContent=false; | ||||
|   } | ||||
|  | ||||
|   deActivateRoute() { | ||||
|     this.noContent=true; | ||||
|   } | ||||
| } | ||||
| @@ -1,4 +1,4 @@ | ||||
| import { Injectable } from '@angular/core'; | ||||
| import { Injectable, Inject, LOCALE_ID } from '@angular/core'; | ||||
| import { Router } from '@angular/router'; | ||||
| import { OAuthService,UserInfo } from 'angular-oauth2-oidc'; | ||||
| import { Store } from '@ngrx/store'; | ||||
| @@ -16,6 +16,7 @@ import {StateSerializerService} from '../services/state-serializer.service'; | ||||
|  | ||||
| @Injectable() | ||||
| export class AppCommonEffects { | ||||
|   locale: string; | ||||
|  | ||||
|   login$ =  createEffect(() => this.actions$.pipe( | ||||
|     ofType(appCommonActions.LOGIN), | ||||
| @@ -47,11 +48,27 @@ export class AppCommonEffects { | ||||
|     first(), | ||||
|     switchMap((action) => { | ||||
|         return zip(this.userService$.getCurrentUser(),from(this.oauthService$.loadUserProfile())).pipe( | ||||
|         switchMap(([user,userInfo]) => {return of(new appCommonActions.InitUserSuccess(user,userInfo as UserInfo))} ), | ||||
|         switchMap(([user,userInfo]) => { | ||||
|           if (location.hostname === 'localhost' || user.language === undefined || user.language === this.locale)  | ||||
|           { | ||||
|             return of(new appCommonActions.InitUserSuccess(user,userInfo as UserInfo)) | ||||
|           } | ||||
|           return of(new appCommonActions.SwitchLanguage(user.language)) | ||||
|         }), | ||||
|         catchError(error => of(new appCommonActions.Fail(error)))) | ||||
|     } | ||||
|   ))); | ||||
|      | ||||
|  | ||||
|   switchLanguage$ = createEffect(() => this.actions$.pipe( | ||||
|     ofType(appCommonActions.SWITCHLANGUAGE), | ||||
|     switchMap((action) => { | ||||
|       const a = action as appCommonActions.SwitchLanguage; | ||||
|       if (location.href.includes(`/${this.locale}/`)) { | ||||
|         const newPath = location.href.replace(`/${this.locale}/`, `/${a.locale}/`); | ||||
|         location.replace(newPath); | ||||
|       } | ||||
|       return of(undefined); | ||||
|     })),{ dispatch:false}); | ||||
|  | ||||
|   initUserPackages$ =  createEffect(() => this.actions$.pipe( | ||||
|     ofType(appCommonActions.INITUSERPACKAGES), | ||||
| @@ -134,15 +151,22 @@ export class AppCommonEffects { | ||||
|       withLatestFrom(this.store$.select(appCommonReducers.selectGetItemTypes)), | ||||
|       switchMap(([action, itemtypes]) => { | ||||
|         const a = action as appCommonActions.EditItem; | ||||
|         var editor =  "property"; | ||||
|         var editor = "property"; | ||||
|         if(a.item.itemType) { | ||||
|           const itemType = itemtypes[a.item.itemType]; | ||||
|           var editor = itemType && itemType.editor ? itemType.editor : editor;   | ||||
|         } | ||||
|       this.router$.navigate(['/editor',editor,'item', a.item.code]) | ||||
|       return []; | ||||
|     } | ||||
|   ))); | ||||
|         if (editor == 'croppingscheme') {  | ||||
|           // Exeception: no 'item' in route | ||||
|           this.router$.navigate(['/editor', editor, a.item.code]) | ||||
|         } | ||||
|         else { | ||||
|           this.router$.navigate(['/editor', editor, 'item', a.item.code]) | ||||
|         } | ||||
|         return []; | ||||
|       } | ||||
|     ) | ||||
|   )); | ||||
|  | ||||
|   viewItem$ =  createEffect(() => this.actions$.pipe( | ||||
|     ofType(appCommonActions.VIEWITEM), | ||||
| @@ -201,7 +225,8 @@ export class AppCommonEffects { | ||||
|  | ||||
|  | ||||
|  | ||||
|   constructor(private actions$: Actions, private store$: Store<appCommonReducers.State>, private oauthService$: OAuthService, private itemService$: ItemService, private folderService$:FolderService, private userService$: UserService, private router$: Router, private stateSerializerService$:StateSerializerService) { | ||||
|   constructor(private actions$: Actions, private store$: Store<appCommonReducers.State>, private oauthService$: OAuthService, private itemService$: ItemService, private folderService$:FolderService, private userService$: UserService, private router$: Router, private stateSerializerService$:StateSerializerService, @Inject(LOCALE_ID) locale: string) { | ||||
|     this.locale = locale; | ||||
|     store$.dispatch(new appCommonActions.LoadItemTypes()); | ||||
|   } | ||||
| } | ||||
| } | ||||
| @@ -25,6 +25,8 @@ export class Item implements IItem { | ||||
|   public state?: number; | ||||
|   public data?:any; | ||||
|   public isEditable?:boolean; | ||||
|   public owner?: string; | ||||
|   public fullPath?: string; | ||||
|  | ||||
|   constructor() {   | ||||
|   } | ||||
|   | ||||
| @@ -1,6 +1,7 @@ | ||||
|  | ||||
| export interface IItemTask  { | ||||
|   code?: string; | ||||
|   workflowCode?: string; | ||||
|   taskType?: string; | ||||
|   attributes?: any; | ||||
|   message?: string, | ||||
| @@ -11,6 +12,7 @@ export interface IItemTask  { | ||||
|  | ||||
| export class ItemTask implements IItemTask { | ||||
|   public code?:string; | ||||
|   public workflowCode?: string; | ||||
|   public taskType?: string; | ||||
|   public attributes?: any; | ||||
|   public message?: string; | ||||
| @@ -18,6 +20,6 @@ export class ItemTask implements IItemTask { | ||||
|   public started?: Date; | ||||
|   public finished?: Date; | ||||
|  | ||||
|   constructor() {   | ||||
|   constructor() { | ||||
|   } | ||||
| } | ||||
| } | ||||
|   | ||||
| @@ -11,4 +11,5 @@ export interface IListItem { | ||||
|     size?: number; | ||||
|     state?: number; | ||||
|     thumbnail?: boolean; | ||||
|     owner?: string; | ||||
| } | ||||
|   | ||||
| @@ -26,9 +26,11 @@ export interface State { | ||||
|   appMenuVisible: boolean, | ||||
|   notificationMenuVisible: boolean, | ||||
|   helpMenuVisible: boolean, | ||||
|   settingMenuVisible: boolean, | ||||
|   unreadNotifications: number, | ||||
|   isOnline: boolean, | ||||
|   isPageMode:boolean | ||||
|   isPageMode:boolean, | ||||
|   settingMenuBackgroundColor:string | ||||
| } | ||||
|  | ||||
| export const initialState: State = { | ||||
| @@ -47,9 +49,11 @@ export const initialState: State = { | ||||
|   appMenuVisible: false, | ||||
|   notificationMenuVisible: false, | ||||
|   helpMenuVisible: false, | ||||
|   settingMenuVisible: false, | ||||
|   unreadNotifications: 0, | ||||
|   isOnline: true, | ||||
|   isPageMode: true | ||||
|   isPageMode: true, | ||||
|   settingMenuBackgroundColor:'rgb(128, 128, 128)' | ||||
| } | ||||
|  | ||||
| export function reducer(state = initialState, action: appCommonActions.Actions ): State { | ||||
| @@ -106,26 +110,29 @@ export function reducer(state = initialState, action: appCommonActions.Actions ) | ||||
|       }); | ||||
|     } | ||||
|     case appCommonActions.TOGGLEMENU: { | ||||
|       return tassign(state, { menuVisible: !state.menuVisible,accountMenuVisible:!state.menuVisible?false:state.accountMenuVisible,appMenuVisible:!state.menuVisible?false:state.appMenuVisible,notificationMenuVisible:!state.menuVisible?false:state.notificationMenuVisible,helpMenuVisible:!state.menuVisible?false:state.helpMenuVisible }); | ||||
|       return tassign(state, { menuVisible: !state.menuVisible,accountMenuVisible:!state.menuVisible?false:state.accountMenuVisible,appMenuVisible:!state.menuVisible?false:state.appMenuVisible,notificationMenuVisible:!state.menuVisible?false:state.notificationMenuVisible,helpMenuVisible:!state.menuVisible?false:state.helpMenuVisible,settingMenuVisible:!state.menuVisible?false:state.settingMenuVisible }); | ||||
|     } | ||||
|     case appCommonActions.TOGGLEACCOUNTMENU: { | ||||
|       return tassign(state, { accountMenuVisible: !state.accountMenuVisible,appMenuVisible:false,notificationMenuVisible:false,helpMenuVisible:false }); | ||||
|       return tassign(state, { accountMenuVisible: !state.accountMenuVisible,appMenuVisible:false,notificationMenuVisible:false,helpMenuVisible:false,settingMenuVisible:false }); | ||||
|     } | ||||
|     case appCommonActions.TOGGLEAPPMENU: { | ||||
|       return tassign(state, { appMenuVisible: !state.appMenuVisible,accountMenuVisible:false,notificationMenuVisible:false,helpMenuVisible:false }); | ||||
|       return tassign(state, { appMenuVisible: !state.appMenuVisible,accountMenuVisible:false,notificationMenuVisible:false,helpMenuVisible:false,settingMenuVisible:false }); | ||||
|     } | ||||
|     case appCommonActions.TOGGLENOTIFICATIONMENU: { | ||||
|       return tassign(state, { notificationMenuVisible : !state.notificationMenuVisible,accountMenuVisible:false,appMenuVisible:false,helpMenuVisible:false }); | ||||
|       return tassign(state, { notificationMenuVisible : !state.notificationMenuVisible,accountMenuVisible:false,appMenuVisible:false,helpMenuVisible:false,settingMenuVisible:false }); | ||||
|     } | ||||
|     case appCommonActions.TOGGLEHELPMENU: { | ||||
|       return tassign(state, { helpMenuVisible : !state.helpMenuVisible,accountMenuVisible:false,appMenuVisible:false,notificationMenuVisible:false }); | ||||
|       return tassign(state, { helpMenuVisible : !state.helpMenuVisible,accountMenuVisible:false,appMenuVisible:false,notificationMenuVisible:false,settingMenuVisible:false }); | ||||
|     } | ||||
|     case appCommonActions.TOGGLESETTINGMENU: { | ||||
|       return tassign(state, { settingMenuVisible : !state.settingMenuVisible,accountMenuVisible:false,appMenuVisible:false,notificationMenuVisible:false,helpMenuVisible:false }); | ||||
|     } | ||||
|     case appCommonActions.ESCAPE: { | ||||
|       return tassign(state, { menuVisible: false,accountMenuVisible:false,appMenuVisible: false,notificationMenuVisible:false,helpMenuVisible:false }); | ||||
|       return tassign(state, { menuVisible: false,accountMenuVisible:false,appMenuVisible: false,notificationMenuVisible:false,helpMenuVisible:false,settingMenuVisible:false }); | ||||
|     } | ||||
|     case appCommonActions.SETMENUVISIBLE: { | ||||
|       const a = action as appCommonActions.SetMenuVisible; | ||||
|       return tassign(state, { menuVisible: a.visible,accountMenuVisible:a.visible?false:state.accountMenuVisible,appMenuVisible:a.visible?false:state.appMenuVisible,notificationMenuVisible:a.visible?false:state.notificationMenuVisible,helpMenuVisible:a.visible?false:state.helpMenuVisible }); | ||||
|       return tassign(state, { menuVisible: a.visible,accountMenuVisible:a.visible?false:state.accountMenuVisible,appMenuVisible:a.visible?false:state.appMenuVisible,notificationMenuVisible:a.visible?false:state.notificationMenuVisible,helpMenuVisible:a.visible?false:state.helpMenuVisible,settingMenuVisible:a.visible?false:state.settingMenuVisible }); | ||||
|     } | ||||
|     case appCommonActions.INITUSERPACKAGESSUCCESS:{ | ||||
|       const a = action as appCommonActions.InitUserPackagesSuccess; | ||||
| @@ -182,6 +189,10 @@ export function reducer(state = initialState, action: appCommonActions.Actions ) | ||||
|       const a = action as appCommonActions.SetUnreadNotifications; | ||||
|       return tassign(state,{unreadNotifications:a.unread}); | ||||
|     } | ||||
|     case appCommonActions.SETSETTINGMENUBACKGROUNDCOLOR: { | ||||
|       const a = action as appCommonActions.SetSettingMenuBackgroundColor; | ||||
|       return tassign(state,{settingMenuBackgroundColor:a.color}); | ||||
|     }     | ||||
|     default: { | ||||
|       return state; | ||||
|     } | ||||
| @@ -203,9 +214,11 @@ export const getAccountMenuVisible = (state: State) => state.accountMenuVisible; | ||||
| export const getAppMenuVisible = (state: State) => state.appMenuVisible; | ||||
| export const getNotificationMenuVisible = (state: State) => state.notificationMenuVisible; | ||||
| export const getHelpMenuVisible = (state: State) => state.helpMenuVisible; | ||||
| export const getSettingMenuVisible = (state: State) => state.settingMenuVisible; | ||||
| export const getUnreadNotifications = (state: State) => state.unreadNotifications; | ||||
| export const getIsOnline = (state: State) => state.isOnline; | ||||
| export const getIsPageMode = (state: State) => state.isPageMode; | ||||
| export const getSettingMenuBackgroundColor = (state: State) => state.settingMenuBackgroundColor; | ||||
|  | ||||
| export const selectAppCommonState = createFeatureSelector<State>(MODULE_NAME); | ||||
|  | ||||
| @@ -227,9 +240,9 @@ export const SelectGetAccountMenuVisible = createSelector(selectAppCommonState,g | ||||
| export const SelectGetAppMenuVisible = createSelector(selectAppCommonState,getAppMenuVisible); | ||||
| export const SelectGetNotificationMenuVisible = createSelector(selectAppCommonState,getNotificationMenuVisible); | ||||
| export const SelectGetHelpMenuVisible = createSelector(selectAppCommonState,getHelpMenuVisible); | ||||
| export const SelectGetSettingMenuVisible = createSelector(selectAppCommonState,getSettingMenuVisible); | ||||
| export const SelectgetUnreadNotifications = createSelector(selectAppCommonState,getUnreadNotifications); | ||||
|  | ||||
| export const SelectGetIsOnline = createSelector(selectAppCommonState,getIsOnline); | ||||
| export const SelectGetIsPageMode = createSelector(selectAppCommonState,getIsPageMode); | ||||
|  | ||||
|  | ||||
| export const SelectGetSettingMenuBackgroundColor= createSelector(selectAppCommonState,getSettingMenuBackgroundColor); | ||||
|   | ||||
| @@ -52,4 +52,20 @@ export class AdminService { | ||||
|   postItemTask(item: IItem, task: IItemTask): Observable<IItemTask> { | ||||
|     return this.httpClient.post<IItemTask>(`${this.ApiEndpoint()}/api/v1/admin/${item.code}/tasks`, task); | ||||
|   } | ||||
|  | ||||
|   getFileStorageOverview(): Observable<any> { | ||||
|     return this.httpClient.get<any>(`${this.ApiEndpoint()}/api/v1/admin/filestorage/folderinfo/overview`); | ||||
|   } | ||||
|  | ||||
|   getFileStorageInfo(user: string): Observable<any> { | ||||
|     return this.httpClient.get<any>(`${this.ApiEndpoint()}/api/v1/admin/filestorage/folderinfo/${user}`); | ||||
|   } | ||||
|  | ||||
|   getFileStorageLog(): Observable<any> { | ||||
|     return this.httpClient.get<any>(`${this.ApiEndpoint()}/api/v1/admin/filestorage/folderinfo/log`); | ||||
|   } | ||||
|  | ||||
|   validateEmail(user: IUser) { | ||||
|     return this.httpClient.post(`${this.ApiEndpoint()}/api/v1/admin/user/${user.code}/validateemail`, user); | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -1,14 +1,12 @@ | ||||
| import { Injectable } from '@angular/core'; | ||||
| import { Observable } from 'rxjs'; | ||||
| import { map } from 'rxjs/operators'; | ||||
| import { IItemType } from '../models/item.type'; | ||||
| import { IItemLinkType } from '../models/itemlink.type'; | ||||
| import { IUrlType } from '../models/url.type'; | ||||
| import { IItem } from '../models/item'; | ||||
| import { IJsonline } from '../models/json-line'; | ||||
| import { IItemTask } from '../models/itemTask'; | ||||
| import { HttpClient, HttpParams, HttpHeaders } from "@angular/common/http"; | ||||
| import { AppConfig } from "../shared/app.config"; | ||||
| import {Injectable} from '@angular/core'; | ||||
| import {Observable} from 'rxjs'; | ||||
| import {IItemType} from '../models/item.type'; | ||||
| import {IItemLinkType} from '../models/itemlink.type'; | ||||
| import {IItem} from '../models/item'; | ||||
| import {IJsonline} from '../models/json-line'; | ||||
| import {IItemTask} from '../models/itemTask'; | ||||
| import {HttpClient, HttpHeaders, HttpParams} from '@angular/common/http'; | ||||
| import {AppConfig} from '../shared/app.config'; | ||||
| import {ItemTypeService} from './itemtype.service'; | ||||
| import {IListItem} from '../models/list.item'; | ||||
|  | ||||
| @@ -81,7 +79,8 @@ export class ItemService { | ||||
|  | ||||
|   getItemList(itemType?: string, dataFilter?: any, level?: number, atItemLocationItemCode?: string, | ||||
|     indexed?: boolean, validToday?: boolean,tags?:string,crs?:string, startDate?: Date, endDate?: Date, | ||||
|     skip?: number, take?: number, sourceTask?: string): Observable<IItem[]> { | ||||
|     skip?: number, take?: number, sourceTask?: string, exactMatchStartOrEndDate?: boolean, owner?:string, | ||||
|     includeFullpath?: boolean): Observable<IItem[]> { | ||||
|     let params = new HttpParams(); | ||||
|     if(itemType)  params = params.append("it", itemType); | ||||
|     if(dataFilter) params = params.append("df", JSON.stringify(dataFilter)); | ||||
| @@ -96,20 +95,29 @@ export class ItemService { | ||||
|     if (sourceTask) params = params.append("sourceTask", sourceTask); | ||||
|     if(skip) params = params.append("skip", skip); | ||||
|     if(take) params = params.append("take", take); | ||||
|     if(exactMatchStartOrEndDate !== undefined) params = params.append("exactMatchStartOrEndDate", exactMatchStartOrEndDate); | ||||
|     if(owner) params = params.append("owner", owner); | ||||
|     if(includeFullpath) params = params.append("includeFullpath",includeFullpath?"true":"false"); | ||||
|     return this.httpClient.get<IItem[]>(`${this.ApiEndpoint()}/api/v1/items/`, { params: params }); | ||||
|   } | ||||
|    | ||||
|   getItemListCount(itemType: string, startDate?: Date, endDate?: Date, sourceTask?: string): Observable<number> { | ||||
|  | ||||
|   getItemListCount(itemType: string, startDate?: Date, endDate?: Date, sourceTask?: string, | ||||
|     indexed?: boolean, exactMatchStartOrEndDate?: boolean, owner?:string): Observable<number> { | ||||
|     let params = new HttpParams(); | ||||
|     params = params.append("it", itemType); | ||||
|     if (sourceTask) params = params.append("sourceTask", sourceTask); | ||||
|     if (startDate) params = params.append("sDate", startDate.toISOString()); | ||||
|     if (endDate) params = params.append("eDate", endDate.toISOString()); | ||||
|     if(indexed) params = params.append("ind",indexed?"true":"false"); | ||||
|     if(exactMatchStartOrEndDate !== undefined) params = params.append("exactMatchStartOrEndDate", exactMatchStartOrEndDate); | ||||
|     if(owner) params = params.append("owner", owner); | ||||
|     return this.httpClient.get<number>(`${this.ApiEndpoint()}/api/v1/items/count`, { params: params }); | ||||
|   } | ||||
|  | ||||
|   getChildItemList(parentcode: string, itemType?: string, dataFilter?: any, level = 1, deep = true, | ||||
|                    startDate?: Date, endDate?: Date, skip?: number, take?: number): Observable<IItem[]> { | ||||
|                    startDate?: Date, endDate?: Date, skip?: number, take?: number, | ||||
|                    exactMatchStartOrEndDate?: boolean, owner?:string, indexed?: boolean, | ||||
|                   atItemLocationItemCode?: string): Observable<IItem[]> { | ||||
|     let params = new HttpParams(); | ||||
|     if(itemType != null) { | ||||
|       params = params.append("it", itemType); | ||||
| @@ -121,13 +129,19 @@ export class ItemService { | ||||
|     params = params.append("deep", deep.toString()); | ||||
|     if (startDate) params = params.append("sDate", startDate.toISOString()); | ||||
|     if (endDate) params = params.append("eDate", endDate.toISOString()); | ||||
|     if(exactMatchStartOrEndDate !== undefined) params = params.append("exactMatchStartOrEndDate", exactMatchStartOrEndDate); | ||||
|     if(owner) params = params.append("owner", owner); | ||||
|  | ||||
|     if(skip) params = params.append("skip", skip); | ||||
|     if(take) params = params.append("take", take); | ||||
|     if(indexed) params = params.append("ind",indexed?"true":"false"); | ||||
|     if(atItemLocationItemCode) params = params.append("ail",atItemLocationItemCode); | ||||
|     return this.httpClient.get<IItem[]>(`${this.ApiEndpoint()}/api/v1/items/${parentcode}/children`, { params: params }); | ||||
|   } | ||||
|  | ||||
|   getChildItemListCount(parentcode: string, itemType?: string,dataFilter?: any): Observable<number> { | ||||
|   getChildItemListCount(parentcode: string, itemType?: string,dataFilter?: any, | ||||
|                         startDate?: Date, endDate?: Date, exactMatchStartOrEndDate?: boolean, owner?:string, | ||||
|                         indexed?: boolean): Observable<number> { | ||||
|     let params = new HttpParams(); | ||||
|     if(itemType != null) { | ||||
|       params = params.append("it", itemType); | ||||
| @@ -135,6 +149,11 @@ export class ItemService { | ||||
|     if (dataFilter != null) { | ||||
|       params = params.append("df", JSON.stringify(dataFilter)); | ||||
|     } | ||||
|     if (startDate) params = params.append("sDate", startDate.toISOString()); | ||||
|     if (endDate) params = params.append("eDate", endDate.toISOString()); | ||||
|     if(exactMatchStartOrEndDate !== undefined) params = params.append("exactMatchStartOrEndDate", exactMatchStartOrEndDate); | ||||
|     if(owner) params = params.append("owner", owner); | ||||
|     if(indexed) params = params.append("ind",indexed?"true":"false"); | ||||
|     return this.httpClient.get<number>(`${this.ApiEndpoint()}/api/v1/items/${parentcode}/children/count`, { params: params }); | ||||
|   } | ||||
|  | ||||
|   | ||||
| @@ -15,37 +15,37 @@ export class ItemTypeService { | ||||
|  | ||||
|      getIcon(itemType: string) { | ||||
|        let icon = "fal fa-file"; | ||||
|        if (this.itemTypes[itemType]) icon = this.itemTypes[itemType].icon; | ||||
|        if (this.itemTypes && this.itemTypes[itemType]) icon = this.itemTypes[itemType].icon; | ||||
|        return icon; | ||||
|      } | ||||
|  | ||||
|      getColor(itemType: string) { | ||||
|        let color = "#000000"; | ||||
|        if (this.itemTypes[itemType]) color = this.itemTypes[itemType].iconColor; | ||||
|        if (this.itemTypes && this.itemTypes[itemType]) color = this.itemTypes[itemType].iconColor; | ||||
|        return color; | ||||
|      } | ||||
|  | ||||
|      getExtraAttributes(itemType: string) { | ||||
|       let extraAttributes = null; | ||||
|       if (this.itemTypes[itemType] && this.itemTypes[itemType].extraAttributes) extraAttributes = this.itemTypes[itemType].extraAttributes; | ||||
|       if (this.itemTypes && this.itemTypes[itemType] && this.itemTypes[itemType]?.extraAttributes) extraAttributes = this.itemTypes[itemType]?.extraAttributes; | ||||
|       return extraAttributes; | ||||
|     } | ||||
|  | ||||
|     getSchema(itemType: string): string { | ||||
|       let schema = null; | ||||
|       if (this.itemTypes[itemType]) schema = this.itemTypes[itemType].schema; | ||||
|       if (this.itemTypes && this.itemTypes[itemType]) schema = this.itemTypes[itemType].schema; | ||||
|       return schema; | ||||
|     } | ||||
|  | ||||
|      hasViewer(item: IItem) { | ||||
|         const itemType: string = item.itemType; | ||||
|         if (this.itemTypes[itemType]) return this.itemTypes[itemType].viewer !== undefined; | ||||
|         if (this.itemTypes && this.itemTypes[itemType]) return this.itemTypes[itemType].viewer !== undefined; | ||||
|         return false; | ||||
|       } | ||||
|  | ||||
|       hasEditor(item: IItem) { | ||||
|         const itemType: string = item.itemType; | ||||
|         if (this.itemTypes[itemType]) return this.itemTypes[itemType].editor !== undefined; | ||||
|         if (this.itemTypes && this.itemTypes[itemType]) return this.itemTypes[itemType].editor !== undefined; | ||||
|         return false; | ||||
|       } | ||||
|  | ||||
|   | ||||
							
								
								
									
										40
									
								
								projects/common/src/fm/services/task.service.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								projects/common/src/fm/services/task.service.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,40 @@ | ||||
| import {Injectable} from '@angular/core'; | ||||
| import {HttpClient, HttpParams} from '@angular/common/http'; | ||||
| import {AppConfig} from '../shared/app.config'; | ||||
|  | ||||
| @Injectable({ | ||||
|   providedIn: 'root', | ||||
| }) | ||||
| export class TaskService { | ||||
|   constructor(public httpClient: HttpClient, public appConfig: AppConfig) { | ||||
|   } | ||||
|  | ||||
|   ApiEndpoint() { | ||||
|     return this.appConfig.getConfig("apiEndPoint"); | ||||
|   } | ||||
|  | ||||
|   getTask(taskCode: string) { | ||||
|     return this.httpClient.get<any>(`${this.appConfig.getConfig('apiEndPoint')}/api/v1/tasks/${taskCode}`) | ||||
|   } | ||||
|  | ||||
|   getTasks(workflowCode: string, itemCode: string = null, taskType: string = null, skip = 0, take = 25) { | ||||
|     let params = new HttpParams(); | ||||
|  | ||||
|     if (workflowCode) { | ||||
|       params = params.append('workflowCode', workflowCode); | ||||
|     } | ||||
|  | ||||
|     if (itemCode) { | ||||
|       params = params.append('itemCode', itemCode); | ||||
|     } | ||||
|  | ||||
|     if (taskType) { | ||||
|       params = params.append('taskType', taskType); | ||||
|     } | ||||
|  | ||||
|     params = params.append('skip', skip.toString()); | ||||
|     params = params.append('take', take.toString()); | ||||
|     return this.httpClient.get<any>(`${this.appConfig.getConfig('apiEndPoint')}/api/v1/tasks`, | ||||
|       {params: params}) | ||||
|   } | ||||
| } | ||||
| @@ -31,8 +31,8 @@ | ||||
|     "tslib": "^2.3.0" | ||||
|   }, | ||||
|   "peerDependencies": { | ||||
|     "@angular/common": "^18.2.3", | ||||
|     "@angular/core": "^18.2.3", | ||||
|     "@angular/common": "18.2.3", | ||||
|     "@angular/core": "18.2.3", | ||||
|     "ol": "^8.2.0" | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -20,7 +20,7 @@ const routes = [ | ||||
|  | ||||
|   { | ||||
|     path: '', | ||||
|     canActivate: [NavBarGuard], | ||||
|     //canActivate: [NavBarGuard], | ||||
|     component: LandingpageComponent | ||||
|   }, | ||||
|   { | ||||
| @@ -43,6 +43,11 @@ const routes = [ | ||||
|     component: TestComponent, | ||||
|     outlet: 'help-menu' | ||||
|   }, | ||||
|   { | ||||
|     path: '', | ||||
|     component: TestComponent, | ||||
|     outlet: 'setting-menu' | ||||
|   }, | ||||
|   { | ||||
|     path: '', | ||||
|     component: LogoComponent, | ||||
|   | ||||
		Reference in New Issue
	
	Block a user