95 Commits

Author SHA1 Message Date
jenkins
c79637be77 [ci skip] Updated packages #2576
Some checks reported errors
FarmMaps.Develop/FarmMapsLib/pipeline/head Something is wrong with the build of this commit
2025-08-11 08:14:46 +00:00
Willem Dantuma
b5e11da9a8 Fix flag check
All checks were successful
FarmMaps.Develop/FarmMapsLib/pipeline/head This commit looks good
2025-08-11 10:11:45 +02:00
jenkins
9d45c25a95 [ci skip] Updated packages #2575
Some checks reported errors
FarmMaps.Develop/FarmMapsLib/pipeline/head Something is wrong with the build of this commit
2025-08-11 07:42:16 +00:00
Willem Dantuma
2ffce50c47 Add hideShowLayerValues flag for fm-map-map
All checks were successful
FarmMaps.Develop/FarmMapsLib/pipeline/head This commit looks good
2025-08-11 09:40:00 +02:00
jenkins
f50ff878e0 [ci skip] Updated packages #2574
Some checks reported errors
FarmMaps.Develop/FarmMapsLib/pipeline/head Something is wrong with the build of this commit
2025-07-30 09:49:37 +00:00
09c74448a8 Merge branch 'develop' of https://git.akkerweb.nl/FarmMaps/FarmMapsLib into develop
All checks were successful
FarmMaps.Develop/FarmMapsLib/pipeline/head This commit looks good
2025-07-30 11:47:01 +02:00
205b73b30e AW-4935 Tools in croppingscheme weer goed zetten op mobile 2025-07-30 11:46:58 +02:00
jenkins
313cc59fe7 [ci skip] Updated packages #2573
Some checks reported errors
FarmMaps.Develop/FarmMapsLib/pipeline/head Something is wrong with the build of this commit
2025-07-30 09:20:14 +00:00
c3fb42c65f AW-4935 Tools in croppingscheme weer goed zetten op mobile
All checks were successful
FarmMaps.Develop/FarmMapsLib/pipeline/head This commit looks good
2025-07-30 11:17:55 +02:00
jenkins
6b73fb0d55 [ci skip] Updated packages #2572
Some checks reported errors
FarmMaps.Develop/FarmMapsLib/pipeline/head Something is wrong with the build of this commit
2025-06-03 10:27:08 +00:00
ea641caf38 AW-6806 Allow delete
All checks were successful
FarmMaps.Develop/FarmMapsLib/pipeline/head This commit looks good
2025-06-03 12:25:16 +02:00
ac15b2018d AW-6806 Allow delete
Some checks failed
FarmMaps.Develop/FarmMapsLib/pipeline/head There was a failure building this commit
2025-06-03 12:15:14 +02:00
jenkins
fe73f615ad [ci skip] Updated packages #2570
Some checks reported errors
FarmMaps.Develop/FarmMapsLib/pipeline/head Something is wrong with the build of this commit
2025-05-13 09:34:44 +00:00
jenkins
3e1b3ee78e Updated packages #2569
All checks were successful
FarmMaps.Develop/FarmMapsLib/pipeline/head This commit looks good
2025-05-13 09:28:46 +00:00
jenkins
58391b7828 [ci skip] Updated packages #2568
All checks were successful
FarmMaps.Develop/FarmMapsLib/pipeline/head This commit looks good
2025-05-12 13:54:16 +00:00
jenkins
b2b2a1e8be Updated packages #2567
All checks were successful
FarmMaps.Develop/FarmMapsLib/pipeline/head This commit looks good
2025-05-12 13:48:35 +00:00
jenkins
0d96a1be4f [ci skip] Updated packages #2566
All checks were successful
FarmMaps.Develop/FarmMapsLib/pipeline/head This commit looks good
2025-05-12 11:01:08 +00:00
d599430cb0 AW-6649 Layers dialog => rename Data to Overlay slide, move below Overlays
All checks were successful
FarmMaps.Develop/FarmMapsLib/pipeline/head This commit looks good
2025-05-12 12:59:12 +02:00
jenkins
e17911b339 [ci skip] Updated packages #2565
Some checks reported errors
FarmMaps.Develop/FarmMapsLib/pipeline/head Something is wrong with the build of this commit
2025-04-30 11:27:32 +00:00
jenkins
9d6cbffb3d Updated packages #2564
All checks were successful
FarmMaps.Develop/FarmMapsLib/pipeline/head This commit looks good
2025-04-30 11:20:25 +00:00
jenkins
a11eb81e73 [ci skip] Updated packages #2563
All checks were successful
FarmMaps.Develop/FarmMapsLib/pipeline/head This commit looks good
2025-04-30 09:21:42 +00:00
jenkins
4fc3ad933c Updated packages #2562
All checks were successful
FarmMaps.Develop/FarmMapsLib/pipeline/head This commit looks good
2025-04-30 09:14:15 +00:00
jenkins
e6d90c9e61 [ci skip] Updated packages #2561
All checks were successful
FarmMaps.Develop/FarmMapsLib/pipeline/head This commit looks good
2025-04-30 06:26:59 +00:00
250b3841fe Merge branch 'develop' of https://git.akkerweb.nl/FarmMaps/FarmMapsLib into develop
All checks were successful
FarmMaps.Develop/FarmMapsLib/pipeline/head This commit looks good
2025-04-30 08:25:09 +02:00
51291cd86f AW-6801 Add switch to add full path to items result 2025-04-30 08:25:00 +02:00
jenkins
e9e3b719a4 [ci skip] Updated packages #2560
Some checks reported errors
FarmMaps.Develop/FarmMapsLib/pipeline/head Something is wrong with the build of this commit
2025-04-29 19:35:08 +00:00
jenkins
1c0ad57b0a Updated packages #2559
All checks were successful
FarmMaps.Develop/FarmMapsLib/pipeline/head This commit looks good
2025-04-29 19:28:05 +00:00
jenkins
8684ba25c8 [ci skip] Updated packages #2558
All checks were successful
FarmMaps.Develop/FarmMapsLib/pipeline/head This commit looks good
2025-04-28 08:22:16 +00:00
78ca3044cf Merge branch 'develop' of https://git.akkerweb.nl/FarmMaps/FarmMapsLib into develop
All checks were successful
FarmMaps.Develop/FarmMapsLib/pipeline/head This commit looks good
2025-04-28 10:20:22 +02:00
2e55b5a70e AW-3101 vnd.farmmaps.itemtype.shape.processed download as shape (zip) 2025-04-28 10:20:19 +02:00
jenkins
af0a3dca2d [ci skip] Updated packages #2557
Some checks reported errors
FarmMaps.Develop/FarmMapsLib/pipeline/head Something is wrong with the build of this commit
2025-04-28 06:47:11 +00:00
f039898c26 AW-3101 vnd.farmmaps.itemtype.geotiff.processed -> Download as tiff
All checks were successful
FarmMaps.Develop/FarmMapsLib/pipeline/head This commit looks good
2025-04-28 08:45:05 +02:00
jenkins
ab19b1c2ce [ci skip] Updated packages #2556
Some checks reported errors
FarmMaps.Develop/FarmMapsLib/pipeline/head Something is wrong with the build of this commit
2025-04-24 14:18:56 +00:00
a2641f8ea5 AW-3101 Alleen relevante plaatje downloaden bij satelliet
All checks were successful
FarmMaps.Develop/FarmMapsLib/pipeline/head This commit looks good
2025-04-24 16:15:57 +02:00
jenkins
d6841c8f83 [ci skip] Updated packages #2555
Some checks reported errors
FarmMaps.Develop/FarmMapsLib/pipeline/head Something is wrong with the build of this commit
2025-04-23 14:39:24 +00:00
187b24ab97 Merge branch 'develop' of https://git.akkerweb.nl/FarmMaps/FarmMapsLib into develop
All checks were successful
FarmMaps.Develop/FarmMapsLib/pipeline/head This commit looks good
2025-04-23 16:37:29 +02:00
b80ddf7854 AW-6790 Admin -> users 2025-04-23 16:37:26 +02:00
jenkins
79bc3d9082 [ci skip] Updated packages #2554
Some checks reported errors
FarmMaps.Develop/FarmMapsLib/pipeline/head Something is wrong with the build of this commit
2025-04-23 13:46:30 +00:00
1c92ad4c28 AW-6790 Admin -> users
All checks were successful
FarmMaps.Develop/FarmMapsLib/pipeline/head This commit looks good
2025-04-23 15:44:36 +02:00
jenkins
61e6de0052 [ci skip] Updated packages #2553
Some checks reported errors
FarmMaps.Develop/FarmMapsLib/pipeline/head Something is wrong with the build of this commit
2025-04-16 13:45:05 +00:00
fb25b92349 AW-6792 Update API
All checks were successful
FarmMaps.Develop/FarmMapsLib/pipeline/head This commit looks good
2025-04-16 15:43:08 +02:00
jenkins
e78f2893ae [ci skip] Updated packages #2552
Some checks reported errors
FarmMaps.Develop/FarmMapsLib/pipeline/head Something is wrong with the build of this commit
2025-04-14 12:57:56 +00:00
51170b45e9 AW-6649 overlays boven luchtfoto’s
All checks were successful
FarmMaps.Develop/FarmMapsLib/pipeline/head This commit looks good
2025-04-14 14:56:06 +02:00
jenkins
7365bea145 [ci skip] Updated packages #2551
Some checks reported errors
FarmMaps.Develop/FarmMapsLib/pipeline/head Something is wrong with the build of this commit
2025-04-14 11:36:12 +00:00
dc096065b4 AW-6649 Achtergrondlagen
All checks were successful
FarmMaps.Develop/FarmMapsLib/pipeline/head This commit looks good
2025-04-14 13:34:18 +02:00
jenkins
b9850311ea [ci skip] Updated packages #2550
Some checks reported errors
FarmMaps.Develop/FarmMapsLib/pipeline/head Something is wrong with the build of this commit
2025-04-14 10:31:45 +00:00
ee9c050db3 AW-6649 Achtergrondlagen
All checks were successful
FarmMaps.Develop/FarmMapsLib/pipeline/head This commit looks good
2025-04-14 12:29:56 +02:00
jenkins
95200d9920 [ci skip] Updated packages #2549
Some checks reported errors
FarmMaps.Develop/FarmMapsLib/pipeline/head Something is wrong with the build of this commit
2025-04-11 21:23:04 +00:00
jenkins
ee1ce21cca Updated packages #2548
All checks were successful
FarmMaps.Develop/FarmMapsLib/pipeline/head This commit looks good
2025-04-11 21:16:35 +00:00
jenkins
467f7447bf [ci skip] Updated packages #2547
All checks were successful
FarmMaps.Develop/FarmMapsLib/pipeline/head This commit looks good
2025-04-11 12:01:45 +00:00
jenkins
1df4496058 Updated packages #2546
All checks were successful
FarmMaps.Develop/FarmMapsLib/pipeline/head This commit looks good
2025-04-11 11:55:57 +00:00
jenkins
2137f3f07e [ci skip] Updated packages #2545
All checks were successful
FarmMaps.Develop/FarmMapsLib/pipeline/head This commit looks good
2025-03-24 08:17:20 +00:00
a46e8040b2 AW-6756 Settingsknop Explorer dezelfde kleur als het logo van de explorer.
All checks were successful
FarmMaps.Develop/FarmMapsLib/pipeline/head This commit looks good
2025-03-24 09:13:47 +01:00
jenkins
2ca9730735 [ci skip] Updated packages #2544
Some checks reported errors
FarmMaps.Develop/FarmMapsLib/pipeline/head Something is wrong with the build of this commit
2025-03-14 14:27:03 +00:00
3d2ca8fb9f Merge branch 'develop' of https://git.akkerweb.nl/FarmMaps/FarmMapsLib into develop
All checks were successful
FarmMaps.Develop/FarmMapsLib/pipeline/head This commit looks good
2025-03-14 15:25:09 +01:00
6810da8b79 AW-6742 Add analyse functions 2025-03-14 15:25:06 +01:00
jenkins
4866a6f22d [ci skip] Updated packages #2543
Some checks reported errors
FarmMaps.Develop/FarmMapsLib/pipeline/head Something is wrong with the build of this commit
2025-03-13 07:46:33 +00:00
84a1004977 Fix redirect URL for locale (without loosing queryparms)
All checks were successful
FarmMaps.Develop/FarmMapsLib/pipeline/head This commit looks good
2025-03-13 08:44:46 +01:00
39c619a837 Fix RVO redirect URL for locale (without loosing queryparms)
Some checks failed
FarmMaps.Develop/FarmMapsLib/pipeline/head There was a failure building this commit
2025-03-13 08:38:24 +01:00
jenkins
758613aa12 [ci skip] Updated packages #2541
Some checks reported errors
FarmMaps.Develop/FarmMapsLib/pipeline/head Something is wrong with the build of this commit
2025-03-12 14:40:01 +00:00
6914a61bc4 Merge branch 'develop' of https://git.akkerweb.nl/FarmMaps/FarmMapsLib into develop
All checks were successful
FarmMaps.Develop/FarmMapsLib/pipeline/head This commit looks good
2025-03-12 15:38:06 +01:00
9f43287433 Revert "Fix RVO redirect URL for locale (without loosing queryparms)"
This reverts commit df14427d60.
2025-03-12 15:37:59 +01:00
jenkins
10df983ae3 [ci skip] Updated packages #2540
Some checks reported errors
FarmMaps.Develop/FarmMapsLib/pipeline/head Something is wrong with the build of this commit
2025-03-12 14:16:55 +00:00
78249811ab Merge branch 'develop' of https://git.akkerweb.nl/FarmMaps/FarmMapsLib into develop
All checks were successful
FarmMaps.Develop/FarmMapsLib/pipeline/head This commit looks good
2025-03-12 15:15:01 +01:00
df14427d60 Fix RVO redirect URL for locale (without loosing queryparms) 2025-03-12 15:14:58 +01:00
jenkins
c7c131d437 [ci skip] Updated packages #2539
Some checks reported errors
FarmMaps.Develop/FarmMapsLib/pipeline/head Something is wrong with the build of this commit
2025-03-12 13:49:12 +00:00
b2fe8f3bd7 Fix RVO redirect URL for locale
All checks were successful
FarmMaps.Develop/FarmMapsLib/pipeline/head This commit looks good
2025-03-12 14:47:17 +01:00
jenkins
3027c69fa8 [ci skip] Updated packages #2538
Some checks reported errors
FarmMaps.Develop/FarmMapsLib/pipeline/head Something is wrong with the build of this commit
2025-03-12 08:00:13 +00:00
5995d205a4 AW-2925 Accidently removed
All checks were successful
FarmMaps.Develop/FarmMapsLib/pipeline/head This commit looks good
2025-03-12 08:58:19 +01:00
jenkins
fd479c92d8 [ci skip] Updated packages #2537
Some checks reported errors
FarmMaps.Develop/FarmMapsLib/pipeline/head Something is wrong with the build of this commit
2025-03-10 10:30:23 +00:00
e9880d6eb2 AW-2925 Data temporal item
All checks were successful
FarmMaps.Develop/FarmMapsLib/pipeline/head This commit looks good
2025-03-10 11:28:34 +01:00
jenkins
a4438d8a90 [ci skip] Updated packages #2536
Some checks reported errors
FarmMaps.Develop/FarmMapsLib/pipeline/head Something is wrong with the build of this commit
2025-03-04 07:54:29 +00:00
89061774de AW-6716 Uploaden avatar geeft foutmelding
All checks were successful
FarmMaps.Develop/FarmMapsLib/pipeline/head This commit looks good
Caused by BREAKING CHANGE: by default the output will be set to blob. Using blob instead of a base64 should decrease the memory usage. If you wish to keep using base64, simply add output="base64" to the <image-cropper> tag. (https://github.com/Mawi137/ngx-image-cropper/releases/tag/7.0.0)
2025-03-04 08:52:38 +01:00
jenkins
362e6c8534 [ci skip] Updated packages #2535
Some checks reported errors
FarmMaps.Develop/FarmMapsLib/pipeline/head Something is wrong with the build of this commit
2025-03-03 14:34:07 +00:00
64a0e58238 AW-3128 Cleanup
All checks were successful
FarmMaps.Develop/FarmMapsLib/pipeline/head This commit looks good
2025-03-03 15:32:16 +01:00
jenkins
a3d4dfbd59 [ci skip] Updated packages #2534
Some checks reported errors
FarmMaps.Develop/FarmMapsLib/pipeline/head Something is wrong with the build of this commit
2025-03-03 14:05:03 +00:00
4c106ebff3 AW-3128 Taalinstellingen profiel gebruiken voor FarmMaps ipv browser instelling
All checks were successful
FarmMaps.Develop/FarmMapsLib/pipeline/head This commit looks good
2025-03-03 15:02:59 +01:00
jenkins
5c8fd64521 [ci skip] Updated packages #2533
Some checks reported errors
FarmMaps.Develop/FarmMapsLib/pipeline/head Something is wrong with the build of this commit
2024-12-03 12:02:22 +00:00
72ba8eca81 AW-6556 The Angular Material version (18.2.4) does not match the Angular CDK version (18.2.3).
All checks were successful
FarmMaps.Develop/FarmMapsLib/pipeline/head This commit looks good
2024-12-03 13:00:12 +01:00
jenkins
f89f741265 [ci skip] Updated packages #2532
Some checks reported errors
FarmMaps.Develop/FarmMapsLib/pipeline/head Something is wrong with the build of this commit
2024-12-02 09:31:15 +00:00
50af55acb2 AW-6480 Blauwe balk van upload venster is niet zichtbaar in de explorer
All checks were successful
FarmMaps.Develop/FarmMapsLib/pipeline/head This commit looks good
2024-12-02 10:29:18 +01:00
jenkins
cc879b85e5 [ci skip] Updated packages #2531
Some checks reported errors
FarmMaps.Develop/FarmMapsLib/pipeline/head Something is wrong with the build of this commit
2024-11-21 09:49:47 +00:00
b4a0a4584d Merge branch 'develop' of https://git.akkerweb.nl/FarmMaps/FarmMapsLib into develop
All checks were successful
FarmMaps.Develop/FarmMapsLib/pipeline/head This commit looks good
2024-11-21 10:47:51 +01:00
8ab1611f39 AW-6504 Support indexed on retrieving child items 2024-11-21 10:47:42 +01:00
jenkins
475c522039 [ci skip] Updated packages #2530
Some checks reported errors
FarmMaps.Develop/FarmMapsLib/pipeline/head Something is wrong with the build of this commit
2024-11-20 15:35:21 +00:00
068396ac9a added TaskService
All checks were successful
FarmMaps.Develop/FarmMapsLib/pipeline/head This commit looks good
2024-11-20 16:33:20 +01:00
jenkins
4a30707ec6 [ci skip] Updated packages #2529
Some checks reported errors
FarmMaps.Develop/FarmMapsLib/pipeline/head Something is wrong with the build of this commit
2024-11-20 08:13:33 +00:00
852b1db895 added workflowcode to IItemTask
All checks were successful
FarmMaps.Develop/FarmMapsLib/pipeline/head This commit looks good
2024-11-20 09:11:34 +01:00
jenkins
fcbd68eca0 [ci skip] Updated packages #2528
Some checks reported errors
FarmMaps.Develop/FarmMapsLib/pipeline/head Something is wrong with the build of this commit
2024-11-19 12:25:40 +00:00
3a42f9114e Merge branch 'develop' of https://git.akkerweb.nl/FarmMaps/FarmMapsLib into develop
All checks were successful
FarmMaps.Develop/FarmMapsLib/pipeline/head This commit looks good
2024-11-19 13:23:36 +01:00
3f664b472c Fixed VM104:1 Uncaught TypeError: Cannot read properties of null (reading 'vnd.farmmaps.itemtype.croppingscheme') at eval (eval at getExtraAttributes (main.ce80740d3a633957.js:311566:14), <anonymous>:1:15) 2024-11-19 13:23:32 +01:00
jenkins
57811f3f2e [ci skip] Updated packages #2527
Some checks reported errors
FarmMaps.Develop/FarmMapsLib/pipeline/head Something is wrong with the build of this commit
2024-11-15 13:08:26 +00:00
5e1bc6d705 AW-6495 Exception editor croppingscheme: do not use 'item' in route
All checks were successful
FarmMaps.Develop/FarmMapsLib/pipeline/head This commit looks good
2024-11-15 14:06:33 +01:00
d4a230f96d AW-6495 Exception editor croppingscheme: do not use 'item' in route 2024-11-15 14:06:11 +01:00
jenkins
ed1e1478b2 [ci skip] Updated packages #2526
Some checks reported errors
FarmMaps.Develop/FarmMapsLib/pipeline/head Something is wrong with the build of this commit
2024-11-14 13:23:40 +00:00
35 changed files with 596 additions and 401 deletions

54
package-lock.json generated
View File

@@ -1,22 +1,22 @@
{
"name": "farmmaps-lib-app",
"version": "4.12.0",
"version": "4.18.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "farmmaps-lib-app",
"version": "4.12.0",
"version": "4.18.0",
"dependencies": {
"@angular-eslint/eslint-plugin": "^18.2.0",
"@angular/animations": "^18.2.3",
"@angular/common": "^18.2.3",
"@angular/compiler": "^18.2.3",
"@angular/core": "^18.2.3",
"@angular/forms": "^18.2.3",
"@angular/platform-browser": "^18.2.3",
"@angular/platform-browser-dynamic": "^18.2.3",
"@angular/router": "^18.2.3",
"@angular/animations": "18.2.3",
"@angular/common": "18.2.3",
"@angular/compiler": "18.2.3",
"@angular/core": "18.2.3",
"@angular/forms": "18.2.3",
"@angular/platform-browser": "18.2.3",
"@angular/platform-browser-dynamic": "18.2.3",
"@angular/router": "18.2.3",
"@farmmaps/common": "file:dist/common",
"@farmmaps/common-map": "file:dist/common-map",
"@farmmaps/common-map3d": "file:dist/common-map3d",
@@ -55,11 +55,11 @@
},
"devDependencies": {
"@angular-builders/custom-webpack": "^18.0.0",
"@angular-devkit/build-angular": "^18.2.3",
"@angular/cli": "^18.2.3",
"@angular/compiler-cli": "^18.2.3",
"@angular/language-service": "^18.2.3",
"@angular/localize": "^18.2.3",
"@angular-devkit/build-angular": "18.2.3",
"@angular/cli": "18.2.3",
"@angular/compiler-cli": "18.2.3",
"@angular/language-service": "18.2.3",
"@angular/localize": "18.2.3",
"@types/arcgis-rest-api": "^10.4.5",
"@types/jasmine": "~2.8.8",
"@types/jasminewd2": "^2.0.9",
@@ -90,14 +90,14 @@
},
"dist/common": {
"name": "@farmmaps/common",
"version": "4.12.0-prerelease.2524",
"version": "4.18.0-prerelease.2575",
"dependencies": {
"tslib": "^2.3.0"
},
"peerDependencies": {
"@angular/common": "^18.2.3",
"@angular/core": "^18.2.3",
"@angular/forms": "^18.2.3",
"@angular/common": "18.2.3",
"@angular/core": "18.2.3",
"@angular/forms": "18.2.3",
"@microsoft/signalr": "^3.1.16",
"@ng-bootstrap/ng-bootstrap": "^17.0.1",
"@ngrx/effects": "^18.0.2",
@@ -115,12 +115,12 @@
},
"dist/common-map": {
"name": "@farmmaps/common-map",
"version": "4.12.0-prerelease.2524",
"version": "4.18.0-prerelease.2575",
"dependencies": {
"tslib": "^2.0.0"
},
"peerDependencies": {
"@angular/core": "^18.2.3",
"@angular/core": "18.2.3",
"@ngrx/effects": "^18.0.2",
"@ngrx/router-store": "^18.0.2",
"@ngrx/store": "^18.0.2",
@@ -130,27 +130,27 @@
},
"dist/common-map3d": {
"name": "@farmmaps/common-map3d",
"version": "4.12.0-prerelease.2524",
"version": "4.18.0-prerelease.2575",
"dependencies": {
"tslib": "^2.0.0"
},
"peerDependencies": {
"@angular/common": "^18.2.3",
"@angular/core": "^18.2.3",
"@angular/common": "18.2.3",
"@angular/core": "18.2.3",
"cesium": "^1.97.0",
"ol-cesium": ">=2.13.0"
}
},
"dist/ng-openlayers": {
"name": "@farmmaps/ng-openlayers",
"version": "4.12.0-prerelease.2524",
"version": "4.18.0-prerelease.2575",
"license": "MPL-2.0",
"dependencies": {
"tslib": "^2.3.0"
},
"peerDependencies": {
"@angular/common": "^18.2.3",
"@angular/core": "^18.2.3",
"@angular/common": "18.2.3",
"@angular/core": "18.2.3",
"ol": "^8.2.0"
}
},

View File

@@ -1,6 +1,6 @@
{
"name": "farmmaps-lib-app",
"version": "4.12.0",
"version": "4.18.0",
"scripts": {
"ng": "ng",
"start": "ng serve",
@@ -12,14 +12,14 @@
"private": true,
"dependencies": {
"@angular-eslint/eslint-plugin": "^18.2.0",
"@angular/animations": "^18.2.3",
"@angular/common": "^18.2.3",
"@angular/compiler": "^18.2.3",
"@angular/core": "^18.2.3",
"@angular/forms": "^18.2.3",
"@angular/platform-browser": "^18.2.3",
"@angular/platform-browser-dynamic": "^18.2.3",
"@angular/router": "^18.2.3",
"@angular/animations": "18.2.3",
"@angular/common": "18.2.3",
"@angular/compiler": "18.2.3",
"@angular/core": "18.2.3",
"@angular/forms": "18.2.3",
"@angular/platform-browser": "18.2.3",
"@angular/platform-browser-dynamic": "18.2.3",
"@angular/router": "18.2.3",
"@farmmaps/common": "file:dist/common",
"@farmmaps/common-map": "file:dist/common-map",
"@farmmaps/common-map3d": "file:dist/common-map3d",
@@ -62,11 +62,11 @@
},
"devDependencies": {
"@angular-builders/custom-webpack": "^18.0.0",
"@angular-devkit/build-angular": "^18.2.3",
"@angular/cli": "^18.2.3",
"@angular/compiler-cli": "^18.2.3",
"@angular/language-service": "^18.2.3",
"@angular/localize": "^18.2.3",
"@angular-devkit/build-angular": "18.2.3",
"@angular/cli": "18.2.3",
"@angular/compiler-cli": "18.2.3",
"@angular/language-service": "18.2.3",
"@angular/localize": "18.2.3",
"@types/arcgis-rest-api": "^10.4.5",
"@types/jasmine": "~2.8.8",
"@types/jasminewd2": "^2.0.9",

View File

@@ -8,7 +8,7 @@
"tslib": "^2.0.0"
},
"peerDependencies": {
"@angular/core": "^18.2.3",
"@angular/core": "18.2.3",
"ngrx-store-localstorage": "^18.0.0",
"@ngrx/effects": "^18.0.2",
"@ngrx/router-store": "^18.0.2",

View File

@@ -10,7 +10,7 @@
<li class="nav-item py-0">
<span><i class="fal fa-layer-group" aria-hidden="true"></i>&nbsp;<span i18n>Base maps</span></span>
<div class="mb-4">
<fm-map-layer-list [baseLayers]="true" [itemLayers]="baseLayers|async" [selectedLayer]="selectedBaseLayer|async" (onSelectLayer)="handleSelectBaseLayer($event)"></fm-map-layer-list>
<fm-map-layer-list [baseLayers]="true" [itemLayers]="baseMaps|async" [selectedLayer]="selectedBaseLayer|async" (onSelectLayer)="handleSelectBaseLayer($event)"></fm-map-layer-list>
</div>
</li>
<li class="nav-item py-0">
@@ -20,12 +20,17 @@
</div>
</li>
<li class="nav-item py-0" *ngIf="selectedItemLayer$ | async as selectedItemLayer">
<span><i class="fal fa-layer-group" aria-hidden="true"></i>&nbsp;<span i18n>Data</span><span class="slideButton"><a href="#" title="Compare" class="btn btn-light btn-sm" (click)="handleToggleShowDatalayerSlide($event)"><i class="fal fa-sliders-h-square"></i></a></span></span>
<span><i class="fal fa-layer-group" aria-hidden="true"></i>&nbsp;<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>&nbsp;<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>

View File

@@ -4,7 +4,7 @@ import { Store } from '@ngrx/store';
import * as mapReducers from '../../reducers/map.reducer';
import * as mapActions from '../../actions/map.actions';
import {createEmpty,extend } from 'ol/extent';
import { Observable } from 'rxjs';
import { filter, map, Observable } from 'rxjs';
@Component({
selector: 'fm-map-layer-switcher',
@@ -17,7 +17,8 @@ export class LayerSwitcher implements OnInit,OnChanges{
public overlayLayers: Observable<Array<IItemLayer>>;
public selectedOverlayLayer: Observable<IItemLayer>;
public selectedItemLayer$: Observable<IItemLayer>;
public baseLayers: Observable<Array<IItemLayer>>;
public baseMaps: Observable<Array<IItemLayer>>;
public aerialMaps: Observable<Array<IItemLayer>>;
public selectedBaseLayer: Observable<IItemLayer>;
constructor( private store: Store<mapReducers.State>) {
@@ -26,7 +27,8 @@ export class LayerSwitcher implements OnInit,OnChanges{
ngOnInit() {
this.overlayLayers = this.store.select(mapReducers.selectGetOverlayLayers);
this.selectedOverlayLayer = this.store.select(mapReducers.selectGetSelectedOverlayLayer);
this.baseLayers = this.store.select(mapReducers.selectGetBaseLayers);
this.baseMaps = this.store.select(mapReducers.selectGetBaseMaps);
this.aerialMaps = this.store.select(mapReducers.selectGetArealMaps);
this.selectedBaseLayer = this.store.select(mapReducers.selectGetSelectedBaseLayer);
this.selectedItemLayer$ = this.store.select(mapReducers.selectGetSelectedItemLayer)
this.showLayerSwitcher = this.store.select(mapReducers.selectGetShowLayerSwitcher);
@@ -83,3 +85,4 @@ export class LayerSwitcher implements OnInit,OnChanges{
event.preventDefault();
}
}

View File

@@ -52,11 +52,20 @@ aol-map { position:absolute;width:100%;height:calc( 100vh );}
pointer-events: none;
}
@media screen and (max-width: 768px) {
.control-container {
margin-left: 1em;
margin-right: 1em;
pointer-events: all;
}
}
.control-container {
float:right;
margin-right: 1em;
pointer-events: all;
@media screen and (min-width: 768px) {
.control-container {
float: right;
margin-right: 1em;
pointer-events: all;
}
}
.fullscreen .viewport-container {

View File

@@ -1,39 +1,39 @@
import { Component, OnInit, OnDestroy, HostListener, ViewChild, AfterViewInit,NgZone,ElementRef } from '@angular/core';
import { Component, OnInit, OnDestroy, HostListener, ViewChild, AfterViewInit, NgZone, ElementRef } from '@angular/core';
import { Location } from '@angular/common';
import { Observable, Subject, Subscription, from,of ,EMPTY } from 'rxjs';
import { withLatestFrom, switchMap,skip } from 'rxjs/operators';
import { Observable, Subject, Subscription, from, of, EMPTY } from 'rxjs';
import { withLatestFrom, switchMap, skip } from 'rxjs/operators';
import { Router, ActivatedRoute, ParamMap } from '@angular/router';
import { Store } from '@ngrx/store';
import { DeviceService } from '@farmmaps/common';
import {getRenderPixel} from 'ol/render';
import { getRenderPixel } from 'ol/render';
// Map
import * as mapReducers from '../../reducers/map.reducer';
import * as mapActions from '../../actions/map.actions';
import { IMapState} from '../../models/map.state';
import { IClickedFeature} from '../../models/clicked.feature';
import { IMapState } from '../../models/map.state';
import { IClickedFeature } from '../../models/clicked.feature';
import { IQuery } from '../../reducers/map.reducer'
import { ISelectedFeatures } from '../../models/selected.features';
import { IItemLayer } from '../../models/item.layer';
import { IListItem, IQueryState } from '@farmmaps/common';
import { IPeriodState } from '../../models/period.state';
import {IStyles} from '../../models/style.cache';
import { IStyles } from '../../models/style.cache';
import { IDroppedFile } from '../aol/file-drop-target/file-drop-target.component';
import { StateSerializerService } from '@farmmaps/common';
import { GeolocationService} from '../../services/geolocation.service';
import { GeolocationService } from '../../services/geolocation.service';
import { GeolocatorService } from '@farmmaps/common';
import {DeviceOrientationService} from '../../services/device-orientation.service';
import { DeviceOrientationService } from '../../services/device-orientation.service';
// AppCommon
import { ResumableFileUploadService, ItemTypeService } from '@farmmaps/common';
import { IItemType, IItem } from '@farmmaps/common';
import {commonReducers} from '@farmmaps/common';
import {commonActions} from '@farmmaps/common';
import { commonReducers } from '@farmmaps/common';
import { commonActions } from '@farmmaps/common';
import {Feature} from 'ol';
import {Geometry,Point,Circle} from 'ol/geom';
import {Extent,createEmpty,extend } from 'ol/extent';
import {transform} from 'ol/proj';
import { Feature } from 'ol';
import { Geometry, Point, Circle } from 'ol/geom';
import { Extent, createEmpty, extend } from 'ol/extent';
import { transform } from 'ol/proj';
import { tassign } from 'tassign';
import * as style from 'ol/style';
@@ -44,7 +44,7 @@ import * as style from 'ol/style';
styleUrls: ['./map.component.scss']
})
export class MapComponent implements OnInit, OnDestroy,AfterViewInit {
export class MapComponent implements OnInit, OnDestroy, AfterViewInit {
title = 'Map';
public openedModalName$: Observable<string> = this.store.select(commonReducers.selectOpenedModalName);
public itemTypes$: Observable<{ [id: string]: IItemType }>;
@@ -54,49 +54,51 @@ export class MapComponent implements OnInit, OnDestroy,AfterViewInit {
public selectedOverlayLayer$: Observable<IItemLayer> = this.store.select(mapReducers.selectGetSelectedOverlayLayer);
public selectedItemLayer$: Observable<IItemLayer> = this.store.select(mapReducers.selectGetSelectedItemLayer);
public baseLayers$: Observable<Array<IItemLayer>> = this.store.select(mapReducers.selectGetBaseLayers);
public selectedBaseLayer$: Observable<IItemLayer> = this.store.select(mapReducers.selectGetSelectedBaseLayer);
public selectedBaseLayer$: Observable<IItemLayer> = this.store.select(mapReducers.selectGetSelectedBaseLayer);
public projection$: Observable<string> = this.store.select(mapReducers.selectGetProjection);
public selectedFeatures$: Subject<ISelectedFeatures> = new Subject<ISelectedFeatures>();
public droppedFile$: Subject<IDroppedFile> = new Subject<IDroppedFile>();
public droppedFile$: Subject<IDroppedFile> = new Subject<IDroppedFile>();
private paramSub: Subscription;
private itemTypeSub: Subscription;
private stateSub: Subscription;
private queryStateSub: Subscription;
private querySub: Subscription;
public parentCode$: Observable<string> =this.store.select(mapReducers.selectGetParentCode);
public parentCode$: Observable<string> = this.store.select(mapReducers.selectGetParentCode);
public panelVisible$: Observable<boolean> = this.store.select(mapReducers.selectGetPanelVisible);
public panelCollapsed$: Observable<boolean> = this.store.select(mapReducers.selectGetPanelCollapsed);
public panelExtraWide$: Observable<boolean> = this.store.select(mapReducers.selectGetPanelExtraWide);
public selectedFeature$: Observable<Feature<Geometry>> = this.store.select(mapReducers.selectGetSelectedFeature);
public clickedFeature: Subject<Feature<Geometry>> = new Subject<Feature<Geometry>>();
public selectedItem$: Observable<IItem> = this.store.select(mapReducers.selectGetSelectedItem);
public parentItem$: Observable<IItem> =this.store.select(mapReducers.selectGetParentItem);
public parentItem$: Observable<IItem> = this.store.select(mapReducers.selectGetParentItem);
public queryState$: Observable<IQueryState> = this.store.select(mapReducers.selectGetQueryState);
public state$:Observable<{mapState:IMapState,queryState:IQueryState}> = this.store.select(mapReducers.selectGetState);
public state$: Observable<{ mapState: IMapState, queryState: IQueryState }> = this.store.select(mapReducers.selectGetState);
public period$: Observable<IPeriodState> = this.store.select(mapReducers.selectGetPeriod);
public clearEnabled$: Observable<boolean> = this.store.select(mapReducers.selectGetClearEnabled);
public searchCollapsed$: Observable<boolean> = this.store.select(mapReducers.selectGetSearchCollapsed);
public searchMinified$: Observable<boolean> = this.store.select(mapReducers.selectGetSearchMinified);
public showDataLayerSlide$: Observable<boolean> = this.store.select(mapReducers.selectGetShowdataLayerSlide);
public menuVisible$: Observable<boolean>;
public query$: Observable<IQuery> = this.store.select(mapReducers.selectGetQuery);
public query$: Observable<IQuery> = this.store.select(mapReducers.selectGetQuery);
public position$: Observable<GeolocationPosition> = this.geolocationService.getCurrentPosition();
public compassHeading$: Observable<number> = this.deviceorientationService.getCurrentCompassHeading();
public baseLayersCollapsed = true;
public overlayLayersCollapsed = true;
public extent$: Observable<Extent> = this.store.select(mapReducers.selectGetExtent);
public styles$:Observable<IStyles> = this.store.select(mapReducers.selectGetStyles);
public styles$: Observable<IStyles> = this.store.select(mapReducers.selectGetStyles);
public fullscreen$: Observable<boolean> = this.store.select(commonReducers.selectGetFullScreen);
private lastUrl = "";
private initialized = false;
public noContent = false;
public overrideSelectedItemLayer = false;
public overrideOverlayLayers = false;
public hideShowLayerValues = false;
public const
public dataLayerSlideValue = 50;
public dataLayerSlideEnabled = false;
private visibleAreaBottom = 0;
private viewEnabled = true;
@ViewChild('map') map;
@ViewChild('contentDiv') contentDiv: ElementRef;
@@ -110,47 +112,48 @@ export class MapComponent implements OnInit, OnDestroy,AfterViewInit {
private geolocationService: GeolocationService,
private geolocaterService: GeolocatorService,
private zone: NgZone,
private deviceorientationService:DeviceOrientationService,
public devicesService:DeviceService) {
if(route && route.snapshot && route.snapshot.data && route.snapshot.data["fm-map-map"]) {
const params = route.snapshot.data["fm-map-map"];
this.overrideSelectedItemLayer = params["overrideSelectedItemlayer"] ? params["overrideSelectedItemlayer"] : false;
this.overrideOverlayLayers = params["overrideOverlayLayers"] ? params["overrideOverlayLayers"] : false;
}
this.querySub = this.query$.pipe(skip(1), withLatestFrom(this.mapState$)).subscribe(([query,mapState]) =>{
if(query && query.querystate) {
let newQueryState = tassign(mapReducers.initialQueryState);
//console.debug(`Do Query`);
const urlparts=[];
if (query.querystate.itemCode && query.querystate.itemCode != "") {
if(query.querystate.itemType && query.querystate.itemType!= "") {
const itemType = this.itemTypeService.itemTypes[query.querystate.itemType];
if (itemType && itemType.viewer && itemType.viewer == "edit_in_editor" && itemType.editor) {
urlparts.push('/editor');
urlparts.push(itemType.editor);
urlparts.push('item');
urlparts.push(query.querystate.itemCode);
}
private deviceorientationService: DeviceOrientationService,
public devicesService: DeviceService) {
if (route && route.snapshot && route.snapshot.data && route.snapshot.data["fm-map-map"]) {
const params = route.snapshot.data["fm-map-map"];
this.overrideSelectedItemLayer = params["overrideSelectedItemlayer"] ? params["overrideSelectedItemlayer"] : false;
this.overrideOverlayLayers = params["overrideOverlayLayers"] ? params["overrideOverlayLayers"] : false;
this.hideShowLayerValues = params["hideShowLayerValues"] ? params["hideShowLayerValues"] : false;
}
this.querySub = this.query$.pipe(skip(1), withLatestFrom(this.mapState$)).subscribe(([query, mapState]) => {
if (query && query.querystate) {
let newQueryState = tassign(mapReducers.initialQueryState);
//console.debug(`Do Query`);
const urlparts = [];
if (query.querystate.itemCode && query.querystate.itemCode != "") {
if (query.querystate.itemType && query.querystate.itemType != "") {
const itemType = this.itemTypeService.itemTypes[query.querystate.itemType];
if (itemType && itemType.viewer && itemType.viewer == "edit_in_editor" && itemType.editor) {
urlparts.push('/editor');
urlparts.push(itemType.editor);
urlparts.push('item');
urlparts.push(query.querystate.itemCode);
}
} else {
newQueryState= query.querystate;
}
if(urlparts.length==0 ) {
newQueryState.itemCode = query.querystate.itemCode;
this.zone.run(() => {
this.replaceUrl(mapState,newQueryState,query.replace);
})
} else {
this.router.navigate(urlparts);
}
} else {
newQueryState = query.querystate;
}
});
this.store.dispatch(new mapActions.Init());
// this.store.select(commonReducers.getRootItems).subscribe((l) => {
// if(l && l.length>0) {
// this.store.dispatch(new mapActions.Init());
// }
// });
if (urlparts.length == 0) {
newQueryState.itemCode = query.querystate.itemCode;
this.zone.run(() => {
this.replaceUrl(mapState, newQueryState, query.replace);
})
} else {
this.router.navigate(urlparts);
}
}
});
this.store.dispatch(new mapActions.Init());
// this.store.select(commonReducers.getRootItems).subscribe((l) => {
// if(l && l.length>0) {
// this.store.dispatch(new mapActions.Init());
// }
// });
}
@HostListener('document:keyup', ['$event'])
@@ -161,27 +164,27 @@ export class MapComponent implements OnInit, OnDestroy,AfterViewInit {
}
}
handlePanelResize(resizeTop:number) {
if(resizeTop==100 || !this.devicesService.IsMobile() ) {
this.visibleAreaBottom=0;
handlePanelResize(resizeTop: number) {
if (resizeTop == 100 || !this.devicesService.IsMobile()) {
this.visibleAreaBottom = 0;
} else {
this.visibleAreaBottom=100-resizeTop;
if(this.visibleAreaBottom>60) {
this.visibleAreaBottom=60;
this.visibleAreaBottom = 100 - resizeTop;
if (this.visibleAreaBottom > 60) {
this.visibleAreaBottom = 60;
}
}
}
}
bottom(panelVisible:boolean) {
if(panelVisible) {
return this.visibleAreaBottom + '%';
bottom(panelVisible: boolean) {
if (panelVisible) {
return this.visibleAreaBottom + '%';
} else {
return "0%";
}
}
handleOpenModal(modalName: string) {
this.store.dispatch(new commonActions.OpenModal(modalName));
this.store.dispatch(new commonActions.OpenModal(modalName));
}
handleCloseModal() {
@@ -189,7 +192,7 @@ export class MapComponent implements OnInit, OnDestroy,AfterViewInit {
}
handleFileDropped(droppedFile: IDroppedFile) {
this.uploadService.addFiles(droppedFile.files, droppedFile.event, { parentCode:droppedFile.parentCode, geometry:droppedFile.geometry });
this.uploadService.addFiles(droppedFile.files, droppedFile.event, { parentCode: droppedFile.parentCode, geometry: droppedFile.geometry });
}
handleFeatureClick(feature: Feature<Geometry>) {
@@ -205,26 +208,26 @@ export class MapComponent implements OnInit, OnDestroy,AfterViewInit {
this.store.dispatch(new mapActions.DoQuery(queryState));
}
handleSidepaneloutletActivate(component:any) {
if(component && component.hasOwnProperty('clickedFeature')) {
(component as IClickedFeature).clickedFeature = this.clickedFeature;
}
if(component && component.hasOwnProperty('extrawide')) {
this.store.dispatch(new mapActions.SetPanelExtraWide(true));
handleSidepaneloutletActivate(component: any) {
if (component && component.hasOwnProperty('clickedFeature')) {
(component as IClickedFeature).clickedFeature = this.clickedFeature;
}
if (component && component.hasOwnProperty('extrawide')) {
this.store.dispatch(new mapActions.SetPanelExtraWide(true));
}
}
}
handleSidepaneloutletDeactivate(component:any) {
if(component && component.hasOwnProperty('clickedFeature')) {
handleSidepaneloutletDeactivate(component: any) {
if (component && component.hasOwnProperty('clickedFeature')) {
(component as IClickedFeature).clickedFeature = null;
}
if(component && component.hasOwnProperty('extrawide')) {
if (component && component.hasOwnProperty('extrawide')) {
this.store.dispatch(new mapActions.SetPanelExtraWide(false));
}
}
handlePrerender(event:any) {
if(!this.dataLayerSlideEnabled) return;
handlePrerender(event: any) {
if (!this.dataLayerSlideEnabled) return;
const ctx = event.context;
const mapSize = this.map.instance.getSize();
const width = mapSize[0] * (this.dataLayerSlideValue / 100);
@@ -243,72 +246,74 @@ export class MapComponent implements OnInit, OnDestroy,AfterViewInit {
ctx.clip();
}
handleSlideChange(event:any) {
this.dataLayerSlideValue = event.target.value;
this.map.instance.render();
handleSlideChange(event: any) {
this.dataLayerSlideValue = event.target.value;
this.map.instance.render();
}
ngOnInit() {
ngOnInit() {
this.initialized = false;
//console.debug("Init");
this.store.dispatch(new mapActions.Clear());
this.selectedFeatures$.next({x:0,y:0,features:[]});
this.selectedFeatures$.next({ x: 0, y: 0, features: [] });
this.selectedFeatures$.next(null);
}
initCustomStyles() {
this.store.dispatch(new mapActions.SetStyle('vnd.farmmaps.itemtype.layer',new style.Style({
this.store.dispatch(new mapActions.SetStyle('vnd.farmmaps.itemtype.layer', new style.Style({
stroke: new style.Stroke({
color: 'red',
lineDash: [ 5,5],
lineDash: [5, 5],
width: 1
}),
geometry:(feature) =>feature.getGeometry()
geometry: (feature) => feature.getGeometry()
})));
this.store.dispatch(new mapActions.SetStyle('vnd.farmmaps.itemtype.layer_selected',new style.Style({
this.store.dispatch(new mapActions.SetStyle('vnd.farmmaps.itemtype.layer_selected', new style.Style({
stroke: new style.Stroke({
color: 'red',
lineDash: [ 5,5],
lineDash: [5, 5],
width: 3
}),
geometry:(feature) =>feature.getGeometry()
geometry: (feature) => feature.getGeometry()
})));
}
round(value:number,decimals:number):number {
round(value: number, decimals: number): number {
const d = Math.pow(10, decimals);
return Math.round((value + Number.EPSILON)*d)/d;
return Math.round((value + Number.EPSILON) * d) / d;
}
getMapStateFromUrl(params:ParamMap):IMapState {
getMapStateFromUrl(params: ParamMap): IMapState {
const hasUrlmapState = params.has("xCenter") && params.has("yCenter");
if (hasUrlmapState) {
const xCenter = parseFloat(params.get("xCenter"));
const yCenter = parseFloat(params.get("yCenter"));
const zoom = parseFloat(params.get("zoom"));
const rotation = parseFloat(params.get("rotation"));
const baseLayer = params.get("baseLayer")?params.get("baseLayer"):"";
const newMapState = {zoom: zoom, rotation: rotation, xCenter: xCenter, yCenter: yCenter, baseLayerCode: baseLayer };
const baseLayer = params.get("baseLayer") ? params.get("baseLayer") : "";
const newMapState = { zoom: zoom, rotation: rotation, xCenter: xCenter, yCenter: yCenter, baseLayerCode: baseLayer };
return newMapState;
} else {
return null;
}
}
normalizeMapState(mapState:IMapState):IMapState {
if(!mapState) return null;
return {zoom: this.round(mapState.zoom,0),
rotation: this.round(mapState.rotation,2),
xCenter: this.round(mapState.xCenter,5),
yCenter: this.round(mapState.yCenter,5),
baseLayerCode: mapState.baseLayerCode };
normalizeMapState(mapState: IMapState): IMapState {
if (!mapState) return null;
return {
zoom: this.round(mapState.zoom, 0),
rotation: this.round(mapState.rotation, 2),
xCenter: this.round(mapState.xCenter, 5),
yCenter: this.round(mapState.yCenter, 5),
baseLayerCode: mapState.baseLayerCode
};
}
serializeMapState(mapState:IMapState):string {
serializeMapState(mapState: IMapState): string {
return JSON.stringify(this.normalizeMapState(mapState));
}
getQueryStateFromUrl(params:ParamMap):IQueryState {
getQueryStateFromUrl(params: ParamMap): IQueryState {
if (params.has("queryState")) {
const queryState = params.get("queryState");
let newQueryState = tassign(mapReducers.initialQueryState);
@@ -323,65 +328,65 @@ export class MapComponent implements OnInit, OnDestroy,AfterViewInit {
ngAfterViewInit() {
//console.debug("View init");
this.noContent=true;
this.noContent = true;
this.route.children.forEach((entry) => {
if(entry.outlet=="primary") {
this.noContent=false;
if (entry.outlet == "primary") {
this.noContent = false;
}
});
this.initCustomStyles();
// url to state
const urlMapState = this.getMapStateFromUrl(this.route.snapshot.paramMap);
const urlQueryState = this.getQueryStateFromUrl(this.route.snapshot.paramMap);
if(urlQueryState && urlMapState && this.noContent) {
this.store.dispatch(new mapActions.SetState(urlMapState,urlQueryState));
window.localStorage.setItem("FarmMapsCommonMap_mapState",this.serializeMapState(urlMapState));
} else if(urlQueryState && this.noContent) {
this.store.dispatch(new mapActions.SetQueryState(urlQueryState));
} else {
this.store.dispatch(new mapActions.SetReplaceUrl(true));
}
const urlMapState = this.getMapStateFromUrl(this.route.snapshot.paramMap);
const urlQueryState = this.getQueryStateFromUrl(this.route.snapshot.paramMap);
if (urlQueryState && urlMapState && this.noContent) {
this.store.dispatch(new mapActions.SetState(urlMapState, urlQueryState));
window.localStorage.setItem("FarmMapsCommonMap_mapState", this.serializeMapState(urlMapState));
} else if (urlQueryState && this.noContent) {
this.store.dispatch(new mapActions.SetQueryState(urlQueryState));
} else {
this.store.dispatch(new mapActions.SetReplaceUrl(true));
}
this.paramSub = this.route.paramMap.pipe(withLatestFrom(this.state$),switchMap(([params,state]) => {
if(this.initialized && this.noContent) {
const urlQueryState = this.getQueryStateFromUrl(params);
if( this.serializeService.serialize(state.queryState) != this.serializeService.serialize(urlQueryState)) {
return of(new mapActions.SetState(state.mapState,urlQueryState));
}
}
return EMPTY;
})).subscribe((action) => {
if(action) {
this.zone.run(() => {
//console.debug("Url to state");
this.store.dispatch(action);
});
this.paramSub = this.route.paramMap.pipe(withLatestFrom(this.state$), switchMap(([params, state]) => {
if (this.initialized && this.noContent) {
const urlQueryState = this.getQueryStateFromUrl(params);
if (this.serializeService.serialize(state.queryState) != this.serializeService.serialize(urlQueryState)) {
return of(new mapActions.SetState(state.mapState, urlQueryState));
}
});
}
return EMPTY;
})).subscribe((action) => {
if (action) {
this.zone.run(() => {
//console.debug("Url to state");
this.store.dispatch(action);
});
}
});
// state to url
this.stateSub = this.state$.pipe(switchMap((state) => {
const newUrl = this.serializeMapState(state.mapState) + "_" + this.serializeService.serialize(state.queryState);
if(this.lastUrl!=newUrl) {
this.lastUrl=newUrl;
if (this.lastUrl != newUrl) {
this.lastUrl = newUrl;
return of(state);
}
else {
return of(null);
}
})).subscribe((newUrlState: any) => {
if(newUrlState) {
//console.debug(`State to url`);
this.replaceUrl(newUrlState.mapState,newUrlState.queryState,newUrlState.replaceUrl);
}
});
this.initialized = true;
if (newUrlState) {
//console.debug(`State to url`);
this.replaceUrl(newUrlState.mapState, newUrlState.queryState, newUrlState.replaceUrl);
}
});
this.initialized = true;
this.showDataLayerSlide$.subscribe((v) => {
this.dataLayerSlideEnabled=v;
this.dataLayerSlideEnabled = v;
this.map.instance.render();
});
this.store.select(mapReducers.selectGetViewEnabled).subscribe((v) => {
@@ -401,7 +406,7 @@ export class MapComponent implements OnInit, OnDestroy,AfterViewInit {
this.store.dispatch(new commonActions.ToggleMenu());
}
handleToggleBaseLayers(event:MouseEvent) {
handleToggleBaseLayers(event: MouseEvent) {
this.baseLayersCollapsed = !this.baseLayersCollapsed;
event.preventDefault();
}
@@ -418,30 +423,30 @@ export class MapComponent implements OnInit, OnDestroy,AfterViewInit {
}
replaceUrl(mapState: IMapState, queryState: IQueryState, replace = true) {
if(this.noContent) {
const newMapState = this.serializeMapState(mapState);
const newQueryState = this.serializeService.serialize(queryState);
const currentMapState = this.serializeMapState(this.getMapStateFromUrl(this.route.snapshot.paramMap));
const urlQueryState = this.getQueryStateFromUrl(this.route.snapshot.paramMap);
const currentQueryState = urlQueryState==null?"":this.serializeService.serialize(urlQueryState);
if(mapState.baseLayerCode!="" && ((newMapState!= currentMapState) || (newQueryState!=currentQueryState))) {
const parts =["."];
parts.push(mapState.xCenter.toFixed(5));
parts.push(mapState.yCenter.toFixed(5));
parts.push( mapState.zoom.toFixed(0));
parts.push( mapState.rotation.toFixed(2));
parts.push(mapState.baseLayerCode);
parts.push( this.serializeService.serialize(queryState));
//console.debug("Replace url",parts);
this.router.navigate(parts, { replaceUrl: replace,relativeTo:this.route.parent });
}
}
if (this.noContent) {
const newMapState = this.serializeMapState(mapState);
const newQueryState = this.serializeService.serialize(queryState);
const currentMapState = this.serializeMapState(this.getMapStateFromUrl(this.route.snapshot.paramMap));
const urlQueryState = this.getQueryStateFromUrl(this.route.snapshot.paramMap);
const currentQueryState = urlQueryState == null ? "" : this.serializeService.serialize(urlQueryState);
if (mapState.baseLayerCode != "" && ((newMapState != currentMapState) || (newQueryState != currentQueryState))) {
const parts = ["."];
parts.push(mapState.xCenter.toFixed(5));
parts.push(mapState.yCenter.toFixed(5));
parts.push(mapState.zoom.toFixed(0));
parts.push(mapState.rotation.toFixed(2));
parts.push(mapState.baseLayerCode);
parts.push(this.serializeService.serialize(queryState));
//console.debug("Replace url",parts);
this.router.navigate(parts, { replaceUrl: replace, relativeTo: this.route.parent });
}
}
}
handleOnMoveEnd(event) {
if(this.initialized && this.viewEnabled) {
this.zone.run(() =>{
handleOnMoveEnd(event) {
if (this.initialized && this.viewEnabled) {
this.zone.run(() => {
//console.debug("Move end");
const map = event.map;
const view = map.getView();
@@ -461,21 +466,23 @@ export class MapComponent implements OnInit, OnDestroy,AfterViewInit {
}
});
});
}
}
}
handleOnMouseDown(event: MouseEvent) {
event.stopPropagation();
this.zone.run(() =>{
this.zone.run(() => {
this.store.dispatch(new commonActions.CloseAll());
});
}
handleShowLayerValues(event: MouseEvent) {
event.stopPropagation();
this.zone.run(() =>{
this.store.dispatch(new mapActions.ToggleLayerValuesEnabled());
});
if (!this.hideShowLayerValues) {
event.stopPropagation();
this.zone.run(() => {
this.store.dispatch(new mapActions.ToggleLayerValuesEnabled());
});
}
}
handleOnDownload(event) {
@@ -491,15 +498,15 @@ export class MapComponent implements OnInit, OnDestroy,AfterViewInit {
}
handleOnToggleVisibility(itemLayer: IItemLayer) {
this.store.dispatch(new mapActions.SetVisibility(itemLayer,!itemLayer.visible));
this.store.dispatch(new mapActions.SetVisibility(itemLayer, !itemLayer.visible));
}
handleOnSetOpacity(event:{ layer: IItemLayer,opacity:number }) {
handleOnSetOpacity(event: { layer: IItemLayer, opacity: number }) {
this.store.dispatch(new mapActions.SetOpacity(event.layer, event.opacity));
}
handleZoomToExtent(itemLayer: IItemLayer) {
const extent = createEmpty();
const extent = createEmpty();
extend(extent, itemLayer.layer.getExtent());
if (extent) {
this.store.dispatch(new mapActions.SetExtent(extent));
@@ -514,21 +521,21 @@ export class MapComponent implements OnInit, OnDestroy,AfterViewInit {
this.store.dispatch(new mapActions.SelectOverlayLayer(itemLayer));
}
handlePeriodChange(period:IPeriodState) {
handlePeriodChange(period: IPeriodState) {
this.store.dispatch(new mapActions.SetPeriod(period));
}
handleCitySearch(location:string) {
handleCitySearch(location: string) {
this.geolocaterService.geocode(location).subscribe(locations => {
if( locations.length > 0) {
const point = new Point([locations[0].coordinates.lon,locations[0].coordinates.lat]);
if (locations.length > 0) {
const point = new Point([locations[0].coordinates.lon, locations[0].coordinates.lat]);
point.transform('EPSG:4326', 'EPSG:3857');
const circle = new Circle(point.getCoordinates(),5000);//
const circle = new Circle(point.getCoordinates(), 5000);//
const extent = createEmpty();
extend(extent, circle.getExtent());
this.store.dispatch(new mapActions.SetExtent(extent))
}
});
});
}
ngOnDestroy() {

View File

@@ -25,7 +25,7 @@ export class SelectedItemCropfieldComponent extends AbstractSelectedItemComponen
public items: Observable<IListItem[]>;
constructor(store: Store<mapReducers.State | commonReducers.State>, itemTypeService: ItemTypeService, location: Location, router: Router, private itemService$: ItemService,private folderService$: FolderService) {
super(store, itemTypeService,location,router);
super(store, itemTypeService, itemService$, location,router);
}
areaInHa(item:IItem):number {

View File

@@ -7,28 +7,31 @@
<h2 *ngIf="parentOfItemType('vnd.farmmaps.itemtype.cropfield')">{{parentItem.name}}</h2>
<h1>{{item.name}}</h1>
</div>
<div class="legend-container" *ngIf="item?.data.layers;let layers">
<div class="card menu-card">
<div *ngIf="layers.length>1">
<select (change)="onLayerChanged($event.target.value)">
<option *ngFor="let l of layers;" [value]="l.index" [selected]="itemLayer.layerIndex == l.index">{{l.name}}</option>
</select>
<ng-container *ngIf="item?.data.layers;let layers">
<div class="legend-container">
<div class="card menu-card">
<div *ngIf="layers.length>1">
<select (change)="onLayerChanged($event.target.value)">
<option *ngFor="let l of layers;" [value]="l.index" [selected]="itemLayer.layerIndex == l.index">{{l.name}}</option>
</select>
</div>
<fm-map-layer-legend [showTitle]="layers.length == 1"
[layer]="layer(layers,itemLayer.layerIndex)" [histogramenabled]="true"></fm-map-layer-legend>
</div>
<fm-map-layer-legend [showTitle]="layers.length == 1"
[layer]="layer(layers,itemLayer.layerIndex)" [histogramenabled]="true"></fm-map-layer-legend>
</div>
</div>
<div class="card menu-card">
<ul class="p-0 mt-2">
<li *ngIf="item.isEditable"><a href="#" class="ms-1 me-1" (click)="handleOnEdit(item)"><i class="fal fa-pencil" aria-hidden="true" i18n-title title="Edit"></i>&nbsp;<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>&nbsp;<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>&nbsp;<span i18n>Remove overlay</span></a></li>
</ng-container>
<li><fm-item-link class="text-primary p-0" [itemCode]="item.code" pathSuffix="data" [showText]="true"></fm-item-link></li>
</ul>
</div>
<fm-map-zoom-to-show-alert [layer]="itemLayer?.layer"></fm-map-zoom-to-show-alert>
<div class="card menu-card">
<ul class="p-0 mt-2">
<li *ngIf="item.isEditable"><a href="#" class="ms-1 me-1" (click)="handleOnEdit(item)"><i class="fal fa-pencil" aria-hidden="true" i18n-title title="Edit"></i>&nbsp;<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>&nbsp;<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>&nbsp;<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>&nbsp;<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>

View File

@@ -1,12 +1,13 @@
import { Component, Injectable } from '@angular/core';
import { Location } from '@angular/common';
import { Store } from '@ngrx/store';
import * as mapReducers from '../../reducers/map.reducer';
import { commonReducers, ItemTypeService, ItemService, FolderService } from '@farmmaps/common';
import { Component, Injectable, OnDestroy } from '@angular/core';
import { Router } from '@angular/router';
import { commonReducers, FolderService, IItem, IItemLinkType, ItemService, ItemTypeService, IUrlType } from '@farmmaps/common';
import { Store } from '@ngrx/store';
import { Subscription } from 'rxjs';
import * as mapActions from '../../actions/map.actions';
import * as mapReducers from '../../reducers/map.reducer';
import { ForItemType } from '../for-item/for-itemtype.decorator';
import { AbstractSelectedItemComponent } from '../selected-item/selected-item.component';
import * as mapActions from '../../actions/map.actions';
@ForItemType("vnd.farmmaps.itemtype.geotiff.processed")
@@ -16,10 +17,15 @@ import * as mapActions from '../../actions/map.actions';
templateUrl: './selected-item-geotiff.component.html',
styleUrls: ['./selected-item-geotiff.component.scss']
})
export class SelectedItemGeotiffComponent extends AbstractSelectedItemComponent {
export class SelectedItemGeotiffComponent extends AbstractSelectedItemComponent implements OnDestroy {
sub: Subscription;
constructor(store: Store<mapReducers.State | commonReducers.State>, itemTypeService: ItemTypeService, location: Location, router: Router, private itemService$: ItemService,private folderService$: FolderService) {
super(store, itemTypeService,location,router);
constructor(store: Store<mapReducers.State | commonReducers.State>, public itemService: ItemService, itemTypeService: ItemTypeService, location: Location, router: Router, private itemService$: ItemService,private folderService$: FolderService) {
super(store, itemTypeService,itemService,location,router);
}
ngOnDestroy(): void {
if (this.sub) this.sub.unsubscribe();
}
onLayerChanged(layerIndex: number) {
@@ -29,4 +35,13 @@ export class SelectedItemGeotiffComponent extends AbstractSelectedItemComponent
layer(layers:any,layerIndex:number) {
return layers.find(l => l.index == layerIndex);
}
download(event:MouseEvent,item:IItem,layers:any,layerIndex:number) {
event.stopPropagation();
event.preventDefault();
const itemLink : IItemLinkType = {itemcode:item.code,query:`layer=${this.layer(layers,layerIndex).name}`,pathsuffix:"download", validminutes:10}
this.sub = this.itemService.getItemLink(itemLink).subscribe((itemLinkUrl:IUrlType) => {
window.location.href = itemLinkUrl.url;
})
}
}

View File

@@ -7,25 +7,28 @@
<h2 *ngIf="parentOfItemType('vnd.farmmaps.itemtype.cropfield')">{{parentItem.name}}</h2>
<h1>{{item.name}}</h1>
</div>
<div class="legend-container" *ngIf="item?.data.layers;let layers">
<div class="card menu-card">
<div *ngIf="layers.length>1">
<select (change)="onLayerChanged($event.target.value)">
<option *ngFor="let l of layers;" [value]="l.index" [selected]="itemLayer.layerIndex == l.index">{{l.name}}</option>
</select>
<ng-container *ngIf="item?.data.layers;let layers">
<div class="legend-container">
<div class="card menu-card">
<div *ngIf="layers.length>1">
<select (change)="onLayerChanged($event.target.value)">
<option *ngFor="let l of layers;" [value]="l.index" [selected]="itemLayer.layerIndex == l.index">{{l.name}}</option>
</select>
</div>
<fm-map-layer-legend [showTitle]="layers.length==1" [layer]="layer(layers,itemLayer.layerIndex)" [histogramenabled]="true"></fm-map-layer-legend>
</div>
<fm-map-layer-legend [showTitle]="layers.length==1" [layer]="layer(layers,itemLayer.layerIndex)" [histogramenabled]="true"></fm-map-layer-legend>
</div>
</div>
<div class="card menu-card">
<ul class="p-0 mt-2">
<li *ngIf="item.isEditable"><a href="#" class="mt-1 me-1" (click)="handleOnEdit(item)" ><i class="fal fa-pencil" aria-hidden="true" i18n-title title="Edit"></i>&nbsp;<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>&nbsp;<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>&nbsp;<span i18n>Remove overlay</span></a></li>
</ng-container>
</ul>
</div>
<div class="card menu-card">
<ul class="p-0 mt-2">
<li *ngIf="item.isEditable"><a href="#" class="mt-1 me-1" (click)="handleOnEdit(item)" ><i class="fal fa-pencil" aria-hidden="true" i18n-title title="Edit"></i>&nbsp;<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>&nbsp;<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>&nbsp;<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>&nbsp;<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>

View File

@@ -1,14 +1,13 @@
import { Component, Input, Injectable, OnInit } from '@angular/core';
import { Location } from '@angular/common';
import { Feature } from 'ol';
import { Component, Injectable, OnDestroy } from '@angular/core';
import { Router } from '@angular/router';
import { commonReducers, FolderService, IItem, IItemLinkType, ItemService, ItemTypeService, IUrlType } from '@farmmaps/common';
import { Store } from '@ngrx/store';
import * as mapReducers from '../../reducers/map.reducer';
import { commonReducers, ItemTypeService, IItem, Item, ItemService, FolderService, IListItem} from '@farmmaps/common';
import * as mapActions from '../../actions/map.actions';
import { Router, ActivatedRoute, ParamMap, Event } from '@angular/router';
import * as mapReducers from '../../reducers/map.reducer';
import { ForItemType } from '../for-item/for-itemtype.decorator';
import { AbstractSelectedItemComponent } from '../selected-item/selected-item.component';
import { Observable } from 'rxjs';
import { Subscription } from 'rxjs';
@ForItemType("vnd.farmmaps.itemtype.shape.processed")
@@ -18,13 +17,18 @@ import { Observable } from 'rxjs';
templateUrl: './selected-item-shape.component.html',
styleUrls: ['./selected-item-shape.component.scss']
})
export class SelectedItemShapeComponent extends AbstractSelectedItemComponent {
constructor(store: Store<mapReducers.State | commonReducers.State>, itemTypeService: ItemTypeService, location: Location, router: Router, private itemService$: ItemService,private folderService$: FolderService) {
super(store, itemTypeService,location,router);
}
export class SelectedItemShapeComponent extends AbstractSelectedItemComponent implements OnDestroy {
public selectedLayer = 0;
sub: Subscription;
constructor(store: Store<mapReducers.State | commonReducers.State>, public itemService: ItemService, itemTypeService: ItemTypeService, location: Location, router: Router, private itemService$: ItemService,private folderService$: FolderService) {
super(store, itemTypeService,itemService,location,router);
}
ngOnDestroy(): void {
if (this.sub) this.sub.unsubscribe();
}
onLayerChanged(layerIndex: number) {
this.store.dispatch(new mapActions.SetLayerIndex(layerIndex));
}
@@ -32,4 +36,13 @@ export class SelectedItemShapeComponent extends AbstractSelectedItemComponent {
layer(layers:any,layerIndex:number) {
return layers.find(l => l.index == layerIndex);
}
download(event:MouseEvent,item:IItem,layers:any,layerIndex:number) {
event.stopPropagation();
event.preventDefault();
const itemLink : IItemLinkType = {itemcode:item.code,query:`layer=${this.layer(layers,layerIndex).name}`,pathsuffix:"download", validminutes:10}
this.sub = this.itemService.getItemLink(itemLink).subscribe((itemLinkUrl:IUrlType) => {
window.location.href = itemLinkUrl.url;
})
}
}

View File

@@ -7,43 +7,46 @@
<h2 *ngIf="parentOfItemType('vnd.farmmaps.itemtype.cropfield')">{{parentItem.name}}</h2>
<h1>{{item.name}}</h1>
</div>
<div class="legend-container" *ngIf="item?.data.layers;let layers">
<ng-container *ngIf="item?.data.layers;let layers">
<div class="legend-container">
<div class="card menu-card">
<h5><span i18n>Date</span>: {{temporalService.selectedDate(itemLayer)}}</h5>
<div class="d-flex justify-content-between">
<div>
<button *ngIf="temporalService.hasPrevious(itemLayer)" type="button" class="btn btn-link p-0" (click)="handlePreviousTemporal($event)">
<i class="fal fa-arrow-circle-left" aria-hidden="true" i18n-title title="Previous"></i>&nbsp;{{ 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)}}&nbsp;<i class="fal fa-arrow-circle-right" aria-hidden="true" i18n-title title="Next"></i>
</button>
</div>
</div>
<fm-map-zoom-to-show-alert [layer]="currentItemLayer()?.layer"></fm-map-zoom-to-show-alert>
</div>
<div class="card menu-card pt-2">
<div *ngIf="layers.length>1">
<select (change)="onLayerChanged($event.target.value)">
<option *ngFor="let l of layers;" [value]="l.index" [selected]="itemLayer.layerIndex == l.index">{{l.name}}</option>
</select>
</div>
<fm-map-layer-legend [showTitle]="layers.length == 1"
[layer]="layer(layers,itemLayer.layerIndex)" [histogramenabled]="true"></fm-map-layer-legend>
</div>
</div>
<div class="card menu-card">
<h5><span i18n>Date</span>: {{temporalService.selectedDate(itemLayer)}}</h5>
<div class="d-flex justify-content-between">
<div>
<button *ngIf="temporalService.hasPrevious(itemLayer)" type="button" class="btn btn-link p-0" (click)="handlePreviousTemporal($event)">
<i class="fal fa-arrow-circle-left" aria-hidden="true" i18n-title title="Previous"></i>&nbsp;{{ 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)}}&nbsp;<i class="fal fa-arrow-circle-right" aria-hidden="true" i18n-title title="Next"></i>
</button>
</div>
</div>
<fm-map-zoom-to-show-alert [layer]="currentItemLayer()?.layer"></fm-map-zoom-to-show-alert>
<ul class="p-0 mt-2">
<li *ngIf="item.isEditable"><a href="#" class="mt-1 me-1" (click)="handleOnEdit(item)"><i class="fal fa-pencil" aria-hidden="true" i18n-title title="Edit"></i>&nbsp;<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>&nbsp;<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>&nbsp;<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>&nbsp;<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>&nbsp;<span i18n>Download</span></a></li>
</ul>
</div>
<div class="card menu-card pt-2">
<div *ngIf="layers.length>1">
<select (change)="onLayerChanged($event.target.value)">
<option *ngFor="let l of layers;" [value]="l.index" [selected]="itemLayer.layerIndex == l.index">{{l.name}}</option>
</select>
</div>
<fm-map-layer-legend [showTitle]="layers.length == 1"
[layer]="layer(layers,itemLayer.layerIndex)" [histogramenabled]="true"></fm-map-layer-legend>
</div>
</div>
<div class="card menu-card">
<ul class="p-0 mt-2">
<li *ngIf="item.isEditable"><a href="#" class="mt-1 me-1" (click)="handleOnEdit(item)"><i class="fal fa-pencil" aria-hidden="true" i18n-title title="Edit"></i>&nbsp;<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>&nbsp;<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>&nbsp;<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>&nbsp;<span i18n>Show chart</span></a></li>
</ul>
</div>
</ng-container>
</div>
</div>
</div>

View File

@@ -1,16 +1,15 @@
import { Component, Injectable } from '@angular/core';
import { Location } from '@angular/common';
import { Store } from '@ngrx/store';
import * as mapReducers from '../../reducers/map.reducer';
import { commonReducers, ItemTypeService, IItem } from '@farmmaps/common';
import { Component, Injectable, OnDestroy } from '@angular/core';
import { Router } from '@angular/router';
import { commonReducers, IItem, IItemLinkType, ItemService, ItemTypeService, IUrlType } from '@farmmaps/common';
import { Store } from '@ngrx/store';
import { Subscription } from 'rxjs';
import * as mapActions from '../../actions/map.actions';
import { IItemLayer, ITemporalItemLayer } from '../../models/item.layer';
import * as mapReducers from '../../reducers/map.reducer';
import { TemporalService } from '../../services/temporal.service';
import { ForItemType } from '../for-item/for-itemtype.decorator';
import { AbstractSelectedItemComponent } from '../selected-item/selected-item.component';
import { ITemporalItemLayer} from '../../models/item.layer';
import * as mapActions from '../../actions/map.actions';
import { IItemLayer } from '../../models/item.layer';
import {TemporalService} from '../../services/temporal.service';
@ForItemType("vnd.farmmaps.itemtype.temporal")
@Injectable()
@@ -19,10 +18,15 @@ import {TemporalService} from '../../services/temporal.service';
templateUrl: './selected-item-temporal.component.html',
styleUrls: ['./selected-item-temporal.component.scss']
})
export class SelectedItemTemporalComponent extends AbstractSelectedItemComponent {
export class SelectedItemTemporalComponent extends AbstractSelectedItemComponent implements OnDestroy {
sub: Subscription;
constructor(store: Store<mapReducers.State | commonReducers.State>, itemTypeService: ItemTypeService, location: Location, router: Router,public temporalService:TemporalService) {
super(store, itemTypeService,location,router);
constructor(store: Store<mapReducers.State | commonReducers.State>, public itemService: ItemService, itemTypeService: ItemTypeService, location: Location, router: Router,public temporalService:TemporalService) {
super(store, itemTypeService,itemService,location,router);
}
ngOnDestroy(): void {
if (this.sub) this.sub.unsubscribe();
}
onLayerChanged(layerIndex: number) {
@@ -33,8 +37,6 @@ export class SelectedItemTemporalComponent extends AbstractSelectedItemComponent
return (this.itemLayer as ITemporalItemLayer)?.selectedItemLayer
}
handleNextTemporal(event:MouseEvent) {
this.store.dispatch(new mapActions.NextTemporal());
event.preventDefault();
@@ -61,4 +63,13 @@ export class SelectedItemTemporalComponent extends AbstractSelectedItemComponent
this.router.navigate(['/viewer', 'temporal', 'item', item.parentCode, new Date(Date.parse(item.dataDate)).getUTCFullYear()]);
return false;
}
download(event:MouseEvent,item:IItem,layers:any,layerIndex:number) {
event.stopPropagation();
event.preventDefault();
const itemLink : IItemLinkType = {itemcode:item.code,query:`layer=${this.layer(layers,layerIndex).name}`,pathsuffix:"download", validminutes:10}
this.sub = this.itemService.getItemLink(itemLink).subscribe((itemLinkUrl:IUrlType) => {
window.location.href = itemLinkUrl.url;
})
}
}

View File

@@ -2,7 +2,7 @@ import {Component, Injectable, Input, Directive} from '@angular/core';
import {Location} from '@angular/common';
import {Store} from '@ngrx/store';
import * as mapReducers from '../../reducers/map.reducer';
import {AppConfig, commonReducers, IItem, ItemTypeService} from '@farmmaps/common';
import {AppConfig, commonReducers, IItem, ItemService, ItemTypeService} from '@farmmaps/common';
import * as mapActions from '../../actions/map.actions';
import {Router} from '@angular/router';
import { IItemLayer } from '../../models/item.layer';
@@ -15,7 +15,7 @@ export abstract class AbstractSelectedItemComponent {
@Input() parentItem: IItem;
@Input() itemLayer: IItemLayer;
@Input() overlayLayers: Array<IItemLayer>;
constructor(public store: Store<mapReducers.State | commonReducers.State>, public itemTypeService: ItemTypeService, private location: Location, public router: Router) {
constructor(public store: Store<mapReducers.State | commonReducers.State>, public itemTypeService: ItemTypeService, public itemService: ItemService, private location: Location, public router: Router) {
}
handleOnView(item: IItem) {
@@ -37,6 +37,11 @@ export abstract class AbstractSelectedItemComponent {
return false;
}
handleOnDelete(item: IItem) {
this.itemService.deleteItem(item.code);
return false;
}
handleAddAsLayer(item: IItem,layerIndex = -1) {
this.store.dispatch(new mapActions.AddLayer(item,layerIndex));
return false;
@@ -76,8 +81,8 @@ export abstract class AbstractSelectedItemComponent {
})
export class SelectedItemComponent extends AbstractSelectedItemComponent {
constructor(store: Store<mapReducers.State | commonReducers.State>, itemTypeService: ItemTypeService, location: Location, router: Router, public config:AppConfig) {
super(store, itemTypeService,location,router);
constructor(store: Store<mapReducers.State | commonReducers.State>, itemTypeService: ItemTypeService, itemService: ItemService, location: Location, router: Router, public config:AppConfig) {
super(store, itemTypeService,itemService,location,router);
}
getThumbnailUrl(item:IItem):string {

View File

@@ -637,6 +637,8 @@ export const selectGetExtent = createSelector(selectMapState, getExtent);
export const selectGetViewExtent = createSelector(selectMapState, getViewExtent);
export const selectGetOverlayLayers = createSelector(selectMapState, getOverlayLayers);
export const selectGetBaseLayers = createSelector(selectMapState, getBaseLayers);
export const selectGetBaseMaps = createSelector(selectGetBaseLayers, (layers) => layers.filter(layer => layer.item.data.category === "baseMap"));
export const selectGetArealMaps = createSelector(selectGetBaseLayers, (layers) => layers.filter(layer => layer.item.data.category === "aerialPhoto").sort((a, b) => a.item.dataDate <= b.item.dataDate ? 1 : -1));
export const selectGetProjection = createSelector(selectMapState, getProjection);
export const selectGetSelectedBaseLayer = createSelector(selectMapState, getSelectedBaseLayer);
export const selectGetSelectedOverlayLayer = createSelector(selectMapState, getSelectedOverlayLayer);

View File

@@ -8,8 +8,8 @@
"tslib": "^2.0.0"
},
"peerDependencies": {
"@angular/common": "^18.2.3",
"@angular/core": "^18.2.3",
"@angular/common": "18.2.3",
"@angular/core": "18.2.3",
"cesium": "^1.97.0",
"ol-cesium": ">=2.13.0"
}

View File

@@ -6,9 +6,9 @@
},
"peerDependencies": {
"@ng-bootstrap/ng-bootstrap": "^17.0.1",
"@angular/common": "^18.2.3",
"@angular/core": "^18.2.3",
"@angular/forms": "^18.2.3",
"@angular/common": "18.2.3",
"@angular/core": "18.2.3",
"@angular/forms": "18.2.3",
"@ngrx/effects": "^18.0.2",
"@ngrx/router-store": "^18.0.2",
"@ngrx/store": "^18.0.2",

View File

@@ -83,6 +83,11 @@ export const SETPAGEMODE = '[AppCommon] SetPageMode';
export const SETUNREADNOTIFICATIONS = '[AppCommon] SetUnreadNotifications';
export const SWITCHLANGUAGE = '[AppCommon] SwitchLanguage';
export const SETSETTINGMENUBACKGROUNDCOLOR = '[AppCommon] SetSettingMenuBackgroundColor';
export class InitUser implements Action {
readonly type = INITUSER;
@@ -371,6 +376,17 @@ export class SetUnreadNotifications implements Action {
}
export class SwitchLanguage implements Action {
readonly type = SWITCHLANGUAGE;
constructor(public locale:string) { }
}
export class SetSettingMenuBackgroundColor implements Action {
readonly type = SETSETTINGMENUBACKGROUNDCOLOR;
constructor(public color:string) { }
}
export type Actions = OpenModal
| InitRoot
@@ -418,6 +434,8 @@ export type Actions = OpenModal
| ToggleHelpMenu
| ToggleSettingMenu
| NotificationEvent
| SetUnreadNotifications;
| SetUnreadNotifications
| SwitchLanguage
| SetSettingMenuBackgroundColor;

View File

@@ -13,6 +13,7 @@ import { SchemaService } from './services/schema.service';
import { FolderService } from './services/folder.service';
import { TimespanService } from './services/timespan.service';
import { ItemService } from './services/item.service';
import { TaskService } from './services/task.service';
import { AdminService } from './services/admin.service';
import { EventService } from './services/event.service';
import { TypeaheadService } from './services/typeahead.service';
@@ -44,6 +45,7 @@ export {
ItemTypeService,
TimespanService,
ItemService,
TaskService,
AdminService,
EventService,
TypeaheadService,

View File

@@ -33,7 +33,7 @@
<fm-resumable-file-upload></fm-resumable-file-upload>
</ng-container>
<div class="user-menu apponly">
<fm-setting-menu [user]="user|async" [showMenu]="settingMenuVisible|async"></fm-setting-menu>
<fm-setting-menu [user]="user|async" [showMenu]="settingMenuVisible|async" [backgroundColor]="settingMenuBackgroundColor|async"></fm-setting-menu>
<fm-help-menu [user]="user|async" [showMenu]="helpMenuVisible|async"></fm-help-menu>
<fm-notification-menu [user]="user|async" [unread]="unreadNotifications|async" [showMenu]="notificationMenuVisible|async"></fm-notification-menu>
<fm-app-menu [user]="user|async" [showMenu]="appMenuVisible|async"></fm-app-menu>

View File

@@ -50,6 +50,7 @@ export class AppComponent implements OnInit, OnDestroy {
public unreadNotifications: Observable<number> = this.store$.select(appReducers.SelectgetUnreadNotifications);
public user: Observable<IUser> = this.store$.select(appReducers.SelectGetUser);
public isPageMode: Observable<boolean> = this.store$.select(appReducers.SelectGetIsPageMode);
public settingMenuBackgroundColor: Observable<string> = this.store$.select(appReducers.SelectGetSettingMenuBackgroundColor);
@Input() showUploadProgress = true;
constructor(

View File

@@ -11,7 +11,7 @@
<i class="fal fa-image"></i>
<div i18n>No image selected</div>
</div>
<image-cropper #imageCropper
<image-cropper #imageCropper output="base64"
[imageChangedEvent]="imageChangedEvent"
[maintainAspectRatio]="true"
[format]="imageType"

View File

@@ -4,6 +4,7 @@ div.resumable-file-upload {
bottom: 0px;
width: 300px;
max-height: 250px;
z-index: 1;
/*z-index:2000 !important;*/
}

View File

@@ -1,5 +1,5 @@
<div>
<div (click)="toggle($event)" class="rounded-circle menu-button hidden" [ngClass]="{'hidden':!user || noContent}">
<div (click)="toggle($event)" class="rounded-circle menu-button hidden" [style.background-color]="backgroundColor" [ngClass]="{'hidden':!user || noContent}">
<span i18n-title title="Settings"><i class="fas fa-gear" aria-hidden="true"></i></span>
<div class="menu hidden" [ngClass]="{'hidden':!showMenu}">
<router-outlet name="setting-menu" (activate)="activateRoute()" (deactivate)="deActivateRoute()"></router-outlet>

View File

@@ -15,6 +15,7 @@ export class SettingMenuComponent implements OnInit {
@Input() user:IUser;
@Input() showMenu:boolean;
@Input() backgroundColor:string;
public noContent = true;
constructor(private store: Store<appReducers.State>) { }

View File

@@ -1,4 +1,4 @@
import { Injectable } from '@angular/core';
import { Injectable, Inject, LOCALE_ID } from '@angular/core';
import { Router } from '@angular/router';
import { OAuthService,UserInfo } from 'angular-oauth2-oidc';
import { Store } from '@ngrx/store';
@@ -16,6 +16,7 @@ import {StateSerializerService} from '../services/state-serializer.service';
@Injectable()
export class AppCommonEffects {
locale: string;
login$ = createEffect(() => this.actions$.pipe(
ofType(appCommonActions.LOGIN),
@@ -47,11 +48,27 @@ export class AppCommonEffects {
first(),
switchMap((action) => {
return zip(this.userService$.getCurrentUser(),from(this.oauthService$.loadUserProfile())).pipe(
switchMap(([user,userInfo]) => {return of(new appCommonActions.InitUserSuccess(user,userInfo as UserInfo))} ),
switchMap(([user,userInfo]) => {
if (location.hostname === 'localhost' || user.language === undefined || user.language === this.locale)
{
return of(new appCommonActions.InitUserSuccess(user,userInfo as UserInfo))
}
return of(new appCommonActions.SwitchLanguage(user.language))
}),
catchError(error => of(new appCommonActions.Fail(error))))
}
)));
switchLanguage$ = createEffect(() => this.actions$.pipe(
ofType(appCommonActions.SWITCHLANGUAGE),
switchMap((action) => {
const a = action as appCommonActions.SwitchLanguage;
if (location.href.includes(`/${this.locale}/`)) {
const newPath = location.href.replace(`/${this.locale}/`, `/${a.locale}/`);
location.replace(newPath);
}
return of(undefined);
})),{ dispatch:false});
initUserPackages$ = createEffect(() => this.actions$.pipe(
ofType(appCommonActions.INITUSERPACKAGES),
@@ -134,15 +151,22 @@ export class AppCommonEffects {
withLatestFrom(this.store$.select(appCommonReducers.selectGetItemTypes)),
switchMap(([action, itemtypes]) => {
const a = action as appCommonActions.EditItem;
var editor = "property";
var editor = "property";
if(a.item.itemType) {
const itemType = itemtypes[a.item.itemType];
var editor = itemType && itemType.editor ? itemType.editor : editor;
}
this.router$.navigate(['/editor',editor,'item', a.item.code])
return [];
}
)));
if (editor == 'croppingscheme') {
// Exeception: no 'item' in route
this.router$.navigate(['/editor', editor, a.item.code])
}
else {
this.router$.navigate(['/editor', editor, 'item', a.item.code])
}
return [];
}
)
));
viewItem$ = createEffect(() => this.actions$.pipe(
ofType(appCommonActions.VIEWITEM),
@@ -201,7 +225,8 @@ export class AppCommonEffects {
constructor(private actions$: Actions, private store$: Store<appCommonReducers.State>, private oauthService$: OAuthService, private itemService$: ItemService, private folderService$:FolderService, private userService$: UserService, private router$: Router, private stateSerializerService$:StateSerializerService) {
constructor(private actions$: Actions, private store$: Store<appCommonReducers.State>, private oauthService$: OAuthService, private itemService$: ItemService, private folderService$:FolderService, private userService$: UserService, private router$: Router, private stateSerializerService$:StateSerializerService, @Inject(LOCALE_ID) locale: string) {
this.locale = locale;
store$.dispatch(new appCommonActions.LoadItemTypes());
}
}
}

View File

@@ -26,6 +26,7 @@ export class Item implements IItem {
public data?:any;
public isEditable?:boolean;
public owner?: string;
public fullPath?: string;
constructor() {
}

View File

@@ -1,6 +1,7 @@
export interface IItemTask {
code?: string;
workflowCode?: string;
taskType?: string;
attributes?: any;
message?: string,
@@ -11,6 +12,7 @@ export interface IItemTask {
export class ItemTask implements IItemTask {
public code?:string;
public workflowCode?: string;
public taskType?: string;
public attributes?: any;
public message?: string;
@@ -18,6 +20,6 @@ export class ItemTask implements IItemTask {
public started?: Date;
public finished?: Date;
constructor() {
constructor() {
}
}
}

View File

@@ -29,7 +29,8 @@ export interface State {
settingMenuVisible: boolean,
unreadNotifications: number,
isOnline: boolean,
isPageMode:boolean
isPageMode:boolean,
settingMenuBackgroundColor:string
}
export const initialState: State = {
@@ -51,7 +52,8 @@ export const initialState: State = {
settingMenuVisible: false,
unreadNotifications: 0,
isOnline: true,
isPageMode: true
isPageMode: true,
settingMenuBackgroundColor:'rgb(128, 128, 128)'
}
export function reducer(state = initialState, action: appCommonActions.Actions ): State {
@@ -187,6 +189,10 @@ export function reducer(state = initialState, action: appCommonActions.Actions )
const a = action as appCommonActions.SetUnreadNotifications;
return tassign(state,{unreadNotifications:a.unread});
}
case appCommonActions.SETSETTINGMENUBACKGROUNDCOLOR: {
const a = action as appCommonActions.SetSettingMenuBackgroundColor;
return tassign(state,{settingMenuBackgroundColor:a.color});
}
default: {
return state;
}
@@ -212,6 +218,7 @@ export const getSettingMenuVisible = (state: State) => state.settingMenuVisible;
export const getUnreadNotifications = (state: State) => state.unreadNotifications;
export const getIsOnline = (state: State) => state.isOnline;
export const getIsPageMode = (state: State) => state.isPageMode;
export const getSettingMenuBackgroundColor = (state: State) => state.settingMenuBackgroundColor;
export const selectAppCommonState = createFeatureSelector<State>(MODULE_NAME);
@@ -238,5 +245,4 @@ export const SelectgetUnreadNotifications = createSelector(selectAppCommonState,
export const SelectGetIsOnline = createSelector(selectAppCommonState,getIsOnline);
export const SelectGetIsPageMode = createSelector(selectAppCommonState,getIsPageMode);
export const SelectGetSettingMenuBackgroundColor= createSelector(selectAppCommonState,getSettingMenuBackgroundColor);

View File

@@ -52,4 +52,20 @@ export class AdminService {
postItemTask(item: IItem, task: IItemTask): Observable<IItemTask> {
return this.httpClient.post<IItemTask>(`${this.ApiEndpoint()}/api/v1/admin/${item.code}/tasks`, task);
}
getFileStorageOverview(): Observable<any> {
return this.httpClient.get<any>(`${this.ApiEndpoint()}/api/v1/admin/filestorage/folderinfo/overview`);
}
getFileStorageInfo(user: string): Observable<any> {
return this.httpClient.get<any>(`${this.ApiEndpoint()}/api/v1/admin/filestorage/folderinfo/${user}`);
}
getFileStorageLog(): Observable<any> {
return this.httpClient.get<any>(`${this.ApiEndpoint()}/api/v1/admin/filestorage/folderinfo/log`);
}
validateEmail(user: IUser) {
return this.httpClient.post(`${this.ApiEndpoint()}/api/v1/admin/user/${user.code}/validateemail`, user);
}
}

View File

@@ -1,14 +1,12 @@
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import { IItemType } from '../models/item.type';
import { IItemLinkType } from '../models/itemlink.type';
import { IUrlType } from '../models/url.type';
import { IItem } from '../models/item';
import { IJsonline } from '../models/json-line';
import { IItemTask } from '../models/itemTask';
import { HttpClient, HttpParams, HttpHeaders } from "@angular/common/http";
import { AppConfig } from "../shared/app.config";
import {Injectable} from '@angular/core';
import {Observable} from 'rxjs';
import {IItemType} from '../models/item.type';
import {IItemLinkType} from '../models/itemlink.type';
import {IItem} from '../models/item';
import {IJsonline} from '../models/json-line';
import {IItemTask} from '../models/itemTask';
import {HttpClient, HttpHeaders, HttpParams} from '@angular/common/http';
import {AppConfig} from '../shared/app.config';
import {ItemTypeService} from './itemtype.service';
import {IListItem} from '../models/list.item';
@@ -81,7 +79,8 @@ export class ItemService {
getItemList(itemType?: string, dataFilter?: any, level?: number, atItemLocationItemCode?: string,
indexed?: boolean, validToday?: boolean,tags?:string,crs?:string, startDate?: Date, endDate?: Date,
skip?: number, take?: number, sourceTask?: string, exactMatchStartOrEndDate?: boolean, owner?:string): Observable<IItem[]> {
skip?: number, take?: number, sourceTask?: string, exactMatchStartOrEndDate?: boolean, owner?:string,
includeFullpath?: boolean): Observable<IItem[]> {
let params = new HttpParams();
if(itemType) params = params.append("it", itemType);
if(dataFilter) params = params.append("df", JSON.stringify(dataFilter));
@@ -96,11 +95,12 @@ export class ItemService {
if (sourceTask) params = params.append("sourceTask", sourceTask);
if(skip) params = params.append("skip", skip);
if(take) params = params.append("take", take);
if(exactMatchStartOrEndDate !== undefined) params = params.append("exactMatchStartOrEndDate", exactMatchStartOrEndDate);
if(exactMatchStartOrEndDate !== undefined) params = params.append("exactMatchStartOrEndDate", exactMatchStartOrEndDate);
if(owner) params = params.append("owner", owner);
if(includeFullpath) params = params.append("includeFullpath",includeFullpath?"true":"false");
return this.httpClient.get<IItem[]>(`${this.ApiEndpoint()}/api/v1/items/`, { params: params });
}
getItemListCount(itemType: string, startDate?: Date, endDate?: Date, sourceTask?: string,
indexed?: boolean, exactMatchStartOrEndDate?: boolean, owner?:string): Observable<number> {
let params = new HttpParams();
@@ -116,7 +116,7 @@ export class ItemService {
getChildItemList(parentcode: string, itemType?: string, dataFilter?: any, level = 1, deep = true,
startDate?: Date, endDate?: Date, skip?: number, take?: number,
exactMatchStartOrEndDate?: boolean, owner?:string): Observable<IItem[]> {
exactMatchStartOrEndDate?: boolean, owner?:string, indexed?: boolean): Observable<IItem[]> {
let params = new HttpParams();
if(itemType != null) {
params = params.append("it", itemType);
@@ -129,15 +129,17 @@ export class ItemService {
if (startDate) params = params.append("sDate", startDate.toISOString());
if (endDate) params = params.append("eDate", endDate.toISOString());
if(exactMatchStartOrEndDate !== undefined) params = params.append("exactMatchStartOrEndDate", exactMatchStartOrEndDate);
if(owner) params = params.append("owner", owner);
if(owner) params = params.append("owner", owner);
if(skip) params = params.append("skip", skip);
if(take) params = params.append("take", take);
if(indexed) params = params.append("ind",indexed?"true":"false");
return this.httpClient.get<IItem[]>(`${this.ApiEndpoint()}/api/v1/items/${parentcode}/children`, { params: params });
}
getChildItemListCount(parentcode: string, itemType?: string,dataFilter?: any,
startDate?: Date, endDate?: Date, exactMatchStartOrEndDate?: boolean, owner?:string): Observable<number> {
startDate?: Date, endDate?: Date, exactMatchStartOrEndDate?: boolean, owner?:string,
indexed?: boolean): Observable<number> {
let params = new HttpParams();
if(itemType != null) {
params = params.append("it", itemType);
@@ -149,6 +151,7 @@ export class ItemService {
if (endDate) params = params.append("eDate", endDate.toISOString());
if(exactMatchStartOrEndDate !== undefined) params = params.append("exactMatchStartOrEndDate", exactMatchStartOrEndDate);
if(owner) params = params.append("owner", owner);
if(indexed) params = params.append("ind",indexed?"true":"false");
return this.httpClient.get<number>(`${this.ApiEndpoint()}/api/v1/items/${parentcode}/children/count`, { params: params });
}

View File

@@ -15,37 +15,37 @@ export class ItemTypeService {
getIcon(itemType: string) {
let icon = "fal fa-file";
if (this.itemTypes[itemType]) icon = this.itemTypes[itemType].icon;
if (this.itemTypes && this.itemTypes[itemType]) icon = this.itemTypes[itemType].icon;
return icon;
}
getColor(itemType: string) {
let color = "#000000";
if (this.itemTypes[itemType]) color = this.itemTypes[itemType].iconColor;
if (this.itemTypes && this.itemTypes[itemType]) color = this.itemTypes[itemType].iconColor;
return color;
}
getExtraAttributes(itemType: string) {
let extraAttributes = null;
if (this.itemTypes[itemType] && this.itemTypes[itemType]?.extraAttributes) extraAttributes = this.itemTypes[itemType]?.extraAttributes;
if (this.itemTypes && this.itemTypes[itemType] && this.itemTypes[itemType]?.extraAttributes) extraAttributes = this.itemTypes[itemType]?.extraAttributes;
return extraAttributes;
}
getSchema(itemType: string): string {
let schema = null;
if (this.itemTypes[itemType]) schema = this.itemTypes[itemType].schema;
if (this.itemTypes && this.itemTypes[itemType]) schema = this.itemTypes[itemType].schema;
return schema;
}
hasViewer(item: IItem) {
const itemType: string = item.itemType;
if (this.itemTypes[itemType]) return this.itemTypes[itemType].viewer !== undefined;
if (this.itemTypes && this.itemTypes[itemType]) return this.itemTypes[itemType].viewer !== undefined;
return false;
}
hasEditor(item: IItem) {
const itemType: string = item.itemType;
if (this.itemTypes[itemType]) return this.itemTypes[itemType].editor !== undefined;
if (this.itemTypes && this.itemTypes[itemType]) return this.itemTypes[itemType].editor !== undefined;
return false;
}

View File

@@ -0,0 +1,40 @@
import {Injectable} from '@angular/core';
import {HttpClient, HttpParams} from '@angular/common/http';
import {AppConfig} from '../shared/app.config';
@Injectable({
providedIn: 'root',
})
export class TaskService {
constructor(public httpClient: HttpClient, public appConfig: AppConfig) {
}
ApiEndpoint() {
return this.appConfig.getConfig("apiEndPoint");
}
getTask(taskCode: string) {
return this.httpClient.get<any>(`${this.appConfig.getConfig('apiEndPoint')}/api/v1/tasks/${taskCode}`)
}
getTasks(workflowCode: string, itemCode: string = null, taskType: string = null, skip = 0, take = 25) {
let params = new HttpParams();
if (workflowCode) {
params = params.append('workflowCode', workflowCode);
}
if (itemCode) {
params = params.append('itemCode', itemCode);
}
if (taskType) {
params = params.append('taskType', taskType);
}
params = params.append('skip', skip.toString());
params = params.append('take', take.toString());
return this.httpClient.get<any>(`${this.appConfig.getConfig('apiEndPoint')}/api/v1/tasks`,
{params: params})
}
}

View File

@@ -31,8 +31,8 @@
"tslib": "^2.3.0"
},
"peerDependencies": {
"@angular/common": "^18.2.3",
"@angular/core": "^18.2.3",
"@angular/common": "18.2.3",
"@angular/core": "18.2.3",
"ol": "^8.2.0"
}
}