Sfoglia il codice sorgente

⬆️ align with EEA version

jmacura 3 anni fa
parent
commit
9fb299f4ec
31 ha cambiato i file con 1418 aggiunte e 331 eliminazioni
  1. 720 0
      package-lock.json
  2. 1 0
      package.json
  3. 51 15
      src/adjuster/adjuster-advanced-panel/adjuster-advanced-panel.component.html
  4. 6 0
      src/adjuster/adjuster-advanced-panel/adjuster-advanced-panel.component.scss
  5. 17 16
      src/adjuster/adjuster-advanced-panel/adjuster-advanced-panel.component.ts
  6. 3 1
      src/adjuster/adjuster-event.service.ts
  7. 30 19
      src/adjuster/adjuster-legend.service.ts
  8. 0 10
      src/adjuster/adjuster-loader.component.html
  9. 10 0
      src/adjuster/adjuster-loader/adjuster-loader.component.html
  10. 0 0
      src/adjuster/adjuster-loader/adjuster-loader.component.scss
  11. 4 3
      src/adjuster/adjuster-loader/adjuster-loader.component.ts
  12. 138 95
      src/adjuster/adjuster-presets.service.ts
  13. 83 0
      src/adjuster/adjuster-simple-panel/adjuster-simple-panel.component.html
  14. 1 0
      src/adjuster/adjuster-simple-panel/adjuster-simple-panel.component.scss
  15. 66 0
      src/adjuster/adjuster-simple-panel/adjuster-simple-panel.component.ts
  16. 55 0
      src/adjuster/adjuster-ui.service.ts
  17. 20 10
      src/adjuster/adjuster.module.ts
  18. 75 96
      src/adjuster/adjuster.service.ts
  19. 13 0
      src/adjuster/dataset-item/dataset-item.component.html
  20. 35 0
      src/adjuster/dataset-item/dataset-item.component.ts
  21. 1 13
      src/adjuster/dataset-list/dataset-list.component.html
  22. 1 0
      src/adjuster/dataset-list/dataset-list.component.scss
  23. 5 15
      src/adjuster/dataset-list/dataset-list.component.ts
  24. 0 6
      src/adjuster/index.ts
  25. 1 0
      src/adjuster/ontology.model.ts
  26. 1 0
      src/app.component.ts
  27. 7 5
      src/app.config.ts
  28. 2 3
      src/app.module.ts
  29. 45 19
      src/app.service.ts
  30. 1 1
      src/attractiveness.config.json
  31. 26 4
      src/translations.json

+ 720 - 0
package-lock.json

@@ -20,6 +20,7 @@
         "@angular-eslint/eslint-plugin-template": "^13.5.0",
         "@angular-eslint/template-parser": "^13.5.0",
         "@angular/cli": "~13.3.9",
+        "@typescript-eslint/eslint-plugin": "^5.36.1",
         "eslint": "^8.20.0",
         "eslint-config-openlayers": "14.0.0",
         "file-loader": "^6.2.0",
@@ -4026,6 +4027,169 @@
       "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==",
       "peer": true
     },
+    "node_modules/@typescript-eslint/eslint-plugin": {
+      "version": "5.36.1",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.36.1.tgz",
+      "integrity": "sha512-iC40UK8q1tMepSDwiLbTbMXKDxzNy+4TfPWgIL661Ym0sD42vRcQU93IsZIrmi+x292DBr60UI/gSwfdVYexCA==",
+      "dev": true,
+      "dependencies": {
+        "@typescript-eslint/scope-manager": "5.36.1",
+        "@typescript-eslint/type-utils": "5.36.1",
+        "@typescript-eslint/utils": "5.36.1",
+        "debug": "^4.3.4",
+        "functional-red-black-tree": "^1.0.1",
+        "ignore": "^5.2.0",
+        "regexpp": "^3.2.0",
+        "semver": "^7.3.7",
+        "tsutils": "^3.21.0"
+      },
+      "engines": {
+        "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/typescript-eslint"
+      },
+      "peerDependencies": {
+        "@typescript-eslint/parser": "^5.0.0",
+        "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0"
+      },
+      "peerDependenciesMeta": {
+        "typescript": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/scope-manager": {
+      "version": "5.36.1",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.36.1.tgz",
+      "integrity": "sha512-pGC2SH3/tXdu9IH3ItoqciD3f3RRGCh7hb9zPdN2Drsr341zgd6VbhP5OHQO/reUqihNltfPpMpTNihFMarP2w==",
+      "dev": true,
+      "dependencies": {
+        "@typescript-eslint/types": "5.36.1",
+        "@typescript-eslint/visitor-keys": "5.36.1"
+      },
+      "engines": {
+        "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/typescript-eslint"
+      }
+    },
+    "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/types": {
+      "version": "5.36.1",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.36.1.tgz",
+      "integrity": "sha512-jd93ShpsIk1KgBTx9E+hCSEuLCUFwi9V/urhjOWnOaksGZFbTOxAT47OH2d4NLJnLhkVD+wDbB48BuaycZPLBg==",
+      "dev": true,
+      "engines": {
+        "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/typescript-eslint"
+      }
+    },
+    "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/typescript-estree": {
+      "version": "5.36.1",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.36.1.tgz",
+      "integrity": "sha512-ih7V52zvHdiX6WcPjsOdmADhYMDN15SylWRZrT2OMy80wzKbc79n8wFW0xpWpU0x3VpBz/oDgTm2xwDAnFTl+g==",
+      "dev": true,
+      "dependencies": {
+        "@typescript-eslint/types": "5.36.1",
+        "@typescript-eslint/visitor-keys": "5.36.1",
+        "debug": "^4.3.4",
+        "globby": "^11.1.0",
+        "is-glob": "^4.0.3",
+        "semver": "^7.3.7",
+        "tsutils": "^3.21.0"
+      },
+      "engines": {
+        "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/typescript-eslint"
+      },
+      "peerDependenciesMeta": {
+        "typescript": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/utils": {
+      "version": "5.36.1",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.36.1.tgz",
+      "integrity": "sha512-lNj4FtTiXm5c+u0pUehozaUWhh7UYKnwryku0nxJlYUEWetyG92uw2pr+2Iy4M/u0ONMKzfrx7AsGBTCzORmIg==",
+      "dev": true,
+      "dependencies": {
+        "@types/json-schema": "^7.0.9",
+        "@typescript-eslint/scope-manager": "5.36.1",
+        "@typescript-eslint/types": "5.36.1",
+        "@typescript-eslint/typescript-estree": "5.36.1",
+        "eslint-scope": "^5.1.1",
+        "eslint-utils": "^3.0.0"
+      },
+      "engines": {
+        "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/typescript-eslint"
+      },
+      "peerDependencies": {
+        "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0"
+      }
+    },
+    "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/visitor-keys": {
+      "version": "5.36.1",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.36.1.tgz",
+      "integrity": "sha512-ojB9aRyRFzVMN3b5joSYni6FAS10BBSCAfKJhjJAV08t/a95aM6tAhz+O1jF+EtgxktuSO3wJysp2R+Def/IWQ==",
+      "dev": true,
+      "dependencies": {
+        "@typescript-eslint/types": "5.36.1",
+        "eslint-visitor-keys": "^3.3.0"
+      },
+      "engines": {
+        "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/typescript-eslint"
+      }
+    },
+    "node_modules/@typescript-eslint/eslint-plugin/node_modules/debug": {
+      "version": "4.3.4",
+      "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
+      "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
+      "dev": true,
+      "dependencies": {
+        "ms": "2.1.2"
+      },
+      "engines": {
+        "node": ">=6.0"
+      },
+      "peerDependenciesMeta": {
+        "supports-color": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@typescript-eslint/eslint-plugin/node_modules/semver": {
+      "version": "7.3.7",
+      "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz",
+      "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==",
+      "dev": true,
+      "dependencies": {
+        "lru-cache": "^6.0.0"
+      },
+      "bin": {
+        "semver": "bin/semver.js"
+      },
+      "engines": {
+        "node": ">=10"
+      }
+    },
     "node_modules/@typescript-eslint/experimental-utils": {
       "version": "5.27.1",
       "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-5.27.1.tgz",
@@ -4045,6 +4209,146 @@
         "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0"
       }
     },
+    "node_modules/@typescript-eslint/parser": {
+      "version": "5.36.1",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.36.1.tgz",
+      "integrity": "sha512-/IsgNGOkBi7CuDfUbwt1eOqUXF9WGVBW9dwEe1pi+L32XrTsZIgmDFIi2RxjzsvB/8i+MIf5JIoTEH8LOZ368A==",
+      "dev": true,
+      "peer": true,
+      "dependencies": {
+        "@typescript-eslint/scope-manager": "5.36.1",
+        "@typescript-eslint/types": "5.36.1",
+        "@typescript-eslint/typescript-estree": "5.36.1",
+        "debug": "^4.3.4"
+      },
+      "engines": {
+        "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/typescript-eslint"
+      },
+      "peerDependencies": {
+        "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0"
+      },
+      "peerDependenciesMeta": {
+        "typescript": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/scope-manager": {
+      "version": "5.36.1",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.36.1.tgz",
+      "integrity": "sha512-pGC2SH3/tXdu9IH3ItoqciD3f3RRGCh7hb9zPdN2Drsr341zgd6VbhP5OHQO/reUqihNltfPpMpTNihFMarP2w==",
+      "dev": true,
+      "peer": true,
+      "dependencies": {
+        "@typescript-eslint/types": "5.36.1",
+        "@typescript-eslint/visitor-keys": "5.36.1"
+      },
+      "engines": {
+        "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/typescript-eslint"
+      }
+    },
+    "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/types": {
+      "version": "5.36.1",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.36.1.tgz",
+      "integrity": "sha512-jd93ShpsIk1KgBTx9E+hCSEuLCUFwi9V/urhjOWnOaksGZFbTOxAT47OH2d4NLJnLhkVD+wDbB48BuaycZPLBg==",
+      "dev": true,
+      "peer": true,
+      "engines": {
+        "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/typescript-eslint"
+      }
+    },
+    "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/typescript-estree": {
+      "version": "5.36.1",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.36.1.tgz",
+      "integrity": "sha512-ih7V52zvHdiX6WcPjsOdmADhYMDN15SylWRZrT2OMy80wzKbc79n8wFW0xpWpU0x3VpBz/oDgTm2xwDAnFTl+g==",
+      "dev": true,
+      "peer": true,
+      "dependencies": {
+        "@typescript-eslint/types": "5.36.1",
+        "@typescript-eslint/visitor-keys": "5.36.1",
+        "debug": "^4.3.4",
+        "globby": "^11.1.0",
+        "is-glob": "^4.0.3",
+        "semver": "^7.3.7",
+        "tsutils": "^3.21.0"
+      },
+      "engines": {
+        "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/typescript-eslint"
+      },
+      "peerDependenciesMeta": {
+        "typescript": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/visitor-keys": {
+      "version": "5.36.1",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.36.1.tgz",
+      "integrity": "sha512-ojB9aRyRFzVMN3b5joSYni6FAS10BBSCAfKJhjJAV08t/a95aM6tAhz+O1jF+EtgxktuSO3wJysp2R+Def/IWQ==",
+      "dev": true,
+      "peer": true,
+      "dependencies": {
+        "@typescript-eslint/types": "5.36.1",
+        "eslint-visitor-keys": "^3.3.0"
+      },
+      "engines": {
+        "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/typescript-eslint"
+      }
+    },
+    "node_modules/@typescript-eslint/parser/node_modules/debug": {
+      "version": "4.3.4",
+      "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
+      "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
+      "dev": true,
+      "peer": true,
+      "dependencies": {
+        "ms": "2.1.2"
+      },
+      "engines": {
+        "node": ">=6.0"
+      },
+      "peerDependenciesMeta": {
+        "supports-color": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@typescript-eslint/parser/node_modules/semver": {
+      "version": "7.3.7",
+      "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz",
+      "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==",
+      "dev": true,
+      "peer": true,
+      "dependencies": {
+        "lru-cache": "^6.0.0"
+      },
+      "bin": {
+        "semver": "bin/semver.js"
+      },
+      "engines": {
+        "node": ">=10"
+      }
+    },
     "node_modules/@typescript-eslint/scope-manager": {
       "version": "5.27.1",
       "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.27.1.tgz",
@@ -4062,6 +4366,163 @@
         "url": "https://opencollective.com/typescript-eslint"
       }
     },
+    "node_modules/@typescript-eslint/type-utils": {
+      "version": "5.36.1",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.36.1.tgz",
+      "integrity": "sha512-xfZhfmoQT6m3lmlqDvDzv9TiCYdw22cdj06xY0obSznBsT///GK5IEZQdGliXpAOaRL34o8phEvXzEo/VJx13Q==",
+      "dev": true,
+      "dependencies": {
+        "@typescript-eslint/typescript-estree": "5.36.1",
+        "@typescript-eslint/utils": "5.36.1",
+        "debug": "^4.3.4",
+        "tsutils": "^3.21.0"
+      },
+      "engines": {
+        "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/typescript-eslint"
+      },
+      "peerDependencies": {
+        "eslint": "*"
+      },
+      "peerDependenciesMeta": {
+        "typescript": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/scope-manager": {
+      "version": "5.36.1",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.36.1.tgz",
+      "integrity": "sha512-pGC2SH3/tXdu9IH3ItoqciD3f3RRGCh7hb9zPdN2Drsr341zgd6VbhP5OHQO/reUqihNltfPpMpTNihFMarP2w==",
+      "dev": true,
+      "dependencies": {
+        "@typescript-eslint/types": "5.36.1",
+        "@typescript-eslint/visitor-keys": "5.36.1"
+      },
+      "engines": {
+        "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/typescript-eslint"
+      }
+    },
+    "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/types": {
+      "version": "5.36.1",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.36.1.tgz",
+      "integrity": "sha512-jd93ShpsIk1KgBTx9E+hCSEuLCUFwi9V/urhjOWnOaksGZFbTOxAT47OH2d4NLJnLhkVD+wDbB48BuaycZPLBg==",
+      "dev": true,
+      "engines": {
+        "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/typescript-eslint"
+      }
+    },
+    "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/typescript-estree": {
+      "version": "5.36.1",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.36.1.tgz",
+      "integrity": "sha512-ih7V52zvHdiX6WcPjsOdmADhYMDN15SylWRZrT2OMy80wzKbc79n8wFW0xpWpU0x3VpBz/oDgTm2xwDAnFTl+g==",
+      "dev": true,
+      "dependencies": {
+        "@typescript-eslint/types": "5.36.1",
+        "@typescript-eslint/visitor-keys": "5.36.1",
+        "debug": "^4.3.4",
+        "globby": "^11.1.0",
+        "is-glob": "^4.0.3",
+        "semver": "^7.3.7",
+        "tsutils": "^3.21.0"
+      },
+      "engines": {
+        "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/typescript-eslint"
+      },
+      "peerDependenciesMeta": {
+        "typescript": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/utils": {
+      "version": "5.36.1",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.36.1.tgz",
+      "integrity": "sha512-lNj4FtTiXm5c+u0pUehozaUWhh7UYKnwryku0nxJlYUEWetyG92uw2pr+2Iy4M/u0ONMKzfrx7AsGBTCzORmIg==",
+      "dev": true,
+      "dependencies": {
+        "@types/json-schema": "^7.0.9",
+        "@typescript-eslint/scope-manager": "5.36.1",
+        "@typescript-eslint/types": "5.36.1",
+        "@typescript-eslint/typescript-estree": "5.36.1",
+        "eslint-scope": "^5.1.1",
+        "eslint-utils": "^3.0.0"
+      },
+      "engines": {
+        "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/typescript-eslint"
+      },
+      "peerDependencies": {
+        "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0"
+      }
+    },
+    "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/visitor-keys": {
+      "version": "5.36.1",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.36.1.tgz",
+      "integrity": "sha512-ojB9aRyRFzVMN3b5joSYni6FAS10BBSCAfKJhjJAV08t/a95aM6tAhz+O1jF+EtgxktuSO3wJysp2R+Def/IWQ==",
+      "dev": true,
+      "dependencies": {
+        "@typescript-eslint/types": "5.36.1",
+        "eslint-visitor-keys": "^3.3.0"
+      },
+      "engines": {
+        "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/typescript-eslint"
+      }
+    },
+    "node_modules/@typescript-eslint/type-utils/node_modules/debug": {
+      "version": "4.3.4",
+      "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
+      "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
+      "dev": true,
+      "dependencies": {
+        "ms": "2.1.2"
+      },
+      "engines": {
+        "node": ">=6.0"
+      },
+      "peerDependenciesMeta": {
+        "supports-color": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@typescript-eslint/type-utils/node_modules/semver": {
+      "version": "7.3.7",
+      "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz",
+      "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==",
+      "dev": true,
+      "dependencies": {
+        "lru-cache": "^6.0.0"
+      },
+      "bin": {
+        "semver": "bin/semver.js"
+      },
+      "engines": {
+        "node": ">=10"
+      }
+    },
     "node_modules/@typescript-eslint/types": {
       "version": "5.27.1",
       "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.27.1.tgz",
@@ -19091,6 +19552,98 @@
       "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==",
       "peer": true
     },
+    "@typescript-eslint/eslint-plugin": {
+      "version": "5.36.1",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.36.1.tgz",
+      "integrity": "sha512-iC40UK8q1tMepSDwiLbTbMXKDxzNy+4TfPWgIL661Ym0sD42vRcQU93IsZIrmi+x292DBr60UI/gSwfdVYexCA==",
+      "dev": true,
+      "requires": {
+        "@typescript-eslint/scope-manager": "5.36.1",
+        "@typescript-eslint/type-utils": "5.36.1",
+        "@typescript-eslint/utils": "5.36.1",
+        "debug": "^4.3.4",
+        "functional-red-black-tree": "^1.0.1",
+        "ignore": "^5.2.0",
+        "regexpp": "^3.2.0",
+        "semver": "^7.3.7",
+        "tsutils": "^3.21.0"
+      },
+      "dependencies": {
+        "@typescript-eslint/scope-manager": {
+          "version": "5.36.1",
+          "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.36.1.tgz",
+          "integrity": "sha512-pGC2SH3/tXdu9IH3ItoqciD3f3RRGCh7hb9zPdN2Drsr341zgd6VbhP5OHQO/reUqihNltfPpMpTNihFMarP2w==",
+          "dev": true,
+          "requires": {
+            "@typescript-eslint/types": "5.36.1",
+            "@typescript-eslint/visitor-keys": "5.36.1"
+          }
+        },
+        "@typescript-eslint/types": {
+          "version": "5.36.1",
+          "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.36.1.tgz",
+          "integrity": "sha512-jd93ShpsIk1KgBTx9E+hCSEuLCUFwi9V/urhjOWnOaksGZFbTOxAT47OH2d4NLJnLhkVD+wDbB48BuaycZPLBg==",
+          "dev": true
+        },
+        "@typescript-eslint/typescript-estree": {
+          "version": "5.36.1",
+          "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.36.1.tgz",
+          "integrity": "sha512-ih7V52zvHdiX6WcPjsOdmADhYMDN15SylWRZrT2OMy80wzKbc79n8wFW0xpWpU0x3VpBz/oDgTm2xwDAnFTl+g==",
+          "dev": true,
+          "requires": {
+            "@typescript-eslint/types": "5.36.1",
+            "@typescript-eslint/visitor-keys": "5.36.1",
+            "debug": "^4.3.4",
+            "globby": "^11.1.0",
+            "is-glob": "^4.0.3",
+            "semver": "^7.3.7",
+            "tsutils": "^3.21.0"
+          }
+        },
+        "@typescript-eslint/utils": {
+          "version": "5.36.1",
+          "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.36.1.tgz",
+          "integrity": "sha512-lNj4FtTiXm5c+u0pUehozaUWhh7UYKnwryku0nxJlYUEWetyG92uw2pr+2Iy4M/u0ONMKzfrx7AsGBTCzORmIg==",
+          "dev": true,
+          "requires": {
+            "@types/json-schema": "^7.0.9",
+            "@typescript-eslint/scope-manager": "5.36.1",
+            "@typescript-eslint/types": "5.36.1",
+            "@typescript-eslint/typescript-estree": "5.36.1",
+            "eslint-scope": "^5.1.1",
+            "eslint-utils": "^3.0.0"
+          }
+        },
+        "@typescript-eslint/visitor-keys": {
+          "version": "5.36.1",
+          "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.36.1.tgz",
+          "integrity": "sha512-ojB9aRyRFzVMN3b5joSYni6FAS10BBSCAfKJhjJAV08t/a95aM6tAhz+O1jF+EtgxktuSO3wJysp2R+Def/IWQ==",
+          "dev": true,
+          "requires": {
+            "@typescript-eslint/types": "5.36.1",
+            "eslint-visitor-keys": "^3.3.0"
+          }
+        },
+        "debug": {
+          "version": "4.3.4",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
+          "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
+          "dev": true,
+          "requires": {
+            "ms": "2.1.2"
+          }
+        },
+        "semver": {
+          "version": "7.3.7",
+          "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz",
+          "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==",
+          "dev": true,
+          "requires": {
+            "lru-cache": "^6.0.0"
+          }
+        }
+      }
+    },
     "@typescript-eslint/experimental-utils": {
       "version": "5.27.1",
       "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-5.27.1.tgz",
@@ -19100,6 +19653,86 @@
         "@typescript-eslint/utils": "5.27.1"
       }
     },
+    "@typescript-eslint/parser": {
+      "version": "5.36.1",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.36.1.tgz",
+      "integrity": "sha512-/IsgNGOkBi7CuDfUbwt1eOqUXF9WGVBW9dwEe1pi+L32XrTsZIgmDFIi2RxjzsvB/8i+MIf5JIoTEH8LOZ368A==",
+      "dev": true,
+      "peer": true,
+      "requires": {
+        "@typescript-eslint/scope-manager": "5.36.1",
+        "@typescript-eslint/types": "5.36.1",
+        "@typescript-eslint/typescript-estree": "5.36.1",
+        "debug": "^4.3.4"
+      },
+      "dependencies": {
+        "@typescript-eslint/scope-manager": {
+          "version": "5.36.1",
+          "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.36.1.tgz",
+          "integrity": "sha512-pGC2SH3/tXdu9IH3ItoqciD3f3RRGCh7hb9zPdN2Drsr341zgd6VbhP5OHQO/reUqihNltfPpMpTNihFMarP2w==",
+          "dev": true,
+          "peer": true,
+          "requires": {
+            "@typescript-eslint/types": "5.36.1",
+            "@typescript-eslint/visitor-keys": "5.36.1"
+          }
+        },
+        "@typescript-eslint/types": {
+          "version": "5.36.1",
+          "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.36.1.tgz",
+          "integrity": "sha512-jd93ShpsIk1KgBTx9E+hCSEuLCUFwi9V/urhjOWnOaksGZFbTOxAT47OH2d4NLJnLhkVD+wDbB48BuaycZPLBg==",
+          "dev": true,
+          "peer": true
+        },
+        "@typescript-eslint/typescript-estree": {
+          "version": "5.36.1",
+          "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.36.1.tgz",
+          "integrity": "sha512-ih7V52zvHdiX6WcPjsOdmADhYMDN15SylWRZrT2OMy80wzKbc79n8wFW0xpWpU0x3VpBz/oDgTm2xwDAnFTl+g==",
+          "dev": true,
+          "peer": true,
+          "requires": {
+            "@typescript-eslint/types": "5.36.1",
+            "@typescript-eslint/visitor-keys": "5.36.1",
+            "debug": "^4.3.4",
+            "globby": "^11.1.0",
+            "is-glob": "^4.0.3",
+            "semver": "^7.3.7",
+            "tsutils": "^3.21.0"
+          }
+        },
+        "@typescript-eslint/visitor-keys": {
+          "version": "5.36.1",
+          "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.36.1.tgz",
+          "integrity": "sha512-ojB9aRyRFzVMN3b5joSYni6FAS10BBSCAfKJhjJAV08t/a95aM6tAhz+O1jF+EtgxktuSO3wJysp2R+Def/IWQ==",
+          "dev": true,
+          "peer": true,
+          "requires": {
+            "@typescript-eslint/types": "5.36.1",
+            "eslint-visitor-keys": "^3.3.0"
+          }
+        },
+        "debug": {
+          "version": "4.3.4",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
+          "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
+          "dev": true,
+          "peer": true,
+          "requires": {
+            "ms": "2.1.2"
+          }
+        },
+        "semver": {
+          "version": "7.3.7",
+          "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz",
+          "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==",
+          "dev": true,
+          "peer": true,
+          "requires": {
+            "lru-cache": "^6.0.0"
+          }
+        }
+      }
+    },
     "@typescript-eslint/scope-manager": {
       "version": "5.27.1",
       "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.27.1.tgz",
@@ -19110,6 +19743,93 @@
         "@typescript-eslint/visitor-keys": "5.27.1"
       }
     },
+    "@typescript-eslint/type-utils": {
+      "version": "5.36.1",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.36.1.tgz",
+      "integrity": "sha512-xfZhfmoQT6m3lmlqDvDzv9TiCYdw22cdj06xY0obSznBsT///GK5IEZQdGliXpAOaRL34o8phEvXzEo/VJx13Q==",
+      "dev": true,
+      "requires": {
+        "@typescript-eslint/typescript-estree": "5.36.1",
+        "@typescript-eslint/utils": "5.36.1",
+        "debug": "^4.3.4",
+        "tsutils": "^3.21.0"
+      },
+      "dependencies": {
+        "@typescript-eslint/scope-manager": {
+          "version": "5.36.1",
+          "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.36.1.tgz",
+          "integrity": "sha512-pGC2SH3/tXdu9IH3ItoqciD3f3RRGCh7hb9zPdN2Drsr341zgd6VbhP5OHQO/reUqihNltfPpMpTNihFMarP2w==",
+          "dev": true,
+          "requires": {
+            "@typescript-eslint/types": "5.36.1",
+            "@typescript-eslint/visitor-keys": "5.36.1"
+          }
+        },
+        "@typescript-eslint/types": {
+          "version": "5.36.1",
+          "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.36.1.tgz",
+          "integrity": "sha512-jd93ShpsIk1KgBTx9E+hCSEuLCUFwi9V/urhjOWnOaksGZFbTOxAT47OH2d4NLJnLhkVD+wDbB48BuaycZPLBg==",
+          "dev": true
+        },
+        "@typescript-eslint/typescript-estree": {
+          "version": "5.36.1",
+          "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.36.1.tgz",
+          "integrity": "sha512-ih7V52zvHdiX6WcPjsOdmADhYMDN15SylWRZrT2OMy80wzKbc79n8wFW0xpWpU0x3VpBz/oDgTm2xwDAnFTl+g==",
+          "dev": true,
+          "requires": {
+            "@typescript-eslint/types": "5.36.1",
+            "@typescript-eslint/visitor-keys": "5.36.1",
+            "debug": "^4.3.4",
+            "globby": "^11.1.0",
+            "is-glob": "^4.0.3",
+            "semver": "^7.3.7",
+            "tsutils": "^3.21.0"
+          }
+        },
+        "@typescript-eslint/utils": {
+          "version": "5.36.1",
+          "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.36.1.tgz",
+          "integrity": "sha512-lNj4FtTiXm5c+u0pUehozaUWhh7UYKnwryku0nxJlYUEWetyG92uw2pr+2Iy4M/u0ONMKzfrx7AsGBTCzORmIg==",
+          "dev": true,
+          "requires": {
+            "@types/json-schema": "^7.0.9",
+            "@typescript-eslint/scope-manager": "5.36.1",
+            "@typescript-eslint/types": "5.36.1",
+            "@typescript-eslint/typescript-estree": "5.36.1",
+            "eslint-scope": "^5.1.1",
+            "eslint-utils": "^3.0.0"
+          }
+        },
+        "@typescript-eslint/visitor-keys": {
+          "version": "5.36.1",
+          "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.36.1.tgz",
+          "integrity": "sha512-ojB9aRyRFzVMN3b5joSYni6FAS10BBSCAfKJhjJAV08t/a95aM6tAhz+O1jF+EtgxktuSO3wJysp2R+Def/IWQ==",
+          "dev": true,
+          "requires": {
+            "@typescript-eslint/types": "5.36.1",
+            "eslint-visitor-keys": "^3.3.0"
+          }
+        },
+        "debug": {
+          "version": "4.3.4",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
+          "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
+          "dev": true,
+          "requires": {
+            "ms": "2.1.2"
+          }
+        },
+        "semver": {
+          "version": "7.3.7",
+          "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz",
+          "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==",
+          "dev": true,
+          "requires": {
+            "lru-cache": "^6.0.0"
+          }
+        }
+      }
+    },
     "@typescript-eslint/types": {
       "version": "5.27.1",
       "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.27.1.tgz",

+ 1 - 0
package.json

@@ -37,6 +37,7 @@
     "@angular-eslint/eslint-plugin-template": "^13.5.0",
     "@angular-eslint/template-parser": "^13.5.0",
     "@angular/cli": "~13.3.9",
+    "@typescript-eslint/eslint-plugin": "^5.36.1",
     "eslint": "^8.20.0",
     "eslint-config-openlayers": "14.0.0",
     "file-loader": "^6.2.0",

+ 51 - 15
src/adjuster/adjuster.component.html → src/adjuster/adjuster-advanced-panel/adjuster-advanced-panel.component.html

@@ -7,50 +7,86 @@
           <button type="button" class="btn btn-primary btn-lg" (click)="adjusterService.apply()"
             [disabled]="adjusterService.isInProcess() || noDataSelected() || noOperationSelected() ">{{'ADJUSTER.calculate' | translateHs: {app: 'default'} }}</button>
         </div>
-        <div>
+        <div class="ps-1 ps-sm-3">
           <button type="button" class="btn btn-sm btn-light hs-lm-item-visibility"
             [ngClass]="adjusterService.allowIndex ? 'hs-checkmark' : 'hs-uncheckmark'"
             (click)="adjusterService.allowIndex = !adjusterService.allowIndex; $event.stopPropagation()"></button>
-          <label class="ps-2 text-secondary">{{'ADJUSTER.index' | translateHs: {app: 'default'} }}</label>
+          <label class="ps-2 text-secondary" [ngClass]="adjusterService.allowIndex ? 'fw-bold' : 'fw-normal'">
+            {{'ADJUSTER.index' | translateHs: {app: 'default'} }}
+          </label>
+          <p class="text-secondary text-justify fst-italic">{{'ADJUSTER.indexDescription' | translateHs: {app: 'default'} }}</p>
         </div>
-        <div>
+        <div class="ps-1 ps-sm-3">
           <button type="button" class="btn btn-sm btn-light hs-lm-item-visibility"
             [ngClass]="adjusterService.allowClusters ? 'hs-checkmark' : 'hs-uncheckmark'"
             (click)="adjusterService.allowClusters = !adjusterService.allowClusters; $event.stopPropagation()"></button>
-            <label class="ps-2 text-secondary">{{'ADJUSTER.clusters' | translateHs: {app: 'default'} }}</label>
+          <label class="ps-2 text-secondary" [ngClass]="adjusterService.allowClusters ? 'fw-bold' : 'fw-normal'">
+            {{'ADJUSTER.clusters' | translateHs: {app: 'default'} }}
+          </label>
+          <p class="text-secondary text-justify fst-italic">{{'ADJUSTER.clustersDescription' | translateHs: {app: 'default'} }}</p>
         </div>
       </div>
       <div class="text-warning pt-2" [hidden]="!noDataSelected() || errorMsg">{{'ADJUSTER.noDataSelectedMsg' | translateHs: {app: 'default'} }}</div>
       <div class="text-danger pt-2" [hidden]="!errorMsg">{{'ADJUSTER.serverError' | translateHs: {app: 'default'} }}: {{errorMsg}}</div>
     </div>
+    <div class="p-2 center-block" [hidden]="!adjusterService.allowClusters">
+      <div class="pt-2 text-secondary">{{'ADJUSTER.numberOfClusters' | translate}}: {{adjusterService.numberOfClusters}}</div>
+      <input type="range" class="form-range" [(ngModel)]="adjusterService.numberOfClusters" min="5" max="15" step="1">
+    </div>
     <div class="p-2 center-block">
-      {{'ADJUSTER.myRoleIs' | translateHs: {app: 'default'} }}:&emsp;
-      <select class="form-select" [(ngModel)]="adjusterPresetsService.activeRole" (ngModelChange)="adjusterPresetsService.pickProblem($event)">
+      <p class="my-1">{{'ADJUSTER.myRoleIs' | translateHs: {app: 'default'} }}:&emsp;</p>
+      <select class="form-select mb-1 mb-sm-2" [(ngModel)]="adjusterPresetsService.activeRole" (ngModelChange)="adjusterPresetsService.pickProblem($event)">
         <option *ngFor="let role of adjusterPresetsService.roles" [ngValue]="role">{{getLabelInCurrentLang(role.labels)}}</option>
       </select>
-      {{'ADJUSTER.myProblemIs' | translateHs: {app: 'default'} }}:&emsp;
+      <p class="my-1">{{'ADJUSTER.myProblemIs' | translateHs: {app: 'default'} }}:&emsp;</p>
       <select class="form-select" [(ngModel)]="adjusterPresetsService.activeProblem" (ngModelChange)="adjusterPresetsService.applyProblem($event)">
         <option *ngFor="let problem of adjusterPresetsService.getActiveRoleProblems()" [ngValue]="problem">{{getLabelInCurrentLang(problem.labels)}}</option>
       </select>
     </div>
-    <button class="btn btn-secondary btn-sm" aria-expanded="false" aria-controls="advancedOptions" (click)="showAdvancedOptions = !showAdvancedOptions">
+    <div class="pt-3 center-block">
+      <button type="button" class="btn btn-primary btn-sm" [disabled]="adjusterService.isInProcess()"
+          (click)="hsLayoutService.setMainPanel('adjuster-simple');$event.preventDefault();">
+        <span class="glyphicon cursor-pointer" class="icon-chevron-left"></span>
+        {{'ADJUSTER.simple' | translateHs: {app: 'default'} }}
+      </button>
+    </div>
+    <!--button class="btn btn-secondary btn-sm" aria-expanded="false" aria-controls="advancedOptions" (click)="showAdvancedOptions = !showAdvancedOptions">
       <span class="glyphicon cursor-pointer" [ngClass]="showAdvancedOptions ? 'icon-chevron-down' : 'icon-chevron-right'"></span>
-      {{'ADJUSTER.advanced' | translateHs: {app: 'default'} }}
-    </button>
-    <div class="p-2 center-block" [hidden]="!showAdvancedOptions">
+      {{'ADJUSTER.moreOpts' | translateHs: {app: 'default'} }}
+    </button-->
+    <div class="p-2 center-block">
       {{'ADJUSTER.classifyBySchema' | translateHs: {app: 'default'} }}:&emsp;
       <select class="form-select" [(ngModel)]="adjusterPresetsService.activeSchema" (ngModelChange)="adjusterPresetsService.changeSchema($event)">
         <option *ngFor="let schema of adjusterPresetsService.schemas" [ngValue]="schema">{{getLabelInCurrentLang(schema.labels)}}</option>
       </select>
     </div>
-    <div class="p-2 center-block" [hidden]="!adjusterService.allowClusters">
-      <div class="pt-2 text-secondary">{{'ADJUSTER.numberOfClusters' | translateHs: {app: 'default'} }}: {{adjusterService.numberOfClusters}}</div>
-      <input type="range" class="form-range" [(ngModel)]="adjusterService.numberOfClusters" min="5" max="15" step="1">
-    </div>
     <div *ngFor="let factor of adjusterService.factors">
       <pra-dataset-list [factor]="factor" *ngIf="hasDatasets(factor)"></pra-dataset-list>
     </div>
     <hr>
+    <div [hidden]="!adjusterService.allowIndex" class="pb-2">
+      <p class="lead">{{ 'ADJUSTER.indexLegend' | translateHs: {app: 'default'} }}</p>
+      <div class="d-flex pb-1">
+        <div *ngFor="let category of adjusterLegendService.staticIndexLegend" class="flex-grow-1">
+          <div [ngStyle]="{'background-color': category}">&nbsp;</div>
+        </div>
+      </div>
+      <div class="d-flex">
+        <div class="flex-grow-1 text-start">{{ 'ADJUSTER.index0' | translateHs: {app: 'default'} }}</div>
+        <div class="flex-grow-1">&nbsp;</div>
+        <div class="flex-grow-1 text-end">{{ 'ADJUSTER.index100' | translateHs: {app: 'default'} }}</div>
+      </div>
+    </div>
+    <div [hidden]="!adjusterService.allowClusters" class="pb-2">
+      <p class="lead">{{ 'ADJUSTER.clusterLegend' | translateHs: {app: 'default'} }}</p>
+      <div class="container">
+        <div class="row row-cols-1 row-cols-sm-2 row-cols-md-3 row-cols-lg-4">
+          <div *ngFor="let color of adjusterLegendService.staticClusterLegend; let i = index" class="col">
+            <div style="background-color: {{color}}" class="cluster-id text-center p-1 py-sm-3 my-1 my-sm-2">#{{i+1}}</div>
+          </div>
+        </div>
+      </div>
+    </div>
     <div class="pt-3 center-block" [hidden]="!adjusterService.clustersLoaded()">
       {{'ADJUSTER.layerManagerLink1' | translateHs: {app: 'default'} }}<br>
       {{'ADJUSTER.layerManagerLink2' | translateHs: {app: 'default'} }} <a href="" (click)="hsLayoutService.setMainPanel('layermanager');$event.preventDefault();">{{'ADJUSTER.layerManagerLinkLMName' | translateHs: {app: 'default'} }}</a>

+ 6 - 0
src/adjuster/adjuster.component.scss → src/adjuster/adjuster-advanced-panel/adjuster-advanced-panel.component.scss

@@ -3,11 +3,17 @@
 @import "bootstrap/scss/mixins";
 @import "bootstrap/scss/forms";
 
+hr {border: 1px solid $primary;}
+
 .center-block {
   text-align: center;
   margin-bottom: 1em;
 }
 
+.cluster-id {
+  text-shadow: -1px 0 white, 0 1px white, 1px 0 white, 0 -1px white;
+}
+
 .cursor-pointer {
   cursor: pointer;
 }

+ 17 - 16
src/adjuster/adjuster.component.ts → src/adjuster/adjuster-advanced-panel/adjuster-advanced-panel.component.ts

@@ -1,19 +1,23 @@
-import {Component, OnInit, ViewRef} from '@angular/core';
+import {Component, ViewRef} from '@angular/core';
 
-import {HsDialogContainerService, HsPanelBaseComponent, HsLayoutService} from 'hslayers-ng';
+import {
+  HsDialogContainerService,
+  HsLayoutService,
+  HsPanelBaseComponent,
+} from 'hslayers-ng';
 
 //import {AdjusterEventService} from './adjuster-event.service';
-import {AdjusterLoaderComponent} from './adjuster-loader.component';
-import {AdjusterPresetsService} from './adjuster-presets.service';
-import {AdjusterService} from './adjuster.service';
+import {AdjusterLegendService} from '../adjuster-legend.service';
+import {AdjusterPresetsService} from '../adjuster-presets.service';
+import {AdjusterService} from '../adjuster.service';
 
 @Component({
-  selector: 'pra-adjuster',
-  templateUrl: './adjuster.component.html',
-  styleUrls: ['./adjuster.component.scss'],
+  selector: 'pra-adjuster-advanced',
+  templateUrl: './adjuster-advanced-panel.component.html',
+  styleUrls: ['./adjuster-advanced-panel.component.scss'],
 })
-export class AdjusterComponent extends HsPanelBaseComponent implements OnInit {
-  name = 'adjuster';
+export class AdjusterAdvancedPanelComponent extends HsPanelBaseComponent {
+  name = 'adjuster-advanced';
   data: any;
   //descriptionVisible: boolean;
   errorMsg: string;
@@ -23,11 +27,12 @@ export class AdjusterComponent extends HsPanelBaseComponent implements OnInit {
 
   constructor(
     public adjusterService: AdjusterService,
+    public adjusterLegendService: AdjusterLegendService,
     public adjusterPresetsService: AdjusterPresetsService,
     public hsDialogContainerService: HsDialogContainerService,
     public hsLayoutService: HsLayoutService
   ) {
-    super(hsLayoutService)
+    super(hsLayoutService);
     //this.descriptionVisible = false;
     //this.method = this.adjusterService.method;
     /*this.adjusterEventService.clustersLoaded.subscribe(({success, err}) => {
@@ -37,10 +42,6 @@ export class AdjusterComponent extends HsPanelBaseComponent implements OnInit {
     });*/
   }
 
-  ngOnInit(): void {
-    this.hsDialogContainerService.create(AdjusterLoaderComponent, {});
-  }
-
   hasDatasets(factor): boolean {
     return factor.datasets.length > 0;
   }
@@ -50,7 +51,7 @@ export class AdjusterComponent extends HsPanelBaseComponent implements OnInit {
   }
 
   isVisible(): boolean {
-    return this.hsLayoutService.panelVisible('adjuster');
+    return this.hsLayoutService.panelVisible('adjuster-advanced');
   }
 
   noDataSelected(): boolean {

+ 3 - 1
src/adjuster/adjuster-event.service.ts

@@ -1,11 +1,13 @@
 import {Injectable} from '@angular/core';
 import {Subject} from 'rxjs';
+
 import {RDFSubject} from './ontology.model';
 
 @Injectable({providedIn: 'root'})
 export class AdjusterEventService {
   layerReady: Subject<{name: string}> = new Subject();
-  loaded: Subject<{success: boolean; type: string; err?}> = new Subject();
+  loaded: Subject<{success: boolean; type: 'index' | 'clusters'; err?}> =
+    new Subject();
   loaderReady: Subject<void> = new Subject();
   methodChanges: Subject<string> = new Subject();
   ontologyLoads: Subject<Array<RDFSubject>> = new Subject();

+ 30 - 19
src/adjuster/adjuster-legend.service.ts

@@ -1,8 +1,14 @@
+/* eslint-disable valid-jsdoc */
 import hsv2rgb from 'hsv2rgb';
 import {Injectable} from '@angular/core';
 
-import {decimal2prettyPerc, obceIndexLayer, perc2color} from '../app.config';
 import {AdjusterPresetsService, Factor} from './adjuster-presets.service';
+import {decimal2prettyPerc, obceIndexLayer, perc2color} from '../app.config';
+
+type FakeLegend = Array<{
+  color: string;
+  name: string;
+}>;
 
 @Injectable({providedIn: 'root'})
 export class AdjusterLegendService {
@@ -21,17 +27,23 @@ export class AdjusterLegendService {
     '#ffff99',
     '#b15928',
   ];
-  constructor(
-    public adjusterPresetsService: AdjusterPresetsService,
-    ) {}
+  staticIndexLegend: any[];
+  staticClusterLegend: any[];
+
+  constructor(public adjusterPresetsService: AdjusterPresetsService) {
+    this.staticIndexLegend = [...Array(50).keys()].map((num) => {
+      return perc2color(num / 50);
+    });
+    this.staticClusterLegend = this.colorPalette;
+  }
 
   createIndexLegend(): FakeLegend {
     return [
-      {color: perc2color(0), name: '0 %'},
-      {color: perc2color(0.25), name: '25 %'},
-      {color: perc2color(0.5), name: '50 %'},
-      {color: perc2color(0.75), name: '75 %'},
-      {color: perc2color(1), name: '100 %'},
+      {color: perc2color(1), name: 'best'},
+      {color: perc2color(0.75), name: 'good'},
+      {color: perc2color(0.5), name: 'mediocre'},
+      {color: perc2color(0.25), name: 'bad'},
+      {color: perc2color(0), name: 'worst'},
     ];
   }
 
@@ -51,20 +63,24 @@ export class AdjusterLegendService {
         attribute: 'aggregate',
         label: 'agregovaný index',
         displayFunction: decimal2prettyPerc,
-      }
+      },
     ];
     for (const factor of factors) {
       attrs.push({
         attribute: factor.id,
         label: this.adjusterPresetsService.getLabelInCurrentLang(factor.labels),
         displayFunction: decimal2prettyPerc,
-      })
+      });
     }
     obceIndexLayer.set('popUp', {
-      attributes: attrs
+      attributes: attrs,
     });
   }
 
+  /**
+   * Updates the color palette with an appropriate number of colors
+   * @param count - number of colors to generate
+   */
   refreshColorPalette(count: number): void {
     this.colorPalette = this.generateRandomColorPalette(count);
   }
@@ -85,15 +101,10 @@ export class AdjusterLegendService {
       h += goldenRatioConjugate;
       h %= 1;
       h *= 360;
-      palette.push(hsv2rgb(h, 0.5, 0.95));
+      const [r, g, b] = hsv2rgb(h, 0.5, 0.95);
+      palette.push(`rgba(${r}, ${g}, ${b}, 1)`);
       i++;
     }
     return palette;
-    //return `rgba(${r}, ${g}, ${b}, 0.7)`;
   }
 }
-
-type FakeLegend = Array<{
-  color: string;
-  name: string;
-}>;

+ 0 - 10
src/adjuster/adjuster-loader.component.html

@@ -1,10 +0,0 @@
-<div class="loader-splash" *ngIf="adjusterService.isInProcess()">
-  <div class="center-block">
-    <h1 [hidden]="!adjusterService.isLoading()">{{'ADJUSTER.loadingData' | translateHs: {app: 'default'} }}</h1>
-    <h1 [hidden]="!adjusterService.isCalculatingRAI()">{{'ADJUSTER.calcAttractivity' | translateHs: {app: 'default'} }}</h1>
-    <h1 [hidden]="!adjusterService.isClustering()">{{'ADJUSTER.calcClusters' | translateHs: {app: 'default'} }}</h1>
-    <div class="spinner-border spinner" role="status">
-      <span class="visually-hidden">{{'ADJUSTER.loading' | translateHs: {app: 'default'} }}...</span>
-    </div>
-  </div>
-</div>

+ 10 - 0
src/adjuster/adjuster-loader/adjuster-loader.component.html

@@ -0,0 +1,10 @@
+<div class="loader-splash" *ngIf="adjusterService.loadInProcess || adjusterService.raiInProcess || adjusterService.clusteringInProcess">
+  <div class="center-block">
+    <h1 [hidden]="!adjusterService.loadInProcess">{{'ADJUSTER.loadingData' | translateHs: {app: 'default'} }}</h1>
+    <h1 [hidden]="!adjusterService.raiInProcess">{{'ADJUSTER.calcAttractivity' | translateHs: {app: 'default'} }}</h1>
+    <h1 [hidden]="!adjusterService.clusteringInProcess">{{'ADJUSTER.calcClusters' | translateHs: {app: 'default'} }}</h1>
+    <div class="spinner-border spinner" role="status">
+      <span class="visually-hidden">{{'ADJUSTER.loading' | translateHs: {app: 'default'} }}...</span>
+    </div>
+  </div>
+</div>

+ 0 - 0
src/adjuster/adjuster-loader.component.scss → src/adjuster/adjuster-loader/adjuster-loader.component.scss


+ 4 - 3
src/adjuster/adjuster-loader.component.ts → src/adjuster/adjuster-loader/adjuster-loader.component.ts

@@ -3,8 +3,8 @@ import {AfterViewInit, Component, Input, ViewRef} from '@angular/core';
 import {HsDialogComponent} from 'hslayers-ng';
 import {HsDialogContainerService} from 'hslayers-ng';
 
-import {AdjusterEventService} from './adjuster-event.service';
-import {AdjusterService} from './adjuster.service';
+import {AdjusterEventService} from '../adjuster-event.service';
+import {AdjusterService} from '../adjuster.service';
 
 @Component({
   selector: 'pra-adjuster-loader',
@@ -12,7 +12,8 @@ import {AdjusterService} from './adjuster.service';
   styleUrls: ['./adjuster-loader.component.scss'],
 })
 export class AdjusterLoaderComponent
-  implements HsDialogComponent, AfterViewInit {
+  implements HsDialogComponent, AfterViewInit
+{
   @Input() data;
   viewRef: ViewRef;
   constructor(

+ 138 - 95
src/adjuster/adjuster-presets.service.ts

@@ -7,13 +7,56 @@ import attractivenessConfig from '../attractiveness.config.json';
 import {AdjusterEventService} from './adjuster-event.service';
 import {RDFSubject} from './ontology.model';
 
+export type Label = {
+  '@value': string;
+  '@language'?: string;
+};
+
+export type Dataset = {
+  id: string;
+  labels: Label[];
+  desc: string;
+  included: boolean;
+};
+
+export type DatasetGroup = {
+  id: string;
+  labels?: Label[];
+};
+
+export type Factor = {
+  id: string;
+  labels: Label[];
+  weight: number;
+  datasets: Dataset[];
+};
+
+export type Problem = {
+  id: string;
+  labels?: Label[];
+  requiredDatasets: string[];
+};
+
+export type Role = {
+  id: string;
+  labels?: Label[];
+  problems?: Problem[];
+};
+
+export type Schema = {
+  id: string;
+  labels?: Label[];
+  groups?: DatasetGroup[];
+};
+
 @Injectable({providedIn: 'root'})
 export class AdjusterPresetsService {
   activeProblem: Problem;
   activeRole: Role;
   activeSchema: Schema;
   applicationLoD = 'http://www.semanticweb.org/attractiveness/municipality';
-  applicationCoverage = 'http://www.semanticweb.org/attractiveness/CzechRepublic';
+  applicationCoverage =
+    'http://www.semanticweb.org/attractiveness/CzechRepublic';
   defaultSchemaId: string;
   enabledRoleIds: Array<string>;
   enabledSchemaIds: Array<string>;
@@ -37,16 +80,14 @@ export class AdjusterPresetsService {
       this.loadRoles();
       this.loadSchemas();
       this.problemChanges.next(this.activeProblem ?? null);
-    })
+    });
   }
 
   applyProblem(problem: Problem) {
-    console.log(problem);
     this.problemChanges.next(problem);
   }
 
   changeSchema(schema: Schema) {
-    console.log(schema);
     this.schemaChanges.next(schema);
   }
 
@@ -59,54 +100,89 @@ export class AdjusterPresetsService {
   }
 
   getGroupDatasets(groupID: string): Array<Dataset> {
-    return this.ontology
-      .find((subject) => subject['@id'] == groupID)["http://www.semanticweb.org/attractiveness/hasDataset"]
-      ?.map((entity) => {
-        const datasetEntity = this.ontology.find((subject) => subject['@id'] == entity['@id']);
-        if (
-          datasetEntity['http://www.semanticweb.org/attractiveness/hasCoverage']?.every((coverageEntity) => coverageEntity['@id'] !== this.applicationCoverage) ||
-          datasetEntity['http://www.semanticweb.org/attractiveness/hasLoD']?.every((lodEntity) => lodEntity['@id'] !== this.applicationLoD)
-        ) {
-          return;
-        }
-        return {
-          id: datasetEntity["@id"],
-          labels: datasetEntity["http://www.w3.org/2000/01/rdf-schema#label"],
-          desc: '',
-          included: true
-        }
-      }).filter(ds => ds) ?? [];
+    return (
+      this.ontology
+        .find((subject) => subject['@id'] == groupID)
+        ['http://www.semanticweb.org/attractiveness/hasDataset']?.map(
+          (entity) => {
+            const datasetEntity = this.ontology.find(
+              (subject) => subject['@id'] == entity['@id']
+            );
+            if (
+              datasetEntity[
+                'http://www.semanticweb.org/attractiveness/hasCoverage'
+              ]?.every(
+                (coverageEntity) =>
+                  coverageEntity['@id'] !== this.applicationCoverage
+              ) ||
+              datasetEntity[
+                'http://www.semanticweb.org/attractiveness/hasLoD'
+              ]?.every((lodEntity) => lodEntity['@id'] !== this.applicationLoD)
+            ) {
+              return;
+            }
+            return {
+              id: datasetEntity['@id'],
+              labels:
+                datasetEntity['http://www.w3.org/2000/01/rdf-schema#label'],
+              desc: datasetEntity[
+                'http://www.semanticweb.org/attractiveness#description'
+              ]?.[0]['@value'], //so far descriptions are only written in en
+              included: true,
+            };
+          }
+        )
+        .filter((ds) => ds) ?? []
+    );
   }
 
   getLabelInCurrentLang(labels: Label[]) {
-    return this.getLabelInLang(labels, this.hsLanguageService.getCurrentLanguageCode('default'));
+    return this.getLabelInLang(
+      labels,
+      this.hsLanguageService.getCurrentLanguageCode('default')
+    );
   }
 
   getLabelInLang(labels: Label[], lang: string) {
-    return labels.find((labelEntity) => labelEntity['@language'] == lang)?.['@value'] ?? labels[0]['@value'];
+    return (
+      labels.find((labelEntity) => labelEntity['@language'] == lang)?.[
+        '@value'
+      ] ?? labels[0]['@value']
+    );
   }
 
   loadRoles() {
     this.roles = this.ontology
-      .filter((subject) => subject['@type']?.includes("http://www.semanticweb.org/attractiveness/Role"))
+      .filter((subject) =>
+        subject['@type']?.includes(
+          'http://www.semanticweb.org/attractiveness/Role'
+        )
+      )
       .map((subject) => {
         return {
           id: subject['@id'],
-          labels: subject["http://www.w3.org/2000/01/rdf-schema#label"],
-          problems: subject["http://www.semanticweb.org/attractiveness/solvesProblem"].map(
-            (problem) => {
-              const problemEntity = this.ontology.find((subject) => subject['@id'] == problem['@id']);
-              return {
-                id: problem['@id'],
-                labels: problemEntity?.["http://www.w3.org/2000/01/rdf-schema#label"],
-                requiredDatasets: problemEntity?.["http://www.semanticweb.org/attractiveness/requiresDataset"].map((dataset) => dataset['@id'])
-              }
-            }
-          )
-        }
+          labels: subject['http://www.w3.org/2000/01/rdf-schema#label'],
+          problems: subject[
+            'http://www.semanticweb.org/attractiveness/solvesProblem'
+          ].map((problem) => {
+            const problemEntity = this.ontology.find(
+              (subject) => subject['@id'] == problem['@id']
+            );
+            return {
+              id: problem['@id'],
+              labels:
+                problemEntity?.['http://www.w3.org/2000/01/rdf-schema#label'],
+              requiredDatasets: problemEntity?.[
+                'http://www.semanticweb.org/attractiveness/requiresDataset'
+              ].map((dataset) => dataset['@id']),
+            };
+          }),
+        };
       });
     if (this.enabledRoleIds) {
-      this.roles = this.roles.filter((role) => this.enabledRoleIds.includes(role.id));
+      this.roles = this.roles.filter((role) =>
+        this.enabledRoleIds.includes(role.id)
+      );
     }
     this.activeRole = this.roles[0];
     this.activeProblem = this.roles[0].problems[0];
@@ -114,25 +190,35 @@ export class AdjusterPresetsService {
 
   loadSchemas() {
     this.schemas = this.ontology
-      .filter((subject) => subject['@type']?.includes("http://www.semanticweb.org/attractiveness/ClassificationSchema"))
+      .filter((subject) =>
+        subject['@type']?.includes(
+          'http://www.semanticweb.org/attractiveness/ClassificationSchema'
+        )
+      )
       .map((subject) => {
         return {
           id: subject['@id'],
-          labels: subject["http://www.w3.org/2000/01/rdf-schema#label"],
-          groups: subject["http://www.semanticweb.org/attractiveness/consistsOf"].map(
-            (group) => {
-              return {
-                id: group['@id'],
-                labels: this.ontology.find((subject) => subject['@id'] == group['@id'])?.["http://www.w3.org/2000/01/rdf-schema#label"]
-              }
-            }
-          )
-        }
+          labels: subject['http://www.w3.org/2000/01/rdf-schema#label'],
+          groups: subject[
+            'http://www.semanticweb.org/attractiveness/consistsOf'
+          ].map((group) => {
+            return {
+              id: group['@id'],
+              labels: this.ontology.find(
+                (subject) => subject['@id'] == group['@id']
+              )?.['http://www.w3.org/2000/01/rdf-schema#label'],
+            };
+          }),
+        };
       });
-      if (this.enabledSchemaIds) {
-        this.schemas = this.schemas.filter((schema) => this.enabledSchemaIds.includes(schema.id));
-      }
-    this.activeSchema = this.schemas.find((schema) => schema.id == this.defaultSchemaId) ?? this.schemas[0];
+    if (this.enabledSchemaIds) {
+      this.schemas = this.schemas.filter((schema) =>
+        this.enabledSchemaIds.includes(schema.id)
+      );
+    }
+    this.activeSchema =
+      this.schemas.find((schema) => schema.id == this.defaultSchemaId) ??
+      this.schemas[0];
     this.schemaChanges.next(this.activeSchema);
   }
 
@@ -141,46 +227,3 @@ export class AdjusterPresetsService {
     this.applyProblem(this.activeProblem);
   }
 }
-
-export type Dataset = {
-  id: string;
-  labels: Label[];
-  desc: string;
-  included: boolean;
-}
-
-export type DatasetGroup = {
-  id: string;
-  labels?: Label[];
-};
-
-export type Factor = {
-  id: string;
-  labels: Label[];
-  weight: number;
-  datasets: Dataset[];
-};
-
-export type Label = {
-  "@value": string
-  "@language"?: string,
-};
-
-export type Problem = {
-  id: string;
-  labels?: Label[];
-  requiredDatasets: string[]
-};
-
-export type Role = {
-  id: string;
-  labels?: Label[];
-  problems?: Problem[];
-};
-
-export type Schema = {
-  id: string,
-  labels?: Label[];
-  groups?: DatasetGroup[];
-};
-

+ 83 - 0
src/adjuster/adjuster-simple-panel/adjuster-simple-panel.component.html

@@ -0,0 +1,83 @@
+<div [hidden]="!isVisible()" class="card mainpanel">
+  <hs-panel-header name="adjuster" [title]="'ADJUSTER.adjustFactorsSimple' | translateHs: {app: 'default'} "></hs-panel-header>
+  <div class="card-body">
+    <div class="p-2 center-block">
+      <div class="d-flex flex-row">
+        <div>
+          <button type="button" class="btn btn-primary btn-lg" (click)="adjusterService.apply()"
+            [disabled]="adjusterService.isInProcess() || adjUIService.noDataSelected() || adjUIService.noOperationSelected() ">{{'ADJUSTER.calculate' | translateHs: {app: 'default'} }}</button>
+        </div>
+        <div class="exclusive ps-1 ps-sm-3">
+          <button type="button" class="btn btn-sm btn-light hs-lm-item-visibility"
+            [ngClass]="adjusterService.allowIndex ? 'hs-checkmark' : 'hs-uncheckmark'"
+            (click)="selectIndex()"></button>
+          <label class="pl-2 text-secondary" [ngClass]="adjusterService.allowIndex ? 'fw-bold' : 'fw-normal'">
+            {{'ADJUSTER.index' | translateHs: {app: 'default'} }}
+          </label>
+          <p class="text-secondary text-justify fst-italic">{{'ADJUSTER.indexDescription' | translateHs: {app: 'default'} }}</p>
+        </div>
+        <div class="exclusive ps-1 ps-sm-3">
+          <button type="button" class="btn btn-sm btn-light hs-lm-item-visibility"
+            [ngClass]="adjusterService.allowClusters ? 'hs-checkmark' : 'hs-uncheckmark'"
+            (click)="selectClusters()"></button>
+          <label class="pl-2 text-secondary" [ngClass]="adjusterService.allowClusters ? 'fw-bold' : 'fw-normal'">
+            {{'ADJUSTER.clusters' | translateHs: {app: 'default'} }}
+          </label>
+          <p class="text-secondary text-justify fst-italic">{{'ADJUSTER.clustersDescription' | translateHs: {app: 'default'} }}</p>
+        </div>
+      </div>
+      <div class="text-warning pt-2" [hidden]="!adjUIService.noDataSelected() || errorMsg">{{'ADJUSTER.noDataSelectedMsg' | translateHs: {app: 'default'} }}</div>
+      <div class="text-danger pt-2" [hidden]="!errorMsg">{{'ADJUSTER.serverError' | translateHs: {app: 'default'} }}: {{errorMsg}}</div>
+    </div>
+    <div class="p-2 center-block" [hidden]="!adjusterService.allowClusters">
+      <div class="pt-2 text-secondary">{{'ADJUSTER.numberOfClusters' | translateHs: {app: 'default'} }}: {{adjusterService.numberOfClusters}}</div>
+      <input type="range" class="form-range" [(ngModel)]="adjusterService.numberOfClusters" min="5" max="15" step="1">
+    </div>
+    <div class="p-2 center-block">
+      <p class="my-1">{{'ADJUSTER.myRoleIs' | translateHs: {app: 'default'} }}:&emsp;</p>
+      <select class="form-select mb-1 mb-sm-2" [(ngModel)]="adjusterPresetsService.activeRole" (ngModelChange)="adjusterPresetsService.pickProblem($event)">
+        <option *ngFor="let role of adjusterPresetsService.roles" [ngValue]="role">{{adjUIService.getLabelInCurrentLang(role.labels)}}</option>
+      </select>
+      <p class="my-1">{{'ADJUSTER.myProblemIs' | translateHs: {app: 'default'} }}:&emsp;</p>
+      <select class="form-select" [(ngModel)]="adjusterPresetsService.activeProblem" (ngModelChange)="adjusterPresetsService.applyProblem($event)">
+        <option *ngFor="let problem of adjusterPresetsService.getActiveRoleProblems()" [ngValue]="problem">{{adjUIService.getLabelInCurrentLang(problem.labels)}}</option>
+      </select>
+    </div>
+    <div class="pt-3 center-block">
+      <button type="button" class="btn btn-primary btn-sm" [disabled]="adjusterService.isInProcess()"
+        (click)="hsLayoutService.setMainPanel('adjuster-advanced', 'default');$event.preventDefault();">
+        <span class="glyphicon cursor-pointer" class="icon-chevron-right"></span>
+        {{'ADJUSTER.advanced' | translateHs: {app: 'default'} }}
+      </button>
+    </div>
+    <hr>
+    <div *ngIf="adjusterService.allowIndex; else clusterLegend" class="pb-2">
+      <p class="lead">{{ 'ADJUSTER.indexLegend' | translateHs: {app: 'default'} }}</p>
+      <div class="d-flex pb-1">
+        <div *ngFor="let category of adjusterLegendService.staticIndexLegend" class="flex-grow-1">
+          <div [ngStyle]="{'background-color': category}">&nbsp;</div>
+        </div>
+      </div>
+      <div class="d-flex">
+        <div class="flex-grow-1 text-start">{{ 'ADJUSTER.index0' | translateHs: {app: 'default'} }}</div>
+        <div class="flex-grow-1">&nbsp;</div>
+        <div class="flex-grow-1 text-end">{{ 'ADJUSTER.index100' | translateHs: {app: 'default'} }}</div>
+      </div>
+    </div>
+    <ng-template #clusterLegend>
+      <p class="lead">{{ 'ADJUSTER.clusterLegend' | translateHs: {app: 'default'} }}</p>
+      <div class="container pb-2">
+        <div class="row row-cols-1 row-cols-sm-2 row-cols-md-3 row-cols-lg-4">
+          <div *ngFor="let color of adjusterLegendService.staticClusterLegend; let i = index" class="col">
+            <div style="background-color: {{color}}" class="cluster-id text-center p-1 py-sm-3 my-1 my-sm-2">#{{i+1}}</div>
+          </div>
+        </div>
+      </div>
+    </ng-template>
+    <hr>
+    <div class="pt-3 center-block" [hidden]="adjusterService.isInProcess()">
+      {{'ADJUSTER.layerManagerLink1' | translateHs: {app: 'default'} }}<br>
+      {{'ADJUSTER.layerManagerLink2' | translateHs: {app: 'default'} }} <a href="" (click)="hsLayoutService.setMainPanel('layermanager', 'default');$event.preventDefault();">{{'ADJUSTER.layerManagerLinkLMName' | translateHs: {app: 'default'} }}</a>
+    </div>
+  </div>
+</div>

+ 1 - 0
src/adjuster/adjuster-simple-panel/adjuster-simple-panel.component.scss

@@ -0,0 +1 @@
+@use '../adjuster-advanced-panel/adjuster-advanced-panel.component.scss';

+ 66 - 0
src/adjuster/adjuster-simple-panel/adjuster-simple-panel.component.ts

@@ -0,0 +1,66 @@
+import {Component, ViewRef} from '@angular/core';
+
+import {HsLayoutService, HsPanelBaseComponent} from 'hslayers-ng';
+
+import {AdjusterLegendService} from '../adjuster-legend.service';
+import {AdjusterPresetsService} from '../adjuster-presets.service';
+import {AdjusterService} from '../adjuster.service';
+import {AdjusterUIService} from '../adjuster-ui.service';
+import {obceIndexLayer} from '../../app.config';
+
+@Component({
+  selector: 'pra-adjuster-simple',
+  templateUrl: './adjuster-simple-panel.component.html',
+  styleUrls: ['./adjuster-simple-panel.component.scss'],
+})
+export class AdjusterSimplePanelComponent extends HsPanelBaseComponent {
+  name = 'adjuster-simple';
+  data: any;
+  errorMsg: string;
+  //method: string;
+  viewRef: ViewRef;
+
+  constructor(
+    public adjUIService: AdjusterUIService,
+    public adjusterLegendService: AdjusterLegendService,
+    public adjusterPresetsService: AdjusterPresetsService,
+    public adjusterService: AdjusterService,
+    public hsLayoutService: HsLayoutService
+  ) {
+    super(hsLayoutService);
+  }
+
+  isVisible(): boolean {
+    return this.hsLayoutService.panelVisible('adjuster-simple');
+  }
+
+  /**
+   * enables index calculation and map layer
+   * disables clusters calculation and map layers
+   */
+  selectIndex() {
+    /* disable/enable calculation */
+    this.adjusterService.allowIndex = true;
+    this.adjusterService.allowClusters = false;
+    /* disable/enable map layers */
+    obceIndexLayer.setVisible(true);
+    for (const method of this.adjusterService.methods) {
+      method.layer?.setVisible(false);
+    }
+  }
+
+  /**
+   * disables index calculation and map layer
+   * enables clusters calculation an map layers
+   */
+  selectClusters() {
+    /* disable/enable calculation */
+    this.adjusterService.allowIndex = false;
+    this.adjusterService.allowClusters = true;
+    /* disable/enable map layers */
+    obceIndexLayer.setVisible(false);
+    for (const method of this.adjusterService.methods) {
+      method.layer?.setVisible(true);
+    }
+  }
+}

+ 55 - 0
src/adjuster/adjuster-ui.service.ts

@@ -0,0 +1,55 @@
+import {Injectable} from '@angular/core';
+
+import {HsDialogContainerService, HsLayoutService} from 'hslayers-ng';
+
+import {AdjusterLoaderComponent} from './adjuster-loader/adjuster-loader.component';
+import {AdjusterPresetsService} from './adjuster-presets.service';
+import {AdjusterService} from './adjuster.service';
+
+@Injectable({providedIn: 'root'})
+export class AdjusterUIService {
+  constructor(
+    public adjusterService: AdjusterService,
+    public adjusterPresetsService: AdjusterPresetsService,
+    private hsDialogContainerService: HsDialogContainerService,
+    public hsLayoutService: HsLayoutService
+  ) {
+    this.hsDialogContainerService.create(AdjusterLoaderComponent, {});
+  }
+
+  hasDatasets(factor): boolean {
+    return factor.datasets.length > 0;
+  }
+
+  getLabelInCurrentLang(labels) {
+    return this.adjusterPresetsService.getLabelInCurrentLang(labels);
+  }
+
+  noDataSelected(): boolean {
+    if (this.adjusterService.factors.length === 0) {
+      return true;
+    }
+    let datasetsEffectivelyTurnedOn = [];
+    for (const factor of this.adjusterService.factors) {
+      if (factor.weight === 0) {
+        continue;
+      }
+      datasetsEffectivelyTurnedOn = [
+        ...datasetsEffectivelyTurnedOn,
+        ...factor.datasets.filter((ds) => ds.included),
+      ];
+    }
+    return datasetsEffectivelyTurnedOn.length === 0;
+  }
+
+  noOperationSelected(): boolean {
+    return (
+      !this.adjusterService.allowIndex && !this.adjusterService.allowClusters
+    );
+  }
+
+  /*selectMethod(): void {
+    this.adjusterService.method = this.method;
+    this.adjusterEventService.methodChanged.next(this.method);
+  }*/
+}

+ 20 - 10
src/adjuster/adjuster.module.ts

@@ -1,30 +1,40 @@
-import {CUSTOM_ELEMENTS_SCHEMA, NgModule} from '@angular/core';
 import {CommonModule} from '@angular/common';
 import {FormsModule} from '@angular/forms';
+import {NgModule} from '@angular/core';
 import {NgbModule} from '@ng-bootstrap/ng-bootstrap';
 import {TranslateModule} from '@ngx-translate/core';
 
-import {HsLanguageModule, HsPanelHelpersModule} from 'hslayers-ng';
+import {
+  HsLanguageModule,
+  HsLayoutModule,
+  HsPanelHelpersModule,
+} from 'hslayers-ng';
 
-import {AdjusterComponent} from './adjuster.component';
-import {AdjusterEventService} from './adjuster-event.service';
-import {AdjusterLoaderComponent} from './adjuster-loader.component';
-import {AdjusterService} from './adjuster.service';
+import {AdjusterAdvancedPanelComponent} from './adjuster-advanced-panel/adjuster-advanced-panel.component';
+import {AdjusterLoaderComponent} from './adjuster-loader/adjuster-loader.component';
+import {AdjusterSimplePanelComponent} from './adjuster-simple-panel/adjuster-simple-panel.component';
+import {DatasetItemComponent} from './dataset-item/dataset-item.component';
 import {DatasetListComponent} from './dataset-list/dataset-list.component';
 import {MetadataDialogComponent} from './metadata-dialog/metadata-dialog.component';
 
 @NgModule({
-  schemas: [CUSTOM_ELEMENTS_SCHEMA],
   imports: [
     CommonModule,
     FormsModule,
     HsLanguageModule,
+    HsLayoutModule,
     HsPanelHelpersModule,
     NgbModule,
     TranslateModule,
   ],
-  exports: [AdjusterComponent],
-  declarations: [AdjusterComponent, AdjusterLoaderComponent, DatasetListComponent, MetadataDialogComponent],
-  providers: [AdjusterService, AdjusterEventService],
+  exports: [AdjusterAdvancedPanelComponent, AdjusterSimplePanelComponent],
+  declarations: [
+    AdjusterAdvancedPanelComponent,
+    AdjusterSimplePanelComponent,
+    AdjusterLoaderComponent,
+    DatasetListComponent,
+    DatasetItemComponent,
+    MetadataDialogComponent,
+  ],
 })
 export class AdjusterModule {}

+ 75 - 96
src/adjuster/adjuster.service.ts

@@ -15,8 +15,15 @@ import clusteringMethods from '../data/clustering_methods.json';
 import {AdjusterEventService} from './adjuster-event.service';
 import {AdjusterLegendService} from './adjuster-legend.service';
 import {AdjusterPresetsService, Factor} from './adjuster-presets.service';
-import {obce, obceIndexLayer, osmLayer} from '../app.config';
 import {RDFSubject} from './ontology.model';
+import {obce, obceIndexLayer, osmLayer} from '../app.config';
+
+type MethodDescription = {
+  codename: string;
+  layer?: VectorLayer<any>;
+  name: string;
+  type: string;
+};
 
 @Injectable({providedIn: 'root'})
 export class AdjusterService {
@@ -29,17 +36,17 @@ export class AdjusterService {
   /** Used in the UI as a selector */
   allowClusters = true;
   /** Used in the UI as a selector */
-  allowIndex = true;
+  allowIndex = false;
   factors: Array<Factor> = [];
   layersReady = new Set();
+  /** Once instantiated, the load is definitely in process */
+  loadInProcess = true;
   //method: string;
   methods: Array<MethodDescription>;
   numberOfClusters: number;
-  private _clusteringInProcess: boolean;
+  clusteringInProcess: boolean;
+  raiInProcess: boolean;
   private _clustersLoaded: boolean;
-  /** Once instantiated, the load is definitely in process */
-  private _loadInProcess = true;
-  private _raiInProcess: boolean;
 
   constructor(
     public adjusterEventService: AdjusterEventService,
@@ -103,16 +110,21 @@ export class AdjusterService {
           id: group.id,
           labels: group.labels,
           weight: this.resetFactorWeights(group.id),
-          datasets: this.adjusterPresetsService.getGroupDatasets(group.id)
-        }
+          datasets: this.adjusterPresetsService.getGroupDatasets(group.id),
+        };
       });
-      this.factors = this.factors.filter((factor) => factor.datasets.length >= 3);
+      this.factors = this.factors.filter(
+        (factor) => factor.datasets.length >= 3
+      );
       this.factors.push({
         id: 'others',
-        labels: [{'@value': 'Ostatní', '@language': 'cs'}, {'@value': 'Others', '@language': 'en'}],
+        labels: [
+          {'@value': 'Ostatní', '@language': 'cs'},
+          {'@value': 'Others', '@language': 'en'},
+        ],
         weight: this.resetFactorWeights('others'),
         datasets: orphanedDatasets,
-      })
+      });
       this.adjusterLegendService.updateIndexLayerPopUps(this.factors);
     });
 
@@ -146,22 +158,20 @@ export class AdjusterService {
   }
 
   calculateIndex(): void {
-    this._raiInProcess = true;
+    this.raiInProcess = true;
     this.$http
       .post(this.serviceBaseUrl + 'cz/scores/', {
         factors: this.factors.map((f) => {
           return {
             factor: f.id,
             weight: f.weight,
-            datasets: f.datasets
-              .filter((ds) => ds.included)
-              .map((ds) => ds.id),
+            datasets: f.datasets.filter((ds) => ds.included).map((ds) => ds.id),
           };
         }),
       })
       .toPromise()
       .then((attractivenessData: any[]) => {
-        console.log("attractivenessData", attractivenessData)
+        console.log('attractivenessData', attractivenessData);
         /* Spread the 'aggregate' value between 0 and 1 */
         const min = attractivenessData.reduce((a, b) =>
           a.aggregate < b.aggregate ? a : b
@@ -184,19 +194,25 @@ export class AdjusterService {
         console.time('forEach-Index');
         this.processIndex(codeRecordRelations);
         console.timeEnd('forEach-Index');
-        this._raiInProcess = false;
+        this.raiInProcess = false;
         this.adjusterEventService.loaded.next({
           success: true,
           type: 'index',
         });
       })
       .catch((error) => {
-        this.hsToastService.createToastPopupMessage('Error loading data', `Error obtaining data from ${this.serviceBaseUrl}.`);
+        this.hsToastService.createToastPopupMessage(
+          'Error loading data',
+          `Error obtaining data from ${this.serviceBaseUrl}.`,
+          {
+            toastStyleClasses: 'bg-warning text-dark',
+          }
+        );
         console.warn(`Error obtaining data from ${this.serviceBaseUrl}.`);
         console.log(error);
-        this._raiInProcess = false;
+        this.raiInProcess = false;
         this.adjusterEventService.loaded.next({
-          success: true,
+          success: false,
           type: 'index',
           err: error,
         });
@@ -204,7 +220,7 @@ export class AdjusterService {
   }
 
   calculateClusters(): void {
-    this._clusteringInProcess = true;
+    this.clusteringInProcess = true;
     /* Pre-process the API params */
     const params = [];
     for (const factor of this.factors) {
@@ -215,16 +231,16 @@ export class AdjusterService {
         const flattenedDataset = {
           id: dataset.id.split('/').slice(-1).pop(), //We do not need full URIs as the URNs are unique across the ontology
           factor: factor.id.split('/').slice(-1).pop(), //We do not need full URIs as the URNs are unique across the ontology
-          weight: factor.weight
+          weight: factor.weight,
         };
-        params.push(flattenedDataset)
+        params.push(flattenedDataset);
       }
     }
 
     this.$http
       .post(this.serviceBaseUrl + 'cz/clusters/', {
         numberOfClusters: this.numberOfClusters,
-        datasets: params
+        datasets: params,
       })
       .toPromise()
       .then((data: any) => {
@@ -260,23 +276,30 @@ export class AdjusterService {
         console.time('forEach-Cluster');
         for (const method of this.methods) {
           this.processClusters(method, codeRecordRelations);
-          method.layer.getSource().legend_categories = this.adjusterLegendService.createClusterLegend(
-            this.numberOfClusters
-          );
+          method.layer.getSource().legend_categories =
+            this.adjusterLegendService.createClusterLegend(
+              this.numberOfClusters
+            );
         }
         console.timeEnd('forEach-Cluster');
         this._clustersLoaded = true;
-        this._clusteringInProcess = false;
+        this.clusteringInProcess = false;
         this.adjusterEventService.loaded.next({
           success: true,
           type: 'clusters',
         });
       })
       .catch((error) => {
-        this.hsToastService.createToastPopupMessage('Error loading data', `Error obtaining data from ${this.serviceBaseUrl}.`);
+        this.hsToastService.createToastPopupMessage(
+          'Error loading data',
+          `Error obtaining data from ${this.serviceBaseUrl}.`,
+          {
+            toastStyleClasses: 'bg-warning text-dark',
+          }
+        );
         console.warn(`Error obtaining data from ${this.serviceBaseUrl}.`);
         console.log(error);
-        this._clusteringInProcess = false;
+        this.clusteringInProcess = false;
         this.adjusterEventService.loaded.next({
           success: false,
           type: 'clusters',
@@ -285,59 +308,36 @@ export class AdjusterService {
       });
   }
 
+  /**
+   * On init, calculate both index and clusters nevertheless if they are enabled or disabled in the UI
+   */
   init(): void {
-    this._loadInProcess = true;
-    this.$http
-      .get(this.serviceBaseUrl + 'cz/datasets/')
-      .toPromise()
-      .then((data: any) => {
-        //console.log(data);
-        /*this.factors = data.map((dataset) => {
-          return {
-            name: dataset.Factor,
-            weight: this.initialWeights[dataset.Factor] ?? 1,
-            datasets: [],
-          };
-        });
-        this.factors = this.hsUtilsService.removeDuplicates(
-          this.factors,
-          'name'
-        );
-        this.factors.forEach((factor) => {
-          factor.datasets = data
-            .filter((ds) => ds.Factor === factor.name)
-            .map((ds) => {
-              return {
-                name: ds.Name,
-                desc: ds.Description,
-                included: true,
-              };
-            });
-        });*/
-        this._loadInProcess = false;
-        this.apply();
-        // In HSL 2.5, setting layer greyscale breaks the print() functionality
-        //this.hsLayerManagerService.setGreyscale(osmLayer);
-      })
-      .catch((error) => {
-        this.hsToastService.createToastPopupMessage('Error loading data', `Web service at ${this.serviceBaseUrl} unavailable!`);
-        console.warn(`Web service at ${this.serviceBaseUrl} unavailable!`);
-        console.log(error);
-        this._loadInProcess = false;
-      });
+    this.calculateIndex();
+    this.calculateClusters();
+    // In HSL 2.5, setting layer greyscale breaks the print() functionality
+    //this.hsLayerManagerService.setGreyscale(osmLayer);
   }
 
   async loadOntology() {
     try {
-      const onto = await this.$http.get<RDFSubject[]>(this.serviceBaseUrl + 'ontology/').toPromise();
+      const onto = await this.$http
+        .get<RDFSubject[]>(this.serviceBaseUrl + 'ontology/')
+        .toPromise();
       this.adjusterEventService.ontologyLoads.next(onto);
       this.adjusterEventService.ontologyLoads.complete();
     } catch (error) {
-      this.hsToastService.createToastPopupMessage('Error loading ontology', `Web service at ${this.serviceBaseUrl} unavailable!`);
-        console.warn(`Web service at ${this.serviceBaseUrl} unavailable!`);
-        console.log(error);
-        this._loadInProcess = false;
+      this.hsToastService.createToastPopupMessage(
+        'Error loading ontology',
+        `Web service at ${this.serviceBaseUrl} unavailable, please, try again later!`,
+        {
+          toastStyleClasses: 'bg-warning text-dark',
+        }
+      );
+      console.warn(`Web service at ${this.serviceBaseUrl} unavailable!`);
+      console.log(error);
+      this.loadInProcess = false;
     }
+    this.loadInProcess = false;
   }
 
   processIndex(codeRecordRelations: Record<string, unknown>): void {
@@ -428,27 +428,6 @@ export class AdjusterService {
    * @returns {boolean} true if clustering or index processing is in process or loading data, false otherwise
    */
   isInProcess(): boolean {
-    return (
-      this._loadInProcess || this._clusteringInProcess || this._raiInProcess
-    );
-  }
-
-  isLoading(): boolean {
-    return this._loadInProcess;
-  }
-
-  isClustering(): boolean {
-    return this._clusteringInProcess;
-  }
-
-  isCalculatingRAI(): boolean {
-    return this._raiInProcess;
+    return this.loadInProcess || this.clusteringInProcess || this.raiInProcess;
   }
 }
-
-type MethodDescription = {
-  codename: string;
-  layer?: VectorLayer<any>;
-  name: string;
-  type: string;
-};

+ 13 - 0
src/adjuster/dataset-item/dataset-item.component.html

@@ -0,0 +1,13 @@
+<button type="button" class="btn btn-sm btn-light hs-lm-item-visibility"
+  [ngClass]="dataset.included ? 'hs-checkmark' : 'hs-uncheckmark'"
+  (click)="dataset.included = !dataset.included;$event.stopPropagation()"></button>
+<!--span class="glyphicon cursor-pointer text-secondary"
+[ngClass]="descriptionVisible ? 'icon-chevron-down' : 'icon-chevron-right'"
+(click)="descriptionVisible = !descriptionVisible"></span-->
+<label class="ps-2 text-secondary"><a class="text-decoration-none"
+    (click)="dataset.included = !dataset.included;$event.stopPropagation()">{{getLabelInCurrentLang(dataset.labels)}}</a></label>
+&nbsp;
+<i class="icon-opennewwindow cursor-pointer text-info" (click)="showMetadataWindow(dataset)"></i>
+<!--div class="p-2 mb-2 text-info" [hidden]="!descriptionVisible">
+{{dataset.desc}}
+</div-->

+ 35 - 0
src/adjuster/dataset-item/dataset-item.component.ts

@@ -0,0 +1,35 @@
+import {Component, Input} from '@angular/core';
+
+import {HsDialogContainerService} from 'hslayers-ng';
+
+import {
+  AdjusterPresetsService,
+  Dataset,
+  Label,
+} from '../adjuster-presets.service';
+import {MetadataDialogComponent} from '../metadata-dialog/metadata-dialog.component';
+
+@Component({
+  selector: 'pra-dataset-item',
+  templateUrl: 'dataset-item.component.html',
+})
+export class DatasetItemComponent {
+  @Input() dataset: Dataset;
+  //descriptionVisible = false;
+
+  constructor(
+    public adjusterPresetsService: AdjusterPresetsService,
+    public hsDialogContainerService: HsDialogContainerService
+  ) {}
+
+  getLabelInCurrentLang(labels: Label[]) {
+    return this.adjusterPresetsService.getLabelInCurrentLang(labels);
+  }
+
+  showMetadataWindow(dataset: Dataset) {
+    this.hsDialogContainerService.create(MetadataDialogComponent, {
+      id: dataset.id,
+      desc: dataset.desc,
+    });
+  }
+}

+ 1 - 13
src/adjuster/dataset-list/dataset-list.component.html

@@ -11,18 +11,6 @@
   max="1.0" step="0.05">
 <div [hidden]="!datasetlistVisible">
   <div *ngFor="let dataset of factor.datasets">
-    <button type="button" class="btn btn-sm btn-light hs-lm-item-visibility"
-      [ngClass]="dataset.included ? 'hs-checkmark' : 'hs-uncheckmark'"
-      (click)="dataset.included = !dataset.included;$event.stopPropagation()"></button>
-    <!-- commented because we do not have descriptions yet -->
-    <!--span class="glyphicon cursor-pointer text-secondary"
-      [ngClass]="descriptionVisible ? 'icon-chevron-down' : 'icon-chevron-right'"
-      (click)="descriptionVisible = !descriptionVisible"></span-->
-    <!--label class="ps-2 cursor-pointer text-secondary"
-      (click)="descriptionVisible = !descriptionVisible">{{dataset.name}}</label-->
-      <label><!-- FIXME: a class="text-info non-underlined-link" (click)="showMetadataWindow(dataset)"-->{{getLabelInCurrentLang(dataset.labels)}}<!--/a--></label>
-    <!--div class="p-2 mb-2 text-info" [hidden]="!descriptionVisible">
-      {{dataset.desc}}
-    </div-->
+    <pra-dataset-item [dataset]="dataset"></pra-dataset-item>
   </div>
 </div>

+ 1 - 0
src/adjuster/dataset-list/dataset-list.component.scss

@@ -0,0 +1 @@
+@use '../adjuster-advanced-panel/adjuster-advanced-panel.component.scss';

+ 5 - 15
src/adjuster/dataset-list/dataset-list.component.ts

@@ -1,33 +1,23 @@
-import {Component, Input, OnInit} from '@angular/core';
+import {Component, Input} from '@angular/core';
 
-import {
-  HsDialogContainerService,
-} from 'hslayers-ng';
+import {HsDialogContainerService} from 'hslayers-ng';
 
 import {AdjusterPresetsService} from '../adjuster-presets.service';
-import {MetadataDialogComponent} from '../metadata-dialog/metadata-dialog.component';
 
 @Component({
   selector: 'pra-dataset-list',
   templateUrl: './dataset-list.component.html',
-  styleUrls: ['../adjuster.component.scss'],
+  styleUrls: ['./dataset-list.component.scss'],
 })
-
-export class DatasetListComponent implements OnInit {
+export class DatasetListComponent {
   @Input() factor;
   datasetlistVisible = false;
   constructor(
     public adjusterPresetsService: AdjusterPresetsService,
-    public hsDialogContainerService: HsDialogContainerService,
+    public hsDialogContainerService: HsDialogContainerService
   ) {}
 
-  ngOnInit() {}
-
   getLabelInCurrentLang(labels) {
     return this.adjusterPresetsService.getLabelInCurrentLang(labels);
   }
-
-  showMetadataWindow(dataset) {
-    this.hsDialogContainerService.create(MetadataDialogComponent, {title: dataset.name});
-  }
 }

+ 0 - 6
src/adjuster/index.ts

@@ -1,6 +0,0 @@
-import {AdjusterComponent} from './adjuster.component';
-//import {AdjusterLoaderComponent} from './adjuster-loader.component';
-import {AdjusterModule} from './adjuster.module';
-import {AdjusterService} from './adjuster.service';
-
-export {AdjusterModule} from './adjuster.module';

+ 1 - 0
src/adjuster/ontology.model.ts

@@ -1,3 +1,4 @@
+/* eslint-disable prettier/prettier */
 // Generated by https://quicktype.io
 
 export interface RDFSubject {

+ 1 - 0
src/app.component.ts

@@ -1,6 +1,7 @@
 import {Component} from '@angular/core';
 
 import {HsConfig, HsLanguageService} from 'hslayers-ng';
+
 import {AppConfig} from './app.config';
 import {AppService} from './app.service';
 

+ 7 - 5
src/app.config.ts

@@ -1,7 +1,7 @@
 //import WMTSTileGrid from 'ol/tilegrid/WMTS';
 import proj4 from 'proj4';
 import {Fill, Stroke, Style} from 'ol/style';
-import {OSM, TileWMS, Vector as VectorSource, XYZ, WMTS} from 'ol/source';
+import {OSM, TileWMS, Vector as VectorSource, XYZ} from 'ol/source';
 import {Tile, Vector as VectorLayer} from 'ol/layer';
 import {TopoJSON} from 'ol/format';
 import {View} from 'ol';
@@ -31,6 +31,8 @@ function getHostname() {
   return urlArr[0] + '//' + domain;
 }
 
+export const DEFAULT_OPACITY = 0.7;
+
 export const cartodbLayer = new Tile({
   properties: {
     title: 'OpenStreetMap světlá',
@@ -39,8 +41,7 @@ export const cartodbLayer = new Tile({
     removable: false,
   },
   source: new XYZ({
-    url:
-      'https://cartodb-basemaps-{a-d}.global.ssl.fastly.net/light_all/{z}/{x}/{y}.png',
+    url: 'https://cartodb-basemaps-{a-d}.global.ssl.fastly.net/light_all/{z}/{x}/{y}.png',
     attributions: [
       'CartoDB Positron, © <a href="https://carto.com/attributions" target="_blank">CARTO</a>',
       '© <a href="https://www.openstreetmap.org/copyright" target="_blank">OpenStreetMap</a> contributors',
@@ -115,7 +116,7 @@ export const mcr500Layer = new Tile({
     },
     attributions: ['© <a href="geoportal.cuzk.cz" target="_blank">ČÚZK</a>'],
   }),
-  
+
   visible: false,
 });
 
@@ -150,7 +151,7 @@ export const perc2color = (perc: number): string => {
   }
   // eslint-disable-next-line @typescript-eslint/no-unused-vars
   const h = r * 0x10000 + g * 0x100 + b * 0x1;
-  return `rgba(${r}, ${g}, ${b}, 0.7)`;
+  return `rgba(${r}, ${g}, ${b}, 1)`;
 };
 
 export const decimal2prettyPerc = (x) => {
@@ -200,6 +201,7 @@ export const obceIndexLayer = new VectorLayer({
     title: 'Obce ČR: Rural attractiveness index',
   },
   source: obce,
+  opacity: DEFAULT_OPACITY,
   visible: true,
   style: indexStyle,
 });

+ 2 - 3
src/app.module.ts

@@ -1,13 +1,12 @@
 import {BrowserModule} from '@angular/platform-browser';
-import {CUSTOM_ELEMENTS_SCHEMA, NgModule} from '@angular/core';
+import {NgModule} from '@angular/core';
 
 import {HslayersModule} from 'hslayers-ng';
 
+import {AdjusterModule} from './adjuster/adjuster.module';
 import {AppComponent} from './app.component';
-import {AdjusterModule} from './adjuster';
 
 @NgModule({
-  schemas: [CUSTOM_ELEMENTS_SCHEMA],
   imports: [BrowserModule, HslayersModule, AdjusterModule],
   declarations: [AppComponent],
   exports: [],

+ 45 - 19
src/app.service.ts

@@ -1,4 +1,3 @@
-import hsv2rgb from 'hsv2rgb';
 import {Feature} from 'ol';
 import {Fill, Stroke, Style} from 'ol/style';
 import {Geometry} from 'ol/geom';
@@ -7,19 +6,29 @@ import {TopoJSON} from 'ol/format';
 import {Vector as VectorLayer} from 'ol/layer';
 import {Vector as VectorSource} from 'ol/source';
 
-import {HsConfig} from 'hslayers-ng';
-import {HsEventBusService} from 'hslayers-ng';
-import {HsLanguageService} from 'hslayers-ng';
-import {HsLayerManagerService} from 'hslayers-ng';
-import {HsLayoutService} from 'hslayers-ng';
-import {HsPanelContainerService} from 'hslayers-ng';
-import {HsSidebarService} from 'hslayers-ng';
+import {
+  HsConfig,
+  HsEventBusService,
+  HsLanguageService,
+  HsLayerManagerService,
+  HsLayoutService,
+  HsPanelContainerService,
+  HsSidebarService,
+} from 'hslayers-ng';
 
-import {AdjusterComponent} from './adjuster/adjuster.component';
+import {AdjusterAdvancedPanelComponent} from './adjuster/adjuster-advanced-panel/adjuster-advanced-panel.component';
 import {AdjusterEventService} from './adjuster/adjuster-event.service';
 import {AdjusterLegendService} from './adjuster/adjuster-legend.service';
 import {AdjusterService} from './adjuster/adjuster.service';
-import {AppConfig, krajeLayer, masLayer, obceIndexLayer, okresyLayer} from './app.config';
+import {AdjusterSimplePanelComponent} from './adjuster/adjuster-simple-panel/adjuster-simple-panel.component';
+import {
+  AppConfig,
+  DEFAULT_OPACITY,
+  krajeLayer,
+  masLayer,
+  obceIndexLayer,
+  okresyLayer,
+} from './app.config';
 
 @Injectable({providedIn: 'root'})
 export class AppService {
@@ -36,15 +45,31 @@ export class AppService {
     public hsSidebarService: HsSidebarService
   ) {
     this.hsSidebarService.addButton({
-      panel: 'adjuster',
+      panel: 'adjuster-simple',
       module: 'pra.adjuster',
       order: 0,
       title: () =>
-        this.hsLanguageService.getTranslation('ADJUSTER.adjustFactors'),
-      description: 'Adjust factors for computation',
+        this.hsLanguageService.getTranslation('ADJUSTER.adjustFactorsSimple'),
+      description: () =>
+        this.hsLanguageService.getTranslation(
+          'ADJUSTER.adjustFactorsSimpleDescription'
+        ),
       icon: 'icon-analytics-piechart',
     });
-    this.hsPanelContainerService.create(AdjusterComponent, {});
+    this.hsPanelContainerService.create(AdjusterSimplePanelComponent, {});
+    this.hsSidebarService.addButton({
+      panel: 'adjuster-advanced',
+      module: 'pra.adjuster',
+      order: 0,
+      title: () =>
+        this.hsLanguageService.getTranslation('ADJUSTER.adjustFactors'),
+      description: () =>
+        this.hsLanguageService.getTranslation(
+          'ADJUSTER.adjustFactorsDescription'
+        ),
+      icon: 'icon-settingsandroid',
+    });
+    this.hsPanelContainerService.create(AdjusterAdvancedPanelComponent, {});
     this.prepareLayers();
     this.adjusterEventService.loaded.subscribe(({success}) => {
       if (success) {
@@ -66,7 +91,7 @@ export class AppService {
 
   init(): void {
     this.hsLanguageService.setLanguage('cs');
-    this.hsLayoutService.setDefaultPanel('adjuster');
+    this.hsLayoutService.setDefaultPanel('adjuster-simple');
   }
 
   /**
@@ -95,6 +120,7 @@ export class AppService {
           url: require('./data/obce_cr_20210310_5p_5514.topojson').default,
           overlaps: false,
         }),
+        opacity: DEFAULT_OPACITY,
         visible: true,
         style: this.generateStyle(method.codename),
       });
@@ -113,7 +139,8 @@ export class AppService {
       .on('featuresloadend', () =>
         this.adjusterEventService.layerReady.next({name: 'index'})
       );
-    (obceIndexLayer.getSource() as any).legend_categories = this.adjusterLegendService.createIndexLegend();
+    (obceIndexLayer.getSource() as any).legend_categories =
+      this.adjusterLegendService.createIndexLegend();
     AppConfig.default_layers.push(masLayer as any);
     AppConfig.default_layers.push(okresyLayer as any);
     AppConfig.default_layers.push(krajeLayer as any);
@@ -154,9 +181,8 @@ export class AppService {
       } else {
         return new Style({
           fill: new Fill({
-            color: this.adjusterLegendService.colorPalette[
-              feature.get(method) - 1
-            ],
+            color:
+              this.adjusterLegendService.colorPalette[feature.get(method) - 1],
           }),
           stroke: new Stroke({
             color: '#FFF',

+ 1 - 1
src/attractiveness.config.json

@@ -24,5 +24,5 @@
     "http://www.semanticweb.org/attractiveness/sustainablecities": 0.85,
     "other": 0
   },
-  "serviceBaseUrl": "https://jmacura.eu/ws/"
+  "serviceBaseUrl": "https://publish.lesprojekt.cz/nodejs/"
 }

+ 26 - 4
src/translations.json

@@ -1,25 +1,36 @@
 {
   "cs": {
     "ADJUSTER": {
-      "adjustFactors": "Vyladit faktory",
+      "adjustFactors": "Atraktivita regionů: Vyladit faktory",
+      "adjustFactorsDescription": "Upravit faktory atraktivity",
+      "adjustFactorsSimple": "Atraktivita regionů",
+      "adjustFactorsSimpleDescription": "Vybrat parametry pro atraktivitu regionů",
       "advanced": "Pokročilé",
       "calculate": "Vypočítat",
       "calcAttractivity": "Počítám atraktivitu",
       "calcClusters": "Počítám shluky",
       "classifyBySchema": "Klasifikovat faktory dle schématu",
+      "clusterLegend": "Barvy shluků",
       "clusters": "Shluky",
+      "clustersDescription": "Skupiny podobných regionů",
       "index": "Index",
+      "index0": "nejméně atraktivní",
+      "index100": "nejvíce atraktivní",
+      "indexDescription": "Žebříček atraktivity",
+      "indexLegend": "Stupnice atraktivity",
       "layerManagerLink1": "Vrstvy můžete prozkoumat",
       "layerManagerLink2": "ve",
       "layerManagerLinkLMName": "Správci vrstev",
       "loading": "Načítám",
       "loadingData": "Načítám data",
+      "moreOpts": "Více možností",
       "myProblemIs": "a chci řešit problém",
       "myRoleIs": "Moje role je",
       "noDataSelectedMsg":
         "Vyberte alespoň jednu datovou sadu a nastavte váhu aspoň jednoho faktoru na ne-nulovou hodnotu.",
       "numberOfClusters": "Počet shluků k vytvoření",
-      "serverError": "Chyba serveru"
+      "serverError": "Chyba serveru",
+      "simple": "Základní"
     },
     "METADATA": {
       "coverage": "Pokrývá území",
@@ -30,24 +41,35 @@
   },
   "en": {
     "ADJUSTER": {
-      "adjustFactors": "Adjust Factors",
+      "adjustFactors": "Regional Attractiveness: Adjust Factors",
+      "adjustFactorsDescription": "Play with attractiveness factors",
+      "adjustFactorsSimple": "Regional Attractiveness",
+      "adjustFactorsSimpleDescription": "Select parametres for region attractiveness",
       "advanced": "Advanced",
       "calculate": "Calculate",
       "calcAttractivity": "Calculating attractivity",
       "calcClusters": "Calculating clusters",
       "classifyBySchema": "Classify factors by schema",
+      "clusterLegend": "Clusters' colours",
       "clusters": "Clusters",
+      "clustersDescription": "Groups of similar regions",
       "index": "Index",
+      "index0": "least attractive",
+      "index100": "most attractive",
+      "indexDescription": "Ranking of attractiveness",
+      "indexLegend": "Attractiveness scale",
       "layerManagerLink1": "You can investigate the layers",
       "layerManagerLink2": "in the",
       "layerManagerLinkLMName": "Layer Manager",
       "loading": "Loading",
       "loadingData": "Loading data",
+      "moreOpts": "More options",
       "myProblemIs": "and I want to solve a problem with",
       "myRoleIs": "My role is",
       "noDataSelectedMsg": "Select at least one dataset and set at least one factor's weight to a non-zero value.",
       "numberOfClusters": "Number of clusters to create",
-      "serverError": "Server error"
+      "serverError": "Server error",
+      "simple": "Basic"
     },
     "METADATA": {
       "coverage": "Covers area",