瀏覽代碼

Merge branch 'develop' of jmacura/polirural-attractiveness-clustering into master

jmacura 5 年之前
父節點
當前提交
c8453f6c5c

+ 4 - 4
.editorconfig

@@ -4,12 +4,12 @@
 # top-most EditorConfig file
 root = true
 
-# Newline ending every file
+# Newline ending every file and set default charset
 [*]
 insert_final_newline = true
+charset = utf-8
 
-# 2 space indentation and set default charset
-[*.js]
+# 2 space indentation
+[*.{js,ts,html,css}]
 indent_style = space
 indent_size = 2
-charset = utf-8

+ 44 - 34
package-lock.json

@@ -865,24 +865,24 @@
       "dev": true
     },
     "angular": {
-      "version": "1.7.9",
-      "resolved": "https://registry.npmjs.org/angular/-/angular-1.7.9.tgz",
-      "integrity": "sha512-5se7ZpcOtu0MBFlzGv5dsM1quQDoDeUTwZrWjGtTNA7O88cD8TEk5IEKCTDa3uECV9XnvKREVUr7du1ACiWGFQ=="
+      "version": "1.8.0",
+      "resolved": "https://registry.npmjs.org/angular/-/angular-1.8.0.tgz",
+      "integrity": "sha512-VdaMx+Qk0Skla7B5gw77a8hzlcOakwF8mjlW13DpIWIDlfqwAbSSLfd8N/qZnzEmQF4jC4iofInd3gE7vL8ZZg=="
     },
     "angular-animate": {
-      "version": "1.7.9",
-      "resolved": "https://registry.npmjs.org/angular-animate/-/angular-animate-1.7.9.tgz",
-      "integrity": "sha512-fV+AISy/HTzurQH2ngsJg+lLIvfu0ahc1h4AYKauaXVw97rZc2k4iUA1bMstiEyClsdayQX568kjQc1NK+oYhw=="
+      "version": "1.8.0",
+      "resolved": "https://registry.npmjs.org/angular-animate/-/angular-animate-1.8.0.tgz",
+      "integrity": "sha512-ROFK3UIn1MSVpqAlay15ZxjPmVbvwaO3Zn/2vhmQdYeqxSbUVuOckcvtDLBpHPGPtOAreu35qfV7NQ7u2EgDcA=="
     },
     "angular-aria": {
-      "version": "1.7.9",
-      "resolved": "https://registry.npmjs.org/angular-aria/-/angular-aria-1.7.9.tgz",
-      "integrity": "sha512-luI3Jemd1AbOQW0krdzfEG3fM0IFtLY0bSSqIDEx3POE0XjKIC1MkrO8Csyq9PPgueLphyAPofzUwZ8YeZ88SA=="
+      "version": "1.8.0",
+      "resolved": "https://registry.npmjs.org/angular-aria/-/angular-aria-1.8.0.tgz",
+      "integrity": "sha512-eCQI6EwgY6bYHdzIUfDABHnZjoZ3bNYpCsnceQF4bLfbq1QtZ7raRPNca45sj6C9Pfjde6PNcEDvuLozFPYnrQ=="
     },
     "angular-cookies": {
-      "version": "1.7.9",
-      "resolved": "https://registry.npmjs.org/angular-cookies/-/angular-cookies-1.7.9.tgz",
-      "integrity": "sha512-3eRq/aPrtCZKDWQnc3nW3sFoMbLiHkCkyDF2O9u7VXnqvVsUPaipk5R1ZqahgcSQHQrN/F5IU4T4nrz52qAZmA=="
+      "version": "1.8.0",
+      "resolved": "https://registry.npmjs.org/angular-cookies/-/angular-cookies-1.8.0.tgz",
+      "integrity": "sha512-gWO3RKF0WMmXhseiN3Aw9aEmQ3mB53wSdAxpeKKHbiDwU7vmK+MBuebyOX9qbwZYubn5nM8LByZVmg7T6jOV1w=="
     },
     "angular-drag-and-drop-lists": {
       "version": "2.1.0",
@@ -900,28 +900,28 @@
       "integrity": "sha1-hecpqGQfqu6zBnpFNFc6S7lx4eo="
     },
     "angular-loader": {
-      "version": "1.7.9",
-      "resolved": "https://registry.npmjs.org/angular-loader/-/angular-loader-1.7.9.tgz",
-      "integrity": "sha512-Hei0AQ96P2qzduWZtAsHvxUnLSLSAxpkjYc7F0JAwNPA14rXYKt20a9crc8CWd/v45Dkz7+SFhb2QMx5nCyNLQ=="
+      "version": "1.8.0",
+      "resolved": "https://registry.npmjs.org/angular-loader/-/angular-loader-1.8.0.tgz",
+      "integrity": "sha512-NCvLLFWCkxLR3/zBaVGM+7q9IJzobx2PVXMnPoKjtAITpM6AhnH5SYFkFzcK1oQ6P6c2v0oLef6oij7mSEj0Mw=="
     },
     "angular-material": {
-      "version": "1.1.22",
-      "resolved": "https://registry.npmjs.org/angular-material/-/angular-material-1.1.22.tgz",
-      "integrity": "sha512-GT8bDfKWj3xIzzYna+adhyim84B2KkqgXozyEZFAbA9yaDTKe4dV1gXA0SXzeCy0aWyVXwfrxrGt4nKjgVMi7g=="
+      "version": "1.1.23",
+      "resolved": "https://registry.npmjs.org/angular-material/-/angular-material-1.1.23.tgz",
+      "integrity": "sha512-hDz78xIVzN2SADlEEHTITzoJgE2C5adB975ExgibCz2pgPlhPH7YtVB9jhRpiBAlg1k5nc8JhZ7smxhU9eTuxQ=="
     },
     "angular-material-bottom-sheet-collapsible": {
       "version": "git+https://github.com/SLeitgeb/angular-material-bottom-sheet-collapsible.git#7e22ce43260e22e519f8a1777cfa9e165cd24c80",
       "from": "git+https://github.com/SLeitgeb/angular-material-bottom-sheet-collapsible.git#7e22ce4"
     },
     "angular-messages": {
-      "version": "1.7.9",
-      "resolved": "https://registry.npmjs.org/angular-messages/-/angular-messages-1.7.9.tgz",
-      "integrity": "sha512-OdJihuO6AW+m1/r9OdW5riCwacn3dL1agQvgu6Cww3a7OARXXN0vxOpsZCNk4yg4CuD7Et3tiz4DymhvZkydvw=="
+      "version": "1.8.0",
+      "resolved": "https://registry.npmjs.org/angular-messages/-/angular-messages-1.8.0.tgz",
+      "integrity": "sha512-LSlyTv80y1vg8Cfdz+RJ0BrraWkq0qsOZHyrHFT8NyYWC5yp6HQabvZvTpKv9YA+6o05wwAU90qXHSrnUlSflA=="
     },
     "angular-mocks": {
-      "version": "1.7.9",
-      "resolved": "https://registry.npmjs.org/angular-mocks/-/angular-mocks-1.7.9.tgz",
-      "integrity": "sha512-LQRqqiV3sZ7NTHBnNmLT0bXtE5e81t97+hkJ56oU0k3dqKv1s6F+nBWRlOVzqHWPGFOiPS8ZJVdrS8DFzHyNIA=="
+      "version": "1.8.0",
+      "resolved": "https://registry.npmjs.org/angular-mocks/-/angular-mocks-1.8.0.tgz",
+      "integrity": "sha512-oFKJIqR6zcsW6V9UQMuUYCXIcTy+n7oYExXxZkvU57hwJQdU1nuNZcSMQA9URiEAPyo7v3bqm0eOP3Ezi7Bigg=="
     },
     "angular-route": {
       "version": "1.4.14",
@@ -929,9 +929,9 @@
       "integrity": "sha1-Ll2/4SOUI8Z4Flw5uzhgGtZqB5Q="
     },
     "angular-sanitize": {
-      "version": "1.7.9",
-      "resolved": "https://registry.npmjs.org/angular-sanitize/-/angular-sanitize-1.7.9.tgz",
-      "integrity": "sha512-nB/xe7JQWF9nLvhHommAICQ3eWrfRETo0EVGFESi952CDzDa+GAJ/2BFBNw44QqQPxj1Xua/uYKrbLsOGWZdbQ=="
+      "version": "1.8.0",
+      "resolved": "https://registry.npmjs.org/angular-sanitize/-/angular-sanitize-1.8.0.tgz",
+      "integrity": "sha512-j5GiOPCvfcDWK5svEOVoPb11X3UDVy/mdHPRWuy14Iyw86xaq+Bb+x/em2sAOa5MQQeY5ciLXbF3RRp8iCKcNg=="
     },
     "angular-socialshare": {
       "version": "2.3.11",
@@ -959,6 +959,15 @@
       "resolved": "https://registry.npmjs.org/angular-update-meta/-/angular-update-meta-2.1.0.tgz",
       "integrity": "sha512-WlQjJ+NtIHSqyM3uIZn0JCFney5vozxaB8lzwe+eP4knQeN8iuATko3rTVgfO3C94JgFnrj2RpwoENbh6pVvTA=="
     },
+    "angularjs-bootstrap-datetimepicker": {
+      "version": "1.1.4",
+      "resolved": "https://registry.npmjs.org/angularjs-bootstrap-datetimepicker/-/angularjs-bootstrap-datetimepicker-1.1.4.tgz",
+      "integrity": "sha1-iKT+oORv6PRWHirDKWT/WJ5UZKk=",
+      "requires": {
+        "angular": "^1.6.4",
+        "moment": "^2.18.1"
+      }
+    },
     "ansi-colors": {
       "version": "3.2.4",
       "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.4.tgz",
@@ -5509,9 +5518,9 @@
       "dev": true
     },
     "hslayers-ng": {
-      "version": "1.23.0",
-      "resolved": "https://registry.npmjs.org/hslayers-ng/-/hslayers-ng-1.23.0.tgz",
-      "integrity": "sha512-FmaLQHLqcV4IKOO1/VtubrwohW7/tPsVyw0IZ5SYJQqfg9RwfSWaztux6I9ERUNn2COjiQ8HFgjLIdHseSjmoA==",
+      "version": "1.24.1",
+      "resolved": "https://registry.npmjs.org/hslayers-ng/-/hslayers-ng-1.24.1.tgz",
+      "integrity": "sha512-19/2NRx48xx9RzgMlSheeJsZ8c+YjXynYBNCodAi1tH0pePbAc9C8pjay21rvCkM0g39d4ANFGP5Z4LElgaLdg==",
       "requires": {
         "angular": "^1.7.9",
         "angular-animate": "^1.7.9",
@@ -5520,7 +5529,7 @@
         "angular-drag-and-drop-lists": ">=2.1.0",
         "angular-gettext": "2.4.x",
         "angular-lazy-image": "^0.3.4",
-        "angular-loader": "1.7.x",
+        "angular-loader": "1.8.x",
         "angular-material": "^1.1.21",
         "angular-material-bottom-sheet-collapsible": "git+https://github.com/SLeitgeb/angular-material-bottom-sheet-collapsible.git#7e22ce4",
         "angular-messages": "^1.7.9",
@@ -5529,6 +5538,7 @@
         "angular-socialshare": "^2.3.11",
         "angular-timelinejs3": "~0.2.3",
         "angular-update-meta": "2.1.0",
+        "angularjs-bootstrap-datetimepicker": "^1.1.4",
         "bootstrap": ">=4.4.1",
         "clipboard": "^2.0.4",
         "cors-anywhere": "^0.4.1",
@@ -6946,9 +6956,9 @@
       }
     },
     "moment": {
-      "version": "2.26.0",
-      "resolved": "https://registry.npmjs.org/moment/-/moment-2.26.0.tgz",
-      "integrity": "sha512-oIixUO+OamkUkwjhAVE18rAMfRJNsNe/Stid/gwHSOfHrOtw9EhAY2AHvdKZ/k/MggcYELFCJz/Sn2pL8b8JMw=="
+      "version": "2.27.0",
+      "resolved": "https://registry.npmjs.org/moment/-/moment-2.27.0.tgz",
+      "integrity": "sha512-al0MUK7cpIcglMv3YF13qSgdAIqxHTO7brRtaz3DlSULbqfazqkc5kEjNrLDOM7fsjshoFIihnU8snrP7zUvhQ=="
     },
     "moment-interval": {
       "version": "0.2.1",

+ 1 - 1
package.json

@@ -25,7 +25,7 @@
   "license": "MIT",
   "dependencies": {
     "csvtojson": "^2.0.10",
-    "hslayers-ng": "^1.23.0",
+    "hslayers-ng": "^1.24.0",
     "hsv2rgb": "^1.1.0",
     "http-server": "^0.12.3"
   },

+ 23 - 0
src/adjuster/adjuster-loader.component.js

@@ -0,0 +1,23 @@
+//Currently unused and replaced by a simple directive
+export const AdjusterLoaderComponent = {
+  template: require('./adjuster-loader.directive.html'),
+  bindings: {},
+  controller: function (
+    $scope,
+    HsCore,
+    HsConfig,
+    PraAdjusterService,
+    HsUtilsService
+  ) {
+    'ngInject';
+    const vm = this;
+
+    angular.extend(vm, {
+      //HsCore,
+      PraAdjusterService,
+    });
+
+    //$scope.$emit('scope_loaded', 'adjuster');
+  },
+  controllerAs: 'vm',
+};

+ 6 - 0
src/adjuster/adjuster-loader.directive.html

@@ -0,0 +1,6 @@
+<div class="center-block">
+  <h1>Calculating clusters</h1>
+  <div class="spinner-border spinner" role="status">
+    <span class="sr-only">Loading...</span>
+  </div>
+</div>

+ 1 - 1
src/adjuster/adjuster.component.js

@@ -1,4 +1,4 @@
-export default {
+export const AdjusterComponent = {
   template: require('./adjuster.directive.html'),
   controller: function (
     $scope,

+ 3 - 13
src/adjuster/adjuster.directive.html

@@ -1,29 +1,19 @@
 <div class="card card-default mainpanel">
   <hs.layout.panel-header panel-name="adjuster" panel-title="'Adjust factors'||translate"></hs.layout.panel-header>
-  <style>
-    .weather-table>tbody>tr>td,
-    .table-condensed>tbody>tr>th,
-    .table-condensed>tfoot>tr>td,
-    .table-condensed>tfoot>tr>th,
-    .table-condensed>thead>tr>td,
-    .table-condensed>thead>tr>th {
-      padding: 2px;
-    }
-  </style>
   <div class="card-body">
     <button type="button" class="btn btn-primary" ng-click="PraAdjusterService.apply()" ng-disabled="PraAdjusterService.isClusteringInProcess()">Calculate clusters</button>
     <div class="card-body">
       <div ng-repeat="factor in PraAdjusterService.factors">
         <div class="d-flex flex-row">
           <div class="p-2 flex-grow-1">
-            <label>{{factor.name}}</label>
+            <span class="glyphicon cursor-pointer" ng-class="datasetlistVisible ? 'icon-chevron-down' : 'icon-chevron-right'"
+              ng-click="datasetlistVisible = !datasetlistVisible"></span>
+            <label class="cursor-pointer" ng-click="datasetlistVisible = !datasetlistVisible">{{factor.name}}</label>
           </div>
           <div class="p-2">{{(factor.weight * 100).toFixed(0)}}&nbsp;%</div>
         </div>
         <input type="range" class="custom-range" ng-model="factor.weight" min="0"
           max="1.0" step="0.05">
-        <span class="glyphicon" ng-class="datasetlistVisible ? 'icon-chevron-left' : 'icon-chevron-right'"
-          ng-click="datasetlistVisible = !datasetlistVisible"></span>
         <div ng-init="datasetlistVisible = false" ng-show="datasetlistVisible">
           <div ng-repeat="dataset in factor.datasets">
             <button type="button" class="btn btn-sm btn-light hs-lm-item-visibility"

+ 7 - 4
src/adjuster/adjuster.module.js

@@ -1,4 +1,4 @@
-import adjusterComponent from './adjuster.component.js';
+import {AdjusterComponent} from './adjuster.component.js';
 import {AdjusterService} from './adjuster.service.js';
 
 angular
@@ -8,7 +8,10 @@ angular
       template: require('./adjuster-sidebar-btn.directive.html'),
     };
   })
-
   .service('PraAdjusterService', AdjusterService)
-
-  .component('pra.adjuster', adjusterComponent);
+  .component('pra.adjuster', AdjusterComponent)
+  .directive('praAdjusterLoader', () => {
+    return {
+      template: require('./adjuster-loader.directive.html'),
+    };
+  });

+ 3 - 3
src/adjuster/adjuster.service.js

@@ -10,9 +10,9 @@ export class AdjusterService {
     this.$rootScope = $rootScope;
     this.$http = $http;
     this.serviceBaseUrl =
-      //$location.host() === 'localhost'
-        'https://jmacura.ml/ws/';
-        //: 'https://publish.lesprojekt.cz/nodejs/';
+      $location.host() === 'localhost'
+        ? 'https://jmacura.ml/ws/'
+        : 'https://publish.lesprojekt.cz/nodejs/';
     this.factors = factors;
     this.clusters = [];
     this._clusteringInProcess = true;

+ 129 - 0
src/app.component.js

@@ -0,0 +1,129 @@
+import VectorLayer from 'ol/layer/Vector';
+import hsv2rgb from 'hsv2rgb';
+import nuts from './nuts.js';
+import {Fill, Stroke, Style} from 'ol/style';
+
+export const HsComponent = {
+  template: (HsCore) => {
+    'ngInject';
+    return HsCore.hslayersNgTemplate;
+  },
+  bindings: {},
+  controller: function (
+    $scope,
+    $compile,
+    gettext,
+    HsCore,
+    HsLayoutService,
+    HsSidebarService,
+    PraAdjusterService
+  ) {
+    'ngInject';
+    const vm = this;
+    vm.exists = HsCore.exists;
+    vm.panelVisible = HsLayoutService.panelVisible;
+    vm.PraAdjusterService = PraAdjusterService;
+    HsLayoutService.sidebarRight = false;
+    // HsLayoutService.sidebarToggleable = false;
+    // HsCore.singleDatasources = true;
+    HsLayoutService.sidebarButtons = true;
+    HsLayoutService.setDefaultPanel('adjuster');
+    $scope.$on('scope_loaded', function (event, args) {
+      if (args === 'Sidebar') {
+        const el = angular.element(
+          '<pra.adjuster hs.draggable ng-if="vm.exists(\'pra.adjuster\')" ng-show="vm.panelVisible(\'adjuster\', this)"></pra.adjuster>'
+        )[0];
+        HsLayoutService.panelListElement.appendChild(el);
+        $compile(el)($scope);
+        const toolbarButton = angular.element(
+          '<div pra-adjuster-sidebar-btn></div>'
+        )[0];
+        HsLayoutService.sidebarListElement.appendChild(toolbarButton);
+        $compile(toolbarButton)(event.targetScope);
+        const loader = angular.element(
+          '<pra-adjuster-loader class="loader-splash" ng-if="vm.PraAdjusterService.isClusteringInProcess()"></pra-adjuster-loader>'
+        )[0];
+        HsLayoutService.contentWrapper
+          .querySelector('.hs-page-content')
+          .appendChild(loader);
+        $compile(loader)(event.targetScope);
+      }
+    });
+    $scope.$on('clusters_loaded', function (event, args) {
+      randomColorPalette = generateRandomColorPalette(
+        PraAdjusterService.clusters.length
+      );
+    });
+  },
+  controllerAs: 'vm',
+};
+
+let randomColorPalette = [];
+
+const stroke = new Stroke({
+  color: '#3399CC',
+  width: 0.25,
+});
+
+const styles = function (feature) {
+  if (isNaN(feature.get('km25.cluster'))) {
+    return [
+      new Style({
+        fill: new Fill({
+          color: '#FFF',
+        }),
+        stroke: stroke,
+      }),
+    ];
+  } else {
+    return [
+      new Style({
+        fill: new Fill({
+          color: randomColorPalette[feature.get('km25.cluster') - 1],
+        }),
+        //stroke: stroke,
+      }),
+    ];
+  }
+};
+
+export const nuts2Layer = new VectorLayer({
+  source: nuts.nuts2Source,
+  visible: false,
+  style: styles,
+  title: 'NUTS2 regions',
+});
+
+export const nuts3Layer = new VectorLayer({
+  source: nuts.nuts3Source,
+  editor: {editable: false},
+  visible: true,
+  style: styles,
+  title: 'NUTS3 regions',
+});
+nuts3Layer.set('popUp', {
+  attributes: [
+    {attribute: 'CNTR_CODE', label: 'Country'},
+    {attribute: 'NUTS_NAME', label: 'Name'},
+    {attribute: 'km25.cluster', label: 'Cluster ID'},
+  ],
+});
+
+/**
+ * https://martin.ankerl.com/2009/12/09/how-to-create-random-colors-programmatically/
+ * @param {number} colorCount Number of colors to randomly generate
+ * @returns {Array<Array<Number>>} Array of RGB colors
+ */
+function generateRandomColorPalette(colorCount) {
+  const palette = [];
+  const goldenRatioConjugate = 0.618033988749895;
+  for (let i = 0; i < colorCount; i++) {
+    let h = Math.random();
+    h += goldenRatioConjugate;
+    h %= 1;
+    h *= 360;
+    palette.push(hsv2rgb(h, 0.5, 0.95));
+  }
+  return palette;
+  //return `rgba(${r}, ${g}, ${b}, 0.7)`;
+}

+ 39 - 0
src/app.css

@@ -0,0 +1,39 @@
+#hs-app {
+  display: block;
+  height: 100vh;
+  position: relative;
+}
+
+.cursor-pointer {
+  cursor: pointer;
+}
+
+.loader-splash {
+  height: 100%;
+  width: 100%;
+  position: absolute;
+  z-index: 1010;
+  top: 0;
+  left: 0;
+  background-color: rgba(65,65,65,.66);
+}
+
+.loader-splash > div {
+  position: relative;
+  margin-top: 20%;
+}
+
+.loader-splash h1 {
+  color: #77bbff;
+}
+
+.loader-splash .spinner {
+  width: 10vh;
+  height: 10vh;
+  color: #77bbff;
+}
+
+.center-block {
+  text-align: center;
+  margin-bottom: 1em;
+}

+ 0 - 220
src/app.js

@@ -1,220 +0,0 @@
-'use strict';
-//import angular from 'angular';
-import 'hslayers-ng/components/add-layers/add-layers.module';
-import 'hslayers-ng/components/datasource-selector/datasource-selector.module';
-import 'hslayers-ng/components/draw/draw.module';
-import 'hslayers-ng/components/info/info.module';
-import 'hslayers-ng/components/measure/measure.module';
-import 'hslayers-ng/components/permalink/permalink.module';
-import 'hslayers-ng/components/print/print.module';
-import 'hslayers-ng/components/query/query.module';
-import 'hslayers-ng/components/search/search.module';
-import 'hslayers-ng/components/sidebar/sidebar.module';
-import 'hslayers-ng/components/toolbar/toolbar.module';
-// hslayers-ng components must be loaded first, otherwise angular will be undefined
-// eslint-disable-next-line sort-imports-es6-autofix/sort-imports-es6
-import './adjuster/adjuster.module.js';
-import VectorLayer from 'ol/layer/Vector';
-import View from 'ol/View';
-import hsv2rgb from 'hsv2rgb';
-import nuts from './nuts.js';
-import {Fill, Stroke, Style} from 'ol/style';
-import {OSM} from 'ol/source';
-import {Tile} from 'ol/layer';
-
-let randomColorPalette = [];
-
-function getHostname() {
-  const url = window.location.href;
-  const urlArr = url.split('/');
-  const domain = urlArr[2];
-  return urlArr[0] + '//' + domain;
-}
-
-const stroke = new Stroke({
-  color: '#3399CC',
-  width: 0.25,
-});
-
-/**
- * https://martin.ankerl.com/2009/12/09/how-to-create-random-colors-programmatically/
- * @param {number} colorCount Number of colors to randomly generate
- * @returns {Array<Array<Number>>} Array of RGB colors
- */
-function generateRandomColorPalette(colorCount) {
-  const palette = [];
-  const goldenRatioConjugate = 0.618033988749895;
-  for (let i = 0; i < colorCount; i++) {
-    let h = Math.random();
-    h += goldenRatioConjugate;
-    h %= 1;
-    h *= 360;
-    palette.push(hsv2rgb(h, 0.5, 0.95));
-  }
-  // eslint-disable-next-line no-unused-vars
-  // const h = r * 0x10000 + g * 0x100 + b * 0x1;
-  return palette;
-  //return `rgba(${r}, ${g}, ${b}, 0.7)`;
-}
-
-const styles = function (feature) {
-  if (isNaN(feature.get('km25.cluster'))) {
-    return [
-      new Style({
-        fill: new Fill({
-          color: '#FFF',
-        }),
-        stroke: stroke,
-      }),
-    ];
-  } else {
-    return [
-      new Style({
-        fill: new Fill({
-          color: randomColorPalette[feature.get('km25.cluster')],
-        }),
-        //stroke: stroke,
-      }),
-    ];
-  }
-};
-
-const nuts2Layer = new VectorLayer({
-  source: nuts.nuts2Source,
-  visible: false,
-  style: styles,
-  title: 'NUTS2 regions',
-});
-
-const nuts3Layer = new VectorLayer({
-  source: nuts.nuts3Source,
-  visible: true,
-  style: styles,
-  title: 'NUTS3 regions',
-});
-//TODO: update to new PopUp config & align with new attrs
-nuts3Layer.set('hoveredKeys', [
-  'NUTS_NAME',
-  'totalForHumans',
-  'Social & Human',
-  'Anthropic',
-  'Institutional',
-  'Economical',
-  'Natural',
-  'Cultural',
-]);
-nuts3Layer.set('hoveredKeysTranslations', {
-  NUTS_NAME: 'Name',
-  totalForHumans: 'Calculated score',
-});
-
-angular
-  .module('hs', [
-    'hs.addLayers',
-    'hs.datasource_selector',
-    'hs.draw',
-    'hs.geolocation',
-    'hs.info',
-    'hs.layermanager',
-    'hs.measure',
-    'hs.permalink',
-    'hs.print',
-    'hs.query',
-    'hs.save-map',
-    'hs.search',
-    'hs.sidebar',
-    'hs.toolbar',
-    'gettext',
-    'pra.adjuster',
-  ])
-  .directive('hs', function (HsConfig, HsCore) {
-    'ngInject';
-    return {
-      template: HsCore.hslayersNgTemplate,
-      /* link: function (scope, element) {
-        HsCore.fullScreenMap(element);
-      } */
-    };
-  })
-  .value('HsConfig', {
-    proxyPrefix: '../8085/',
-    default_layers: [
-      new Tile({
-        source: new OSM(),
-        title: 'OpenStreetMap',
-        base: true,
-        removable: false,
-      }),
-      nuts2Layer,
-      nuts3Layer,
-    ],
-    popUpDisplay: 'hover',
-    project_name: 'erra/map',
-    default_view: new View({
-      center: [2433348.3022471312, 7744501.813885343],
-      zoom: 3.6,
-      units: 'm',
-    }),
-    advanced_form: true,
-    datasources: [],
-    hostname: {
-      default: {
-        title: 'Default',
-        type: 'default',
-        editable: false,
-        url: getHostname(),
-      },
-    },
-    panelWidths: {},
-    // allowAddExternalDatasets: false,
-    panelsEnabled: {
-      composition_browser: false,
-      draw: false,
-      //info: false,
-      saveMap: false,
-      language: false,
-    },
-    /*searchProvider: (q) => {
-      return `/app/jupyter-test/8085/search/?q=${q}`;
-    },*/
-    sizeMode: 'fullscreen',
-  })
-  .controller('MainController', function (
-    $scope,
-    $compile,
-    gettext,
-    HsCore,
-    HsLayoutService,
-    HsSidebarService,
-    PraAdjusterService
-  ) {
-    'ngInject';
-    const vm = this;
-    vm.exists = HsCore.exists;
-    vm.panelVisible = HsLayoutService.panelVisible;
-    HsLayoutService.sidebarRight = false;
-    // HsLayoutService.sidebarToggleable = false;
-    // HsCore.singleDatasources = true;
-    HsLayoutService.sidebarButtons = true;
-    HsLayoutService.setDefaultPanel('adjuster');
-    $scope.$on('scope_loaded', function (event, args) {
-      if (args === 'Sidebar') {
-        const el = angular.element(
-          '<pra.adjuster hs.draggable ng-if="vm.exists(\'pra.adjuster\')" ng-show="vm.panelVisible(\'adjuster\', this)"></pra.adjuster>'
-        )[0];
-        HsLayoutService.panelListElement.appendChild(el);
-        $compile(el)($scope);
-
-        const toolbarButton = angular.element(
-          '<div pra-adjuster-sidebar-btn></div>'
-        )[0];
-        HsLayoutService.sidebarListElement.appendChild(toolbarButton);
-        $compile(toolbarButton)(event.targetScope);
-      }
-    });
-    $scope.$on('clusters_loaded', function (event, args) {
-      randomColorPalette = generateRandomColorPalette(
-        PraAdjusterService.clusters.length
-      );
-    });
-  });

+ 90 - 0
src/app.module.js

@@ -0,0 +1,90 @@
+'use strict';
+import 'hslayers-ng/components/add-layers/add-layers.module';
+import 'hslayers-ng/components/core/core.module';
+import 'hslayers-ng/components/datasource-selector/datasource-selector.module';
+import 'hslayers-ng/components/draw/draw.module';
+import 'hslayers-ng/components/info/info.module';
+import 'hslayers-ng/components/map/map.module';
+import 'hslayers-ng/components/measure/measure.module';
+import 'hslayers-ng/components/permalink/permalink.module';
+import 'hslayers-ng/components/print/print.module';
+import 'hslayers-ng/components/query/query.module';
+import 'hslayers-ng/components/search/search.module';
+import 'hslayers-ng/components/sidebar/sidebar.module';
+import 'hslayers-ng/components/toolbar/toolbar.module';
+// hslayers-ng components must be loaded first, otherwise angular will be undefined
+// eslint-disable-next-line sort-imports-es6-autofix/sort-imports-es6
+import './adjuster/adjuster.module.js';
+import './app.css';
+import View from 'ol/View';
+import angular from 'angular';
+import {HsComponent, nuts2Layer, nuts3Layer} from './app.component.js';
+import {OSM} from 'ol/source';
+import {Tile} from 'ol/layer';
+
+function getHostname() {
+  const url = window.location.href;
+  const urlArr = url.split('/');
+  const domain = urlArr[2];
+  return urlArr[0] + '//' + domain;
+}
+
+angular
+  .module('hs', [
+    'hs.addLayers',
+    'hs.core',
+    'hs.datasource_selector',
+    'hs.geolocation',
+    'hs.info',
+    'hs.layermanager',
+    'hs.map',
+    'hs.measure',
+    'hs.permalink',
+    'hs.print',
+    'hs.query',
+    'hs.save-map',
+    'hs.search',
+    'hs.sidebar',
+    'hs.toolbar',
+    'gettext',
+    'pra.adjuster',
+  ])
+  .value('HsConfig', {
+    //proxyPrefix: '../8085/',
+    default_layers: [
+      new Tile({
+        source: new OSM(),
+        title: 'OpenStreetMap',
+        base: true,
+        removable: false,
+      }),
+      nuts2Layer,
+      nuts3Layer,
+    ],
+    popUpDisplay: 'hover',
+    project_name: 'erra/map',
+    default_view: new View({
+      center: [2433348.3022471312, 7744501.813885343],
+      zoom: 3.6,
+      units: 'm',
+    }),
+    advanced_form: true,
+    datasources: [],
+    hostname: {
+      default: {
+        title: 'Default',
+        type: 'default',
+        editable: false,
+        url: getHostname(),
+      },
+    },
+    panelWidths: {},
+    // allowAddExternalDatasets: false,
+    panelsEnabled: {
+      composition_browser: false,
+      saveMap: false,
+      language: false,
+    },
+    sizeMode: 'fullscreen',
+  })
+  .component('hs', HsComponent).name;

+ 2 - 2
src/index.html

@@ -3,7 +3,7 @@
 
 <head>
   <meta charset="utf-8">
-  <title>Rural attractiveness</title>
+  <title>Rural attractiveness clusters</title>
   <meta name="description"
     content="Rural attractiveness calculation and visualization application developed in PoliRural project. 2020">
   <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
@@ -15,7 +15,7 @@
 </head>
 
 <body>
-  <div hs ng-app="hs" ng-controller="MainController as vm" style="height: 100vh;"></div>
+  <hs ng-app="hs" id="hs-app" ng-strict-di></hs>
   <% for (var js in htmlWebpackPlugin.files.js) { %>
     <script type="application/javascript" src="<%= htmlWebpackPlugin.files.js[js] %>"></script>
   <% } %>

+ 1 - 1
webpack.common.js

@@ -18,7 +18,7 @@ const hslPaths = require(path.join(
 ));
 
 module.exports = {
-  entry: {main: './src/app.js'},
+  entry: {main: './src/app.module.js'},
   output: {
     // Path at which output assets will be served
     publicPath: '',