diff --git a/src/app/model/data-storage-entity.model.spec.ts b/src/app/model/data-storage-entity.model.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..3995ffb5a5f3e9b74c39bf8cf0ed39eff0411181 --- /dev/null +++ b/src/app/model/data-storage-entity.model.spec.ts @@ -0,0 +1,7 @@ +import { DataStorageEntity } from './data-storage-entity.model'; + +describe('DataStorageEntity', () => { + it('should create an instance', () => { + expect(new DataStorageEntity()).toBeTruthy(); + }); +}); diff --git a/src/app/model/data-storage-entity.model.ts b/src/app/model/data-storage-entity.model.ts new file mode 100644 index 0000000000000000000000000000000000000000..d6e2a4d965919cf17fb8b7468fd20a621afca773 --- /dev/null +++ b/src/app/model/data-storage-entity.model.ts @@ -0,0 +1,12 @@ +export class DataStorageEntity { + constructor( + public description?: string, + public name?: string, + public id?: string, + public type?: string, + public map?: { + features: [], + type: string + } + ) {} +} diff --git a/src/app/model/enumeration/subtype.model.ts b/src/app/model/enumeration/subtype.model.ts new file mode 100644 index 0000000000000000000000000000000000000000..06861ae6eaf893a48a5d18005e0db7d4501f46f3 --- /dev/null +++ b/src/app/model/enumeration/subtype.model.ts @@ -0,0 +1,17 @@ +export enum Subtype { + Layer = 'Layer', + HeatLayer = 'HeatLayer', +} + +export namespace Subtype { + export function values() { + return Object.keys(Subtype) + .filter((type) => isNaN(<any>type) && type !== 'values') + .map((x) => { + return { + enumVal: x, + value: x.toLowerCase(), + }; + }); + } +} \ No newline at end of file diff --git a/src/app/pages/dashboard-management/dashboard-info/dashboard-info.component.ts b/src/app/pages/dashboard-management/dashboard-info/dashboard-info.component.ts index 8192fbe8959c24a0750529ae9ed2c9a32cf463d8..897a0660a5a05514e469b7f7d8d84733aa5ae873 100644 --- a/src/app/pages/dashboard-management/dashboard-info/dashboard-info.component.ts +++ b/src/app/pages/dashboard-management/dashboard-info/dashboard-info.component.ts @@ -37,10 +37,12 @@ export class DashboardInfoComponent implements OnInit { } } saveDashboard(name, description, note){ + console.log("here first"); this.dashboardPage.name = name; this.dashboardPage.description = description; this.dashboardPage.note = note; - this.dashboardPage.content = JSON.stringify(this.items); + //this.dashboardPage.content = this; + console.log(JSON.stringify(this.items)); this.dashboardPageService.updatePageById(this.dashboardPage).subscribe((res) => { // console.log('## Saved Dashboard with id:' + this.dashboardPage.id); this.toastrService.success(this.translateService.instant('dashboardPage.updated'), this.translateService.instant('general.success')); diff --git a/src/app/pages/dashboard-management/services/datastorage.service.ts b/src/app/pages/dashboard-management/services/datastorage.service.ts index 40f8ff2893bd05e018a136702f62e4deab0d0be7..0e5e88c0c8b1026eba3f720f896fa302d7461895 100644 --- a/src/app/pages/dashboard-management/services/datastorage.service.ts +++ b/src/app/pages/dashboard-management/services/datastorage.service.ts @@ -3,6 +3,7 @@ import { HttpClient } from '@angular/common/http'; import { Injectable } from '@angular/core'; import { ConfigService } from '@ngx-config/core'; import { Observable } from 'rxjs'; +import { map } from "rxjs/operators"; import { DataStorageLayer } from '../../map-layers/map/map.component'; @Injectable({ @@ -20,9 +21,9 @@ export class DatastorageService { getMapLayers(id:string = undefined): Observable<any> { if (id !== undefined){ - return this.http.get<any>(`${this.apiURL}/getTData/mapLayer/${this.city}/${id}`); + return this.http.get<any>(`https://${this.city}.urbanite.esilab.org/data/getTData/mapLayer/${this.city}/${id}`); } else{ - return this.http.get<any>(`${this.apiURL}/getTData/mapLayer/${this.city}`); + return this.http.get<any>(`https://${this.city}.urbanite.esilab.org/data/getTData/mapLayer/${this.city}`); } } diff --git a/src/app/pages/map-layers/map/map-modal/map-modal.component.html b/src/app/pages/map-layers/map/map-modal/map-modal.component.html index 943b3aa88481cede1b13e6311d5d56535508928a..cf93f307e0b985b731d379cfd0b6a19f8f90cbcb 100644 --- a/src/app/pages/map-layers/map/map-modal/map-modal.component.html +++ b/src/app/pages/map-layers/map/map-modal/map-modal.component.html @@ -1,8 +1,8 @@ -<nb-card size="small"> +<nb-card size="tiny"> <nb-card-header> {{ layer}} </nb-card-header> <nb-card-body> - <p>{{ description }}</p> + <p class="text">{{ description }}</p> </nb-card-body> </nb-card> \ No newline at end of file diff --git a/src/app/pages/map-layers/map/map-modal/map-modal.component.scss b/src/app/pages/map-layers/map/map-modal/map-modal.component.scss index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..111bee1da72cf1841d1b26d2006ffaf1fd08a097 100644 --- a/src/app/pages/map-layers/map/map-modal/map-modal.component.scss +++ b/src/app/pages/map-layers/map/map-modal/map-modal.component.scss @@ -0,0 +1,5 @@ +nb-card-body { + max-width: 450px; + height: auto; + max-height: auto; +} \ No newline at end of file diff --git a/src/app/pages/map-layers/map/map.component.ts b/src/app/pages/map-layers/map/map.component.ts index 137431af35153432d989c19fb8e467585a6be067..7d174c44e4a92bd07cf1693bf9557e937348abd8 100644 --- a/src/app/pages/map-layers/map/map.component.ts +++ b/src/app/pages/map-layers/map/map.component.ts @@ -28,15 +28,22 @@ import { TranslateService } from '@ngx-translate/core'; import { DashboardGuideComponent } from '../../dashboard-management/dashboard-guide/dashboard-guide.component'; import { NbDialogService } from '@nebular/theme'; import { MapModalComponent } from './map-modal/map-modal.component'; +import { DataStorageEntity } from '../../../model/data-storage-entity.model'; +import { Subtype } from '../../../model/enumeration/subtype.model'; export interface DataStorageLayer { id: string; name: string; - description: String; + description: string; alternateName: string; type: string; + subtype: Subtype; map: L.GeoJSON; geometry: L.GeoJSON; + properties?: { + name: string; + alternateName: string, + } } export interface FeatureProperties { @@ -51,18 +58,18 @@ export interface FeatureProperties { }) export class MapComponent implements OnInit { constructor( - public dialogService: NbDialogService, + public dialogService: NbDialogService, private dashboardPageService: DashboardPageCrudService, - private configService: ConfigService, - private dataStorageService: DatastorageService, - private translateService: TranslateService, + private configService: ConfigService, + private dataStorageService: DatastorageService, + private translateService: TranslateService, private messinaClientService: MessinaClientService, private modalService: NbDialogService) { - this.fillGeojesonlayer(); + //this.fillGeojesonlayer(); } public map: L.Map; - + public legend = new (L.Control.extend({ options: { position: 'bottomright' } })); @@ -85,12 +92,11 @@ export class MapComponent implements OnInit { pilot: string; layersByPilot: { [key: string]: string[] } = { - MESSINA: ["Point of Interests", "ATM Stops", "Messina - Dinnamare", "Messina - Centro", "Messina - Litoranea", "Cameras", - "Messina Incidenti 2018", "Messina Incidenti 2019", "Messina Incidenti 2020"], + MESSINA: [], BILBAO: [], AMSTERDAM: [], - HELSINKI: ["Helsinki Bike Stations", "Helsinki Terminalit", "Helsinki Cyclist"], - URBANITE: ["Bilbao Air Quality", "Bilbao Sound", "Point of Interests", "ATM Stops", "Messina - Dinnamare", "Messina - Centro", "Messina - Litoranea", "Cameras"], + HELSINKI: [], + URBANITE: [], } coordinatesByPilot: { [key: string]: L.LatLngExpression } = { @@ -101,129 +107,39 @@ export class MapComponent implements OnInit { URBANITE: [60.1695200, 24.9354500], } - geojsonLayerContent: { [key: string]: L.GeoJSON } = { - "Point of Interests": <L.GeoJSON>this.getLayer("Point of Interests", <any>Messina_POIs['results']['features']), - "ATM Stops": <L.GeoJSON>this.getLayer("ATM Stops", <any>Messina_ATM_Stops['results']['features']), - "Cameras": <L.GeoJSON>this.getLayer("Cameras", <any>Messina_Cameras['results']['features']), - //"Messina - Dinnamare": <any>this.messinaClientService.getCyclingPaths(), FUTURE IMPLEMENTATION - "Messina - Dinnamare": <L.GeoJSON>this.getLayer("Messina - Dinnamare", <any>Messina_cycling_path[0].location), - "Messina - Centro": <L.GeoJSON>this.getLayer("Messina - Centro", <any>Messina_cycling_path[1].location), - "Messina - Litoranea": <L.GeoJSON>this.getLayer("Messina - Litoranea", <any>Messina_cycling_path[2].location), - - "Messina Incidenti 2018": <L.GeoJSON>this.getLayer("Messina Incidenti 2018", <any>Messina_Incidenti_2018['features']), - "Messina Incidenti 2019": <L.GeoJSON>this.getLayer("Messina Incidenti 2019", <any>Messina_Incidenti_2019['features']), - "Messina Incidenti 2020": <L.GeoJSON>this.getLayer("Messina Incidenti 2020", <any>Messina_Incidenti_2020['features']), - "Helsinki Bike Stations": <L.GeoJSON>this.getLayer("Helsinki Bike Stations", <any>Helsinki_Bike[0].map), - "Helsinki Terminalit": <L.GeoJSON>this.getLayer("Helsinki Bike Stations", <any>Helsinki_Terminalit[0].map), - "Helsinki Cyclist": <L.GeoJSON>this.getLayer("Helsinki Bike Stations", <any>Helsinki_Cyclist[0].map), - }; - - - fillGeojesonlayer() { - let arrays: Array<DataStorageLayer> = <any>Amsterdam_bike; - //console.log(arrays); - arrays.forEach(layer => { - //console.log(layer); - this.geojsonLayerContent[layer.name] = <L.GeoJSON>this.getLayer(layer.name, layer.map); - // console.log(layer.name); - this.layersByPilot['AMSTERDAM'] = this.layersByPilot['AMSTERDAM'].concat(layer.name); - }); - - this.geojsonLayerContent["Messina Districts"] = <L.GeoJSON>this.getLayer("Messina Districts", <any>Messina_district); - this.layersByPilot['MESSINA'] = this.layersByPilot['MESSINA'].concat("Messina Districts"); - - - let level: DataStorageLayer; - let arrayBilbao: Array<DataStorageLayer> = <any>Bilbao_layers; - //console.log(arrayBilbao); - arrayBilbao.forEach(layer => { - //console.log(layer); - this.geojsonLayerContent[layer.name] = <L.GeoJSON>this.getLayer(layer.name, layer.map); - // console.log(layer.name); - this.layersByPilot['BILBAO'] = this.layersByPilot['BILBAO'].concat(layer.name); - }); - - // arrayBilbao.forEach(layer => { - // //console.log(layer.map['features']); - // level = layer.map['features']; - // console.log(level); - // this.geojsonLayerContent[""] = <L.GeoJSON>this.getLayer(layer.name, layer.map); - // <L.GeoJSON>this.getLayer("", layer.map); - // console.log(layer.name); - // this.layersByPilot['BILBAO'] = this.layersByPilot['BILBAO'].concat(layer.name); - // }); - - // arrays = <any>Bilbao_wifi; - // console.log(arrays); - // arrays.forEach(layer => { - // //console.log(layer.map['features']); - // //console.log(layer); - // // level = layer.map['features']; - // // console.log(level); - // this.geojsonLayerContent[""] = <L.GeoJSON>this.getLayer(layer.name, layer.map); - // <L.GeoJSON>this.getLayer("", layer.map); - // console.log(layer.name); - // this.layersByPilot['BILBAO'] = this.layersByPilot['BILBAO'].concat(layer.name); - // }); - - arrays = <any>Helsinki_layers; - console.log(arrays); - arrays.forEach(layer => { - //console.log(layer); - this.geojsonLayerContent[layer.name] = <L.GeoJSON>this.getLayer(layer.name, layer.map); - // console.log(layer.name); - this.layersByPilot['HELSINKI'] = this.layersByPilot['HELSINKI'].concat(layer.name); - }); - - this.layersByPilot['URBANITE'] = this.layersByPilot['AMSTERDAM'].concat(this.layersByPilot['BILBAO']).concat(this.layersByPilot['HELSINKI']).concat(this.layersByPilot['MESSINA']); - - } - - layerDescription: { [key: string]: string } = { - "Point of Interests": "Point of interests of Messina", - "ATM Stops": "ATM Stops of Messina", - "Cameras": "Cameras of Messina", - "Messina - Dinnamare": Messina_cycling_path[0].description, - "Messina - Centro": Messina_cycling_path[1].description, - "Messina - Litoranea": "Pista ciclabile Messina - Litoranea", - "Messina Incidenti 2018": "Summary of road incidents in 2020\r\n Yellow: road incidents with injured\nOrange: road incidents with less than 3 deaths\nRed: road incidents with more than 3 deaths", - - "Messina Incidenti 2019": "Summary of road incidents in 2019\r\n Yellow: road incidents with injured\nOrange: road incidents with less than 3 deaths\nRed: road incidents with more than 3 deaths", - - "Messina Incidenti 2020": "Summary of road incidents in 2020\r\n Yellow: road incidents with injured\nOrange: road incidents with less than 3 deaths\nRed: road incidents with more than 3 deaths", - - "Messina Districts": "Population of Messina divided by district. In this layer you can see some informations related to the population residents, building, housing, families, genders (females, males), ages (under 20 F/M, adults F/M and over 65 F/M) divided by districts of Messina City.", - "District II": "Population of Messina divided by district", - "District III": "Population of Messina divided by district", - "District IV": "Population of Messina divided by district", - "District V": "Population of Messina divided by district", - "District VI": "Population of Messina divided by district", - "Bilbao Air Quality": Bilbao_air_quality[0].description, - "Bilbao Bike": Bilbao_bike[0].description, - "Bilbao Wifi": Bilbao_wifi[0].description, - "Amsterdam Bike": Amsterdam_bike[0].description, - }; + geojsonLayerContent: { [key: string]: L.GeoJSON } = {}; + layerDescription: { [key: string]: string } = {}; heatlayerLayerContent: { [key: string]: L.HeatLayer } = { - "Bilbao Sound": <L.HeatLayer>L.heatLayer(this.heatLayerConverter(<any>Bilbao_sound[0].map), this.heatOptions), }; ngOnInit(): void { this.pilot = this.configService.getSettings("default_pilot"); + this.dataStorageService.getMapLayers().subscribe((entities: DataStorageLayer[]) => { + //console.log(entities); + entities.forEach(entity => { + console.log(entity); + if (entity.subtype == Subtype.HeatLayer) { + this.heatlayerLayerContent[entity.alternateName] = <L.HeatLayer>L.heatLayer(this.heatLayerConverter(<any>entity.map), this.heatOptions); + } else { + this.geojsonLayerContent[entity.alternateName] = <L.GeoJSON>this.getLayer(entity.alternateName, entity.map); + } + this.layerDescription[entity.alternateName] = entity.description; + this.layersByPilot[this.pilot] = this.layersByPilot[this.pilot].concat(entity.alternateName); + }); + }, err => { console.log(err) }); } onChange(event: any) { let clickedLayerName = event.option.value; let geojsonLayer = <L.GeoJSON>this.geojsonLayerContent[clickedLayerName]; let heatLayer = <L.HeatLayer>this.heatlayerLayerContent[clickedLayerName]; - - + console.log("geojsonlayer value ", geojsonLayer); + console.log("heatLayer value ", heatLayer); if (event.option.selected === true) { - //console.log("CHARGE LAYER-> " + clickedLayerName) - if (clickedLayerName !== "Bilbao Sound") { + if (geojsonLayer !== null || geojsonLayer !== undefined) { this.map.addLayer(geojsonLayer); - //pointToLayer icon geojsonLayer.eachLayer((layer: L.Layer) => { if (layer instanceof L.Marker) { @@ -241,14 +157,11 @@ export class MapComponent implements OnInit { }); } else { this.map.addLayer(heatLayer); - this.map.addControl(this.legend); - //console.log("CHARGE HEAT LAYER-> " + clickedLayerName); } - } - else { + } else { //console.log("DECHARGE LAYER-> " + clickedLayerName) - if (clickedLayerName !== "Bilbao Sound") { + if (geojsonLayer !== null || geojsonLayer !== undefined) { this.map = this.map.removeLayer(geojsonLayer); } else { this.map = this.map.removeLayer(heatLayer); @@ -256,6 +169,8 @@ export class MapComponent implements OnInit { } } + + } /** @@ -285,7 +200,7 @@ export class MapComponent implements OnInit { let grades: string[] = ["Low level", "Mid level", "High level"] let labels = ["<strong>Sound Level</strong>"]; for (let i = 0; i < grades.length; i++) { - div.innerHTML += '<i style="background: ' + this.getLegendColor(i) + '">' + ' ' + '</i> ' + `<b>${grades[i]}</b>` + '<br>' + div.innerHTML += '<i style="background: ' + this.getLegendColor(i) + '">' + ' ' + '</i> ' + `<b>${grades[i]}</b>` + '<br>' } return div; @@ -303,34 +218,34 @@ export class MapComponent implements OnInit { public getLayer(title: string, l) { let layer = L.geoJSON(l, { onEachFeature: (feature, layer) => { - console.log(feature) + //console.log(feature) layer.bindPopup(this.getPopupContent(title, feature)) }, style: (feature) => { - let style={ - color:'blue' + let style = { + color: 'blue' } - if(feature['properties']!=null && feature['properties']!=undefined){ + if (feature['properties'] != null && feature['properties'] != undefined) { + + if (feature.properties.hasOwnProperty('fill')) { + style['fillColor'] = feature.properties['fill']; + } - if(feature.properties.hasOwnProperty('fill')){ - style['fillColor']=feature.properties['fill']; - } - - if(feature.properties.hasOwnProperty('fill-opacity')){ - style['fillOpacity']=feature.properties['fill-opacity']; + if (feature.properties.hasOwnProperty('fill-opacity')) { + style['fillOpacity'] = feature.properties['fill-opacity']; } - if (feature.properties.hasOwnProperty('stroke')){ - style['color']=feature.properties['stroke'] + if (feature.properties.hasOwnProperty('stroke')) { + style['color'] = feature.properties['stroke'] } - if (feature.properties.hasOwnProperty('stroke-width')){ - style['weight']=feature.properties['stroke-width'] + if (feature.properties.hasOwnProperty('stroke-width')) { + style['weight'] = feature.properties['stroke-width'] } - if (feature.properties.hasOwnProperty('stroke-opacity')){ - style['opacity']=feature.properties['stroke-opacity'] + if (feature.properties.hasOwnProperty('stroke-opacity')) { + style['opacity'] = feature.properties['stroke-opacity'] } // if(feature.properties.hasOwnProperty('fill')){ @@ -372,7 +287,7 @@ export class MapComponent implements OnInit { } getLegendColor(v: number) { - switch(v) { + switch (v) { case 1: return 'yellow' case 2: diff --git a/src/assets/config.json b/src/assets/config.json index 5c0beacb726b2281f8e6aa1007ff02595ecaad46..4a1395269b9aaeb49906c2cdab377ad8c1554da9 100644 --- a/src/assets/config.json +++ b/src/assets/config.json @@ -35,8 +35,8 @@ ], "enable_demo_pages":true, "pilots":["URBANITE","AMSTERDAM","BILBAO","HELSINKI","MESSINA"], - "default_pilot":"MESSINA", - "datastorageURL": "https://messina.urbanite.esilab.org/api/data/v3", + "default_pilot":"BILBAO", + "datastorageURL": "https://messina.urbanite.esilab.org/data", "amsterdam":{ "api_base_url":"https://urbanite-node1.comune.messina.it", "token":"mcOUnnIyupQJzbitPX7Q2MnyqrVQUkmo",