Compare commits
145 Commits
2024.10
...
eed70c449b
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
eed70c449b | ||
| 4bef16aa2b | |||
| 05bc18c291 | |||
| 35ab2f7c90 | |||
| 2eca9b2562 | |||
|
|
e0c89f4358 | ||
| 604c1176c3 | |||
|
|
0ff8992874 | ||
| b5b84c2547 | |||
| c2b016b2b9 | |||
|
|
d44531274b | ||
| c52ee36d1b | |||
|
|
9b86927e2c | ||
|
|
e224b80995 | ||
|
|
88f3d9ef1a | ||
| 6737029a61 | |||
|
|
d4786564bd | ||
| 6fd69d7999 | |||
|
|
4ec75b3d5a | ||
| 04e3f1e71f | |||
| f66187d3a2 | |||
|
|
df77631299 | ||
| a8d0f05c81 | |||
|
|
df0d13e5dd | ||
|
|
c79637be77 | ||
|
|
b347220dd4 | ||
|
|
b5e11da9a8 | ||
|
|
edeadef96f | ||
|
|
267a299589 | ||
|
|
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 | ||
|
|
134220d75f | ||
|
|
80ef4ed6fe | ||
|
|
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 | |||
|
|
d21f304081 | ||
| 2bad3274fd | |||
|
|
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 |
@@ -129,7 +129,7 @@
|
||||
"extract-i18n": {
|
||||
"builder": "@angular-devkit/build-angular:extract-i18n",
|
||||
"options": {
|
||||
"browserTarget": "farmmaps-lib-app:build"
|
||||
"buildTarget": "farmmaps-lib-app:build"
|
||||
}
|
||||
},
|
||||
"test": {
|
||||
|
||||
9387
package-lock.json
generated
9387
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
64
package.json
64
package.json
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "farmmaps-lib-app",
|
||||
"version": "4.11.1",
|
||||
"scripts": {
|
||||
"version": "4.20.0",
|
||||
"scripts": {
|
||||
"ng": "ng",
|
||||
"start": "ng serve",
|
||||
"build": "ng build",
|
||||
@@ -10,25 +10,25 @@
|
||||
"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": "19.2.18",
|
||||
"@angular/common": "19.2.18",
|
||||
"@angular/compiler": "19.2.18",
|
||||
"@angular/core": "19.2.18",
|
||||
"@angular/forms": "19.2.18",
|
||||
"@angular/platform-browser": "19.2.18",
|
||||
"@angular/platform-browser-dynamic": "19.2.18",
|
||||
"@angular/router": "19.2.18",
|
||||
"@farmmaps/common": "file:dist/common",
|
||||
"@farmmaps/common-map": "file:dist/common-map",
|
||||
"@farmmaps/common-map3d": "file:dist/common-map3d",
|
||||
"@farmmaps/ng-openlayers": "file:dist/ng-openlayers",
|
||||
"@microsoft/signalr": "^3.1.16",
|
||||
"@ng-bootstrap/ng-bootstrap": "^17.0.1",
|
||||
"@ngrx/effects": "^18.0.2",
|
||||
"@ngrx/router-store": "^18.0.2",
|
||||
"@ngrx/store": "^18.0.2",
|
||||
"@ng-bootstrap/ng-bootstrap": "^18.0.0",
|
||||
"@ngrx/effects": "19.2.1",
|
||||
"@ngrx/router-store": "19.2.1",
|
||||
"@ngrx/store": "19.2.1",
|
||||
"@popperjs/core": "^2.11.8",
|
||||
"angular-oauth2-oidc": "^17.0.2",
|
||||
"assert": "^2.0.0",
|
||||
@@ -39,11 +39,11 @@
|
||||
"core-js": "^2.6.12",
|
||||
"https-browserify": "^1.0.0",
|
||||
"moment": "^2.29.4",
|
||||
"ngrx-store-localstorage": "^18.0.0",
|
||||
"ngx-avatars": "^1.8.0",
|
||||
"ngrx-store-localstorage": "19.0.2",
|
||||
"ngx-avatars": "1.9.3",
|
||||
"ngx-clipboard": "^16.0.0",
|
||||
"ngx-image-cropper": "^7.0.0",
|
||||
"ngx-uploadx": "^6.2.0",
|
||||
"ngx-uploadx": "7.0.1",
|
||||
"ol": "^8.2.0",
|
||||
"olcs": "^2.13.1",
|
||||
"resumablejs": "^1.1.0",
|
||||
@@ -54,19 +54,19 @@
|
||||
"tslib": "^2.4.0",
|
||||
"url": "^0.11.0",
|
||||
"util": "^0.12.4",
|
||||
"zone.js": "~0.14.10"
|
||||
"zone.js": "~0.15.1"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"optionalDependencies": {
|
||||
"@lmdb/lmdb-linux-x64": "^3.1.0",
|
||||
"@rollup/rollup-linux-x64-gnu": "^4.21.2"
|
||||
},
|
||||
"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",
|
||||
"devDependencies": {
|
||||
"@angular-builders/custom-webpack": "19.0.1",
|
||||
"@angular-devkit/build-angular": "19.2.19",
|
||||
"@angular/cli": "19.2.19",
|
||||
"@angular/compiler-cli": "19.2.18",
|
||||
"@angular/language-service": "19.2.18",
|
||||
"@angular/localize": "19.2.18",
|
||||
"@types/arcgis-rest-api": "^10.4.5",
|
||||
"@types/jasmine": "~2.8.8",
|
||||
"@types/jasminewd2": "^2.0.9",
|
||||
@@ -85,9 +85,15 @@
|
||||
"karma-coverage-istanbul-reporter": "^3.0.3",
|
||||
"karma-jasmine": "^5.1.0",
|
||||
"karma-jasmine-html-reporter": "^2.0.0",
|
||||
"ng-packagr": "^18.2.1",
|
||||
"ng-packagr": "^19.2.2",
|
||||
"protractor": "~7.0.0",
|
||||
"ts-node": "^8.8.1",
|
||||
"typescript": "~5.4.4"
|
||||
"typescript": "~5.8.3"
|
||||
},
|
||||
"overrides": {
|
||||
"some-library": {
|
||||
"@angular/common": "$@angular/common",
|
||||
"@angular/core": "$@angular/core"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,11 +8,11 @@
|
||||
"tslib": "^2.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@angular/core": "^18.2.3",
|
||||
"ngrx-store-localstorage": "^18.0.0",
|
||||
"@ngrx/effects": "^18.0.2",
|
||||
"@ngrx/router-store": "^18.0.2",
|
||||
"@ngrx/store": "^18.0.2",
|
||||
"@angular/core": "19.2.18",
|
||||
"ngrx-store-localstorage": "19.0.2",
|
||||
"@ngrx/effects": "19.2.1",
|
||||
"@ngrx/router-store": "19.2.1",
|
||||
"@ngrx/store": "19.2.1",
|
||||
"tassign": "^1.0.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
@@ -300,7 +302,7 @@ export class SetReplaceUrl implements Action {
|
||||
export class SetFeatures implements Action {
|
||||
readonly type = SETFEATURES;
|
||||
|
||||
constructor(public features: Array<Feature<Geometry>>) { }
|
||||
constructor(public features: Array<Feature<Geometry>>, public zoomToExtent: boolean = true) { }
|
||||
}
|
||||
|
||||
export class SetLayerValuesLocation implements Action {
|
||||
@@ -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 },
|
||||
|
||||
@@ -14,8 +14,9 @@ export interface IDroppedFile {
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: 'fm-map-file-drop-target',
|
||||
template: ''
|
||||
selector: 'fm-map-file-drop-target',
|
||||
template: '',
|
||||
standalone: false
|
||||
})
|
||||
export class FileDropTargetComponent implements OnInit, OnDestroy {
|
||||
element: Element;
|
||||
|
||||
@@ -4,10 +4,11 @@ import Overlay from 'ol/Overlay';
|
||||
import { fromLonLat, toLonLat } from 'ol/proj';
|
||||
|
||||
|
||||
@Component({
|
||||
selector: 'fm-map-gps-location',
|
||||
templateUrl: './gps-location.component.html',
|
||||
styleUrls: ['./gps-location.component.scss']
|
||||
@Component({
|
||||
selector: 'fm-map-gps-location',
|
||||
templateUrl: './gps-location.component.html',
|
||||
styleUrls: ['./gps-location.component.scss'],
|
||||
standalone: false
|
||||
})
|
||||
export class GpsLocation implements OnInit,OnChanges{
|
||||
|
||||
|
||||
@@ -21,12 +21,13 @@ import { Geometry } from 'ol/geom';
|
||||
import BaseLayer from 'ol/layer/Base';
|
||||
import Feature from 'ol/Feature';
|
||||
|
||||
@Component({
|
||||
selector: 'fm-map-item-layers',
|
||||
template: `<ng-content></ng-content>`,
|
||||
providers: [
|
||||
{ provide: LayerGroupComponent, useExisting: forwardRef(() => ItemLayersComponent) }
|
||||
]
|
||||
@Component({
|
||||
selector: 'fm-map-item-layers',
|
||||
template: `<ng-content></ng-content>`,
|
||||
providers: [
|
||||
{ provide: LayerGroupComponent, useExisting: forwardRef(() => ItemLayersComponent) }
|
||||
],
|
||||
standalone: false
|
||||
})
|
||||
|
||||
export class ItemLayersComponent extends LayerGroupComponent implements OnChanges, OnInit,OnDestroy {
|
||||
|
||||
@@ -21,12 +21,13 @@ import { Subscription } from 'rxjs';
|
||||
import { getCenter } from 'ol/extent';
|
||||
import { formatNumber } from '@angular/common';
|
||||
|
||||
@Component({
|
||||
selector: 'fm-map-item-source-vector',
|
||||
template: `<ng-content></ng-content>`,
|
||||
providers: [
|
||||
{ provide: SourceVectorComponent, useExisting: forwardRef(() => ItemVectorSourceComponent) }
|
||||
]
|
||||
@Component({
|
||||
selector: 'fm-map-item-source-vector',
|
||||
template: `<ng-content></ng-content>`,
|
||||
providers: [
|
||||
{ provide: SourceVectorComponent, useExisting: forwardRef(() => ItemVectorSourceComponent) }
|
||||
],
|
||||
standalone: false
|
||||
})
|
||||
export class ItemVectorSourceComponent extends SourceVectorComponent implements OnInit, OnDestroy, OnChanges {
|
||||
instance: Vector<Feature<Geometry>>;
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import { Component,Input,Output,EventEmitter } from '@angular/core';
|
||||
import { IItemLayer } from '../../../models/item.layer';
|
||||
|
||||
@Component({
|
||||
selector: 'fm-map-layer-list',
|
||||
templateUrl: './layer-list.component.html',
|
||||
styleUrls: ['./layer-list.component.scss']
|
||||
@Component({
|
||||
selector: 'fm-map-layer-list',
|
||||
templateUrl: './layer-list.component.html',
|
||||
styleUrls: ['./layer-list.component.scss'],
|
||||
standalone: false
|
||||
})
|
||||
|
||||
export class LayerListComponent {
|
||||
|
||||
@@ -14,9 +14,10 @@ import { GeoJSON, WKT } from 'ol/format';
|
||||
import { Point } from 'ol/geom';
|
||||
|
||||
@Component({
|
||||
selector: 'fm-map-layer-values',
|
||||
templateUrl: './layer-values.component.html',
|
||||
styleUrls: ['./layer-values.component.scss']
|
||||
selector: 'fm-map-layer-values',
|
||||
templateUrl: './layer-values.component.html',
|
||||
styleUrls: ['./layer-values.component.scss'],
|
||||
standalone: false
|
||||
})
|
||||
export class LayerValuesComponent implements OnInit, AfterViewInit {
|
||||
|
||||
|
||||
@@ -6,10 +6,11 @@ import { Geometry } from 'ol/geom';
|
||||
import Feature from 'ol/Feature';
|
||||
|
||||
@Component({
|
||||
selector: 'fm-map-aol-layer-vector-image',
|
||||
template: `
|
||||
selector: 'fm-map-aol-layer-vector-image',
|
||||
template: `
|
||||
<ng-content></ng-content>
|
||||
`,
|
||||
standalone: false
|
||||
})
|
||||
export class LayerVectorImageComponent extends LayerVectorComponent implements OnInit, OnDestroy, OnChanges {
|
||||
//public source: Vector;
|
||||
|
||||
@@ -5,10 +5,11 @@ import {View} from 'ol';
|
||||
import { fromLonLat } from 'ol/proj';
|
||||
|
||||
|
||||
@Component({
|
||||
selector: 'fm-map-pan-to-location',
|
||||
templateUrl: './pan-to-location.component.html',
|
||||
styleUrls: ['./pan-to-location.component.scss']
|
||||
@Component({
|
||||
selector: 'fm-map-pan-to-location',
|
||||
templateUrl: './pan-to-location.component.html',
|
||||
styleUrls: ['./pan-to-location.component.scss'],
|
||||
standalone: false
|
||||
})
|
||||
export class PanToLocation implements OnInit,OnChanges{
|
||||
|
||||
|
||||
@@ -5,10 +5,11 @@ import {View} from 'ol';
|
||||
|
||||
|
||||
|
||||
@Component({
|
||||
selector: 'fm-map-rotation-reset',
|
||||
templateUrl: './rotation-reset.component.html',
|
||||
styleUrls: ['./rotation-reset.component.scss']
|
||||
@Component({
|
||||
selector: 'fm-map-rotation-reset',
|
||||
templateUrl: './rotation-reset.component.html',
|
||||
styleUrls: ['./rotation-reset.component.scss'],
|
||||
standalone: false
|
||||
})
|
||||
export class RotationResetComponent implements OnInit {
|
||||
view: View;
|
||||
|
||||
@@ -3,9 +3,10 @@ import { ActivatedRoute } from '@angular/router';
|
||||
import { ViewComponent, MapComponent } from '@farmmaps/ng-openlayers';
|
||||
|
||||
|
||||
@Component({
|
||||
selector: 'fm-map-zoom-to-extent',
|
||||
template: `<ng-content></ng-content>`
|
||||
@Component({
|
||||
selector: 'fm-map-zoom-to-extent',
|
||||
template: `<ng-content></ng-content>`,
|
||||
standalone: false
|
||||
})
|
||||
export class ZoomToExtentComponent implements OnChanges {
|
||||
view: ViewComponent;
|
||||
|
||||
@@ -10,10 +10,11 @@ import { Store } from '@ngrx/store';
|
||||
import { Observable } from 'rxjs';
|
||||
|
||||
|
||||
@Component({
|
||||
selector: 'fm-map-feature-list-container',
|
||||
templateUrl: './feature-list-container.component.html',
|
||||
styleUrls: ['./feature-list-container.component.scss']
|
||||
@Component({
|
||||
selector: 'fm-map-feature-list-container',
|
||||
templateUrl: './feature-list-container.component.html',
|
||||
styleUrls: ['./feature-list-container.component.scss'],
|
||||
standalone: false
|
||||
})
|
||||
export class FeatureListContainerComponent {
|
||||
|
||||
|
||||
@@ -11,10 +11,11 @@ import { Observable } from 'rxjs';
|
||||
@ForChild()
|
||||
@ForItemType("vnd.farmmaps.itemtype.cropfield")
|
||||
@Injectable()
|
||||
@Component({
|
||||
selector: 'fm-map-feature-list-cropfield',
|
||||
templateUrl: './feature-list-cropfield.component.html',
|
||||
styleUrls: ['./feature-list-cropfield.component.scss']
|
||||
@Component({
|
||||
selector: 'fm-map-feature-list-cropfield',
|
||||
templateUrl: './feature-list-cropfield.component.html',
|
||||
styleUrls: ['./feature-list-cropfield.component.scss'],
|
||||
standalone: false
|
||||
})
|
||||
export class FeatureListCropfieldComponent extends AbstractFeatureListComponent implements OnInit {
|
||||
|
||||
|
||||
@@ -13,10 +13,11 @@ import { Geometry} from 'ol/geom';
|
||||
|
||||
@ForItemType("vnd.farmmaps.itemtype.croppingscheme")
|
||||
@Injectable()
|
||||
@Component({
|
||||
selector: 'fm-map-feature-list-croppingscheme',
|
||||
templateUrl: './feature-list-croppingscheme.component.html',
|
||||
styleUrls: ['./feature-list-croppingscheme.component.scss']
|
||||
@Component({
|
||||
selector: 'fm-map-feature-list-croppingscheme',
|
||||
templateUrl: './feature-list-croppingscheme.component.html',
|
||||
styleUrls: ['./feature-list-croppingscheme.component.scss'],
|
||||
standalone: false
|
||||
})
|
||||
export class FeatureListCroppingschemeComponent extends AbstractFeatureListComponent {
|
||||
|
||||
|
||||
@@ -5,13 +5,14 @@ import { AbstractFeatureListFeatureComponent,FeatureListFeatureComponent } from
|
||||
import { WidgetHostDirective } from '../widget-host/widget-host.directive';
|
||||
|
||||
|
||||
@Component({
|
||||
selector: 'fm-map-feature-list-feature-container',
|
||||
template: `
|
||||
@Component({
|
||||
selector: 'fm-map-feature-list-feature-container',
|
||||
template: `
|
||||
<div>
|
||||
<ng-template fm-map-widget-host></ng-template>
|
||||
</div>
|
||||
`
|
||||
`,
|
||||
standalone: false
|
||||
})
|
||||
export class FeatureListFeatureContainerComponent {
|
||||
|
||||
|
||||
@@ -12,10 +12,11 @@ import {getArea} from 'ol/sphere';
|
||||
|
||||
@ForItemType("vnd.farmmaps.itemtype.cropfield")
|
||||
@Injectable()
|
||||
@Component({
|
||||
selector: 'fm-map-feature-list-feature-cropfield',
|
||||
templateUrl: './feature-list-feature-cropfield.component.html',
|
||||
styleUrls: ['./feature-list-feature-cropfield.component.scss']
|
||||
@Component({
|
||||
selector: 'fm-map-feature-list-feature-cropfield',
|
||||
templateUrl: './feature-list-feature-cropfield.component.html',
|
||||
styleUrls: ['./feature-list-feature-cropfield.component.scss'],
|
||||
standalone: false
|
||||
})
|
||||
export class FeatureListFeatureCropfieldComponent extends AbstractFeatureListFeatureComponent {
|
||||
|
||||
|
||||
@@ -10,9 +10,10 @@ import { ForItemType } from '../for-item/for-itemtype.decorator';
|
||||
@ForItemType("vnd.farmmaps.itemtype.croppingscheme")
|
||||
@Injectable()
|
||||
@Component({
|
||||
selector: 'fm-map-feature-list-feature-croppingscheme',
|
||||
templateUrl: './feature-list-feature-croppingscheme.component.html',
|
||||
styleUrls: ['./feature-list-feature-croppingscheme.component.scss']
|
||||
selector: 'fm-map-feature-list-feature-croppingscheme',
|
||||
templateUrl: './feature-list-feature-croppingscheme.component.html',
|
||||
styleUrls: ['./feature-list-feature-croppingscheme.component.scss'],
|
||||
standalone: false
|
||||
})
|
||||
export class FeatureListFeatureCroppingschemeComponent extends AbstractFeatureListFeatureComponent {
|
||||
|
||||
|
||||
@@ -17,10 +17,11 @@ export abstract class AbstractFeatureListFeatureComponent {
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
@Component({
|
||||
selector: 'fm-map-feature-list-feature',
|
||||
templateUrl: './feature-list-feature.component.html',
|
||||
styleUrls: ['./feature-list-feature.component.scss']
|
||||
@Component({
|
||||
selector: 'fm-map-feature-list-feature',
|
||||
templateUrl: './feature-list-feature.component.html',
|
||||
styleUrls: ['./feature-list-feature.component.scss'],
|
||||
standalone: false
|
||||
})
|
||||
export class FeatureListFeatureComponent extends AbstractFeatureListFeatureComponent {
|
||||
|
||||
|
||||
@@ -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,31 @@
|
||||
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'],
|
||||
standalone: false
|
||||
})
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -57,10 +57,11 @@ export abstract class AbstractFeatureListComponent {
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
@Component({
|
||||
selector: 'fm-map-feature-list',
|
||||
templateUrl: './feature-list.component.html',
|
||||
styleUrls: ['./feature-list.component.scss']
|
||||
@Component({
|
||||
selector: 'fm-map-feature-list',
|
||||
templateUrl: './feature-list.component.html',
|
||||
styleUrls: ['./feature-list.component.scss'],
|
||||
standalone: false
|
||||
})
|
||||
export class FeatureListComponent extends AbstractFeatureListComponent {
|
||||
|
||||
|
||||
@@ -6,9 +6,10 @@ import * as render from 'ol/render';
|
||||
import * as style from 'ol/style';
|
||||
|
||||
@Component({
|
||||
selector: 'fm-map-feature-thumbnail',
|
||||
templateUrl: './feature-thumbnail.component.html',
|
||||
styleUrls: ['./feature-thumbnail.component.scss']
|
||||
selector: 'fm-map-feature-thumbnail',
|
||||
templateUrl: './feature-thumbnail.component.html',
|
||||
styleUrls: ['./feature-thumbnail.component.scss'],
|
||||
standalone: false
|
||||
})
|
||||
export class GeometryThumbnailComponent implements AfterViewInit {
|
||||
|
||||
|
||||
@@ -3,8 +3,9 @@ import { Layer } from 'ol/layer';
|
||||
import { Source } from 'ol/source';
|
||||
import { MapComponent } from '@farmmaps/ng-openlayers';
|
||||
|
||||
@Directive({
|
||||
selector: '[fmMapIfZoomToShow]',
|
||||
@Directive({
|
||||
selector: '[fmMapIfZoomToShow]',
|
||||
standalone: false
|
||||
})
|
||||
export class ifZoomToShowDirective implements OnInit {
|
||||
@Input()
|
||||
|
||||
@@ -4,13 +4,14 @@ import { WidgetHostDirective } from '../widget-host/widget-host.directive';
|
||||
import { IItem, IListItem } from '@farmmaps/common';
|
||||
|
||||
|
||||
@Component({
|
||||
selector: 'fm-map-item-list-item-container',
|
||||
template: `
|
||||
@Component({
|
||||
selector: 'fm-map-item-list-item-container',
|
||||
template: `
|
||||
<div style="height:100%">
|
||||
<ng-template fm-map-widget-host></ng-template>
|
||||
</div>
|
||||
`
|
||||
`,
|
||||
standalone: false
|
||||
})
|
||||
export class ItemListItemContainerComponent {
|
||||
|
||||
|
||||
@@ -40,10 +40,11 @@ export abstract class AbstractItemWidgetComponent {
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
@Component({
|
||||
selector: 'fm-map-item-list-item',
|
||||
templateUrl: './item-list-item.component.html',
|
||||
styleUrls: ['./item-list-item.component.scss']
|
||||
@Component({
|
||||
selector: 'fm-map-item-list-item',
|
||||
templateUrl: './item-list-item.component.html',
|
||||
styleUrls: ['./item-list-item.component.scss'],
|
||||
standalone: false
|
||||
})
|
||||
export class ItemListItemComponent extends AbstractItemListItemComponent {
|
||||
|
||||
|
||||
@@ -28,9 +28,10 @@ export abstract class AbstractItemListComponent {
|
||||
|
||||
@Injectable()
|
||||
@Component({
|
||||
selector: 'fm-map-item-list',
|
||||
templateUrl: './item-list.component.html',
|
||||
styleUrls: ['./item-list.component.scss']
|
||||
selector: 'fm-map-item-list',
|
||||
templateUrl: './item-list.component.html',
|
||||
styleUrls: ['./item-list.component.scss'],
|
||||
standalone: false
|
||||
})
|
||||
export class ItemListComponent extends AbstractItemListComponent {
|
||||
|
||||
|
||||
@@ -8,9 +8,10 @@ import { AbstractItemWidgetComponent } from '../item-list-item/item-list-item.co
|
||||
|
||||
@Injectable()
|
||||
@Component({
|
||||
selector: 'fm-map-item-widget-list',
|
||||
templateUrl: './item-widget-list.component.html',
|
||||
styleUrls: ['./item-widget-list.component.scss']
|
||||
selector: 'fm-map-item-widget-list',
|
||||
templateUrl: './item-widget-list.component.html',
|
||||
styleUrls: ['./item-widget-list.component.scss'],
|
||||
standalone: false
|
||||
})
|
||||
export class ItemWidgetListComponent implements AfterViewInit {
|
||||
|
||||
|
||||
@@ -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,12 +4,13 @@ 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',
|
||||
templateUrl: './layer-switcher.component.html',
|
||||
styleUrls: ['./layer-switcher.component.scss']
|
||||
@Component({
|
||||
selector: 'fm-map-layer-switcher',
|
||||
templateUrl: './layer-switcher.component.html',
|
||||
styleUrls: ['./layer-switcher.component.scss'],
|
||||
standalone: false
|
||||
})
|
||||
export class LayerSwitcher implements OnInit,OnChanges{
|
||||
|
||||
@@ -17,7 +18,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 +28,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 +86,4 @@ export class LayerSwitcher implements OnInit,OnChanges{
|
||||
event.preventDefault();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,12 +2,13 @@ import {Component, Input} from '@angular/core';
|
||||
import {IHistogram, ILayer} from '../../../models/color.map';
|
||||
|
||||
@Component({
|
||||
selector: 'fm-map-histogram-details',
|
||||
templateUrl: './histogram-details.component.html',
|
||||
styles: ['.nopadding{\n' +
|
||||
' padding: 0 !important;\n' +
|
||||
' margin: 0 !important;\n' +
|
||||
'}']
|
||||
selector: 'fm-map-histogram-details',
|
||||
templateUrl: './histogram-details.component.html',
|
||||
styles: ['.nopadding{\n' +
|
||||
' padding: 0 !important;\n' +
|
||||
' margin: 0 !important;\n' +
|
||||
'}'],
|
||||
standalone: false
|
||||
})
|
||||
export class HistogramDetailsComponent {
|
||||
|
||||
|
||||
@@ -2,10 +2,11 @@ import { Component, OnInit, Input,AfterViewInit } from '@angular/core';
|
||||
import { IColorMap, IColor, IColorEntry,ILayer, IRenderer } from '../../models/color.map';
|
||||
|
||||
|
||||
@Component({
|
||||
selector: 'fm-map-layer-legend',
|
||||
templateUrl: './legend.component.html',
|
||||
styleUrls: ['./legend.component.scss']
|
||||
@Component({
|
||||
selector: 'fm-map-layer-legend',
|
||||
templateUrl: './legend.component.html',
|
||||
styleUrls: ['./legend.component.scss'],
|
||||
standalone: false
|
||||
})
|
||||
export class LegendComponent implements OnInit,AfterViewInit {
|
||||
|
||||
|
||||
@@ -2,12 +2,13 @@ import { Component, Input } from '@angular/core';
|
||||
import { IStatistics } from '../../../models/color.map';
|
||||
|
||||
@Component({
|
||||
selector: 'fm-map-statistics-details',
|
||||
templateUrl: './statistics-details.component.html',
|
||||
styles: ['.nopadding{\n' +
|
||||
' padding: 0 !important;\n' +
|
||||
' margin: 0 !important;\n' +
|
||||
'}']
|
||||
selector: 'fm-map-statistics-details',
|
||||
templateUrl: './statistics-details.component.html',
|
||||
styles: ['.nopadding{\n' +
|
||||
' padding: 0 !important;\n' +
|
||||
' margin: 0 !important;\n' +
|
||||
'}'],
|
||||
standalone: false
|
||||
})
|
||||
export class StatisticsDetailsComponent {
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ div.map-search {
|
||||
}
|
||||
|
||||
.disabled {
|
||||
color:lighten(#000000,80%);
|
||||
color:adjust(#000000,80%);
|
||||
}
|
||||
|
||||
:host ::ng-deep ngb-typeahead-window.dropdown-menu {
|
||||
|
||||
@@ -6,10 +6,11 @@ import { IQueryState } from '@farmmaps/common';
|
||||
import { IPeriodState } from '../../models/period.state';
|
||||
import { tassign } from 'tassign';
|
||||
|
||||
@Component({
|
||||
selector: 'fm-map-map-search',
|
||||
templateUrl: './map-search.component.html',
|
||||
styleUrls: ['./map-search.component.scss']
|
||||
@Component({
|
||||
selector: 'fm-map-map-search',
|
||||
templateUrl: './map-search.component.html',
|
||||
styleUrls: ['./map-search.component.scss'],
|
||||
standalone: false
|
||||
})
|
||||
export class MapSearchComponent {
|
||||
|
||||
|
||||
@@ -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,50 +1,51 @@
|
||||
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';
|
||||
|
||||
|
||||
@Component({
|
||||
selector: 'fm-map-map',
|
||||
templateUrl: './map.component.html',
|
||||
styleUrls: ['./map.component.scss']
|
||||
@Component({
|
||||
selector: 'fm-map-map',
|
||||
templateUrl: './map.component.html',
|
||||
styleUrls: ['./map.component.scss'],
|
||||
standalone: false
|
||||
})
|
||||
|
||||
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 +55,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 +113,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 +165,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 +193,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 +209,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 +247,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 +329,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 +407,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 +424,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 +467,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 +499,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 +522,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() {
|
||||
|
||||
@@ -9,9 +9,10 @@ export interface IMetaData {
|
||||
attributes: any
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: 'fm-map-meta-data-modal',
|
||||
templateUrl: 'meta-data-modal.component.html'
|
||||
@Component({
|
||||
selector: 'fm-map-meta-data-modal',
|
||||
templateUrl: 'meta-data-modal.component.html',
|
||||
standalone: false
|
||||
})
|
||||
export class MetaDataModalComponent {
|
||||
|
||||
|
||||
@@ -15,10 +15,11 @@ const after = (one: NgbDateStruct, two: NgbDateStruct) =>
|
||||
!one || !two ? false : one.year === two.year ? one.month === two.month ? one.day === two.day
|
||||
? false : one.day > two.day : one.month > two.month : one.year > two.year;
|
||||
|
||||
@Component({
|
||||
selector: 'fm-map-select-period-modal',
|
||||
templateUrl: 'select-period-modal.component.html',
|
||||
styleUrls: ['select-period-modal.component.scss']
|
||||
@Component({
|
||||
selector: 'fm-map-select-period-modal',
|
||||
templateUrl: 'select-period-modal.component.html',
|
||||
styleUrls: ['select-period-modal.component.scss'],
|
||||
standalone: false
|
||||
})
|
||||
export class SelectPeriodModalComponent {
|
||||
|
||||
|
||||
@@ -5,10 +5,11 @@ import { WidgetHostDirective } from '../widget-host/widget-host.directive';
|
||||
import { IItemLayer } from '../../models/item.layer';
|
||||
|
||||
|
||||
@Component({
|
||||
selector: 'fm-map-selected-item-container',
|
||||
templateUrl: './selected-item-container.component.html',
|
||||
styleUrls: ['./selected-item-container.component.scss']
|
||||
@Component({
|
||||
selector: 'fm-map-selected-item-container',
|
||||
templateUrl: './selected-item-container.component.html',
|
||||
styleUrls: ['./selected-item-container.component.scss'],
|
||||
standalone: false
|
||||
})
|
||||
export class SelectedItemContainerComponent {
|
||||
|
||||
|
||||
@@ -15,17 +15,18 @@ import { withLatestFrom,switchMap,combineLatest } from 'rxjs/operators';
|
||||
|
||||
@ForItemType("vnd.farmmaps.itemtype.cropfield")
|
||||
@Injectable()
|
||||
@Component({
|
||||
selector: 'fm-map-selected-item-cropfield',
|
||||
templateUrl: './selected-item-cropfield.component.html',
|
||||
styleUrls: ['./selected-item-cropfield.component.scss']
|
||||
@Component({
|
||||
selector: 'fm-map-selected-item-cropfield',
|
||||
templateUrl: './selected-item-cropfield.component.html',
|
||||
styleUrls: ['./selected-item-cropfield.component.scss'],
|
||||
standalone: false
|
||||
})
|
||||
export class SelectedItemCropfieldComponent extends AbstractSelectedItemComponent implements OnInit{
|
||||
|
||||
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,25 +1,32 @@
|
||||
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")
|
||||
@Injectable()
|
||||
@Component({
|
||||
selector: 'fm-map-selected-item-geotiff',
|
||||
templateUrl: './selected-item-geotiff.component.html',
|
||||
styleUrls: ['./selected-item-geotiff.component.scss']
|
||||
@Component({
|
||||
selector: 'fm-map-selected-item-geotiff',
|
||||
templateUrl: './selected-item-geotiff.component.html',
|
||||
styleUrls: ['./selected-item-geotiff.component.scss'],
|
||||
standalone: false
|
||||
})
|
||||
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 +36,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,30 +1,35 @@
|
||||
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")
|
||||
@Injectable()
|
||||
@Component({
|
||||
selector: 'fm-map-selected-item-shape',
|
||||
templateUrl: './selected-item-shape.component.html',
|
||||
styleUrls: ['./selected-item-shape.component.scss']
|
||||
@Component({
|
||||
selector: 'fm-map-selected-item-shape',
|
||||
templateUrl: './selected-item-shape.component.html',
|
||||
styleUrls: ['./selected-item-shape.component.scss'],
|
||||
standalone: false
|
||||
})
|
||||
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 +37,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,28 +1,33 @@
|
||||
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()
|
||||
@Component({
|
||||
selector: 'fm-map-selected-item-temporal',
|
||||
templateUrl: './selected-item-temporal.component.html',
|
||||
styleUrls: ['./selected-item-temporal.component.scss']
|
||||
@Component({
|
||||
selector: 'fm-map-selected-item-temporal',
|
||||
templateUrl: './selected-item-temporal.component.html',
|
||||
styleUrls: ['./selected-item-temporal.component.scss'],
|
||||
standalone: false
|
||||
})
|
||||
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 +38,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 +64,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;
|
||||
@@ -69,15 +74,16 @@ export abstract class AbstractSelectedItemComponent {
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
@Component({
|
||||
selector: 'fm-map-selected-item',
|
||||
templateUrl: './selected-item.component.html',
|
||||
styleUrls: ['./selected-item.component.scss']
|
||||
@Component({
|
||||
selector: 'fm-map-selected-item',
|
||||
templateUrl: './selected-item.component.html',
|
||||
styleUrls: ['./selected-item.component.scss'],
|
||||
standalone: false
|
||||
})
|
||||
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 {
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { Directive, ViewContainerRef } from '@angular/core';
|
||||
|
||||
@Directive({
|
||||
selector: '[fm-map-widget-host]',
|
||||
selector: '[fm-map-widget-host]',
|
||||
standalone: false
|
||||
})
|
||||
export class WidgetHostDirective {
|
||||
constructor(public viewContainerRef: ViewContainerRef) { }
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import { Component, OnInit, Input } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'fm-map-widget-status',
|
||||
templateUrl: './widget-status.component.html',
|
||||
styleUrls: ['./widget-status.component.css']
|
||||
selector: 'fm-map-widget-status',
|
||||
templateUrl: './widget-status.component.html',
|
||||
styleUrls: ['./widget-status.component.css'],
|
||||
standalone: false
|
||||
})
|
||||
export class WidgetStatusComponent implements OnInit {
|
||||
@Input() stage: Stage;
|
||||
|
||||
@@ -2,9 +2,10 @@ import { Component, Input } from '@angular/core';
|
||||
import { Layer } from 'ol/layer';
|
||||
import { Source } from 'ol/source';
|
||||
|
||||
@Component({
|
||||
selector: 'fm-map-zoom-to-show-alert',
|
||||
template: '<div *fmMapIfZoomToShow="layer$" class="alert alert-info"><i class="fas fa-search-plus" aria-hidden="true" i18n-title title="Add as layer"></i> <span i18n>Zoom in to show layer</span></div>'
|
||||
@Component({
|
||||
selector: 'fm-map-zoom-to-show-alert',
|
||||
template: '<div *fmMapIfZoomToShow="layer$" class="alert alert-info"><i class="fas fa-search-plus" aria-hidden="true" i18n-title title="Add as layer"></i> <span i18n>Zoom in to show layer</span></div>',
|
||||
standalone: false
|
||||
})
|
||||
export class ZoomToShowAlert {
|
||||
public layer$: Layer<Source>;
|
||||
|
||||
@@ -166,12 +166,14 @@ export class MapEffects {
|
||||
zoomToExtent2$ = createEffect(() => this.actions$.pipe(
|
||||
ofType(mapActions.SETFEATURES),
|
||||
switchMap((action: mapActions.SetFeatures) => {
|
||||
const extent = createEmpty();
|
||||
if (extent) {
|
||||
for (const f of action.features) {
|
||||
extend(extent, (f as Feature<Geometry>).getGeometry().getExtent());
|
||||
if (action.zoomToExtent) {
|
||||
const extent = createEmpty();
|
||||
if (extent) {
|
||||
for (const f of action.features) {
|
||||
extend(extent, (f as Feature<Geometry>).getGeometry().getExtent());
|
||||
}
|
||||
if (action.features.length > 0) return of(new mapActions.SetExtent(extent));
|
||||
}
|
||||
if (action.features.length > 0) return of(new mapActions.SetExtent(extent));
|
||||
}
|
||||
return EMPTY;
|
||||
})));
|
||||
|
||||
@@ -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": "19.2.18",
|
||||
"@angular/core": "19.2.18",
|
||||
"cesium": "^1.97.0",
|
||||
"ol-cesium": ">=2.13.0"
|
||||
}
|
||||
|
||||
@@ -7,10 +7,11 @@ import VectorSynchronizer from 'olcs/VectorSynchronizer';
|
||||
import { mapReducers,mapActions } from '@farmmaps/common-map';
|
||||
import { Store } from '@ngrx/store';
|
||||
|
||||
@Component({
|
||||
selector: 'fm-map3d-switch2d3d',
|
||||
templateUrl: './switch2d3d.component.html',
|
||||
styleUrls: ['./switch2d3d.component.scss']
|
||||
@Component({
|
||||
selector: 'fm-map3d-switch2d3d',
|
||||
templateUrl: './switch2d3d.component.html',
|
||||
styleUrls: ['./switch2d3d.component.scss'],
|
||||
standalone: false
|
||||
})
|
||||
export class Switch2D3DComponent {
|
||||
|
||||
|
||||
@@ -5,20 +5,20 @@
|
||||
"registry": "https://repository.akkerweb.nl/repository/npm-hosted/"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@ng-bootstrap/ng-bootstrap": "^17.0.1",
|
||||
"@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",
|
||||
"@ng-bootstrap/ng-bootstrap": "^18.0.0",
|
||||
"@angular/common": "19.2.18",
|
||||
"@angular/core": "19.2.18",
|
||||
"@angular/forms": "19.2.18",
|
||||
"@ngrx/effects": "19.2.1",
|
||||
"@ngrx/router-store": "19.2.1",
|
||||
"@ngrx/store": "19.2.1",
|
||||
"tassign": "^1.0.0",
|
||||
"bootstrap": "^5.3.3",
|
||||
"@microsoft/signalr": "^3.1.16",
|
||||
"ngx-uploadx": "^6.2.0",
|
||||
"ngx-uploadx": "7.0.1",
|
||||
"angular-oauth2-oidc": "^17.0.2",
|
||||
"moment": "^2.29.4",
|
||||
"ngx-avatars": "^1.8.0",
|
||||
"ngx-avatars": "1.9.3",
|
||||
"ngx-image-cropper": "^7.0.0",
|
||||
"ngx-clipboard": "^16.0.0"
|
||||
}
|
||||
|
||||
@@ -83,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;
|
||||
|
||||
@@ -371,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
|
||||
@@ -418,6 +434,8 @@ export type Actions = OpenModal
|
||||
| ToggleHelpMenu
|
||||
| ToggleSettingMenu
|
||||
| NotificationEvent
|
||||
| SetUnreadNotifications;
|
||||
| SetUnreadNotifications
|
||||
| SwitchLanguage
|
||||
| SetSettingMenuBackgroundColor;
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// angular modules
|
||||
import { NgModule, APP_INITIALIZER, ModuleWithProviders, Injector, Optional, SkipSelf } from '@angular/core';
|
||||
import { NgModule, ModuleWithProviders, Injector, Optional, SkipSelf, inject, provideAppInitializer } from '@angular/core';
|
||||
import { DatePipe } from '@angular/common';
|
||||
import { HTTP_INTERCEPTORS } from '@angular/common/http';
|
||||
|
||||
@@ -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,
|
||||
@@ -88,12 +90,10 @@ export class AppCommonServiceModule {
|
||||
providers: [
|
||||
AppConfig,
|
||||
ItemTypeService,
|
||||
{
|
||||
provide: APP_INITIALIZER,
|
||||
useFactory: appConfigFactory,
|
||||
deps: [Injector, AppConfig, OAuthService, AuthConfigFactory, OAuthStorage, ItemTypeService],
|
||||
multi: true
|
||||
},
|
||||
provideAppInitializer(() => {
|
||||
const initializerFn = (appConfigFactory)(inject(Injector), inject(AppConfig), inject(OAuthService), inject(AuthConfigFactory), inject(OAuthStorage), inject(ItemTypeService));
|
||||
return initializerFn();
|
||||
}),
|
||||
{
|
||||
provide: HTTP_INTERCEPTORS,
|
||||
useClass: AccessTokenInterceptor,
|
||||
|
||||
@@ -6,9 +6,10 @@ import * as appReducers from '../../reducers/app-common.reducer';
|
||||
import * as appActions from '../../actions/app-common.actions';
|
||||
|
||||
@Component({
|
||||
selector: 'fm-app-menu',
|
||||
templateUrl: './app-menu.component.html',
|
||||
styleUrls: ['./app-menu.component.scss']
|
||||
selector: 'fm-app-menu',
|
||||
templateUrl: './app-menu.component.html',
|
||||
styleUrls: ['./app-menu.component.scss'],
|
||||
standalone: false
|
||||
})
|
||||
export class AppMenuComponent implements OnInit {
|
||||
|
||||
|
||||
@@ -33,7 +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"></fm-setting-menu>
|
||||
<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>
|
||||
|
||||
@@ -19,12 +19,13 @@ import { AppConfig } from '../../shared/app.config';
|
||||
|
||||
import * as appReducers from '../../reducers/app-common.reducer';
|
||||
|
||||
@Component({
|
||||
selector: 'fm-app',
|
||||
templateUrl: './app.component.html',
|
||||
styleUrls: ['./app.component.scss'],
|
||||
encapsulation: ViewEncapsulation.None,
|
||||
changeDetection: ChangeDetectionStrategy.OnPush
|
||||
@Component({
|
||||
selector: 'fm-app',
|
||||
templateUrl: './app.component.html',
|
||||
styleUrls: ['./app.component.scss'],
|
||||
encapsulation: ViewEncapsulation.None,
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
standalone: false
|
||||
})
|
||||
export class AppComponent implements OnInit, OnDestroy {
|
||||
|
||||
@@ -50,6 +51,7 @@ export class AppComponent implements OnInit, OnDestroy {
|
||||
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(
|
||||
|
||||
@@ -3,9 +3,10 @@ import { Router } from '@angular/router';
|
||||
import { OAuthService } from 'angular-oauth2-oidc';
|
||||
import { Location} from '@angular/common';
|
||||
|
||||
@Component({
|
||||
selector: 'fm-auth-callback',
|
||||
template:'<div></div>'
|
||||
@Component({
|
||||
selector: 'fm-auth-callback',
|
||||
template: '<div></div>',
|
||||
standalone: false
|
||||
})
|
||||
export class AuthCallbackComponent {
|
||||
|
||||
|
||||
@@ -3,9 +3,10 @@ import { IUser } from '../../models/user';
|
||||
import { AppConfig } from '../../shared/app.config';
|
||||
|
||||
@Component({
|
||||
selector: 'fm-avatar',
|
||||
templateUrl: './avatar.component.html',
|
||||
styleUrls: ['./avatar.component.css']
|
||||
selector: 'fm-avatar',
|
||||
templateUrl: './avatar.component.html',
|
||||
styleUrls: ['./avatar.component.css'],
|
||||
standalone: false
|
||||
})
|
||||
export class AvatarComponent implements OnInit {
|
||||
|
||||
|
||||
@@ -3,9 +3,10 @@ import { Component, EventEmitter, HostListener, Output } from '@angular/core';
|
||||
import { DeviceService } from '../../services/device.service';
|
||||
|
||||
@Component({
|
||||
selector: 'fm-back-button',
|
||||
templateUrl: './back-button.component.html',
|
||||
styleUrls: ['./back-button.component.scss']
|
||||
selector: 'fm-back-button',
|
||||
templateUrl: './back-button.component.html',
|
||||
styleUrls: ['./back-button.component.scss'],
|
||||
standalone: false
|
||||
})
|
||||
export class BackButtonComponent {
|
||||
@Output() beforeLocationBack = new EventEmitter();
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -5,9 +5,10 @@ import { ImageCroppedEvent,LoadedImage } from 'ngx-image-cropper';
|
||||
import {ImageService } from '../../services/image.service';
|
||||
|
||||
@Component({
|
||||
selector: 'fm-edit-image-modal',
|
||||
templateUrl: './edit-image-modal.component.html',
|
||||
styleUrls: ['./edit-image-modal.component.scss']
|
||||
selector: 'fm-edit-image-modal',
|
||||
templateUrl: './edit-image-modal.component.html',
|
||||
styleUrls: ['./edit-image-modal.component.scss'],
|
||||
standalone: false
|
||||
})
|
||||
export class EditImageModalComponent implements OnInit {
|
||||
|
||||
|
||||
@@ -2,9 +2,10 @@ import { Component, ChangeDetectorRef, Input,SimpleChanges,OnChanges, Output,Eve
|
||||
import { IItem } from '../../models/item';
|
||||
|
||||
@Component({
|
||||
selector: 'fm-gradient-select',
|
||||
templateUrl: './gradient-select.component.html',
|
||||
styleUrls: ['./gradient-select.component.scss']
|
||||
selector: 'fm-gradient-select',
|
||||
templateUrl: './gradient-select.component.html',
|
||||
styleUrls: ['./gradient-select.component.scss'],
|
||||
standalone: false
|
||||
})
|
||||
export class GradientSelectComponent implements OnChanges {
|
||||
|
||||
|
||||
@@ -6,9 +6,10 @@ import { GradientService } from '../../common-service.module';
|
||||
|
||||
|
||||
@Component({
|
||||
selector: 'fm-gradient',
|
||||
templateUrl: './gradient.component.html',
|
||||
styleUrls: ['./gradient.component.scss']
|
||||
selector: 'fm-gradient',
|
||||
templateUrl: './gradient.component.html',
|
||||
styleUrls: ['./gradient.component.scss'],
|
||||
standalone: false
|
||||
})
|
||||
export class GradientComponent implements OnInit,OnChanges {
|
||||
|
||||
|
||||
@@ -7,8 +7,9 @@ import { skip } from 'rxjs/operators';
|
||||
import {OAuthService } from 'angular-oauth2-oidc';
|
||||
import { IUser } from '../../models/user';
|
||||
|
||||
@Directive({
|
||||
selector: '[fm-hasclaim]',
|
||||
@Directive({
|
||||
selector: '[fm-hasclaim]',
|
||||
standalone: false
|
||||
})
|
||||
export class HasClaimDirective implements OnInit{
|
||||
@Input('fm-hasclaim') claim:string;
|
||||
|
||||
@@ -4,8 +4,9 @@ import {PackageService} from '../../services/package.service';
|
||||
import * as appCommonReducer from '../../reducers/app-common.reducer';
|
||||
import {Store} from '@ngrx/store';
|
||||
|
||||
@Directive({
|
||||
selector: '[fmHasPackage]',
|
||||
@Directive({
|
||||
selector: '[fmHasPackage]',
|
||||
standalone: false
|
||||
})
|
||||
export class HasPackageDirective implements OnDestroy, AfterViewInit {
|
||||
|
||||
|
||||
@@ -5,7 +5,8 @@ import { Observable, Subscription } from 'rxjs';
|
||||
import { IUser } from '../../models/user';
|
||||
|
||||
@Directive({
|
||||
selector: '[fmHasRole]',
|
||||
selector: '[fmHasRole]',
|
||||
standalone: false
|
||||
})
|
||||
export class HasRoleDirective implements OnInit, OnDestroy{
|
||||
@Input('fmHasRole') role:string;
|
||||
|
||||
@@ -7,9 +7,10 @@ import * as appReducers from '../../reducers/app-common.reducer';
|
||||
import * as appActions from '../../actions/app-common.actions';
|
||||
|
||||
@Component({
|
||||
selector: 'fm-help-menu',
|
||||
templateUrl: './help-menu.component.html',
|
||||
styleUrls: ['./help-menu.component.scss']
|
||||
selector: 'fm-help-menu',
|
||||
templateUrl: './help-menu.component.html',
|
||||
styleUrls: ['./help-menu.component.scss'],
|
||||
standalone: false
|
||||
})
|
||||
export class HelpMenuComponent implements OnInit {
|
||||
|
||||
|
||||
@@ -7,8 +7,9 @@ import { ClipboardService } from 'ngx-clipboard'
|
||||
|
||||
|
||||
@Component({
|
||||
selector: 'fm-item-link',
|
||||
templateUrl: './item-link.component.html'
|
||||
selector: 'fm-item-link',
|
||||
templateUrl: './item-link.component.html',
|
||||
standalone: false
|
||||
})
|
||||
export class ItemLinkComponent implements OnDestroy {
|
||||
|
||||
|
||||
@@ -3,10 +3,11 @@ import { Store, Action } from '@ngrx/store';
|
||||
import * as appReducers from '../../reducers/app-common.reducer';
|
||||
import * as commonActions from '../../actions/app-common.actions';
|
||||
|
||||
@Component({
|
||||
selector: 'fm-menu-background',
|
||||
templateUrl: './menu-background.component.html',
|
||||
styleUrls: ['./menu-background.component.scss'],
|
||||
@Component({
|
||||
selector: 'fm-menu-background',
|
||||
templateUrl: './menu-background.component.html',
|
||||
styleUrls: ['./menu-background.component.scss'],
|
||||
standalone: false
|
||||
})
|
||||
export class MenuBackgroundComponent implements OnInit {
|
||||
@Input() visible = false;
|
||||
|
||||
@@ -4,6 +4,8 @@ import { Component, OnInit } from '@angular/core';
|
||||
selector: 'fm-not-found',
|
||||
templateUrl: './not-found.component.html'
|
||||
// styleUrls: ['./not-found.component.css']
|
||||
,
|
||||
standalone: false
|
||||
})
|
||||
export class NotFoundComponent implements OnInit {
|
||||
constructor() { }
|
||||
|
||||
@@ -2,7 +2,8 @@ import { Component, OnInit } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'fm-not-implemented',
|
||||
templateUrl: './not-implemented.component.html'
|
||||
templateUrl: './not-implemented.component.html',
|
||||
standalone: false
|
||||
})
|
||||
export class NotImplementedComponent implements OnInit {
|
||||
constructor() { }
|
||||
|
||||
@@ -6,9 +6,10 @@ import * as appReducers from '../../reducers/app-common.reducer';
|
||||
import * as appActions from '../../actions/app-common.actions';
|
||||
|
||||
@Component({
|
||||
selector: 'fm-notification-menu',
|
||||
templateUrl: './notification-menu.component.html',
|
||||
styleUrls: ['./notification-menu.component.scss']
|
||||
selector: 'fm-notification-menu',
|
||||
templateUrl: './notification-menu.component.html',
|
||||
styleUrls: ['./notification-menu.component.scss'],
|
||||
standalone: false
|
||||
})
|
||||
export class NotificationMenuComponent implements OnInit {
|
||||
|
||||
|
||||
@@ -4,8 +4,9 @@ import {PackageService} from '../../services/package.service';
|
||||
import * as appCommonReducer from '../../reducers/app-common.reducer';
|
||||
import {Store} from '@ngrx/store';
|
||||
|
||||
@Directive({
|
||||
selector: '[fmPackageExists]',
|
||||
@Directive({
|
||||
selector: '[fmPackageExists]',
|
||||
standalone: false
|
||||
})
|
||||
export class PackageExistsDirective implements OnDestroy, AfterViewInit {
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ div.resumable-file-upload {
|
||||
bottom: 0px;
|
||||
width: 300px;
|
||||
max-height: 250px;
|
||||
z-index: 1;
|
||||
/*z-index:2000 !important;*/
|
||||
}
|
||||
|
||||
@@ -44,7 +45,7 @@ div.card-header span.fa {
|
||||
|
||||
.upload-file .progress-container .progress-bar {
|
||||
display: block;
|
||||
background-color: color("green");
|
||||
background-color: green;
|
||||
width: 0%;
|
||||
height: 100%;
|
||||
}
|
||||
@@ -83,7 +84,7 @@ div.card-header span.fa {
|
||||
}
|
||||
|
||||
.upload-file.done > div > span.fa-check {
|
||||
color: color("green");
|
||||
color: green;
|
||||
width: 20px;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
|
||||
@@ -9,7 +9,8 @@ import * as commonActions from '../../actions/app-common.actions';
|
||||
@Component({
|
||||
selector: 'fm-resumable-file-upload',
|
||||
templateUrl: './resumable-file-upload.component.html',
|
||||
styleUrls: ['./resumable-file-upload.component.scss']
|
||||
styleUrls: ['./resumable-file-upload.component.scss'],
|
||||
standalone: false
|
||||
})
|
||||
|
||||
export class ResumableFileUploadComponent implements OnInit, OnDestroy {
|
||||
|
||||
@@ -7,9 +7,10 @@ import * as appCommonActions from '../../actions/app-common.actions';
|
||||
|
||||
|
||||
@Component({
|
||||
selector: 'fm-session-cleared',
|
||||
templateUrl: 'session-cleared.component.html',
|
||||
styleUrls: ['session-cleared.component.scss']
|
||||
selector: 'fm-session-cleared',
|
||||
templateUrl: 'session-cleared.component.html',
|
||||
styleUrls: ['session-cleared.component.scss'],
|
||||
standalone: false
|
||||
})
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<div>
|
||||
<div (click)="toggle($event)" class="rounded-circle menu-button hidden" [ngClass]="{'hidden':!user || noContent}">
|
||||
<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>
|
||||
|
||||
@@ -7,14 +7,16 @@ 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']
|
||||
selector: 'fm-setting-menu',
|
||||
templateUrl: './setting-menu.component.html',
|
||||
styleUrls: ['./setting-menu.component.scss'],
|
||||
standalone: false
|
||||
})
|
||||
export class SettingMenuComponent implements OnInit {
|
||||
|
||||
@Input() user:IUser;
|
||||
@Input() showMenu:boolean;
|
||||
@Input() backgroundColor:string;
|
||||
public noContent = true;
|
||||
|
||||
constructor(private store: Store<appReducers.State>) { }
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import { Component, Input,Output,ViewChild,EventEmitter, ElementRef,OnChanges,SimpleChanges,HostListener,ChangeDetectorRef, ViewEncapsulation } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'fm-side-panel',
|
||||
templateUrl: 'side-panel.component.html',
|
||||
styleUrls: ['side-panel.component.scss']
|
||||
@Component({
|
||||
selector: 'fm-side-panel',
|
||||
templateUrl: 'side-panel.component.html',
|
||||
styleUrls: ['side-panel.component.scss'],
|
||||
standalone: false
|
||||
})
|
||||
|
||||
|
||||
|
||||
@@ -6,16 +6,17 @@ import {TypeaheadService} from '../../services/typeahead.service';
|
||||
import {NgbTypeahead} from '@ng-bootstrap/ng-bootstrap';
|
||||
|
||||
@Component({
|
||||
selector: 'fm-tag-input',
|
||||
templateUrl: 'tag-input.component.html',
|
||||
styleUrls: ['tag-input.component.scss'],
|
||||
providers: [
|
||||
{
|
||||
provide: NG_VALUE_ACCESSOR,
|
||||
useExisting: forwardRef(() => TagInputComponent),
|
||||
multi: true
|
||||
}
|
||||
]
|
||||
selector: 'fm-tag-input',
|
||||
templateUrl: 'tag-input.component.html',
|
||||
styleUrls: ['tag-input.component.scss'],
|
||||
providers: [
|
||||
{
|
||||
provide: NG_VALUE_ACCESSOR,
|
||||
useExisting: forwardRef(() => TagInputComponent),
|
||||
multi: true
|
||||
}
|
||||
],
|
||||
standalone: false
|
||||
})
|
||||
|
||||
export class TagInputComponent implements ControlValueAccessor {
|
||||
|
||||
@@ -7,11 +7,12 @@ import { commonReducers,ItemTypeService } from '../../../public-api'
|
||||
import { EditImageModalComponent} from '../edit-image-modal/edit-image-modal.component';
|
||||
import { AppConfig } from "../../shared/app.config";
|
||||
|
||||
@Component({
|
||||
selector: 'fm-thumbnail',
|
||||
templateUrl: 'thumbnail.component.html',
|
||||
styleUrls: ['thumbnail.component.scss']
|
||||
})
|
||||
@Component({
|
||||
selector: 'fm-thumbnail',
|
||||
templateUrl: 'thumbnail.component.html',
|
||||
styleUrls: ['thumbnail.component.scss'],
|
||||
standalone: false
|
||||
})
|
||||
|
||||
|
||||
export class ThumbnailComponent {
|
||||
|
||||
@@ -7,10 +7,11 @@ export interface TimeSpan {
|
||||
endDate:Date;
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: 'fm-timespan',
|
||||
templateUrl: './timespan.component.html',
|
||||
styleUrls: ['./timespan.component.css']
|
||||
@Component({
|
||||
selector: 'fm-timespan',
|
||||
templateUrl: './timespan.component.html',
|
||||
styleUrls: ['./timespan.component.css'],
|
||||
standalone: false
|
||||
})
|
||||
export class TimespanComponent implements OnInit, OnChanges {
|
||||
|
||||
|
||||
@@ -6,9 +6,10 @@ import * as appReducers from '../../reducers/app-common.reducer';
|
||||
import * as appActions from '../../actions/app-common.actions';
|
||||
|
||||
@Component({
|
||||
selector: 'fm-user-menu',
|
||||
templateUrl: './user-menu.component.html',
|
||||
styleUrls: ['./user-menu.component.scss']
|
||||
selector: 'fm-user-menu',
|
||||
templateUrl: './user-menu.component.html',
|
||||
styleUrls: ['./user-menu.component.scss'],
|
||||
standalone: false
|
||||
})
|
||||
export class UserMenuComponent implements OnInit {
|
||||
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -26,6 +26,7 @@ export class Item implements IItem {
|
||||
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() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,7 +29,8 @@ export interface State {
|
||||
settingMenuVisible: boolean,
|
||||
unreadNotifications: number,
|
||||
isOnline: boolean,
|
||||
isPageMode:boolean
|
||||
isPageMode:boolean,
|
||||
settingMenuBackgroundColor:string
|
||||
}
|
||||
|
||||
export const initialState: State = {
|
||||
@@ -51,7 +52,8 @@ export const initialState: State = {
|
||||
settingMenuVisible: false,
|
||||
unreadNotifications: 0,
|
||||
isOnline: true,
|
||||
isPageMode: true
|
||||
isPageMode: true,
|
||||
settingMenuBackgroundColor:'rgb(128, 128, 128)'
|
||||
}
|
||||
|
||||
export function reducer(state = initialState, action: appCommonActions.Actions ): State {
|
||||
@@ -187,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;
|
||||
}
|
||||
@@ -212,6 +218,7 @@ 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);
|
||||
|
||||
@@ -238,5 +245,4 @@ export const SelectgetUnreadNotifications = createSelector(selectAppCommonState,
|
||||
|
||||
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';
|
||||
|
||||
@@ -27,7 +25,8 @@ export class ItemService {
|
||||
return this.httpClient.get<{ [id: string]: IItemType }>(`${this.ApiEndpoint()}/api/v1/itemtypes/`);
|
||||
}
|
||||
|
||||
getFeatures(extent: number[], crs: string, searchText?: string, searchTags?:string,startDate?:Date,endDate?:Date,itemType?:string,parentCode?:string,dataFilter?:string,level?:number,indexed?:boolean): Observable<any> {
|
||||
getFeatures(extent: number[], crs: string, searchText?: string, searchTags?:string,startDate?:Date,endDate?:Date,
|
||||
itemType?:string,parentCode?:string,dataFilter?:string,level?:number,indexed?:boolean,atItemLocationItemCode?: string): Observable<any> {
|
||||
let params = new HttpParams();
|
||||
params = params.append("crs", crs);
|
||||
if (extent) params =params.append("bbox", extent.join(","));
|
||||
@@ -45,6 +44,7 @@ export class ItemService {
|
||||
if (parentCode) params = params.append("pc", parentCode);
|
||||
if (dataFilter) params = params.append("df", dataFilter);
|
||||
if (level) params = params.append("lvl", level.toString());
|
||||
if (atItemLocationItemCode) params = params.append("ail", atItemLocationItemCode);
|
||||
params = params.append("ind", indexed ?? true);
|
||||
return this.httpClient.get<any>(`${this.ApiEndpoint()}/api/v1/items/features/`, {params:params});
|
||||
}
|
||||
@@ -81,7 +81,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 +97,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 +131,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 +151,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;
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user