Compare commits
2 Commits
930d4fe0b7
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fdfc1bc5c1 | ||
| e7b1842297 |
@@ -52,6 +52,7 @@ ng serve
|
||||
```
|
||||
*Go*`
|
||||
|
||||
|
||||
Point your browser to http://localhost:4200
|
||||
|
||||
*ESLint*
|
||||
|
||||
28
angular.json
28
angular.json
@@ -129,7 +129,7 @@
|
||||
"extract-i18n": {
|
||||
"builder": "@angular-devkit/build-angular:extract-i18n",
|
||||
"options": {
|
||||
"buildTarget": "farmmaps-lib-app:build"
|
||||
"browserTarget": "farmmaps-lib-app:build"
|
||||
}
|
||||
},
|
||||
"test": {
|
||||
@@ -294,31 +294,5 @@
|
||||
},
|
||||
"cli": {
|
||||
"analytics": false
|
||||
},
|
||||
"schematics": {
|
||||
"@schematics/angular:component": {
|
||||
"type": "component"
|
||||
},
|
||||
"@schematics/angular:directive": {
|
||||
"type": "directive"
|
||||
},
|
||||
"@schematics/angular:service": {
|
||||
"type": "service"
|
||||
},
|
||||
"@schematics/angular:guard": {
|
||||
"typeSeparator": "."
|
||||
},
|
||||
"@schematics/angular:interceptor": {
|
||||
"typeSeparator": "."
|
||||
},
|
||||
"@schematics/angular:module": {
|
||||
"typeSeparator": "."
|
||||
},
|
||||
"@schematics/angular:pipe": {
|
||||
"typeSeparator": "."
|
||||
},
|
||||
"@schematics/angular:resolver": {
|
||||
"typeSeparator": "."
|
||||
}
|
||||
}
|
||||
}
|
||||
11283
package-lock.json
generated
11283
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
66
package.json
66
package.json
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "farmmaps-lib-app",
|
||||
"version": "4.20.0",
|
||||
"scripts": {
|
||||
"version": "4.19.1",
|
||||
"scripts": {
|
||||
"ng": "ng",
|
||||
"start": "ng serve",
|
||||
"build": "ng build",
|
||||
@@ -10,25 +10,25 @@
|
||||
"e2e": "ng e2e"
|
||||
},
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@angular-eslint/eslint-plugin": "20.7.0",
|
||||
"@angular/animations": "20.3.16",
|
||||
"@angular/common": "20.3.16",
|
||||
"@angular/compiler": "20.3.16",
|
||||
"@angular/core": "20.3.16",
|
||||
"@angular/forms": "20.3.16",
|
||||
"@angular/platform-browser": "20.3.16",
|
||||
"@angular/platform-browser-dynamic": "20.3.16",
|
||||
"@angular/router": "20.3.16",
|
||||
"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",
|
||||
"@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": "^19.0.0",
|
||||
"@ngrx/effects": "20.1.0",
|
||||
"@ngrx/router-store": "20.1.0",
|
||||
"@ngrx/store": "20.1.0",
|
||||
"@ng-bootstrap/ng-bootstrap": "^17.0.1",
|
||||
"@ngrx/effects": "^18.0.2",
|
||||
"@ngrx/router-store": "^18.0.2",
|
||||
"@ngrx/store": "^18.0.2",
|
||||
"@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": "20.1.0",
|
||||
"ngx-avatars": "1.10.0",
|
||||
"ngrx-store-localstorage": "^18.0.0",
|
||||
"ngx-avatars": "^1.8.0",
|
||||
"ngx-clipboard": "^16.0.0",
|
||||
"ngx-image-cropper": "^7.0.0",
|
||||
"ngx-uploadx": "7.0.1",
|
||||
"ngx-uploadx": "^6.2.0",
|
||||
"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.15.1"
|
||||
"zone.js": "~0.14.10"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"optionalDependencies": {
|
||||
"@lmdb/lmdb-linux-x64": "^3.1.0",
|
||||
"@rollup/rollup-linux-x64-gnu": "^4.21.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@angular-builders/custom-webpack": "20.0.0",
|
||||
"@angular-devkit/build-angular": "20.3.14",
|
||||
"@angular/cli": "20.3.14",
|
||||
"@angular/compiler-cli": "20.3.16",
|
||||
"@angular/language-service": "20.3.16",
|
||||
"@angular/localize": "20.3.16",
|
||||
"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",
|
||||
"@types/arcgis-rest-api": "^10.4.5",
|
||||
"@types/jasmine": "~2.8.8",
|
||||
"@types/jasminewd2": "^2.0.9",
|
||||
@@ -85,15 +85,9 @@
|
||||
"karma-coverage-istanbul-reporter": "^3.0.3",
|
||||
"karma-jasmine": "^5.1.0",
|
||||
"karma-jasmine-html-reporter": "^2.0.0",
|
||||
"ng-packagr": "^20.3.2",
|
||||
"ng-packagr": "^18.2.1",
|
||||
"protractor": "~7.0.0",
|
||||
"ts-node": "^8.8.1",
|
||||
"typescript": "~5.8.3"
|
||||
},
|
||||
"overrides": {
|
||||
"some-library": {
|
||||
"@angular/common": "$@angular/common",
|
||||
"@angular/core": "$@angular/core"
|
||||
}
|
||||
"typescript": "~5.4.4"
|
||||
}
|
||||
}
|
||||
@@ -8,11 +8,11 @@
|
||||
"tslib": "^2.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@angular/core": "20.3.16",
|
||||
"ngrx-store-localstorage": "20.1.0",
|
||||
"@ngrx/effects": "20.1.0",
|
||||
"@ngrx/router-store": "20.1.0",
|
||||
"@ngrx/store": "20.1.0",
|
||||
"@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",
|
||||
"tassign": "^1.0.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,9 +14,8 @@ export interface IDroppedFile {
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: 'fm-map-file-drop-target',
|
||||
template: '',
|
||||
standalone: false
|
||||
selector: 'fm-map-file-drop-target',
|
||||
template: ''
|
||||
})
|
||||
export class FileDropTargetComponent implements OnInit, OnDestroy {
|
||||
element: Element;
|
||||
|
||||
@@ -4,11 +4,10 @@ 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'],
|
||||
standalone: false
|
||||
@Component({
|
||||
selector: 'fm-map-gps-location',
|
||||
templateUrl: './gps-location.component.html',
|
||||
styleUrls: ['./gps-location.component.scss']
|
||||
})
|
||||
export class GpsLocation implements OnInit,OnChanges{
|
||||
|
||||
|
||||
@@ -21,13 +21,12 @@ 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) }
|
||||
],
|
||||
standalone: false
|
||||
@Component({
|
||||
selector: 'fm-map-item-layers',
|
||||
template: `<ng-content></ng-content>`,
|
||||
providers: [
|
||||
{ provide: LayerGroupComponent, useExisting: forwardRef(() => ItemLayersComponent) }
|
||||
]
|
||||
})
|
||||
|
||||
export class ItemLayersComponent extends LayerGroupComponent implements OnChanges, OnInit,OnDestroy {
|
||||
|
||||
@@ -21,13 +21,12 @@ 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) }
|
||||
],
|
||||
standalone: false
|
||||
@Component({
|
||||
selector: 'fm-map-item-source-vector',
|
||||
template: `<ng-content></ng-content>`,
|
||||
providers: [
|
||||
{ provide: SourceVectorComponent, useExisting: forwardRef(() => ItemVectorSourceComponent) }
|
||||
]
|
||||
})
|
||||
export class ItemVectorSourceComponent extends SourceVectorComponent implements OnInit, OnDestroy, OnChanges {
|
||||
instance: Vector<Feature<Geometry>>;
|
||||
|
||||
@@ -1,50 +1,31 @@
|
||||
<div>
|
||||
@if (itemLayers.length > 0) {
|
||||
<div class="layerlist">
|
||||
<div class="list-group">
|
||||
@for (itemLayer of itemLayers; track itemLayer) {
|
||||
<div class="list-group-item list-group-item-action p-2 text-truncate" [ngClass]="{'active' : selectedLayer==itemLayer}">
|
||||
<div (click)="handleSelectLayer($event,itemLayer)" [title]="itemLayer.item.name">{{itemLayer.item.name}}</div>
|
||||
@if (selectedLayer==itemLayer && !baseLayers) {
|
||||
<div class="mt-1">
|
||||
<span class="btn-group">
|
||||
<a title="Toggle visibility"href="#" class="btn btn-light btn-sm" (click)="handleToggleVisibility($event,itemLayer)"><i class="fa" aria-hidden="true" [ngClass]="{'fa-eye':!itemLayer.visible,'fa-eye-slash':itemLayer.visible}"></i></a>
|
||||
@if (itemLayer.visible) {
|
||||
<a title="Transparency 25%" href="#" class="btn btn-light btn-sm" (click)="handleSetOpacity($event,itemLayer,0.25)">25%</a>
|
||||
}
|
||||
@if (itemLayer.visible) {
|
||||
<a title="Transparency 50%" href="#" class="btn btn-light btn-sm" (click)="handleSetOpacity($event,itemLayer,0.5)">50%</a>
|
||||
}
|
||||
@if (itemLayer.visible) {
|
||||
<a title="Transparency 75%" href="#" class="btn btn-light btn-sm" (click)="handleSetOpacity($event,itemLayer,0.75)">75%</a>
|
||||
}
|
||||
@if (itemLayer.visible) {
|
||||
<a title="No transparency" href="#" class="btn btn-light btn-sm" (click)="handleSetOpacity($event,itemLayer,1)">100%</a>
|
||||
}
|
||||
</span>
|
||||
<a href="#" title="Zoom to extent" class="btn btn-light btn-sm" (click)="handleZoomToExtent($event,itemLayer)"><i class="far fa-search-plus" aria-hidden="true"></i></a>
|
||||
@if (firstLayer(itemLayer)) {
|
||||
<span><a href="#" title="Toggle legend" class="btn btn-light btn-sm" (click)="itemLayer.legendVisible=toggleLegend($event,itemLayer.legendVisible)"><i class="far fa-chart-bar" aria-hidden="true"></i></a></span>
|
||||
}
|
||||
@if (!dataLayers) {
|
||||
<span class="float-end"><a href="#" title="Remove overlay" class="btn btn-light btn-sm" (click)="handleDelete($event,itemLayer)"><i class="fas fa-layer-minus" aria-hidden="true"></i></a></span>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
@if (itemLayer.legendVisible) {
|
||||
<div>
|
||||
<div class="card legend">
|
||||
<fm-map-layer-legend [layer]="firstLayer(itemLayer)" (click)="handleLegendClick($event,itemLayer);" [histogramenabled]="true"></fm-map-layer-legend>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
} @else {
|
||||
<div class="list-group">
|
||||
<div class="list-group-item" i18n>No layers</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
<div>
|
||||
<div class="layerlist" *ngIf="itemLayers.length > 0;else noLayers">
|
||||
<div class="list-group">
|
||||
<div *ngFor="let itemLayer of itemLayers" class="list-group-item list-group-item-action p-2 text-truncate" [ngClass]="{'active' : selectedLayer==itemLayer}">
|
||||
<div (click)="handleSelectLayer($event,itemLayer)" [title]="itemLayer.item.name">{{itemLayer.item.name}}</div>
|
||||
<div class="mt-1" *ngIf="selectedLayer==itemLayer && !baseLayers">
|
||||
<span class="btn-group">
|
||||
<a title="Toggle visibility"href="#" class="btn btn-light btn-sm" (click)="handleToggleVisibility($event,itemLayer)"><i class="fa" aria-hidden="true" [ngClass]="{'fa-eye':!itemLayer.visible,'fa-eye-slash':itemLayer.visible}"></i></a>
|
||||
<a title="Transparency 25%" *ngIf="itemLayer.visible" href="#" class="btn btn-light btn-sm" (click)="handleSetOpacity($event,itemLayer,0.25)">25%</a>
|
||||
<a title="Transparency 50%" *ngIf="itemLayer.visible" href="#" class="btn btn-light btn-sm" (click)="handleSetOpacity($event,itemLayer,0.5)">50%</a>
|
||||
<a title="Transparency 75%" *ngIf="itemLayer.visible" href="#" class="btn btn-light btn-sm" (click)="handleSetOpacity($event,itemLayer,0.75)">75%</a>
|
||||
<a title="No transparency" *ngIf="itemLayer.visible" href="#" class="btn btn-light btn-sm" (click)="handleSetOpacity($event,itemLayer,1)">100%</a>
|
||||
</span>
|
||||
<a href="#" title="Zoom to extent" class="btn btn-light btn-sm" (click)="handleZoomToExtent($event,itemLayer)"><i class="far fa-search-plus" aria-hidden="true"></i></a>
|
||||
<span *ngIf="firstLayer(itemLayer)"><a href="#" title="Toggle legend" class="btn btn-light btn-sm" (click)="itemLayer.legendVisible=toggleLegend($event,itemLayer.legendVisible)"><i class="far fa-chart-bar" aria-hidden="true"></i></a></span>
|
||||
<span *ngIf="!dataLayers" class="float-end"><a href="#" title="Remove overlay" class="btn btn-light btn-sm" (click)="handleDelete($event,itemLayer)"><i class="fas fa-layer-minus" aria-hidden="true"></i></a></span>
|
||||
</div>
|
||||
<div *ngIf="itemLayer.legendVisible">
|
||||
<div class="card legend">
|
||||
<fm-map-layer-legend [layer]="firstLayer(itemLayer)" (click)="handleLegendClick($event,itemLayer);" [histogramenabled]="true"></fm-map-layer-legend>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<ng-template #noLayers>
|
||||
<div class="list-group">
|
||||
<div class="list-group-item" i18n>No layers</div>
|
||||
</div>
|
||||
</ng-template>
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
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'],
|
||||
standalone: false
|
||||
@Component({
|
||||
selector: 'fm-map-layer-list',
|
||||
templateUrl: './layer-list.component.html',
|
||||
styleUrls: ['./layer-list.component.scss']
|
||||
})
|
||||
|
||||
export class LayerListComponent {
|
||||
|
||||
@@ -1,27 +1,18 @@
|
||||
<div #layerValues class="layer-values">
|
||||
@if (enabled$ | async) {
|
||||
<div class="cross" >
|
||||
<div class="pointer"></div>
|
||||
@if ((layerValues$ | async ); as layers) {
|
||||
<div class="values-container border border-dark rounded p-2">
|
||||
<div class="lonlat pb-2 "><span class="font-weight-bold">{{lonlat$}}</span><i class="ms-2 fal fa-copy" (click)="copyToClipboard()"></i> </div>
|
||||
@if (layers.length>0 ) {
|
||||
<ul class="value-list p-0 mb-0">
|
||||
@for (layerValue of layers; track layerValue) {
|
||||
<li class="border-top pt-1 pb-1 value">
|
||||
<div>{{layerValue.layerName}}</div>
|
||||
<div>{{layerValue.date|date}}</div>
|
||||
<div>@if (layerValue.quantity) {
|
||||
<span><span class="me-1">{{layerValue.quantity}}</span> </span>
|
||||
}<span class="me-1 font-weight-bold">{{getScaledValue(layerValue)}}</span><span>{{layerValue.unit}}</span></div>
|
||||
</li>
|
||||
}
|
||||
</ul>
|
||||
} @else {
|
||||
<div i18n class="border-top pt-1 pb-1">No data at location</div>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
<div class="cross" *ngIf="enabled$ | async">
|
||||
<div class="pointer"></div>
|
||||
<div class="values-container border border-dark rounded p-2" *ngIf="(layerValues$ | async ) as layers">
|
||||
<div class="lonlat pb-2 "><span class="font-weight-bold">{{lonlat$}}</span><i class="ms-2 fal fa-copy" (click)="copyToClipboard()"></i> </div>
|
||||
<ul class="value-list p-0 mb-0" *ngIf="layers.length>0 ;else no_data">
|
||||
<li class="border-top pt-1 pb-1 value" *ngFor="let layerValue of layers">
|
||||
<div>{{layerValue.layerName}}</div>
|
||||
<div>{{layerValue.date|date}}</div>
|
||||
<div><span *ngIf="layerValue.quantity"><span class="me-1">{{layerValue.quantity}}</span> </span><span class="me-1 font-weight-bold">{{getScaledValue(layerValue)}}</span><span>{{layerValue.unit}}</span></div>
|
||||
</li>
|
||||
</ul>
|
||||
<ng-template #no_data>
|
||||
<div i18n class="border-top pt-1 pb-1">No data at location</div>
|
||||
</ng-template>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -14,10 +14,9 @@ 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'],
|
||||
standalone: false
|
||||
selector: 'fm-map-layer-values',
|
||||
templateUrl: './layer-values.component.html',
|
||||
styleUrls: ['./layer-values.component.scss']
|
||||
})
|
||||
export class LayerValuesComponent implements OnInit, AfterViewInit {
|
||||
|
||||
|
||||
@@ -6,11 +6,10 @@ 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,11 +5,10 @@ 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'],
|
||||
standalone: false
|
||||
@Component({
|
||||
selector: 'fm-map-pan-to-location',
|
||||
templateUrl: './pan-to-location.component.html',
|
||||
styleUrls: ['./pan-to-location.component.scss']
|
||||
})
|
||||
export class PanToLocation implements OnInit,OnChanges{
|
||||
|
||||
|
||||
@@ -5,11 +5,10 @@ import {View} from 'ol';
|
||||
|
||||
|
||||
|
||||
@Component({
|
||||
selector: 'fm-map-rotation-reset',
|
||||
templateUrl: './rotation-reset.component.html',
|
||||
styleUrls: ['./rotation-reset.component.scss'],
|
||||
standalone: false
|
||||
@Component({
|
||||
selector: 'fm-map-rotation-reset',
|
||||
templateUrl: './rotation-reset.component.html',
|
||||
styleUrls: ['./rotation-reset.component.scss']
|
||||
})
|
||||
export class RotationResetComponent implements OnInit {
|
||||
view: View;
|
||||
|
||||
@@ -3,10 +3,9 @@ import { ActivatedRoute } from '@angular/router';
|
||||
import { ViewComponent, MapComponent } from '@farmmaps/ng-openlayers';
|
||||
|
||||
|
||||
@Component({
|
||||
selector: 'fm-map-zoom-to-extent',
|
||||
template: `<ng-content></ng-content>`,
|
||||
standalone: false
|
||||
@Component({
|
||||
selector: 'fm-map-zoom-to-extent',
|
||||
template: `<ng-content></ng-content>`
|
||||
})
|
||||
export class ZoomToExtentComponent implements OnChanges {
|
||||
view: ViewComponent;
|
||||
|
||||
@@ -10,11 +10,10 @@ 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'],
|
||||
standalone: false
|
||||
@Component({
|
||||
selector: 'fm-map-feature-list-container',
|
||||
templateUrl: './feature-list-container.component.html',
|
||||
styleUrls: ['./feature-list-container.component.scss']
|
||||
})
|
||||
export class FeatureListContainerComponent {
|
||||
|
||||
|
||||
@@ -1,20 +1,14 @@
|
||||
<div class="card border-0">
|
||||
@if ((schemeItem|async); as schemeItem) {
|
||||
<div class="card-body">
|
||||
<fm-back-button></fm-back-button>
|
||||
<h4 i18n>Farm</h4>
|
||||
<h3>{{schemeItem.name}}</h3>
|
||||
@if (features; as features) {
|
||||
<div>
|
||||
<div class="cropfields">
|
||||
@for (feature of features; track feature) {
|
||||
<div class="row m-0 ps-3 pe-3" [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>
|
||||
<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>
|
||||
|
||||
@@ -11,11 +11,10 @@ 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'],
|
||||
standalone: false
|
||||
@Component({
|
||||
selector: 'fm-map-feature-list-cropfield',
|
||||
templateUrl: './feature-list-cropfield.component.html',
|
||||
styleUrls: ['./feature-list-cropfield.component.scss']
|
||||
})
|
||||
export class FeatureListCropfieldComponent extends AbstractFeatureListComponent implements OnInit {
|
||||
|
||||
|
||||
@@ -1,17 +1,13 @@
|
||||
<div class="card border-0">
|
||||
<div class="card-body">
|
||||
<fm-back-button></fm-back-button>
|
||||
<h3><i class="far fa-farm"></i> <span i18n>Farms</span></h3>
|
||||
@if (features; as features) {
|
||||
<div>
|
||||
<div class="farms">
|
||||
@for (feature of features; track feature) {
|
||||
<div class="row m-0 ps-3 pe-3"[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>
|
||||
<div class="card border-0">
|
||||
<div class="card-body">
|
||||
<fm-back-button></fm-back-button>
|
||||
<h3><i class="far fa-farm"></i> <span i18n>Farms</span></h3>
|
||||
<div *ngIf="features;let features">
|
||||
<div class="farms">
|
||||
<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>
|
||||
|
||||
@@ -13,11 +13,10 @@ 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'],
|
||||
standalone: false
|
||||
@Component({
|
||||
selector: 'fm-map-feature-list-croppingscheme',
|
||||
templateUrl: './feature-list-croppingscheme.component.html',
|
||||
styleUrls: ['./feature-list-croppingscheme.component.scss']
|
||||
})
|
||||
export class FeatureListCroppingschemeComponent extends AbstractFeatureListComponent {
|
||||
|
||||
|
||||
@@ -5,14 +5,13 @@ 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 {
|
||||
|
||||
|
||||
@@ -1,16 +1,14 @@
|
||||
@if (feature; as feature) {
|
||||
<div class="d-flex m-0">
|
||||
<div class="p-2">
|
||||
<div class="thumbnail">
|
||||
<fm-map-feature-thumbnail [feature]="feature"></fm-map-feature-thumbnail>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex-grow p-2 overflow-hidden">
|
||||
<h1 class="card-title" title="{{feature.get('name')}}">{{feature.get('name')}}</h1>
|
||||
<div class="card-text"><span>{{areaInHa(feature)| number:'1.2-2'}}
|
||||
ha</span> <span>{{feature.get('cropTypeName')}}</span> </div>
|
||||
<div class="card-text"><span>{{feature.get('datadate')|date}}</span> -
|
||||
<span>{{feature.get('dataenddate')|date}}</span> </div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
<div *ngIf="feature;let feature" class="d-flex m-0">
|
||||
<div class="p-2">
|
||||
<div class="thumbnail">
|
||||
<fm-map-feature-thumbnail [feature]="feature"></fm-map-feature-thumbnail>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex-grow p-2 overflow-hidden">
|
||||
<h1 class="card-title" title="{{feature.get('name')}}">{{feature.get('name')}}</h1>
|
||||
<div class="card-text"><span>{{areaInHa(feature)| number:'1.2-2'}}
|
||||
ha</span> <span>{{feature.get('cropTypeName')}}</span> </div>
|
||||
<div class="card-text"><span>{{feature.get('datadate')|date}}</span> -
|
||||
<span>{{feature.get('dataenddate')|date}}</span> </div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -12,11 +12,10 @@ 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'],
|
||||
standalone: false
|
||||
@Component({
|
||||
selector: 'fm-map-feature-list-feature-cropfield',
|
||||
templateUrl: './feature-list-feature-cropfield.component.html',
|
||||
styleUrls: ['./feature-list-feature-cropfield.component.scss']
|
||||
})
|
||||
export class FeatureListFeatureCropfieldComponent extends AbstractFeatureListFeatureComponent {
|
||||
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
@if (feature; as feature) {
|
||||
<div class="row m-0">
|
||||
<div *ngIf="feature;let feature" class="row m-0">
|
||||
<div class="col p-2">
|
||||
<h1 class="card-title" title="{{feature.get('name')}}">{{feature.get('name')}}</h1>
|
||||
<div class="card-text">{{feature.get('datadate')|date:'shortDate'}}</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
@@ -10,10 +10,9 @@ 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'],
|
||||
standalone: false
|
||||
selector: 'fm-map-feature-list-feature-croppingscheme',
|
||||
templateUrl: './feature-list-feature-croppingscheme.component.html',
|
||||
styleUrls: ['./feature-list-feature-croppingscheme.component.scss']
|
||||
})
|
||||
export class FeatureListFeatureCroppingschemeComponent extends AbstractFeatureListFeatureComponent {
|
||||
|
||||
|
||||
@@ -1,18 +1,12 @@
|
||||
@if (feature; as feature) {
|
||||
<div class="row m-0">
|
||||
<div *ngIf="feature;let feature" class="row m-0">
|
||||
<div class="col-3 w-25 m-0 p-2 thumbnail">
|
||||
@if (feature.get('thumbnail')) {
|
||||
<img [src]="config.getConfig('apiEndPoint') + '/api/v1/items/'+feature.get('code')+'/thumbnail'" />
|
||||
}
|
||||
@if (!feature.get('thumbnail')) {
|
||||
<div [style.background-color]="itemTypeService.getColor(feature.get('itemType'))">
|
||||
<i [ngClass]="itemTypeService.getIcon(feature.get('itemType'))"></i>
|
||||
</div>
|
||||
}
|
||||
<img *ngIf="feature.get('thumbnail')" [src]="config.getConfig('apiEndPoint') + '/api/v1/items/'+feature.get('code')+'/thumbnail'" />
|
||||
<div *ngIf="!feature.get('thumbnail')" [style.background-color]="itemTypeService.getColor(feature.get('itemType'))">
|
||||
<i [ngClass]="itemTypeService.getIcon(feature.get('itemType'))"></i>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col p-2">
|
||||
<h1 class="card-title" title="{{feature.get('name')}}"><i [ngClass]="itemTypeService.getIcon(feature.get('itemType'))" [style.color]="itemTypeService.getColor(feature.get('itemType'))"></i> {{feature.get('name')}}</h1>
|
||||
<div class="card-text">{{feature.get('datadate')|date:'shortDate'}}</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
@@ -17,11 +17,10 @@ export abstract class AbstractFeatureListFeatureComponent {
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
@Component({
|
||||
selector: 'fm-map-feature-list-feature',
|
||||
templateUrl: './feature-list-feature.component.html',
|
||||
styleUrls: ['./feature-list-feature.component.scss'],
|
||||
standalone: false
|
||||
@Component({
|
||||
selector: 'fm-map-feature-list-feature',
|
||||
templateUrl: './feature-list-feature.component.html',
|
||||
styleUrls: ['./feature-list-feature.component.scss']
|
||||
})
|
||||
export class FeatureListFeatureComponent extends AbstractFeatureListFeatureComponent {
|
||||
|
||||
|
||||
@@ -1,20 +1,14 @@
|
||||
<div class="card border-0">
|
||||
@if ((schemeItem|async); as schemeItem) {
|
||||
<div class="card-body">
|
||||
<fm-back-button></fm-back-button>
|
||||
<h4 i18n>Farm</h4>
|
||||
<h3>{{schemeItem.name}}</h3>
|
||||
@if (features; as features) {
|
||||
<div>
|
||||
<div class="cropfields">
|
||||
@for (feature of features; track feature) {
|
||||
<div class="row m-0 ps-3 pe-3" [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>
|
||||
<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>
|
||||
|
||||
@@ -11,11 +11,10 @@ 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
|
||||
@Component({
|
||||
selector: 'fm-map-feature-list-observation',
|
||||
templateUrl: './feature-list-observation.component.html',
|
||||
styleUrls: ['./feature-list-observation.component.scss']
|
||||
})
|
||||
export class FeatureListObservationComponent extends AbstractFeatureListComponent implements OnInit {
|
||||
|
||||
|
||||
@@ -1,10 +1,6 @@
|
||||
@if (features; as features) {
|
||||
<div>
|
||||
<fm-back-button></fm-back-button>
|
||||
@for (feature of features; track feature) {
|
||||
<div class="row m-0 ps-3 pe-3" [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 *ngIf="features;let features">
|
||||
<fm-back-button></fm-back-button>
|
||||
<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>
|
||||
|
||||
@@ -57,11 +57,10 @@ export abstract class AbstractFeatureListComponent {
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
@Component({
|
||||
selector: 'fm-map-feature-list',
|
||||
templateUrl: './feature-list.component.html',
|
||||
styleUrls: ['./feature-list.component.scss'],
|
||||
standalone: false
|
||||
@Component({
|
||||
selector: 'fm-map-feature-list',
|
||||
templateUrl: './feature-list.component.html',
|
||||
styleUrls: ['./feature-list.component.scss']
|
||||
})
|
||||
export class FeatureListComponent extends AbstractFeatureListComponent {
|
||||
|
||||
|
||||
@@ -6,10 +6,9 @@ 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'],
|
||||
standalone: false
|
||||
selector: 'fm-map-feature-thumbnail',
|
||||
templateUrl: './feature-thumbnail.component.html',
|
||||
styleUrls: ['./feature-thumbnail.component.scss']
|
||||
})
|
||||
export class GeometryThumbnailComponent implements AfterViewInit {
|
||||
|
||||
|
||||
@@ -3,9 +3,8 @@ import { Layer } from 'ol/layer';
|
||||
import { Source } from 'ol/source';
|
||||
import { MapComponent } from '@farmmaps/ng-openlayers';
|
||||
|
||||
@Directive({
|
||||
selector: '[fmMapIfZoomToShow]',
|
||||
standalone: false
|
||||
@Directive({
|
||||
selector: '[fmMapIfZoomToShow]',
|
||||
})
|
||||
export class ifZoomToShowDirective implements OnInit {
|
||||
@Input()
|
||||
|
||||
@@ -4,14 +4,13 @@ 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 {
|
||||
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
@if (item; as item) {
|
||||
<div class="widget" [style.background-color]="itemTypeService.getColor(item.itemType)">
|
||||
<div class="align-middle icon" [ngClass]="itemTypeService.getIcon(item.itemType)"></div>
|
||||
<div class="title">{{item.name}}</div>
|
||||
</div>
|
||||
}
|
||||
<div *ngIf="item;let item" class="widget" [style.background-color]="itemTypeService.getColor(item.itemType)">
|
||||
<div class="align-middle icon" [ngClass]="itemTypeService.getIcon(item.itemType)"></div>
|
||||
<div class="title">{{item.name}}</div>
|
||||
</div>
|
||||
|
||||
@@ -40,11 +40,10 @@ export abstract class AbstractItemWidgetComponent {
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
@Component({
|
||||
selector: 'fm-map-item-list-item',
|
||||
templateUrl: './item-list-item.component.html',
|
||||
styleUrls: ['./item-list-item.component.scss'],
|
||||
standalone: false
|
||||
@Component({
|
||||
selector: 'fm-map-item-list-item',
|
||||
templateUrl: './item-list-item.component.html',
|
||||
styleUrls: ['./item-list-item.component.scss']
|
||||
})
|
||||
export class ItemListItemComponent extends AbstractItemListItemComponent {
|
||||
|
||||
|
||||
@@ -1,11 +1,7 @@
|
||||
@if (items; as items) {
|
||||
<div class="widget-container pt-0">
|
||||
@for (item of items; track item) {
|
||||
<div class="widget" (click)="handleItemClick(item)">
|
||||
<div class="content">
|
||||
<fm-map-item-list-item-container [item]="item" class="item-container"></fm-map-item-list-item-container>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
<div *ngIf="items;let items" class="widget-container pt-0">
|
||||
<div class="widget" *ngFor="let item of items" (click)="handleItemClick(item)">
|
||||
<div class="content">
|
||||
<fm-map-item-list-item-container [item]="item" class="item-container"></fm-map-item-list-item-container>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
@@ -28,10 +28,9 @@ export abstract class AbstractItemListComponent {
|
||||
|
||||
@Injectable()
|
||||
@Component({
|
||||
selector: 'fm-map-item-list',
|
||||
templateUrl: './item-list.component.html',
|
||||
styleUrls: ['./item-list.component.scss'],
|
||||
standalone: false
|
||||
selector: 'fm-map-item-list',
|
||||
templateUrl: './item-list.component.html',
|
||||
styleUrls: ['./item-list.component.scss']
|
||||
})
|
||||
export class ItemListComponent extends AbstractItemListComponent {
|
||||
|
||||
|
||||
@@ -1,11 +1,7 @@
|
||||
@if (widgets; as widgets) {
|
||||
<div class="widget-container pt-0">
|
||||
@for (widget of widgets; track widget) {
|
||||
<div class="widget">
|
||||
<div class="content">
|
||||
<ng-template #widgetTemplate></ng-template>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
<div *ngIf="widgets;let widgets" class="widget-container pt-0">
|
||||
<div class="widget" *ngFor="let widget of widgets">
|
||||
<div class="content">
|
||||
<ng-template #widgetTemplate></ng-template>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
@@ -8,10 +8,9 @@ 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'],
|
||||
standalone: false
|
||||
selector: 'fm-map-item-widget-list',
|
||||
templateUrl: './item-widget-list.component.html',
|
||||
styleUrls: ['./item-widget-list.component.scss']
|
||||
})
|
||||
export class ItemWidgetListComponent implements AfterViewInit {
|
||||
|
||||
|
||||
@@ -1,39 +1,37 @@
|
||||
<div class="btn btn-outline-primary layer-switcher" (click)="handleClick($event)">
|
||||
<i class="fal fa-layer-group"></i>
|
||||
<div class="layers hidden" [ngClass]="{'hidden':!(showLayerSwitcher|async)}" (click)="$event.stopPropagation();">
|
||||
<div class="card layers-card m-1">
|
||||
<div class="card-header">
|
||||
<span i18n>Layers</span>
|
||||
<i class="float-end fas fa-times" (click)="close($event)"></i>
|
||||
</div>
|
||||
<ul class="navbar-nav">
|
||||
<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]="baseMaps|async" [selectedLayer]="selectedBaseLayer|async" (onSelectLayer)="handleSelectBaseLayer($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>Overlays</span></span>
|
||||
<div class="mb-4">
|
||||
<fm-map-layer-list [itemLayers]="overlayLayers|async" [selectedLayer]="selectedOverlayLayer|async" (onDelete)="handleOnDelete($event)" (onToggleVisibility)="handleOnToggleVisibility($event)" (onSetOpacity)="handleOnSetOpacity($event)" (onZoomToExtent)="handleZoomToExtent($event)" (onSelectLayer)="handleSelectOverlayLayer($event)"></fm-map-layer-list>
|
||||
</div>
|
||||
</li>
|
||||
@if (selectedItemLayer$ | async; as selectedItemLayer) {
|
||||
<li class="nav-item py-0">
|
||||
<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>
|
||||
</div>
|
||||
<div class="btn btn-outline-primary layer-switcher" (click)="handleClick($event)">
|
||||
<i class="fal fa-layer-group"></i>
|
||||
<div class="layers hidden" [ngClass]="{'hidden':!(showLayerSwitcher|async)}" (click)="$event.stopPropagation();">
|
||||
<div class="card layers-card m-1">
|
||||
<div class="card-header">
|
||||
<span i18n>Layers</span>
|
||||
<i class="float-end fas fa-times" (click)="close($event)"></i>
|
||||
</div>
|
||||
<ul class="navbar-nav">
|
||||
<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]="baseMaps|async" [selectedLayer]="selectedBaseLayer|async" (onSelectLayer)="handleSelectBaseLayer($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>Overlays</span></span>
|
||||
<div class="mb-4">
|
||||
<fm-map-layer-list [itemLayers]="overlayLayers|async" [selectedLayer]="selectedOverlayLayer|async" (onDelete)="handleOnDelete($event)" (onToggleVisibility)="handleOnToggleVisibility($event)" (onSetOpacity)="handleOnSetOpacity($event)" (onZoomToExtent)="handleZoomToExtent($event)" (onSelectLayer)="handleSelectOverlayLayer($event)"></fm-map-layer-list>
|
||||
</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>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>
|
||||
</div>
|
||||
|
||||
@@ -6,11 +6,10 @@ import * as mapActions from '../../actions/map.actions';
|
||||
import {createEmpty,extend } from 'ol/extent';
|
||||
import { filter, map, Observable } from 'rxjs';
|
||||
|
||||
@Component({
|
||||
selector: 'fm-map-layer-switcher',
|
||||
templateUrl: './layer-switcher.component.html',
|
||||
styleUrls: ['./layer-switcher.component.scss'],
|
||||
standalone: false
|
||||
@Component({
|
||||
selector: 'fm-map-layer-switcher',
|
||||
templateUrl: './layer-switcher.component.html',
|
||||
styleUrls: ['./layer-switcher.component.scss']
|
||||
})
|
||||
export class LayerSwitcher implements OnInit,OnChanges{
|
||||
|
||||
|
||||
@@ -8,8 +8,8 @@
|
||||
<div class="col-8 nopadding" ><span i18n>Max</span>:</div>
|
||||
<div class="col-4 pull-left nopadding">{{ getScaledValue(histogram.max)| number:'1.0-2'}}</div>
|
||||
|
||||
@if (showConfidenceInterval()) {
|
||||
<ng-container *ngIf="showConfidenceInterval()">
|
||||
<div class="col-8 nopadding"><span i18n>Confidence interval</span>:</div>
|
||||
<div class="col-4 pull-left nopadding">{{ getScaledValue(histogram.confidence * 100)| number:'1.0-0'}}%</div>
|
||||
}
|
||||
</ng-container>
|
||||
</div>
|
||||
|
||||
@@ -2,13 +2,12 @@ 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' +
|
||||
'}'],
|
||||
standalone: false
|
||||
selector: 'fm-map-histogram-details',
|
||||
templateUrl: './histogram-details.component.html',
|
||||
styles: ['.nopadding{\n' +
|
||||
' padding: 0 !important;\n' +
|
||||
' margin: 0 !important;\n' +
|
||||
'}']
|
||||
})
|
||||
export class HistogramDetailsComponent {
|
||||
|
||||
|
||||
@@ -1,68 +1,48 @@
|
||||
@if (showLegend()) {
|
||||
<table class="container">
|
||||
<tr>
|
||||
<td colspan="3">
|
||||
<div class="title">
|
||||
@if (showTitle) {
|
||||
<h4>{{layer.name}}</h4>
|
||||
}
|
||||
@if (layer.unit) {
|
||||
<b>({{layer.unit}})</b>
|
||||
}
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<a i18n-title title="more info"><i class="fal fa-info-circle text-primary" (click)="hideHistogramDetails = !hideHistogramDetails"></i></a>
|
||||
</td>
|
||||
<td colspan="2">
|
||||
@if (histogramenabled) {
|
||||
<div class="title">
|
||||
<h4>{{histogram}}</h4>
|
||||
@if (histogramunit) {
|
||||
<b>({{histogramunit}})</b>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
</td>
|
||||
</tr>
|
||||
@for (entry of layer.renderer.colorMap.entries; track entry; let i = $index) {
|
||||
<tr>
|
||||
<td class="legend-items"><span [style.background-color]="getAlphaHex(entry.color)" [style.border-color]="getHex(entry.color)"class="color"></span></td>
|
||||
<td class="legend-items-text">@if (!entry.label) {
|
||||
<span>{{getScaledValue(entry.value,layer.scale) | number:'1.0-2'}} {{legendunit}}</span>
|
||||
}@if (entry.label) {
|
||||
<span>{{entry.label}}</span>
|
||||
}</td>
|
||||
<td class="histogram-items">
|
||||
@if (showHistogram()) {
|
||||
<div>
|
||||
<span class="bar" [style.background-color]="getHex(entry.color)" [style.width]="getPart(layer.renderer, i)">
|
||||
</span>
|
||||
@if (getPercentage(layer.renderer,i); as percentage) {
|
||||
<span class="bar-label">{{percentage | number:'1.0-2'}} %</span>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
@if (showHistogram()) {
|
||||
<tr>
|
||||
<td colspan="4" class="pb-1 pt-1">
|
||||
<div class="info" [ngbCollapse]="hideHistogramDetails">
|
||||
@if (bandContainsStatistics()) {
|
||||
<fm-map-statistics-details [statistics]="layer.renderer.band.statistics" [scale]="layer.scale"></fm-map-statistics-details>
|
||||
} @else {
|
||||
<fm-map-histogram-details [histogram]="layer.renderer.band.histogram" [scale]="layer.scale"></fm-map-histogram-details>
|
||||
}
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
</table>
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<table class="container" *ngIf="showLegend()">
|
||||
<tr>
|
||||
<td colspan="3">
|
||||
<div class="title">
|
||||
<h4 *ngIf="showTitle">{{layer.name}}</h4>
|
||||
<b *ngIf="layer.unit">({{layer.unit}})</b>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<a i18n-title title="more info"><i class="fal fa-info-circle text-primary" (click)="hideHistogramDetails = !hideHistogramDetails"></i></a>
|
||||
</td>
|
||||
<td colspan="2">
|
||||
<div class="title" *ngIf="histogramenabled">
|
||||
<h4>{{histogram}}</h4>
|
||||
<b *ngIf="histogramunit">({{histogramunit}})</b>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr *ngFor="let entry of layer.renderer.colorMap.entries; let i = index ">
|
||||
<td class="legend-items"><span [style.background-color]="getAlphaHex(entry.color)" [style.border-color]="getHex(entry.color)"class="color"></span></td>
|
||||
<td class="legend-items-text"><span *ngIf="!entry.label">{{getScaledValue(entry.value,layer.scale) | number:'1.0-2'}} {{legendunit}}</span><span *ngIf="entry.label">{{entry.label}}</span></td>
|
||||
<td class="histogram-items">
|
||||
<div *ngIf="showHistogram()">
|
||||
<span class="bar" [style.background-color]="getHex(entry.color)" [style.width]="getPart(layer.renderer, i)">
|
||||
</span>
|
||||
<span *ngIf="getPercentage(layer.renderer,i) as percentage" class="bar-label">{{percentage | number:'1.0-2'}} %</span>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr *ngIf="showHistogram()">
|
||||
<td colspan="4" class="pb-1 pt-1">
|
||||
<div class="info" [ngbCollapse]="hideHistogramDetails">
|
||||
<ng-container *ngIf="bandContainsStatistics(); else histogram">
|
||||
<fm-map-statistics-details [statistics]="layer.renderer.band.statistics" [scale]="layer.scale"></fm-map-statistics-details>
|
||||
</ng-container>
|
||||
|
||||
<ng-template #histogram>
|
||||
<fm-map-histogram-details [histogram]="layer.renderer.band.histogram" [scale]="layer.scale"></fm-map-histogram-details>
|
||||
</ng-template>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -2,11 +2,10 @@ 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'],
|
||||
standalone: false
|
||||
@Component({
|
||||
selector: 'fm-map-layer-legend',
|
||||
templateUrl: './legend.component.html',
|
||||
styleUrls: ['./legend.component.scss']
|
||||
})
|
||||
export class LegendComponent implements OnInit,AfterViewInit {
|
||||
|
||||
|
||||
@@ -29,8 +29,8 @@
|
||||
<div class="col-4 pull-left nopadding">{{getSquaredScaledValue(statistics.variance)| number:'1.0-2'}}</div>
|
||||
<div class="col-8 nopadding"><span i18n>Coefficient of variation</span>:</div>
|
||||
<div class="col-4 pull-left nopadding">{{statistics.variationCoefficient | number:'1.0-2'}}</div>
|
||||
@if (statistics.confidenceIntervalLow !== undefined) {
|
||||
<ng-container *ngIf="statistics.confidenceIntervalLow !== undefined">
|
||||
<div class="col-8 nopadding">90% <span i18n>Confidence interval</span>:</div>
|
||||
<div class="col-4 pull-left nopadding">{{getScaledValue(statistics.confidenceIntervalLow) | number:'1.0-2'}} - {{getScaledValue(statistics.confidenceIntervalHigh) | number:'1.0-2'}}</div>
|
||||
}
|
||||
</ng-container>
|
||||
</div>
|
||||
|
||||
@@ -2,13 +2,12 @@ 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' +
|
||||
'}'],
|
||||
standalone: false
|
||||
selector: 'fm-map-statistics-details',
|
||||
templateUrl: './statistics-details.component.html',
|
||||
styles: ['.nopadding{\n' +
|
||||
' padding: 0 !important;\n' +
|
||||
' margin: 0 !important;\n' +
|
||||
'}']
|
||||
})
|
||||
export class StatisticsDetailsComponent {
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ div.map-search {
|
||||
}
|
||||
|
||||
.disabled {
|
||||
color:adjust(#000000,80%);
|
||||
color:lighten(#000000,80%);
|
||||
}
|
||||
|
||||
:host ::ng-deep ngb-typeahead-window.dropdown-menu {
|
||||
|
||||
@@ -6,11 +6,10 @@ 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'],
|
||||
standalone: false
|
||||
@Component({
|
||||
selector: 'fm-map-map-search',
|
||||
templateUrl: './map-search.component.html',
|
||||
styleUrls: ['./map-search.component.scss']
|
||||
})
|
||||
export class MapSearchComponent {
|
||||
|
||||
|
||||
@@ -1,109 +1,95 @@
|
||||
@if ({
|
||||
mapState:mapState$|async,
|
||||
extent:extent$|async,
|
||||
baseLayers:baseLayers$|async,
|
||||
overlayLayers:overlayLayers$|async,
|
||||
selectedItemLayer:selectedItemLayer$|async,
|
||||
features:features$|async,
|
||||
position:position$|async,
|
||||
parentCode:parentCode$|async,
|
||||
panelVisible:panelVisible$|async,
|
||||
openedModalName:openedModalName$|async,
|
||||
panelCollapsed:panelCollapsed$|async,
|
||||
panelExtraWide:panelExtraWide$|async,
|
||||
searchMinified:searchMinified$|async,
|
||||
selectedItem:selectedItem$|async,
|
||||
parentItem:parentItem$|async,
|
||||
queryState:queryState$|async,
|
||||
searchCollapsed:searchCollapsed$|async,
|
||||
clearEnabled:clearEnabled$|async,
|
||||
period:period$|async,
|
||||
compassHeading:compassHeading$|async,
|
||||
styles:styles$|async,
|
||||
selectedFeature:selectedFeature$|async,
|
||||
fullscreen:fullscreen$|async,
|
||||
showDataLayerSlide:showDataLayerSlide$|async,
|
||||
menuVisible:menuVisible$|async,
|
||||
}; as state) {
|
||||
<aol-map #map (moveEnd)="handleOnMoveEnd($event)" (click)="handleOnMouseDown($event)" (dblClick)="handleShowLayerValues($event)" [ngClass]="{'panel-visible':state.panelVisible,'fullscreen':state.fullscreen }" class="map">
|
||||
<div>
|
||||
</div>
|
||||
<aol-view [zoom]="state.mapState.zoom" [rotation]="state.mapState.rotation">
|
||||
<aol-coordinate [x]="state.mapState.xCenter" [y]="state.mapState.yCenter" [srid]="'EPSG:4326'"></aol-coordinate>
|
||||
<fm-map-zoom-to-extent [extent]="state.extent" [animate]="true"></fm-map-zoom-to-extent>
|
||||
</aol-view>
|
||||
<aol-interaction-default></aol-interaction-default>
|
||||
<aol-interaction-dragrotateandzoom></aol-interaction-dragrotateandzoom>
|
||||
<fm-map-item-layers [itemLayers]="state.baseLayers"></fm-map-item-layers>
|
||||
@if (!overrideOverlayLayers) {
|
||||
<fm-map-item-layers [itemLayers]="state.overlayLayers"></fm-map-item-layers>
|
||||
}
|
||||
@if (!overrideSelectedItemLayer) {
|
||||
<fm-map-item-layers [itemLayer]="state.selectedItemLayer" (onPrerender)="handlePrerender($event)"></fm-map-item-layers>
|
||||
}
|
||||
<aol-layer-vector>
|
||||
<fm-map-item-source-vector [styles]="state.styles" [features]="state.features" (onFeatureSelected)="handleFeatureClick($event)" (onFeatureHover)="handleFeatureHover($event)" [selectedFeature]="state.selectedFeature" [selectedItem]="state.selectedItem"></fm-map-item-source-vector>
|
||||
</aol-layer-vector>
|
||||
<router-outlet name="map-layers"></router-outlet>
|
||||
<fm-map-gps-location [position]="state.position" [headingTolerance]="20" [showHeading]="devicesService.IsMobile()" [showTolerance]="devicesService.IsMobile()" [heading]="state.compassHeading"></fm-map-gps-location>
|
||||
<fm-map-layer-values></fm-map-layer-values>
|
||||
<div class="viewport-container" [ngStyle]="{'bottom': bottom(state.panelVisible)}">
|
||||
<div class="control-container">
|
||||
<router-outlet name="map-controls"></router-outlet>
|
||||
<fm-map-layer-switcher></fm-map-layer-switcher>
|
||||
<fm-map-pan-to-location [position]="state.position" [mapState]="state.mapState" [animate]="true"></fm-map-pan-to-location>
|
||||
<fm-map-rotation-reset></fm-map-rotation-reset>
|
||||
</div>
|
||||
<div class="slide-container" [ngClass]="{'showDataLayerSlide':state.showDataLayerSlide}">
|
||||
<form>
|
||||
<input class="dataLayerSlide" (input)="handleSlideChange($event)" type="range" style="width: 100%" value="{{dataLayerSlideValue}}"/>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<fm-map-file-drop-target [parentCode]="state.parentCode" (onFileDropped)="handleFileDropped($event)"></fm-map-file-drop-target>
|
||||
@if (noContent) {
|
||||
<div>
|
||||
<fm-map-map-search #mapSearch [openedModalName]="state.openedModalName" (onOpenModal)="handleOpenModal($event)" (onCloseModal)="handleCloseModal()" [ngClass]="{'menuVisible':state.menuVisible}" (onToggleMenu)="handleToggleMenu($event)" (onSearchCollapse)="handleSearchCollapse($event)" (onSearchExpand)="handleSearchExpand($event)" [collapsed]="state.searchCollapsed" [searchMinified]="state.searchMinified" (onSearch)="handleSearch($event)" (onClear)="handleClearSearch($event)" [filterOptions]="state.queryState" [clearEnabled]="state.clearEnabled" [period]="state.period" (onPeriodChange)="handlePeriodChange($event)" (onCitySearch)="handleCitySearch($event)"></fm-map-map-search>
|
||||
</div>
|
||||
}
|
||||
<div class="side-panel-container">
|
||||
<fm-side-panel [resizeable]="true" (onResize)="handlePanelResize($event)" [visible]="state.panelVisible && noContent" [collapsed]="state.panelCollapsed" [collapsable]="false" [extrawide]="state.panelExtraWide">
|
||||
@if (noContent) {
|
||||
<div class="panel-wrapper">
|
||||
@if (!(state.searchMinified)) {
|
||||
<div class="panel-top bg-secondary">
|
||||
</div>
|
||||
}
|
||||
<div class="panel-bottom">
|
||||
@if (!(state.selectedItem)) {
|
||||
<div>
|
||||
<fm-map-feature-list-container [features]="state.features" [selectedFeature]="state.selectedFeature" [queryState]="state.queryState" [clickedFeature]="clickedFeature"></fm-map-feature-list-container>
|
||||
</div>
|
||||
}
|
||||
@if (state.selectedItem; as item) {
|
||||
<div>
|
||||
<fm-map-selected-item-container [item]="item" [parentItem]="state.parentItem" [itemLayer]="state.selectedItemLayer" [overlayLayers]="state.overlayLayers"></fm-map-selected-item-container>
|
||||
</div>
|
||||
}
|
||||
@if (state.features.length == 0) {
|
||||
<div class="no-results m-2">
|
||||
@if (state.queryState.query) {
|
||||
<div>Cannot find <span>{{state.queryState?.query}}</span></div>
|
||||
}
|
||||
@if (state.queryState?.tags) {
|
||||
<div>Cannot find tag <span>{{state.queryState?.tags}}</span></div>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</fm-side-panel>
|
||||
<fm-side-panel [resizeable]="true" [visible]="!noContent" [extrawide]="state.panelExtraWide">
|
||||
<router-outlet (activate)="handleSidepaneloutletActivate($event)" (deactivate)="handleSidepaneloutletDeactivate($event)"></router-outlet>
|
||||
</fm-side-panel>
|
||||
</div>
|
||||
</aol-map>
|
||||
}
|
||||
|
||||
|
||||
<ng-container *ngIf="{
|
||||
mapState:mapState$|async,
|
||||
extent:extent$|async,
|
||||
baseLayers:baseLayers$|async,
|
||||
overlayLayers:overlayLayers$|async,
|
||||
selectedItemLayer:selectedItemLayer$|async,
|
||||
features:features$|async,
|
||||
position:position$|async,
|
||||
parentCode:parentCode$|async,
|
||||
panelVisible:panelVisible$|async,
|
||||
openedModalName:openedModalName$|async,
|
||||
panelCollapsed:panelCollapsed$|async,
|
||||
panelExtraWide:panelExtraWide$|async,
|
||||
searchMinified:searchMinified$|async,
|
||||
selectedItem:selectedItem$|async,
|
||||
parentItem:parentItem$|async,
|
||||
queryState:queryState$|async,
|
||||
searchCollapsed:searchCollapsed$|async,
|
||||
clearEnabled:clearEnabled$|async,
|
||||
period:period$|async,
|
||||
compassHeading:compassHeading$|async,
|
||||
styles:styles$|async,
|
||||
selectedFeature:selectedFeature$|async,
|
||||
fullscreen:fullscreen$|async,
|
||||
showDataLayerSlide:showDataLayerSlide$|async
|
||||
} as state">
|
||||
<aol-map #map (moveEnd)="handleOnMoveEnd($event)" (click)="handleOnMouseDown($event)" (dblClick)="handleShowLayerValues($event)" [ngClass]="{'panel-visible':state.panelVisible,'fullscreen':state.fullscreen }" class="map">
|
||||
<div>
|
||||
|
||||
</div>
|
||||
|
||||
<aol-view [zoom]="state.mapState.zoom" [rotation]="state.mapState.rotation">
|
||||
<aol-coordinate [x]="state.mapState.xCenter" [y]="state.mapState.yCenter" [srid]="'EPSG:4326'"></aol-coordinate>
|
||||
<fm-map-zoom-to-extent [extent]="state.extent" [animate]="true"></fm-map-zoom-to-extent>
|
||||
</aol-view>
|
||||
|
||||
<aol-interaction-default></aol-interaction-default>
|
||||
<aol-interaction-dragrotateandzoom></aol-interaction-dragrotateandzoom>
|
||||
<fm-map-item-layers [itemLayers]="state.baseLayers"></fm-map-item-layers>
|
||||
<fm-map-item-layers *ngIf="!overrideOverlayLayers" [itemLayers]="state.overlayLayers"></fm-map-item-layers>
|
||||
<fm-map-item-layers *ngIf="!overrideSelectedItemLayer" [itemLayer]="state.selectedItemLayer" (onPrerender)="handlePrerender($event)"></fm-map-item-layers>
|
||||
<aol-layer-vector>
|
||||
<fm-map-item-source-vector [styles]="state.styles" [features]="state.features" (onFeatureSelected)="handleFeatureClick($event)" (onFeatureHover)="handleFeatureHover($event)" [selectedFeature]="state.selectedFeature" [selectedItem]="state.selectedItem"></fm-map-item-source-vector>
|
||||
</aol-layer-vector>
|
||||
<router-outlet name="map-layers"></router-outlet>
|
||||
<fm-map-gps-location [position]="state.position" [headingTolerance]="20" [showHeading]="devicesService.IsMobile()" [showTolerance]="devicesService.IsMobile()" [heading]="state.compassHeading"></fm-map-gps-location>
|
||||
<fm-map-layer-values></fm-map-layer-values>
|
||||
<div class="viewport-container" [ngStyle]="{'bottom': bottom(state.panelVisible)}">
|
||||
<div class="control-container">
|
||||
<router-outlet name="map-controls"></router-outlet>
|
||||
<fm-map-layer-switcher></fm-map-layer-switcher>
|
||||
<fm-map-pan-to-location [position]="state.position" [mapState]="state.mapState" [animate]="true"></fm-map-pan-to-location>
|
||||
<fm-map-rotation-reset></fm-map-rotation-reset>
|
||||
</div>
|
||||
<div class="slide-container" [ngClass]="{'showDataLayerSlide':state.showDataLayerSlide}">
|
||||
<form>
|
||||
<input class="dataLayerSlide" (input)="handleSlideChange($event)" type="range" style="width: 100%" value="{{dataLayerSlideValue}}"/>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<fm-map-file-drop-target [parentCode]="state.parentCode" (onFileDropped)="handleFileDropped($event)"></fm-map-file-drop-target>
|
||||
|
||||
<div *ngIf="noContent">
|
||||
<fm-map-map-search #mapSearch [openedModalName]="state.openedModalName" (onOpenModal)="handleOpenModal($event)" (onCloseModal)="handleCloseModal()" [ngClass]="{'menuVisible':state.menuVisible}" (onToggleMenu)="handleToggleMenu($event)" (onSearchCollapse)="handleSearchCollapse($event)" (onSearchExpand)="handleSearchExpand($event)" [collapsed]="state.searchCollapsed" [searchMinified]="state.searchMinified" (onSearch)="handleSearch($event)" (onClear)="handleClearSearch($event)" [filterOptions]="state.queryState" [clearEnabled]="state.clearEnabled" [period]="state.period" (onPeriodChange)="handlePeriodChange($event)" (onCitySearch)="handleCitySearch($event)"></fm-map-map-search>
|
||||
</div>
|
||||
<div class="side-panel-container">
|
||||
|
||||
<fm-side-panel [resizeable]="true" (onResize)="handlePanelResize($event)" [visible]="state.panelVisible && noContent" [collapsed]="state.panelCollapsed" [collapsable]="false" [extrawide]="state.panelExtraWide">
|
||||
<div class="panel-wrapper" *ngIf="noContent">
|
||||
<div class="panel-top bg-secondary" *ngIf="!(state.searchMinified)">
|
||||
</div>
|
||||
<div class="panel-bottom">
|
||||
|
||||
<div *ngIf="!(state.selectedItem)">
|
||||
<fm-map-feature-list-container [features]="state.features" [selectedFeature]="state.selectedFeature" [queryState]="state.queryState" [clickedFeature]="clickedFeature"></fm-map-feature-list-container>
|
||||
</div>
|
||||
|
||||
<div *ngIf="state.selectedItem;let item">
|
||||
<fm-map-selected-item-container [item]="item" [parentItem]="state.parentItem" [itemLayer]="state.selectedItemLayer" [overlayLayers]="state.overlayLayers"></fm-map-selected-item-container>
|
||||
</div>
|
||||
<div *ngIf="state.features.length == 0" class="no-results m-2">
|
||||
<div *ngIf="state.queryState.query">Cannot find <span>{{state.queryState?.query}}</span></div>
|
||||
<div *ngIf="state.queryState?.tags">Cannot find tag <span>{{state.queryState?.tags}}</span></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</fm-side-panel>
|
||||
<fm-side-panel [resizeable]="true" [visible]="!noContent" [extrawide]="state.panelExtraWide">
|
||||
<router-outlet (activate)="handleSidepaneloutletActivate($event)" (deactivate)="handleSidepaneloutletDeactivate($event)"></router-outlet>
|
||||
</fm-side-panel>
|
||||
</div>
|
||||
</aol-map>
|
||||
</ng-container>
|
||||
|
||||
|
||||
|
||||
@@ -38,11 +38,10 @@ import { tassign } from 'tassign';
|
||||
import * as style from 'ol/style';
|
||||
|
||||
|
||||
@Component({
|
||||
selector: 'fm-map-map',
|
||||
templateUrl: './map.component.html',
|
||||
styleUrls: ['./map.component.scss'],
|
||||
standalone: false
|
||||
@Component({
|
||||
selector: 'fm-map-map',
|
||||
templateUrl: './map.component.html',
|
||||
styleUrls: ['./map.component.scss']
|
||||
})
|
||||
|
||||
export class MapComponent implements OnInit, OnDestroy, AfterViewInit {
|
||||
|
||||
@@ -9,10 +9,9 @@ export interface IMetaData {
|
||||
attributes: any
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: 'fm-map-meta-data-modal',
|
||||
templateUrl: 'meta-data-modal.component.html',
|
||||
standalone: false
|
||||
@Component({
|
||||
selector: 'fm-map-meta-data-modal',
|
||||
templateUrl: 'meta-data-modal.component.html'
|
||||
})
|
||||
export class MetaDataModalComponent {
|
||||
|
||||
|
||||
@@ -15,11 +15,10 @@ 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'],
|
||||
standalone: false
|
||||
@Component({
|
||||
selector: 'fm-map-select-period-modal',
|
||||
templateUrl: 'select-period-modal.component.html',
|
||||
styleUrls: ['select-period-modal.component.scss']
|
||||
})
|
||||
export class SelectPeriodModalComponent {
|
||||
|
||||
|
||||
@@ -5,11 +5,10 @@ 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'],
|
||||
standalone: false
|
||||
@Component({
|
||||
selector: 'fm-map-selected-item-container',
|
||||
templateUrl: './selected-item-container.component.html',
|
||||
styleUrls: ['./selected-item-container.component.scss']
|
||||
})
|
||||
export class SelectedItemContainerComponent {
|
||||
|
||||
|
||||
@@ -1,23 +1,19 @@
|
||||
<div class="spacer"></div>
|
||||
@if (item; as item) {
|
||||
<div>
|
||||
<div class="card border-0">
|
||||
<div class="card-body">
|
||||
<fm-back-button></fm-back-button>
|
||||
<div class="card menu-card">
|
||||
<h1>Cropfield</h1>
|
||||
<h4>{{item.name}}</h4>
|
||||
<div class="card-text"><span>{{areaInHa(item)| number:'1.2-2'}} ha</span> <span>{{item.data.cropTypeName}}</span></div>
|
||||
<div class="card-text"><span>{{item.data.startDate|date}}</span> - <span>{{item.data.endDate|date}}</span> </div>
|
||||
<ul class="p-0 mt-2">
|
||||
@if (item.isEditable) {
|
||||
<li><a href="#" (click)="handleOnEdit(item)"><i class="fal fa-pencil" aria-hidden="true" i18n-title title="Edit"></i> <span i18n>Edit</span></a></li>
|
||||
}
|
||||
</ul>
|
||||
</div>
|
||||
<div *ngIf="item;let item">
|
||||
<div class="card border-0">
|
||||
<div class="card-body">
|
||||
<fm-back-button></fm-back-button>
|
||||
<div class="card menu-card">
|
||||
<h1>Cropfield</h1>
|
||||
<h4>{{item.name}}</h4>
|
||||
<div class="card-text"><span>{{areaInHa(item)| number:'1.2-2'}} ha</span> <span>{{item.data.cropTypeName}}</span></div>
|
||||
<div class="card-text"><span>{{item.data.startDate|date}}</span> - <span>{{item.data.endDate|date}}</span> </div>
|
||||
<ul class="p-0 mt-2">
|
||||
<li *ngIf="item.isEditable"><a href="#" (click)="handleOnEdit(item)"><i class="fal fa-pencil" aria-hidden="true" i18n-title title="Edit"></i> <span i18n>Edit</span></a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<fm-map-item-list [items]="(items|async)"></fm-map-item-list>
|
||||
<fm-map-item-widget-list [item]="item"></fm-map-item-widget-list>
|
||||
</div>
|
||||
<fm-map-item-list [items]="(items|async)"></fm-map-item-list>
|
||||
<fm-map-item-widget-list [item]="item"></fm-map-item-widget-list>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
@@ -15,11 +15,10 @@ 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'],
|
||||
standalone: false
|
||||
@Component({
|
||||
selector: 'fm-map-selected-item-cropfield',
|
||||
templateUrl: './selected-item-cropfield.component.html',
|
||||
styleUrls: ['./selected-item-cropfield.component.scss']
|
||||
})
|
||||
export class SelectedItemCropfieldComponent extends AbstractSelectedItemComponent implements OnInit{
|
||||
|
||||
|
||||
@@ -1,51 +1,37 @@
|
||||
<div class="spacer"></div>
|
||||
@if (item; as item) {
|
||||
<div>
|
||||
<div class="card border-0">
|
||||
<div class="card-body">
|
||||
<fm-back-button></fm-back-button>
|
||||
<div class="card menu-card">
|
||||
@if (parentOfItemType('vnd.farmmaps.itemtype.cropfield')) {
|
||||
<h2>{{parentItem.name}}</h2>
|
||||
}
|
||||
<h1>{{item.name}}</h1>
|
||||
</div>
|
||||
@if (item?.data.layers; as layers) {
|
||||
<div class="legend-container">
|
||||
<div class="card menu-card">
|
||||
@if (layers.length>1) {
|
||||
<div>
|
||||
<select (change)="onLayerChanged($event.target.value)">
|
||||
@for (l of layers; track l) {
|
||||
<option [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">
|
||||
@if (item.isEditable) {
|
||||
<li><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>
|
||||
}
|
||||
@if (itemTypeService.isLayer(item)) {
|
||||
@if (!getItemLayer(item,itemLayer.layerIndex)) {
|
||||
<li><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>
|
||||
}
|
||||
@if (getItemLayer(item,itemLayer.layerIndex)) {
|
||||
<li><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>
|
||||
}
|
||||
}
|
||||
<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>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
<div class="spacer"></div>
|
||||
<div *ngIf="item;let item">
|
||||
<div class="card border-0">
|
||||
<div class="card-body">
|
||||
<fm-back-button></fm-back-button>
|
||||
<div class="card menu-card">
|
||||
<h2 *ngIf="parentOfItemType('vnd.farmmaps.itemtype.cropfield')">{{parentItem.name}}</h2>
|
||||
<h1>{{item.name}}</h1>
|
||||
</div>
|
||||
<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>
|
||||
</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>
|
||||
<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>
|
||||
|
||||
@@ -12,11 +12,10 @@ import { AbstractSelectedItemComponent } from '../selected-item/selected-item.co
|
||||
|
||||
@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'],
|
||||
standalone: false
|
||||
@Component({
|
||||
selector: 'fm-map-selected-item-geotiff',
|
||||
templateUrl: './selected-item-geotiff.component.html',
|
||||
styleUrls: ['./selected-item-geotiff.component.scss']
|
||||
})
|
||||
export class SelectedItemGeotiffComponent extends AbstractSelectedItemComponent implements OnDestroy {
|
||||
sub: Subscription;
|
||||
|
||||
@@ -1,49 +1,35 @@
|
||||
<div class="spacer"></div>
|
||||
@if (item; as item) {
|
||||
<div>
|
||||
<div class="card border-0">
|
||||
<div class="card-body">
|
||||
<fm-back-button></fm-back-button>
|
||||
<div class="card menu-card">
|
||||
@if (parentOfItemType('vnd.farmmaps.itemtype.cropfield')) {
|
||||
<h2>{{parentItem.name}}</h2>
|
||||
}
|
||||
<h1>{{item.name}}</h1>
|
||||
</div>
|
||||
@if (item?.data.layers; as layers) {
|
||||
<div class="legend-container">
|
||||
<div class="card menu-card">
|
||||
@if (layers.length>1) {
|
||||
<div>
|
||||
<select (change)="onLayerChanged($event.target.value)">
|
||||
@for (l of layers; track l) {
|
||||
<option [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">
|
||||
@if (item.isEditable) {
|
||||
<li><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>
|
||||
}
|
||||
@if (itemTypeService.isLayer(item)) {
|
||||
@if (!getItemLayer(item,itemLayer.layerIndex)) {
|
||||
<li><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>
|
||||
}
|
||||
@if (getItemLayer(item,itemLayer.layerIndex)) {
|
||||
<li><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>
|
||||
}
|
||||
}
|
||||
<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>
|
||||
<div *ngIf="item;let item">
|
||||
<div class="card border-0">
|
||||
<div class="card-body">
|
||||
<fm-back-button></fm-back-button>
|
||||
<div class="card menu-card">
|
||||
<h2 *ngIf="parentOfItemType('vnd.farmmaps.itemtype.cropfield')">{{parentItem.name}}</h2>
|
||||
<h1>{{item.name}}</h1>
|
||||
</div>
|
||||
<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>
|
||||
</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>
|
||||
}
|
||||
</div>
|
||||
|
||||
@@ -12,11 +12,10 @@ 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'],
|
||||
standalone: false
|
||||
@Component({
|
||||
selector: 'fm-map-selected-item-shape',
|
||||
templateUrl: './selected-item-shape.component.html',
|
||||
styleUrls: ['./selected-item-shape.component.scss']
|
||||
})
|
||||
export class SelectedItemShapeComponent extends AbstractSelectedItemComponent implements OnDestroy {
|
||||
public selectedLayer = 0;
|
||||
|
||||
@@ -1,70 +1,52 @@
|
||||
<div class="spacer"></div>
|
||||
@if (selectedItem(); as item) {
|
||||
<div>
|
||||
<div class="card border-0">
|
||||
<div class="card-body">
|
||||
<fm-back-button></fm-back-button>
|
||||
<div class="card menu-card">
|
||||
@if (parentOfItemType('vnd.farmmaps.itemtype.cropfield')) {
|
||||
<h2>{{parentItem.name}}</h2>
|
||||
}
|
||||
<h1>{{item.name}}</h1>
|
||||
</div>
|
||||
@if (item?.data.layers; as 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>
|
||||
@if (temporalService.hasPrevious(itemLayer)) {
|
||||
<button 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>
|
||||
@if (temporalService.hasNext(itemLayer)) {
|
||||
<button 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">
|
||||
@if (layers.length>1) {
|
||||
<div>
|
||||
<select (change)="onLayerChanged($event.target.value)">
|
||||
@for (l of layers; track l) {
|
||||
<option [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">
|
||||
@if (item.isEditable) {
|
||||
<li><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>
|
||||
}
|
||||
@if (itemTypeService.isLayer(item)) {
|
||||
@if (!getItemLayer(item,itemLayer.layerIndex)) {
|
||||
<li><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>
|
||||
}
|
||||
@if (getItemLayer(item,itemLayer.layerIndex)) {
|
||||
<li><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>
|
||||
}
|
||||
}
|
||||
<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>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
<div class="spacer"></div>
|
||||
<div *ngIf="selectedItem();let item">
|
||||
<div class="card border-0">
|
||||
<div class="card-body">
|
||||
<fm-back-button></fm-back-button>
|
||||
<div class="card menu-card">
|
||||
<h2 *ngIf="parentOfItemType('vnd.farmmaps.itemtype.cropfield')">{{parentItem.name}}</h2>
|
||||
<h1>{{item.name}}</h1>
|
||||
</div>
|
||||
<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">
|
||||
<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>
|
||||
</ng-container>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -13,11 +13,10 @@ import { AbstractSelectedItemComponent } from '../selected-item/selected-item.co
|
||||
|
||||
@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'],
|
||||
standalone: false
|
||||
@Component({
|
||||
selector: 'fm-map-selected-item-temporal',
|
||||
templateUrl: './selected-item-temporal.component.html',
|
||||
styleUrls: ['./selected-item-temporal.component.scss']
|
||||
})
|
||||
export class SelectedItemTemporalComponent extends AbstractSelectedItemComponent implements OnDestroy {
|
||||
sub: Subscription;
|
||||
|
||||
@@ -1,31 +1,21 @@
|
||||
@if (item; as item) {
|
||||
<div>
|
||||
<div class="card border-0">
|
||||
<fm-thumbnail [item]="item" [edit]="item.isEditable"></fm-thumbnail>
|
||||
</div>
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<fm-back-button></fm-back-button>
|
||||
<h1 class="card-title">{{item.name}}</h1>
|
||||
<div class="card menu-card">
|
||||
<ul class="p-0 mt-2">
|
||||
@if (itemTypeService.hasViewer(item)) {
|
||||
<li><a href="#" (click)="handleOnView(item)" class="btn btn-outline-secondary"><i class="fal fa-eye" aria-hidden="true" title="View"></i> <span i18n>View</span></a></li>
|
||||
}
|
||||
@if (item.isEditable) {
|
||||
<li><a href="#" (click)="handleOnEdit(item)"><i class="fal fa-pencil" aria-hidden="true" title="Edit"></i> <span i18n>Edit</span></a></li>
|
||||
}
|
||||
@if (itemTypeService.isLayer(item)) {
|
||||
@if (!getItemLayer(item)) {
|
||||
<li><a href="#" (click)="handleAddAsLayer(item)"><i class="fas fa-layer-plus" aria-hidden="true" i18n-title title="Add as layer"></i> <span i18n>Add as overlay</span></a></li>
|
||||
}
|
||||
@if (getItemLayer(item)) {
|
||||
<li ><a href="#" (click)="handleRemoveLayer(item)"><i class="fas fa-layer-minus" aria-hidden="true" i18n-title title="Remove overlay"></i> <span i18n>Remove overlay</span></a></li>
|
||||
}
|
||||
}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
<div *ngIf="item;let item">
|
||||
<div class="card border-0">
|
||||
<fm-thumbnail [item]="item" [edit]="item.isEditable"></fm-thumbnail>
|
||||
</div>
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<fm-back-button></fm-back-button>
|
||||
<h1 class="card-title">{{item.name}}</h1>
|
||||
<div class="card menu-card">
|
||||
<ul class="p-0 mt-2">
|
||||
<li *ngIf="itemTypeService.hasViewer(item)"><a href="#" (click)="handleOnView(item)" class="btn btn-outline-secondary"><i class="fal fa-eye" aria-hidden="true" title="View"></i> <span i18n>View</span></a></li>
|
||||
<li *ngIf="item.isEditable"><a href="#" (click)="handleOnEdit(item)"><i class="fal fa-pencil" aria-hidden="true" title="Edit"></i> <span i18n>Edit</span></a></li>
|
||||
<ng-container *ngIf="itemTypeService.isLayer(item)">
|
||||
<li *ngIf="!getItemLayer(item)"><a href="#" (click)="handleAddAsLayer(item)"><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)"><a href="#" (click)="handleRemoveLayer(item)"><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>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -74,11 +74,10 @@ export abstract class AbstractSelectedItemComponent {
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
@Component({
|
||||
selector: 'fm-map-selected-item',
|
||||
templateUrl: './selected-item.component.html',
|
||||
styleUrls: ['./selected-item.component.scss'],
|
||||
standalone: false
|
||||
@Component({
|
||||
selector: 'fm-map-selected-item',
|
||||
templateUrl: './selected-item.component.html',
|
||||
styleUrls: ['./selected-item.component.scss']
|
||||
})
|
||||
export class SelectedItemComponent extends AbstractSelectedItemComponent {
|
||||
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import { Directive, ViewContainerRef } from '@angular/core';
|
||||
|
||||
@Directive({
|
||||
selector: '[fm-map-widget-host]',
|
||||
standalone: false
|
||||
selector: '[fm-map-widget-host]',
|
||||
})
|
||||
export class WidgetHostDirective {
|
||||
constructor(public viewContainerRef: ViewContainerRef) { }
|
||||
|
||||
@@ -1,16 +1,6 @@
|
||||
<div>
|
||||
@switch (stage) {
|
||||
@case (StageEnum.DevelopmentPreAlpha) {
|
||||
<h6 style="color:darkred" [ngbTooltip]="info"><b><span i18n>Stage:Pre-alpha</span></b></h6>
|
||||
}
|
||||
@case (StageEnum.DevelopmentAlpha) {
|
||||
<h6 style="color:red" [ngbTooltip]="info"><b><span i18n>Stage:Alpha</span></b></h6>
|
||||
}
|
||||
@case (StageEnum.DevelopmentBeta) {
|
||||
<h6 style="color:orange" [ngbTooltip]="info" ><b><span i18n>Stage:Beta</span></b></h6>
|
||||
}
|
||||
@case (StageEnum.ReleaseCandidate) {
|
||||
<h6 style="color:green" [ngbTooltip]="info" ><b><span i18n>Stage:RC</span></b></h6>
|
||||
}
|
||||
}
|
||||
</div>
|
||||
<div [ngSwitch]="stage">
|
||||
<h6 *ngSwitchCase="StageEnum.DevelopmentPreAlpha" style="color:darkred" [ngbTooltip]="info"><b><span i18n>Stage:Pre-alpha</span></b></h6>
|
||||
<h6 *ngSwitchCase="StageEnum.DevelopmentAlpha" style="color:red" [ngbTooltip]="info"><b><span i18n>Stage:Alpha</span></b></h6>
|
||||
<h6 *ngSwitchCase="StageEnum.DevelopmentBeta" style="color:orange" [ngbTooltip]="info" ><b><span i18n>Stage:Beta</span></b></h6>
|
||||
<h6 *ngSwitchCase="StageEnum.ReleaseCandidate" style="color:green" [ngbTooltip]="info" ><b><span i18n>Stage:RC</span></b></h6>
|
||||
</div>
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
import { Component, OnInit, Input } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'fm-map-widget-status',
|
||||
templateUrl: './widget-status.component.html',
|
||||
styleUrls: ['./widget-status.component.css'],
|
||||
standalone: false
|
||||
selector: 'fm-map-widget-status',
|
||||
templateUrl: './widget-status.component.html',
|
||||
styleUrls: ['./widget-status.component.css']
|
||||
})
|
||||
export class WidgetStatusComponent implements OnInit {
|
||||
@Input() stage: Stage;
|
||||
|
||||
@@ -2,10 +2,9 @@ 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>',
|
||||
standalone: false
|
||||
@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>'
|
||||
})
|
||||
export class ZoomToShowAlert {
|
||||
public layer$: Layer<Source>;
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"compilerOptions": {
|
||||
"outDir": "../../out-tsc/lib",
|
||||
"module": "es2015",
|
||||
"moduleResolution": "bundler",
|
||||
"moduleResolution": "node",
|
||||
"declaration": true,
|
||||
"sourceMap": true,
|
||||
"inlineSources": true,
|
||||
@@ -18,7 +18,9 @@
|
||||
],
|
||||
"paths": {
|
||||
"@angular/*": [
|
||||
"node_modules/@angular/*"
|
||||
|
||||
"node_modules/@angular/*"
|
||||
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"compilerOptions": {
|
||||
"outDir": "../../out-tsc/lib",
|
||||
"module": "es2015",
|
||||
"moduleResolution": "bundler",
|
||||
"moduleResolution": "node",
|
||||
"declaration": true,
|
||||
"sourceMap": true,
|
||||
"inlineSources": true,
|
||||
@@ -18,7 +18,9 @@
|
||||
],
|
||||
"paths": {
|
||||
"@angular/*": [
|
||||
"node_modules/@angular/*"
|
||||
|
||||
"node_modules/@angular/*"
|
||||
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
@@ -8,8 +8,8 @@
|
||||
"tslib": "^2.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@angular/common": "20.3.16",
|
||||
"@angular/core": "20.3.16",
|
||||
"@angular/common": "18.2.3",
|
||||
"@angular/core": "18.2.3",
|
||||
"cesium": "^1.97.0",
|
||||
"ol-cesium": ">=2.13.0"
|
||||
}
|
||||
|
||||
@@ -7,11 +7,10 @@ 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'],
|
||||
standalone: false
|
||||
@Component({
|
||||
selector: 'fm-map3d-switch2d3d',
|
||||
templateUrl: './switch2d3d.component.html',
|
||||
styleUrls: ['./switch2d3d.component.scss']
|
||||
})
|
||||
export class Switch2D3DComponent {
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"outDir": "../../out-tsc/lib",
|
||||
"target": "es2015",
|
||||
"module": "es2015",
|
||||
"moduleResolution": "bundler",
|
||||
"moduleResolution": "node",
|
||||
"declaration": true,
|
||||
"sourceMap": true,
|
||||
"inlineSources": true,
|
||||
@@ -19,7 +19,9 @@
|
||||
],
|
||||
"paths": {
|
||||
"@angular/*": [
|
||||
"node_modules/@angular/*"
|
||||
|
||||
"node_modules/@angular/*"
|
||||
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"outDir": "../../out-tsc/lib",
|
||||
"target": "es2015",
|
||||
"module": "es2015",
|
||||
"moduleResolution": "bundler",
|
||||
"moduleResolution": "node",
|
||||
"declaration": true,
|
||||
"sourceMap": true,
|
||||
"inlineSources": true,
|
||||
@@ -19,7 +19,9 @@
|
||||
],
|
||||
"paths": {
|
||||
"@angular/*": [
|
||||
"node_modules/@angular/*"
|
||||
|
||||
"node_modules/@angular/*"
|
||||
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
@@ -5,20 +5,20 @@
|
||||
"registry": "https://repository.akkerweb.nl/repository/npm-hosted/"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@ng-bootstrap/ng-bootstrap": "^19.0.0",
|
||||
"@angular/common": "20.3.16",
|
||||
"@angular/core": "20.3.16",
|
||||
"@angular/forms": "20.3.16",
|
||||
"@ngrx/effects": "20.1.0",
|
||||
"@ngrx/router-store": "20.1.0",
|
||||
"@ngrx/store": "20.1.0",
|
||||
"@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",
|
||||
"tassign": "^1.0.0",
|
||||
"bootstrap": "^5.3.3",
|
||||
"@microsoft/signalr": "^3.1.16",
|
||||
"ngx-uploadx": "7.0.1",
|
||||
"ngx-uploadx": "^6.2.0",
|
||||
"angular-oauth2-oidc": "^17.0.2",
|
||||
"moment": "^2.29.4",
|
||||
"ngx-avatars": "1.10.0",
|
||||
"ngx-avatars": "^1.8.0",
|
||||
"ngx-image-cropper": "^7.0.0",
|
||||
"ngx-clipboard": "^16.0.0"
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// angular modules
|
||||
import { NgModule, ModuleWithProviders, Injector, Optional, SkipSelf, inject, provideAppInitializer } from '@angular/core';
|
||||
import { NgModule, APP_INITIALIZER, ModuleWithProviders, Injector, Optional, SkipSelf } from '@angular/core';
|
||||
import { DatePipe } from '@angular/common';
|
||||
import { HTTP_INTERCEPTORS } from '@angular/common/http';
|
||||
|
||||
@@ -90,10 +90,12 @@ export class AppCommonServiceModule {
|
||||
providers: [
|
||||
AppConfig,
|
||||
ItemTypeService,
|
||||
provideAppInitializer(() => {
|
||||
const initializerFn = (appConfigFactory)(inject(Injector), inject(AppConfig), inject(OAuthService), inject(AuthConfigFactory), inject(OAuthStorage), inject(ItemTypeService));
|
||||
return initializerFn();
|
||||
}),
|
||||
{
|
||||
provide: APP_INITIALIZER,
|
||||
useFactory: appConfigFactory,
|
||||
deps: [Injector, AppConfig, OAuthService, AuthConfigFactory, OAuthStorage, ItemTypeService],
|
||||
multi: true
|
||||
},
|
||||
{
|
||||
provide: HTTP_INTERCEPTORS,
|
||||
useClass: AccessTokenInterceptor,
|
||||
|
||||
@@ -6,10 +6,9 @@ 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'],
|
||||
standalone: false
|
||||
selector: 'fm-app-menu',
|
||||
templateUrl: './app-menu.component.html',
|
||||
styleUrls: ['./app-menu.component.scss']
|
||||
})
|
||||
export class AppMenuComponent implements OnInit {
|
||||
|
||||
|
||||
@@ -1,51 +1,47 @@
|
||||
<div class="app fullscreen" (click)="handleClick($event)" [ngClass]="{'fullscreen' :(fullScreen|async),'pagemode':(isPageMode|async),'appmode':!(isPageMode|async)}">
|
||||
<nav class="navbar navbar-light navbar-expand bg-light navigation-clean">
|
||||
<div class="container-fluid p-3 justify-content-start">
|
||||
<div class="header-logo pageonly"><router-outlet name="header-logo"></router-outlet></div>
|
||||
<button type="button" class="btn btn-outline-secondary apponly" (click)="handleToggleMenu($event)"><i class="fal fa-bars" aria-hidden="true"></i></button>
|
||||
<router-outlet name="menu" class="ms-4"></router-outlet>
|
||||
<div class="collapse navbar-collapse pageonly">
|
||||
<a class="btn btn-primary ms-auto" role="button" [routerLink]="[ startPage == null?'/map':startPage]">
|
||||
@if ((user|async)==null) {
|
||||
<span i18n>Sign in</span>
|
||||
}
|
||||
@if ((user|async)!=null) {
|
||||
<span i18n>To app</span>
|
||||
}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
<div class="body">
|
||||
<router-outlet></router-outlet>
|
||||
</div>
|
||||
<fm-menu-background [visible]="menuVisible|async"></fm-menu-background>
|
||||
<fm-side-panel [visible]="menuVisible|async" [left]="true" class="menu" (click)="handleStopBubble($event)">
|
||||
<div class="container-fluid">
|
||||
<div class="body">
|
||||
<div class="d-flex flex-row">
|
||||
<div class="mt-2 mb-2 flex-grow-1 logo" (click)="handleHome($event)"><router-outlet name="side-panel-logo"></router-outlet></div>
|
||||
<div class="mt-2 mb-2 ms-2"><button type="button" class="btn btn-outline-secondary" (click)="handleToggleMenu($event)"><i class="fal fa-times" aria-hidden="true"></i></button></div>
|
||||
</div>
|
||||
<div class="d-flex flex-column cards">
|
||||
<router-outlet name="side-panel-menu"></router-outlet>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</fm-side-panel>
|
||||
@if (showUploadProgress) {
|
||||
<fm-resumable-file-upload></fm-resumable-file-upload>
|
||||
}
|
||||
<div class="user-menu apponly">
|
||||
<fm-setting-menu [user]="user|async" [showMenu]="settingMenuVisible|async" [backgroundColor]="settingMenuBackgroundColor|async"></fm-setting-menu>
|
||||
<fm-help-menu [user]="user|async" [showMenu]="helpMenuVisible|async"></fm-help-menu>
|
||||
<fm-notification-menu [user]="user|async" [unread]="unreadNotifications|async" [showMenu]="notificationMenuVisible|async"></fm-notification-menu>
|
||||
<fm-app-menu [user]="user|async" [showMenu]="appMenuVisible|async"></fm-app-menu>
|
||||
<fm-user-menu [user]="user|async" [showMenu]="accountMenuVisible|async"></fm-user-menu>
|
||||
</div>
|
||||
<div class="healthstatus-container online apponly" [ngClass]="{'online' :(isOnline|async)}">
|
||||
<div class="healthstatus alert alert-danger m-0" >
|
||||
<span i18n>Not connected, make sure your device has an active internet connection</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="app fullscreen" (click)="handleClick($event)" [ngClass]="{'fullscreen' :(fullScreen|async),'pagemode':(isPageMode|async),'appmode':!(isPageMode|async)}">
|
||||
<nav class="navbar navbar-light navbar-expand bg-light navigation-clean">
|
||||
<div class="container-fluid p-3 justify-content-start">
|
||||
<div class="header-logo pageonly"><router-outlet name="header-logo"></router-outlet></div>
|
||||
<button type="button" class="btn btn-outline-secondary apponly" (click)="handleToggleMenu($event)"><i class="fal fa-bars" aria-hidden="true"></i></button>
|
||||
<router-outlet name="menu" class="ms-4"></router-outlet>
|
||||
<div class="collapse navbar-collapse pageonly">
|
||||
<a class="btn btn-primary ms-auto" role="button" [routerLink]="[ startPage == null?'/map':startPage]">
|
||||
<span *ngIf="(user|async)==null" i18n>Sign in</span>
|
||||
<span *ngIf="(user|async)!=null" i18n>To app</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
<div class="body">
|
||||
<router-outlet></router-outlet>
|
||||
</div>
|
||||
<fm-menu-background [visible]="menuVisible|async"></fm-menu-background>
|
||||
<fm-side-panel [visible]="menuVisible|async" [left]="true" class="menu" (click)="handleStopBubble($event)">
|
||||
<div class="container-fluid">
|
||||
<div class="body">
|
||||
<div class="d-flex flex-row">
|
||||
<div class="mt-2 mb-2 flex-grow-1 logo" (click)="handleHome($event)"><router-outlet name="side-panel-logo"></router-outlet></div>
|
||||
<div class="mt-2 mb-2 ms-2"><button type="button" class="btn btn-outline-secondary" (click)="handleToggleMenu($event)"><i class="fal fa-times" aria-hidden="true"></i></button></div>
|
||||
</div>
|
||||
<div class="d-flex flex-column cards">
|
||||
<router-outlet name="side-panel-menu"></router-outlet>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</fm-side-panel>
|
||||
<ng-container *ngIf="showUploadProgress">
|
||||
<fm-resumable-file-upload></fm-resumable-file-upload>
|
||||
</ng-container>
|
||||
<div class="user-menu apponly">
|
||||
<fm-setting-menu [user]="user|async" [showMenu]="settingMenuVisible|async" [backgroundColor]="settingMenuBackgroundColor|async"></fm-setting-menu>
|
||||
<fm-help-menu [user]="user|async" [showMenu]="helpMenuVisible|async"></fm-help-menu>
|
||||
<fm-notification-menu [user]="user|async" [unread]="unreadNotifications|async" [showMenu]="notificationMenuVisible|async"></fm-notification-menu>
|
||||
<fm-app-menu [user]="user|async" [showMenu]="appMenuVisible|async"></fm-app-menu>
|
||||
<fm-user-menu [user]="user|async" [showMenu]="accountMenuVisible|async"></fm-user-menu>
|
||||
</div>
|
||||
<div class="healthstatus-container online apponly" [ngClass]="{'online' :(isOnline|async)}">
|
||||
<div class="healthstatus alert alert-danger m-0" >
|
||||
<span i18n>Not connected, make sure your device has an active internet connection</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Component, OnInit, OnDestroy, Inject, Optional, ViewEncapsulation, RendererFactory2, PLATFORM_ID, ChangeDetectionStrategy, HostListener, Input, DOCUMENT } from '@angular/core';
|
||||
import { Component, OnInit, OnDestroy, Inject, Optional, ViewEncapsulation, RendererFactory2, PLATFORM_ID, ChangeDetectionStrategy, HostListener, Input } from '@angular/core';
|
||||
import { Router, NavigationStart, NavigationEnd, RouteConfigLoadStart, RouteConfigLoadEnd, ActivatedRoute, PRIMARY_OUTLET } from '@angular/router';
|
||||
import { Meta, Title, MetaDefinition } from '@angular/platform-browser';
|
||||
import { Meta, Title, MetaDefinition } from '@angular/platform-browser'; import { DOCUMENT } from "@angular/common";
|
||||
import { Subscription, Observable } from 'rxjs';
|
||||
import { distinctUntilChanged } from 'rxjs/operators';
|
||||
import { Store, Action } from '@ngrx/store';
|
||||
@@ -19,13 +19,12 @@ 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,
|
||||
standalone: false
|
||||
@Component({
|
||||
selector: 'fm-app',
|
||||
templateUrl: './app.component.html',
|
||||
styleUrls: ['./app.component.scss'],
|
||||
encapsulation: ViewEncapsulation.None,
|
||||
changeDetection: ChangeDetectionStrategy.OnPush
|
||||
})
|
||||
export class AppComponent implements OnInit, OnDestroy {
|
||||
|
||||
|
||||
@@ -3,10 +3,9 @@ import { Router } from '@angular/router';
|
||||
import { OAuthService } from 'angular-oauth2-oidc';
|
||||
import { Location} from '@angular/common';
|
||||
|
||||
@Component({
|
||||
selector: 'fm-auth-callback',
|
||||
template: '<div></div>',
|
||||
standalone: false
|
||||
@Component({
|
||||
selector: 'fm-auth-callback',
|
||||
template:'<div></div>'
|
||||
})
|
||||
export class AuthCallbackComponent {
|
||||
|
||||
|
||||
@@ -3,10 +3,9 @@ import { IUser } from '../../models/user';
|
||||
import { AppConfig } from '../../shared/app.config';
|
||||
|
||||
@Component({
|
||||
selector: 'fm-avatar',
|
||||
templateUrl: './avatar.component.html',
|
||||
styleUrls: ['./avatar.component.css'],
|
||||
standalone: false
|
||||
selector: 'fm-avatar',
|
||||
templateUrl: './avatar.component.html',
|
||||
styleUrls: ['./avatar.component.css']
|
||||
})
|
||||
export class AvatarComponent implements OnInit {
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
@if (show()) {
|
||||
<div class="back-button mb-2">
|
||||
<div *ngIf="show()" class="back-button mb-2">
|
||||
<i class="fal fa-arrow-left"></i> <span i18n="@FmBackButton">Back</span>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
@@ -3,10 +3,9 @@ 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'],
|
||||
standalone: false
|
||||
selector: 'fm-back-button',
|
||||
templateUrl: './back-button.component.html',
|
||||
styleUrls: ['./back-button.component.scss']
|
||||
})
|
||||
export class BackButtonComponent {
|
||||
@Output() beforeLocationBack = new EventEmitter();
|
||||
|
||||
@@ -5,34 +5,32 @@
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="modal-body">
|
||||
<div class="cropper">
|
||||
@if (!isImageLoaded) {
|
||||
<div class="no-image" (click)="fileInput.click()">
|
||||
<i class="fal fa-image"></i>
|
||||
<div i18n>No image selected</div>
|
||||
</div>
|
||||
}
|
||||
<image-cropper #imageCropper output="base64"
|
||||
[imageChangedEvent]="imageChangedEvent"
|
||||
[maintainAspectRatio]="true"
|
||||
[format]="imageType"
|
||||
[aspectRatio]="aspectRatio"
|
||||
[autoCrop]="true"
|
||||
[resizeToWidth]="maxWidth"
|
||||
[roundCropper]="roundImage"
|
||||
(imageCropped)="imageCropped($event)"
|
||||
(imageLoaded)="imageLoaded($event)"
|
||||
(cropperReady)="cropperReady()"
|
||||
(loadImageFailed)="loadImageFailed()"
|
||||
[imageURL]="imageUrl"
|
||||
></image-cropper>
|
||||
<div *ngIf="!isImageLoaded" class="no-image" (click)="fileInput.click()">
|
||||
<i class="fal fa-image"></i>
|
||||
<div i18n>No image selected</div>
|
||||
</div>
|
||||
<image-cropper #imageCropper output="base64"
|
||||
[imageChangedEvent]="imageChangedEvent"
|
||||
[maintainAspectRatio]="true"
|
||||
[format]="imageType"
|
||||
[aspectRatio]="aspectRatio"
|
||||
[autoCrop]="true"
|
||||
[resizeToWidth]="maxWidth"
|
||||
[roundCropper]="roundImage"
|
||||
(imageCropped)="imageCropped($event)"
|
||||
(imageLoaded)="imageLoaded($event)"
|
||||
(cropperReady)="cropperReady()"
|
||||
(loadImageFailed)="loadImageFailed()"
|
||||
[imageURL]="imageUrl"
|
||||
></image-cropper>
|
||||
</div>
|
||||
<input #fileInput type="file" (change)="fileChangeEvent($event)" style="display:none" accept="image/*"/>
|
||||
<span class="btn btn-primary" (click)="fileInput.click()" i18n>Select image</span>
|
||||
<input #fileInput type="file" (change)="fileChangeEvent($event)" style="display:none" accept="image/*"/>
|
||||
<span class="btn btn-primary" (click)="fileInput.click()" i18n>Select image</span>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="submit" class="btn btn-primary" i18n [disabled]="!isImageLoaded" (click)="save()">Apply</button>
|
||||
<button type="submit" class="btn btn-primary" i18n [disabled]="!isImageLoaded" (click)="save()">Apply</button>
|
||||
<button type="button" autofocus class="btn btn-secondary" (click)="modal.close('Save click')" i18n="@@buttonCancel">Cancel</button>
|
||||
</div>
|
||||
</div>
|
||||
</ng-template>
|
||||
|
||||
@@ -5,10 +5,9 @@ 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'],
|
||||
standalone: false
|
||||
selector: 'fm-edit-image-modal',
|
||||
templateUrl: './edit-image-modal.component.html',
|
||||
styleUrls: ['./edit-image-modal.component.scss']
|
||||
})
|
||||
export class EditImageModalComponent implements OnInit {
|
||||
|
||||
|
||||
@@ -1,28 +1,16 @@
|
||||
@if (gradientItems) {
|
||||
<div class="form-control gradient-select" (click)="handleToggleList()">
|
||||
@if (selectedItem) {
|
||||
<div>
|
||||
@if (showLabel) {
|
||||
<div>{{selectedItem?.name}}</div>
|
||||
}
|
||||
<fm-gradient [gradientItem]="selectedItem"></fm-gradient>
|
||||
</div>
|
||||
}
|
||||
<div class="gradient-list" [ngClass]="{'visible':listVisible}">
|
||||
@if (gradientItems) {
|
||||
<ul>
|
||||
@for (item of gradientItems; track item) {
|
||||
<li (click)="handleSelect(item)" [ngClass]="{'bg-primary':isSelected(item),'text-white':isSelected(item)} ">
|
||||
<div>{{item?.name}}</div>
|
||||
<div><fm-gradient [gradientItem]="item"></fm-gradient></div>
|
||||
</li>
|
||||
}
|
||||
</ul>
|
||||
}
|
||||
@if (showAdd) {
|
||||
<div class="addGradient"><a href="#" i18n (click)="handleAdd($event)" >Add gradient</a></div>
|
||||
}
|
||||
<div *ngIf="gradientItems" class="form-control gradient-select" (click)="handleToggleList()">
|
||||
<div *ngIf="selectedItem">
|
||||
<div *ngIf="showLabel">{{selectedItem?.name}}</div>
|
||||
<fm-gradient [gradientItem]="selectedItem"></fm-gradient>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
<div class="gradient-list" [ngClass]="{'visible':listVisible}">
|
||||
<ul *ngIf="gradientItems">
|
||||
<li *ngFor="let item of gradientItems" (click)="handleSelect(item)" [ngClass]="{'bg-primary':isSelected(item),'text-white':isSelected(item)} ">
|
||||
<div>{{item?.name}}</div>
|
||||
<div><fm-gradient [gradientItem]="item"></fm-gradient></div>
|
||||
</li>
|
||||
</ul>
|
||||
<div *ngIf="showAdd" class="addGradient"><a href="#" i18n (click)="handleAdd($event)" >Add gradient</a></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -2,10 +2,9 @@ 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'],
|
||||
standalone: false
|
||||
selector: 'fm-gradient-select',
|
||||
templateUrl: './gradient-select.component.html',
|
||||
styleUrls: ['./gradient-select.component.scss']
|
||||
})
|
||||
export class GradientSelectComponent implements OnChanges {
|
||||
|
||||
|
||||
@@ -6,10 +6,9 @@ import { GradientService } from '../../common-service.module';
|
||||
|
||||
|
||||
@Component({
|
||||
selector: 'fm-gradient',
|
||||
templateUrl: './gradient.component.html',
|
||||
styleUrls: ['./gradient.component.scss'],
|
||||
standalone: false
|
||||
selector: 'fm-gradient',
|
||||
templateUrl: './gradient.component.html',
|
||||
styleUrls: ['./gradient.component.scss']
|
||||
})
|
||||
export class GradientComponent implements OnInit,OnChanges {
|
||||
|
||||
|
||||
@@ -7,9 +7,8 @@ import { skip } from 'rxjs/operators';
|
||||
import {OAuthService } from 'angular-oauth2-oidc';
|
||||
import { IUser } from '../../models/user';
|
||||
|
||||
@Directive({
|
||||
selector: '[fm-hasclaim]',
|
||||
standalone: false
|
||||
@Directive({
|
||||
selector: '[fm-hasclaim]',
|
||||
})
|
||||
export class HasClaimDirective implements OnInit{
|
||||
@Input('fm-hasclaim') claim:string;
|
||||
|
||||
@@ -4,9 +4,8 @@ import {PackageService} from '../../services/package.service';
|
||||
import * as appCommonReducer from '../../reducers/app-common.reducer';
|
||||
import {Store} from '@ngrx/store';
|
||||
|
||||
@Directive({
|
||||
selector: '[fmHasPackage]',
|
||||
standalone: false
|
||||
@Directive({
|
||||
selector: '[fmHasPackage]',
|
||||
})
|
||||
export class HasPackageDirective implements OnDestroy, AfterViewInit {
|
||||
|
||||
|
||||
@@ -5,8 +5,7 @@ import { Observable, Subscription } from 'rxjs';
|
||||
import { IUser } from '../../models/user';
|
||||
|
||||
@Directive({
|
||||
selector: '[fmHasRole]',
|
||||
standalone: false
|
||||
selector: '[fmHasRole]',
|
||||
})
|
||||
export class HasRoleDirective implements OnInit, OnDestroy{
|
||||
@Input('fmHasRole') role:string;
|
||||
|
||||
@@ -7,10 +7,9 @@ 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'],
|
||||
standalone: false
|
||||
selector: 'fm-help-menu',
|
||||
templateUrl: './help-menu.component.html',
|
||||
styleUrls: ['./help-menu.component.scss']
|
||||
})
|
||||
export class HelpMenuComponent implements OnInit {
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
<span class="item-link" (click)="copylink(copiedtt)" triggers="manual" ngbTooltip="Link copied" #copiedtt="ngbTooltip" ><i ngbTooltip='Copy link' class="fa-solid fa-link"></i> @if (showText) {<span i18n>Copy link</span>}</span>
|
||||
<span class="item-link" (click)="copylink(copiedtt)" triggers="manual" ngbTooltip="Link copied" #copiedtt="ngbTooltip" ><i ngbTooltip='Copy link' class="fa-solid fa-link"></i> <span *ngIf="showText" i18n>Copy link</span></span>
|
||||
@@ -7,9 +7,8 @@ import { ClipboardService } from 'ngx-clipboard'
|
||||
|
||||
|
||||
@Component({
|
||||
selector: 'fm-item-link',
|
||||
templateUrl: './item-link.component.html',
|
||||
standalone: false
|
||||
selector: 'fm-item-link',
|
||||
templateUrl: './item-link.component.html'
|
||||
})
|
||||
export class ItemLinkComponent implements OnDestroy {
|
||||
|
||||
|
||||
@@ -3,11 +3,10 @@ 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'],
|
||||
standalone: false
|
||||
@Component({
|
||||
selector: 'fm-menu-background',
|
||||
templateUrl: './menu-background.component.html',
|
||||
styleUrls: ['./menu-background.component.scss'],
|
||||
})
|
||||
export class MenuBackgroundComponent implements OnInit {
|
||||
@Input() visible = false;
|
||||
|
||||
@@ -4,8 +4,6 @@ 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,8 +2,7 @@ import { Component, OnInit } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'fm-not-implemented',
|
||||
templateUrl: './not-implemented.component.html',
|
||||
standalone: false
|
||||
templateUrl: './not-implemented.component.html'
|
||||
})
|
||||
export class NotImplementedComponent implements OnInit {
|
||||
constructor() { }
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user