From d0be823cdb51906d49bfecb7cc0e9095b9bed79b Mon Sep 17 00:00:00 2001
From: Roberto Callari <robertocallari89@gmail.com>
Date: Mon, 14 Jun 2021 18:27:18 +0200
Subject: [PATCH] messina traffic first commit

---
 angular.json                                  |   6 +-
 package-lock.json                             |  22 +-
 package.json                                  |   2 +
 src/app/pages/home/home.component.html        | 156 +++++++----
 src/app/pages/home/home.component.scss        |   3 +
 .../service/messina-client.service.spec.ts    |  16 ++
 .../messina/service/messina-client.service.ts |  39 +++
 .../messina/traffic/traffic.component.ts      | 247 ++++++++++++------
 src/assets/config.json                        |   3 +-
 src/assets/messina/POIs.json                  |  27 ++
 src/assets/messina/POIs_geojson.json          |  36 +++
 .../messina/Traffic_GroupByDatetime.json      | 238 +++++++++++++++++
 src/assets/messina/Traffic_GroupByRoad.json   |  81 ++++++
 src/assets/messina/stops.json                 |  32 +++
 src/assets/messina/stops_geojson.json         |  47 ++++
 src/typings.d.ts                              |   5 +
 16 files changed, 823 insertions(+), 137 deletions(-)
 create mode 100644 src/app/pages/messina/service/messina-client.service.spec.ts
 create mode 100644 src/app/pages/messina/service/messina-client.service.ts
 create mode 100644 src/assets/messina/POIs.json
 create mode 100644 src/assets/messina/POIs_geojson.json
 create mode 100644 src/assets/messina/Traffic_GroupByDatetime.json
 create mode 100644 src/assets/messina/Traffic_GroupByRoad.json
 create mode 100644 src/assets/messina/stops.json
 create mode 100644 src/assets/messina/stops_geojson.json

diff --git a/angular.json b/angular.json
index 73654365..87de3191 100644
--- a/angular.json
+++ b/angular.json
@@ -43,7 +43,8 @@
               "node_modules/leaflet/dist/leaflet.css",
               "node_modules/ngx-owl-carousel-o/lib/styles/prebuilt-themes/owl.carousel.min.css",
               "node_modules/ngx-owl-carousel-o/lib/styles/prebuilt-themes/owl.theme.default.min.css",
-              "src/app/@theme/styles/styles.scss"
+              "src/app/@theme/styles/styles.scss",
+              "node_modules/leaflet-timedimension/dist/leaflet.timedimension.control.css"
             ],
             "scripts": [
               "node_modules/pace-js/pace.min.js",
@@ -54,7 +55,8 @@
               "node_modules/tinymce/plugins/table/plugin.min.js",
               "node_modules/echarts/dist/echarts.min.js",
               "node_modules/echarts/dist/extension/bmap.min.js",
-              "node_modules/chart.js/dist/Chart.min.js"
+              "node_modules/chart.js/dist/Chart.min.js",
+              "node_modules/iso8601-js-period/iso8601.js"
             ],
             "allowedCommonJsDependencies": [
               "angular2-chartjs",
diff --git a/package-lock.json b/package-lock.json
index 2b444859..512bbba7 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -11233,6 +11233,11 @@
       "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
       "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA="
     },
+    "iso8601-js-period": {
+      "version": "0.2.1",
+      "resolved": "https://registry.npmjs.org/iso8601-js-period/-/iso8601-js-period-0.2.1.tgz",
+      "integrity": "sha512-iDyz2TQFBd5WhCZjruOwHj01JkQGu7YbVLCVdpA7lCGEcBzE3ffCPAhLh/M8TAp//kCixPpYN4XU54WHCxvD2Q=="
+    },
     "isobject": {
       "version": "2.1.0",
       "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz",
@@ -12276,6 +12281,15 @@
       "resolved": "https://registry.npmjs.org/leaflet/-/leaflet-1.2.0.tgz",
       "integrity": "sha512-Bold8phAE6WcRsuwhofrQ7cOK1REFHaYIkKuj7+TBYK3ONKRpGGIb5oXR5akYotFnrWN0TWKh6Svlhflm3dogg=="
     },
+    "leaflet-timedimension": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/leaflet-timedimension/-/leaflet-timedimension-1.1.1.tgz",
+      "integrity": "sha512-ejXldN94veRsWka1vpC+4rbH+2+3d3ztn2xYx4jcXtjYDrKC/sNnoqCmyH2UEYIy51PI2851aI2k8uGdOEbhlw==",
+      "requires": {
+        "iso8601-js-period": "^0.2.1",
+        "leaflet": "~0.7.4 || ~1"
+      }
+    },
     "less": {
       "version": "3.12.2",
       "resolved": "https://registry.npmjs.org/less/-/less-3.12.2.tgz",
@@ -13714,8 +13728,9 @@
       "dev": true
     },
     "moment": {
-      "version": "2.18.1",
-      "resolved": ""
+      "version": "2.29.1",
+      "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz",
+      "integrity": "sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ=="
     },
     "morgan": {
       "version": "1.10.0",
@@ -23418,7 +23433,8 @@
         },
         "ssri": {
           "version": "6.0.1",
-          "resolved": "",
+          "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.1.tgz",
+          "integrity": "sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA==",
           "dev": true,
           "requires": {
             "figgy-pudding": "^3.5.1"
diff --git a/package.json b/package.json
index f7478844..46ffa936 100644
--- a/package.json
+++ b/package.json
@@ -66,7 +66,9 @@
     "eva-icons": "^1.1.3",
     "intl": "1.2.5",
     "ionicons": "2.0.1",
+    "iso8601-js-period": "^0.2.1",
     "leaflet": "1.2.0",
+    "leaflet-timedimension": "^1.1.1",
     "nebular-icons": "1.1.0",
     "ng2-ckeditor": "^1.2.9",
     "ng2-smart-table": "^1.6.0",
diff --git a/src/app/pages/home/home.component.html b/src/app/pages/home/home.component.html
index 9e13193c..a31eec0a 100644
--- a/src/app/pages/home/home.component.html
+++ b/src/app/pages/home/home.component.html
@@ -1,5 +1,5 @@
 <div [ngSwitch]="pilotName">
-    
+
     <div *ngSwitchCase="'URBANITE'">
         <section class="jumbotron text-center">
             <div class="container">
@@ -9,48 +9,109 @@
                 </p>
             </div>
         </section>
-        
-        <section>
-            <div class="container">
-                <div class="row d-flex justify-content-between align-items-stretch" >
-                    <mat-card class="col-5">
+
+        <div class="row d-flex justify-content-around">
+            <mat-card class="col-3">
+                <mat-card-header>
+                  <mat-card-title>Amsterdam</mat-card-title>
+                  <mat-card-subtitle>Subtitle</mat-card-subtitle>
+                </mat-card-header>
+                <img mat-card-image src="https://material.angular.io/assets/img/examples/shiba2.jpg" alt="Photo of a Shiba Inu">
+                <mat-card-content>
+                  <p>
+                    The Shiba Inu is the smallest of the six original and distinct spitz breeds of dog from Japan.
+                    A small, agile dog that copes very well with mountainous terrain, the Shiba Inu was originally
+                    bred for hunting.
+                  </p>
+                </mat-card-content>
+              </mat-card>
+              <mat-card class="col-3">
+                <mat-card-header>
+                  <mat-card-title>Bilbao</mat-card-title>
+                  <mat-card-subtitle>Dog Breed</mat-card-subtitle>
+                </mat-card-header>
+                <img mat-card-image src="https://material.angular.io/assets/img/examples/shiba2.jpg" alt="Photo of a Shiba Inu">
+                <mat-card-content>
+                  <p>
+                    The Shiba Inu is the smallest of the six original and distinct spitz breeds of dog from Japan.
+                    A small, agile dog that copes very well with mountainous terrain, the Shiba Inu was originally
+                    bred for hunting.
+                  </p>
+                </mat-card-content>
+              </mat-card>
+            </div>
+
+            <div class="row d-flex justify-content-around">
+                <mat-card class="col-3">
+                    <mat-card-header>
+                      <mat-card-title>Helsinki</mat-card-title>
+                      <mat-card-subtitle>Dog Breed</mat-card-subtitle>
+                    </mat-card-header>
+                    <img mat-card-image src="https://material.angular.io/assets/img/examples/shiba2.jpg" alt="Photo of a Shiba Inu">
+                    <mat-card-content>
+                      <p>
+                        The Shiba Inu is the smallest of the six original and distinct spitz breeds of dog from Japan.
+                        A small, agile dog that copes very well with mountainous terrain, the Shiba Inu was originally
+                        bred for hunting.
+                      </p>
+                    </mat-card-content>
+                  </mat-card>
+
+                  <mat-card class="col-3">
+                    <mat-card-header>
+                      <mat-card-title>Messina</mat-card-title>
+                      <mat-card-subtitle>Dog Breed</mat-card-subtitle>
+                    </mat-card-header>
+                    <img mat-card-image src="https://material.angular.io/assets/img/examples/shiba2.jpg" alt="Photo of a Shiba Inu">
+                    <mat-card-content>
+                      <p>
+                        The Shiba Inu is the smallest of the six original and distinct spitz breeds of dog from Japan.
+                        A small, agile dog that copes very well with mountainous terrain, the Shiba Inu was originally
+                        bred for hunting.
+                      </p>
+                    </mat-card-content>
+                  </mat-card>
+                </div>
+
+        <!-- <section> -->
+            <!-- <div class="container"> -->
+                <!-- <div class="row d-flex" >
+                    <mat-card>
                         <mat-card-header>
                             <mat-card-title>What About Urbanite</mat-card-title>
                         </mat-card-header>
                         <mat-card-content class="text-justify">
+                            <p>In recent years, with the population and size of cities increasing exponentially, transportation has become even more important.
+                                The need for more efficient mobility solutions has been met with a variety of new concepts like sharing vehicles, electric scooters
+                                for rent, and even disruptive start-ups like Uber or Cabify, which are causing a stir with previously used models.
+                                However, such new models are putting public administrations in a challenging situation. The EU-funded URBANITE project aims to develop
+                                a solution that collects and analyses data, that combined with AI, can assist public administrations in policy-related decisions
+                                concerning urban transformation caused by these new transportation and business models.
+                                URBANITE focuses also on social aspects, by analyzing stakeholders’ trust in technologies aiding decision-making.</p>
                             <p>
-                                In recent years, with the population and size of cities increasing exponentially, transportation has become even more important. 
-                                The need for more efficient mobility solutions has been met with a variety of new concepts like sharing vehicles, electric scooters 
-                                for rent, and even disruptive start-ups like Uber or Cabify, which are causing a stir with previously used models. 
-                                However, such new models are putting public administrations in a challenging situation. The EU-funded URBANITE project aims to develop 
-                                a solution that collects and analyses data, that combined with AI, can assist public administrations in policy-related decisions 
-                                concerning urban transformation caused by these new transportation and business models. 
-                                URBANITE focuses also on social aspects, by analyzing stakeholders’ trust in technologies aiding decision-making.
-                            </p>
-                            <p>
-                                Cities are facing a revolution in urban mobility. Emerging start-ups are offering innovative mobility solutions to satisfy 
-                                the demand of the growing population, both living or moving into the cities every day. We are moving from the concept of owning 
-                                to sharing a vehicle; from using public transport services to moving around with a hop on/off bike or electric scooter; 
-                                disruptive start-ups (Uber, Cabify) are shaking up traditionally established business models... 
-                                But this innovation is also bringing up unforeseen consequences that public administrations need to manage. 
-                                Electric scooters driven in pedestrian areas are posing safety risks and even pedestrian kills; piles of broken bikes 
-                                are laying around in streets; protests and strikes by taxi drivers; electric charge points need to coexist with the 
-                                growing demand for public parking spaces. It is in this new context that public administrations need means to help them understand 
-                                this new scenario, supporting them in making policy–related decisions and predicting eventualities. 
-                                There is a need of a platform that can harvest, fuse and curate data from heterogeneous sources, that can extract knowledge to help 
-                                in the decision-making processes and simulation of solutions to anticipate behaviours and delimit unforeseen consequences. 
-                                Besides, such intelligent platform can foster cross-departmental collaboration by eradicating internal silos. 
-                                URBANITE will analyse the impact, trust and attitudes of civil servants, citizens and other stakeholders with respect to the 
-                                integration of disruptive technologies such as AI, DSS, big data analytics and predictive algorithms in a data–driven decision-making 
-                                process. To this end, URBANITE will provide recommendations, pathways and toolkits (both ICT-based such as data management platform and 
-                                DSS, and non-ICT such as co-creation activities and a repository of social-related assets) for city managers. Results will be validated 
+                                Cities are facing a revolution in urban mobility. Emerging start-ups are offering innovative mobility solutions to satisfy
+                                the demand of the growing population, both living or moving into the cities every day. We are moving from the concept of owning
+                                to sharing a vehicle; from using public transport services to moving around with a hop on/off bike or electric scooter;
+                                disruptive start-ups (Uber, Cabify) are shaking up traditionally established business models...
+                                But this innovation is also bringing up unforeseen consequences that public administrations need to manage.
+                                Electric scooters driven in pedestrian areas are posing safety risks and even pedestrian kills; piles of broken bikes
+                                are laying around in streets; protests and strikes by taxi drivers; electric charge points need to coexist with the
+                                growing demand for public parking spaces. It is in this new context that public administrations need means to help them understand
+                                this new scenario, supporting them in making policy–related decisions and predicting eventualities.
+                                There is a need of a platform that can harvest, fuse and curate data from heterogeneous sources, that can extract knowledge to help
+                                in the decision-making processes and simulation of solutions to anticipate behaviours and delimit unforeseen consequences.
+                                Besides, such intelligent platform can foster cross-departmental collaboration by eradicating internal silos.
+                                URBANITE will analyse the impact, trust and attitudes of civil servants, citizens and other stakeholders with respect to the
+                                integration of disruptive technologies such as AI, DSS, big data analytics and predictive algorithms in a data–driven decision-making
+                                process. To this end, URBANITE will provide recommendations, pathways and toolkits (both ICT-based such as data management platform and
+                                DSS, and non-ICT such as co-creation activities and a repository of social-related assets) for city managers. Results will be validated
                                 in 4 real use cases: Amsterdam, Bilbao, Helsinki and Messina.
 
                             </p>
                         </mat-card-content>
-                    </mat-card>
-        
-                    <mat-card class="col-6 h-100">
+                    </mat-card> -->
+
+                    <!-- <mat-card class="col-5 h-100">
                         <mat-card-content class="text-center">
                             <owl-carousel-o [options]="customOptions">
                                 <ng-template carouselSlide id="1"><img class="d-block w-100" src="/assets/images/am1.jpg">
@@ -65,28 +126,31 @@
                                 </ng-template>
                             </owl-carousel-o>
                         </mat-card-content>
-                    </mat-card>
-                </div>
-            </div>
-        </section>
+                    </mat-card> -->
+                <!-- </div> -->
+            <!-- </div> -->
+        <!-- </section>
+        <section> -->
+           
+        <!-- </section> -->
     </div>
-    
-    
+
+
     <div *ngSwitchCase="'MESSINA'">
         {{pilotName}}
     </div>
-    
-    
+
+
     <div *ngSwitchCase="'BILBAO'">
         {{pilotName}}
     </div>
-    
-    
+
+
     <div *ngSwitchCase="'HELSINKI'">
         {{pilotName}}
     </div>
-    
-    
+
+
     <div *ngSwitchCase="'AMSTERDAM'">
         {{pilotName}}
     </div>
diff --git a/src/app/pages/home/home.component.scss b/src/app/pages/home/home.component.scss
index e69de29b..515069d5 100644
--- a/src/app/pages/home/home.component.scss
+++ b/src/app/pages/home/home.component.scss
@@ -0,0 +1,3 @@
+mat-card{
+    margin-top: 10px;
+}
\ No newline at end of file
diff --git a/src/app/pages/messina/service/messina-client.service.spec.ts b/src/app/pages/messina/service/messina-client.service.spec.ts
new file mode 100644
index 00000000..601a4dca
--- /dev/null
+++ b/src/app/pages/messina/service/messina-client.service.spec.ts
@@ -0,0 +1,16 @@
+import { TestBed } from '@angular/core/testing';
+
+import { MessinaClientService } from './messina-client.service';
+
+describe('MessinaClientService', () => {
+  let service: MessinaClientService;
+
+  beforeEach(() => {
+    TestBed.configureTestingModule({});
+    service = TestBed.inject(MessinaClientService);
+  });
+
+  it('should be created', () => {
+    expect(service).toBeTruthy();
+  });
+});
diff --git a/src/app/pages/messina/service/messina-client.service.ts b/src/app/pages/messina/service/messina-client.service.ts
new file mode 100644
index 00000000..17127b9d
--- /dev/null
+++ b/src/app/pages/messina/service/messina-client.service.ts
@@ -0,0 +1,39 @@
+import { HttpClient } from '@angular/common/http';
+import { Injectable } from '@angular/core';
+import { ConfigService } from '@ngx-config/core';
+import { Observable, of } from 'rxjs';
+
+import messina from '../../../../assets/messina/Traffic_GroupByDatetime.json';
+import poi from '../../../../assets/messina/POIs_geojson.json';
+import stop from '../../../../assets/messina/stops_geojson.json';
+
+@Injectable({
+  providedIn: 'root'
+})
+export class MessinaClientService {
+
+  private apiURL: any;
+
+  constructor(configService: ConfigService,private http:HttpClient) {
+    this.apiURL = configService.getSettings("messina_api_base_url");
+  }
+
+  getTrafficByDateTime(startDateTime:string,endDateTime:string,page:number=0,pageSize?:number): Observable<any> {
+    //groupBy:string='datetime'
+    //return this.http.get<any>(`${this.apiURL}/Idra/api/v1/administration/version`);
+    return of(messina);
+  }
+
+  getPOI(): Observable<any> {
+    //groupBy:string='datetime'
+    //return this.http.get<any>(`${this.apiURL}/Idra/api/v1/administration/version`);
+    return of(poi);
+  }
+
+  getStops(): Observable<any> {
+    //groupBy:string='datetime'
+    //return this.http.get<any>(`${this.apiURL}/Idra/api/v1/administration/version`);
+    return of(stop);
+  }
+
+}
diff --git a/src/app/pages/messina/traffic/traffic.component.ts b/src/app/pages/messina/traffic/traffic.component.ts
index 06768134..bbfed444 100644
--- a/src/app/pages/messina/traffic/traffic.component.ts
+++ b/src/app/pages/messina/traffic/traffic.component.ts
@@ -1,9 +1,9 @@
-import { Component, OnInit } from '@angular/core';
+import { Component, OnInit, Output } from '@angular/core';
+import { color } from 'd3-color';
 
 import * as L from 'leaflet';
-import AMTram2020 from '../../../../assets/map/am_tram_2020.json';
-import AMTram2020_Stops from '../../../../assets/map/am_tramstop_2020.json';
-
+import 'leaflet-timedimension';
+import { MessinaClientService } from '../service/messina-client.service';
 
 @Component({
   selector: 'ngx-leaflet',
@@ -13,10 +13,12 @@ import AMTram2020_Stops from '../../../../assets/map/am_tramstop_2020.json';
     <nb-card class="col-12">
       <nb-card-header>Street Traffic</nb-card-header>
       <nb-card-body>
-        <div leaflet id="map2" #map2 
-        [leafletOptions]="options1" 
-        [leafletLayersControl]="layersControl"
-        [leafletLayers]="layers2"></div>
+      <div class="map"
+     leaflet
+     [leafletOptions]="options"
+     [leafletLayers]="layers"
+     [leafletFitBounds]="fitbounds"
+     ></div>
         <div class="mt-1">
           <p> Real-time data with traffic information on <b>Messina</b>. </p>
           <p> Input Filters (Limit N-days on UI): <i>StartDateTime</i>, <i>EndDateTime</i></p>
@@ -26,96 +28,171 @@ import AMTram2020_Stops from '../../../../assets/map/am_tramstop_2020.json';
 </div>
   `,
 })
-export class TrafficComponent {
+export class TrafficComponent implements OnInit {
+  
+  constructor(private messinaClient:MessinaClientService){}
 
-  public map1: L.Map;
-  public map2: L.Map;
+  geojson:any;
+  geojsonH:any;
+  fitbounds=null;
+  instant=null;
 
+  ngOnInit(): void {
 
-  icon = new L.Icon({
-    iconSize: [25, 41],
-    iconAnchor: [13, 41],
-    iconUrl: 'assets/img/markers/marker-icon.png',
-    iconRetinaUrl: 'assets/img/markers/marker-icon-2x.png',
-    shadowUrl: 'assets/img/markers/marker-shadow.png'
-  });
+    this.geojson = {
+      "type":"FeatureCollection",
+      "features":[]
+    }
 
-  options = {
-    layers: [
-      L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { maxZoom: 18, attribution: '...' }),
-    ],
-    zoom: 9,
-    center: L.latLng({ lat: 52.372664783594274, lng: 4.8950958251953125 }),
-  };
+    this.geojsonH = {
+      "type":"FeatureCollection",
+      "features":[{
+        "type": "Feature",
+        "properties": {
+          "times":[]
+        },
+        "geometry": {
+          "type": "LineString",
+          "coordinates": []
+        }
+      }]
+    }
 
-  layersControl = {
-    overlays: {
-      'Messina Tram - 2020': this.getLayer('Tram 2020',<any>AMTram2020),
-      'Messina Tram Stops - 2020': this.getLayer('Stop Tram 2020',<any>AMTram2020_Stops),
+    //start & end DateTime
+    this.messinaClient.getTrafficByDateTime(null,null).subscribe(res => {
+      this.trafficMapConverter(res);
+      this.displayStops();
+      this.displayPOIs();
+    })
+  }
+
+  private displayStops() {
+    this.messinaClient.getStops().subscribe(res => {
+      let stopLayer = L.geoJSON(res['results'], {
+        pointToLayer: (feature, latlng) => {
+          let icon= new L.Icon({
+            iconSize: [24,36],
+            iconAnchor: [12,36],
+            iconUrl: '/assets/img/markers/marker-icon.png',
+            shadowUrl: '/assets/img/markers/marker-shadow.png'
+          })
+          return L.marker(latlng,{icon:icon})
+        }
+      });
+      this.layers.push(stopLayer);
+    });
+  }
+
+  private displayPOIs() {
+    this.messinaClient.getPOI().subscribe(res => {
+      let stopLayer = L.geoJSON(res['results'], {
+        pointToLayer: (feature, latlng) => {
+          let icon= new L.Icon({
+            iconSize: [24,36],
+            iconAnchor: [12,36],
+            iconUrl: '/assets/img/markers/marker-icon.png',
+            shadowUrl: '/assets/img/markers/marker-shadow.png'
+          })
+          return L.marker(latlng,{icon:icon})
+        }
+      });
+      this.layers.push(stopLayer);
+    });
+  }
+
+  private trafficMapConverter(messina) {
+    for (let r in messina['roads']) {
+      let feature = messina['roads'][r].roadShape;
+      feature.properties['roadKey'] = r;
+      this.geojson.features.push(feature);
     }
+
+    for (let result of messina['results']) {
+      let millis = new Date(result['datetime']).getTime();
+      if (this.geojsonH.features[0].properties.times.indexOf(millis) < 0) {
+        this.geojsonH.features[0].properties.times.push(millis);
+        this.geojsonH.features[0].geometry.coordinates.push([15.529174804687498, 38.20365531807149]);
+      }
+      for (let d of result['data']) {
+        for (let f of this.geojson.features) {
+          if (d.roadKey == f.properties['roadKey']) {
+            f.properties[millis] = d['JF'];
+          }
+        }
+      }
+    }
+
+    this.addGeoJSONLayers(this.geojson,this.geojsonH);
   }
 
-  options1 = {
+  options = {
     layers: [
-      L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { maxZoom: 18, attribution: '...' }),
+      L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', 
+      { 
+        maxZoom: 15, 
+        attribution: 'Powered by <a href="https://www.geoapify.com/" target="_blank">Geoapify</a> | © OpenStreetMap <a href="https://www.openstreetmap.org/copyright" target="_blank">contributors</a>',
+        id: 'osm-bright'
+       })
     ],
-    zoom: 9,
-    center: L.latLng({ lat: 52.372664783594274, lng: 4.8950958251953125 }),
+    zoom: 5,
+    center: L.latLng(41.983994270935625, 12.436523437499998),
+    timeDimension: true,
+    timeDimensionControl: true,
+    timeDimensionControlOptions: {
+      timeSliderDragUpdate: true,
+      loopButton: true,
+      autoPlay: true,
+      playerOptions: {
+          transitionTime: 1000,
+          loop: true
+      }
+  }
   };
 
-  layer = L.marker([52.372664783594274, 4.8950958251953125], {
-    icon: L.icon({
-      iconSize: [25, 41],
-      iconAnchor: [13, 41],
-      iconUrl: 'assets/img/markers/marker-icon.png',
-      iconRetinaUrl: 'assets/img/markers/marker-icon-2x.png',
-      shadowUrl: 'assets/img/markers/marker-shadow.png'
-    })
-  }).bindPopup("Messina");
-
-  
-  layer2 = L.marker([52.372664783594274, 4.8950958251953125], {
-    icon: L.icon({
-      iconSize: [25, 41],
-      iconAnchor: [13, 41],
-      iconUrl: 'assets/img/markers/marker-icon.png',
-      iconRetinaUrl: 'assets/img/markers/marker-icon-2x.png',
-      shadowUrl: 'assets/img/markers/marker-shadow.png'
+  layers = [];
+
+  addGeoJSONLayers(dataGeojson,hiddenGeojson) {
+    let geojsonLayer = L.geoJSON(dataGeojson,{
+      style:(feature)=>{
+        let v=feature.properties[this.instant];
+        let color='green';
+        if(v>=2.5 && v<5){
+          color='yellow'
+        }else if(v>=5 && v<7.5){
+          color='orange'
+        }else if(v>=7.5){
+          color='red';
+        }
+        return {color:color};
+      }
     })
-  }).bindPopup("Messina");
-
-
-  layers = [this.layer];
-  layers2 = [this.layer2];
-
+    
+    this.layers.push(geojsonLayer)
+    this.fitbounds = geojsonLayer.getBounds()
+
+    let hiddenLayer = L.timeDimension.layer.geoJson(L.geoJSON(hiddenGeojson,{
+      pointToLayer: (feature, latlng) => {
+        return L.circleMarker(latlng, {
+          radius: 10.0001,
+          fillColor: "#ff7800",
+          color: "#000",
+          weight: 0,
+          opacity: 0,
+          fillOpacity: 0.0001
+        });
+      }
+    }), {
+        updateTimeDimension: true,
+        duration: 'PT5M',
+        updateTimeDimensionMode: 'replace',
+        addlastPoint: true
+      }).on('timeload',(event)=>{
+        this.instant = event.time;
+        geojsonLayer.eachLayer(l=> geojsonLayer.resetStyle(l));
+      })
+    
+      this.layers.push(hiddenLayer);
+}
 
-  public getLayer(title,l) {
-  
-      let layer = L.geoJSON(l,
-        {
-          pointToLayer: function (feature, latlng) {
-
-            let icon = L.icon({
-              iconSize: [25, 41],
-              iconAnchor: [13, 41],
-              iconUrl: 'assets/img/markers/marker-icon.png',
-              iconRetinaUrl: 'assets/img/markers/marker-icon-2x.png',
-              shadowUrl: 'assets/img/markers/marker-shadow.png'
-            });
-            let zIndexOffset = 100;
-            return L.marker(latlng, { icon: icon, zIndexOffset: zIndexOffset, riseOnHover: true, riseOffset: 500 });
-          },
-          onEachFeature: (feature, layer) => {
-            let text="";
-            for(let p in feature.properties){
-              text+=`${p}: ${feature.properties[p]}\n`;
-            }
-            layer.bindPopup(text);
-          }
-        })
-        .on('popupclose', ($event) => {
-        })
-        return layer;
-  }
   
 }
diff --git a/src/assets/config.json b/src/assets/config.json
index 71e7e42a..4806b2e5 100644
--- a/src/assets/config.json
+++ b/src/assets/config.json
@@ -25,5 +25,6 @@
     ],
     "enable_demo_pages":false,
     "pilots":["URBANITE","AMSTERDAM","BILBAO","HELSINKI","MESSINA"],
-    "default_pilot":"URBANITE"
+    "default_pilot":"URBANITE",
+    "messina_api_base_url":""
 }
\ No newline at end of file
diff --git a/src/assets/messina/POIs.json b/src/assets/messina/POIs.json
new file mode 100644
index 00000000..3ef38cfa
--- /dev/null
+++ b/src/assets/messina/POIs.json
@@ -0,0 +1,27 @@
+{
+	"results": [
+		{
+			"name": "Zanghi Dr. Letterio",
+			"category": "Medical_Facility",
+			"type": "Pharmacy",
+			"location": {
+				"type": "Point",
+				"coordinates": [15.54983932, 38.18324646]
+			}
+		},
+		{
+			"name": "Zuiki",
+			"category": "Retail_Services",
+			"type": "Clothing Store",
+			"location": {
+				"type": "Point",
+				"coordinates": [15.55326244, 38.18506583]
+			}
+		}
+	],
+	"total": 2,
+	"count": 2,
+	"pageSize": 10,
+	"page": 1,
+	"totalPages": 1
+}
diff --git a/src/assets/messina/POIs_geojson.json b/src/assets/messina/POIs_geojson.json
new file mode 100644
index 00000000..56545b23
--- /dev/null
+++ b/src/assets/messina/POIs_geojson.json
@@ -0,0 +1,36 @@
+{
+	"results": {
+		"type": "FeatureCollection",
+  		"features": [
+  			{
+			  "type": "Feature",
+			  "properties": {
+				  "name": "Zanghi Dr. Letterio",
+				"category": "Medical_Facility",
+				"type": "Pharmacy"
+			  },
+			  "geometry": {
+				"type": "Point",
+				"coordinates": [15.54983932, 38.18324646]
+			  }
+			},
+			{
+			  "type": "Feature",
+			  "properties": {
+			  	"name": "Zuiki",
+				"category": "Retail_Services",
+				"type": "Clothing Store"
+			  },
+			  "geometry": {
+				"type": "Point",
+				"coordinates": [15.55326244, 38.18506583]
+			  }
+			}
+  		]
+	},
+	"total": 2,
+	"count": 2,
+	"pageSize": 10,
+	"page": 1,
+	"totalPages": 1
+}
diff --git a/src/assets/messina/Traffic_GroupByDatetime.json b/src/assets/messina/Traffic_GroupByDatetime.json
new file mode 100644
index 00000000..ab71492e
--- /dev/null
+++ b/src/assets/messina/Traffic_GroupByDatetime.json
@@ -0,0 +1,238 @@
+{
+	"roads": {
+		"A20_Messina-C./Allacciamento-Raccordo-A20-P.To-Messina+": {
+			"path": "A20",
+			"road": "Messina C./Allacciamento Raccordo A20 P.To Messina",
+			"QD": "+",
+			"len": 2.04652,
+			"roadShape": {
+				"type": "Feature",
+				"properties": {},
+				"geometry": {
+					"type": "LineString",
+					"coordinates": [
+          [
+            15.536041259765625,
+            38.199338565983844
+          ],
+          [
+            15.475616455078125,
+            38.08377048360514
+          ]
+        ]
+				}
+			}
+		},
+		"Orientale-Sicula_Messina+": {
+			"path": "Orientale Sicula",
+			"road": "Messina",
+			"QD": "+",
+			"len": 2.04652,
+			"roadShape": {
+				"type": "Feature",
+				"properties": {
+				},
+				"geometry": {
+					"type": "LineString",
+					"coordinates": [
+          [
+            15.5126953125,
+            38.201496974020806
+          ],
+          [
+            15.46600341796875,
+            38.12591462924157
+          ],
+          [
+            15.393218994140625,
+            38.10754709314396
+          ],
+          [
+            15.408325195312498,
+            38.06539235133249
+          ],
+          [
+            15.389099121093752,
+            38.0091482264894
+          ]
+        ]
+				}
+			}
+		}
+	},
+	"results": [
+		{
+			"datetime": "2021-06-06T21:23:09.000+00:00",
+			"data": [
+				{
+					"roadKey": "A20_Messina-C./Allacciamento-Raccordo-A20-P.To-Messina+",
+					"JF": 0.07951,
+					"SP": 79.57,
+					"SU": 79.57,
+					"FF": 80,
+					"CN": 0.89
+				},
+				{
+					"roadKey": "Orientale-Sicula_Messina+",
+					"JF": 1.07951,
+					"SP": 89.57,
+					"SU": 79.57,
+					"FF": 84,
+					"CN": 0.89
+				}
+			]
+		},
+		{
+			"datetime": "2021-06-06T21:28:09.000+00:00",
+			"data": [
+				{
+					"roadKey": "A20_Messina-C./Allacciamento-Raccordo-A20-P.To-Messina+",
+					"JF": 0,
+					"SP": 80,
+					"SU": 103.47,
+					"FF": 80,
+					"CN": 0.94
+				},
+				{
+					"roadKey": "Orientale-Sicula_Messina+",
+					"JF": 1.01,
+					"SP": 81,
+					"SU": 107.47,
+					"FF": 80,
+					"CN": 0.94
+				}
+			]
+		},
+		{
+			"datetime": "2021-06-06T21:33:09.000+00:00",
+			"data": [
+				{
+					"roadKey": "A20_Messina-C./Allacciamento-Raccordo-A20-P.To-Messina+",
+					"JF": 8.07951,
+					"SP": 79.57,
+					"SU": 79.57,
+					"FF": 80,
+					"CN": 0.89
+				},
+				{
+					"roadKey": "Orientale-Sicula_Messina+",
+					"JF": 3.07951,
+					"SP": 89.57,
+					"SU": 79.57,
+					"FF": 84,
+					"CN": 0.89
+				}
+			]
+		},
+		{
+			"datetime": "2021-06-06T21:38:09.000+00:00",
+			"data": [
+				{
+					"roadKey": "A20_Messina-C./Allacciamento-Raccordo-A20-P.To-Messina+",
+					"JF": 5.6,
+					"SP": 80,
+					"SU": 103.47,
+					"FF": 80,
+					"CN": 0.94
+				},
+				{
+					"roadKey": "Orientale-Sicula_Messina+",
+					"JF": 3.01,
+					"SP": 81,
+					"SU": 107.47,
+					"FF": 80,
+					"CN": 0.94
+				}
+			]
+		},
+		{
+			"datetime": "2021-06-06T21:43:09.000+00:00",
+			"data": [
+				{
+					"roadKey": "A20_Messina-C./Allacciamento-Raccordo-A20-P.To-Messina+",
+					"JF": 6.07951,
+					"SP": 79.57,
+					"SU": 79.57,
+					"FF": 80,
+					"CN": 0.89
+				},
+				{
+					"roadKey": "Orientale-Sicula_Messina+",
+					"JF": 1.07951,
+					"SP": 89.57,
+					"SU": 79.57,
+					"FF": 84,
+					"CN": 0.89
+				}
+			]
+		},
+		{
+			"datetime": "2021-06-06T21:48:09.000+00:00",
+			"data": [
+				{
+					"roadKey": "A20_Messina-C./Allacciamento-Raccordo-A20-P.To-Messina+",
+					"JF": 0,
+					"SP": 80,
+					"SU": 103.47,
+					"FF": 80,
+					"CN": 0.94
+				},
+				{
+					"roadKey": "Orientale-Sicula_Messina+",
+					"JF": 1.01,
+					"SP": 81,
+					"SU": 107.47,
+					"FF": 80,
+					"CN": 0.94
+				}
+			]
+		},
+		{
+			"datetime": "2021-06-06T21:53:09.000+00:00",
+			"data": [
+				{
+					"roadKey": "A20_Messina-C./Allacciamento-Raccordo-A20-P.To-Messina+",
+					"JF": 3.07951,
+					"SP": 79.57,
+					"SU": 79.57,
+					"FF": 80,
+					"CN": 0.89
+				},
+				{
+					"roadKey": "Orientale-Sicula_Messina+",
+					"JF": 6.07951,
+					"SP": 89.57,
+					"SU": 79.57,
+					"FF": 84,
+					"CN": 0.89
+				}
+			]
+		},
+		{
+			"datetime": "2021-06-06T21:58:09.000+00:00",
+			"data": [
+				{
+					"roadKey": "A20_Messina-C./Allacciamento-Raccordo-A20-P.To-Messina+",
+					"JF": 0,
+					"SP": 80,
+					"SU": 103.47,
+					"FF": 80,
+					"CN": 0.94
+				},
+				{
+					"roadKey": "Orientale-Sicula_Messina+",
+					"JF": 1.01,
+					"SP": 81,
+					"SU": 107.47,
+					"FF": 80,
+					"CN": 0.94
+				}
+			]
+		}
+	],
+	"total": 6,
+	"count": 4,
+	"pageSize": 4,
+	"page": 1,
+	"totalPages": 2
+}
diff --git a/src/assets/messina/Traffic_GroupByRoad.json b/src/assets/messina/Traffic_GroupByRoad.json
new file mode 100644
index 00000000..027a881c
--- /dev/null
+++ b/src/assets/messina/Traffic_GroupByRoad.json
@@ -0,0 +1,81 @@
+{
+	"results": {
+		"A20_Messina-C./Allacciamento-Raccordo-A20-P.To-Messina+": {
+			"data": [
+				{
+					"datetime": "2021-06-06T21:23:09.000+00:00",
+					"JF": 0.07951,
+					"SP": 79.57,
+					"SU": 79.57,
+					"FF": 80,
+					"CN": 0.89
+				},
+				{
+					"datetime": "2021-06-06T21:28:09.000+00:00",
+					"JF": 0,
+					"SP": 80,
+					"SU": 103.47,
+					"FF": 80,
+					"CN": 0.94
+				}
+			],
+			"count": 2,
+			"path": "A20",
+			"road": "Messina C./Allacciamento Raccordo A20 P.To Messina",
+			"QD": "+",
+			"len": 2.04652,
+			"roadShape": {
+				"type": "Feature",
+				"properties": {},
+				"geometry": {
+					"type": "LineString",
+					"coordinates": [
+						[15.54036, 38.19869],
+						[15.54018, 38.19861]
+					]
+				}
+			}
+		},
+		"Orientale-Sicula_Messina+": {
+			"data": [
+				{
+					"datetime": "2021-06-06T21:23:09.000+00:00",
+					"JF": 1.07951,
+					"SP": 89.57,
+					"SU": 79.57,
+					"FF": 84,
+					"CN": 0.89
+				},
+				{
+					"datetime": "2021-06-06T21:28:09.000+00:00",
+					"JF": 1.01,
+					"SP": 81,
+					"SU": 107.47,
+					"FF": 80,
+					"CN": 0.94
+				}
+			],
+			"count": 2,
+			"path": "Orientale Sicula",
+			"road": "Messina",
+			"QD": "+",
+			"len": 2.04652,
+			"roadShape": {
+				"type": "Feature",
+				"properties": {},
+				"geometry": {
+					"type": "LineString",
+					"coordinates": [
+						[15.53685, 38.1605],
+						[15.53698, 38.16061]
+					]
+				}
+			}
+		}
+	},
+	"total": 6,
+	"count": 4,
+	"pageSize": 4,
+	"page": 1,
+	"totalPages": 2
+}
diff --git a/src/assets/messina/stops.json b/src/assets/messina/stops.json
new file mode 100644
index 00000000..ea7230dc
--- /dev/null
+++ b/src/assets/messina/stops.json
@@ -0,0 +1,32 @@
+{
+	"results": [
+		{
+            "stop_name": "Via La Farina, ATM",
+            "stop_times": [
+            	"04:05:00",
+            	"05:10:00"
+            ],
+			"location": {
+				"type": "Point",
+				"coordinates": [15.5445, 38.1689]
+			}
+		},
+		{
+            "stop_name": "P.zza della Repubblica",
+		            "stop_times": [
+		            	"10:50:00",
+		            	"14:10:00",
+		            	"20:30:00"
+		            ],
+			"location": {
+				"type": "Point",
+				"coordinates": [15.5603, 38.1862]
+			}
+		}
+	],
+	"total": 2,
+	"count": 2,
+	"pageSize": 10,
+	"page": 1,
+	"totalPages": 1
+}
diff --git a/src/assets/messina/stops_geojson.json b/src/assets/messina/stops_geojson.json
new file mode 100644
index 00000000..e3d78018
--- /dev/null
+++ b/src/assets/messina/stops_geojson.json
@@ -0,0 +1,47 @@
+{
+	"results": {
+		"type": "FeatureCollection",
+		"features": [
+		    {
+		        "type": "Feature",
+		        "properties": {
+		            "stop_name": "Via La Farina, ATM",
+		            "stop_times": [
+		            	"04:05:00",
+		            	"05:10:00"
+		            ]
+		        },
+		        "geometry": {
+		            "type": "Point",
+		            "coordinates": [
+		                15.5445,
+		                38.1689
+		            ]
+		        }
+		    },
+		    {
+		        "type": "Feature",
+		        "properties": {
+		            "stop_name": "P.zza della Repubblica",
+		            "stop_times": [
+		            	"10:50:00",
+		            	"14:10:00",
+		            	"20:30:00"
+		            ]
+		        },
+		        "geometry": {
+		            "type": "Point",
+		            "coordinates": [
+		                15.5603,
+		                38.1862
+		            ]
+		        }
+		    }
+		]
+	},
+	"total": 2,
+	"count": 2,
+	"pageSize": 10,
+	"page": 1,
+	"totalPages": 1
+}
diff --git a/src/typings.d.ts b/src/typings.d.ts
index 03eef4f3..ae7cf8d5 100644
--- a/src/typings.d.ts
+++ b/src/typings.d.ts
@@ -13,3 +13,8 @@ interface NodeModule {
 declare var tinymce: any;
 
 declare var echarts: any;
+
+import * as L from 'leaflet';
+declare module 'leaflet' {
+   var timeDimension: any;
+}
\ No newline at end of file
-- 
GitLab