diff --git a/src/app/pages/simulation-wizard/existing-simulations/existing-simulations.component.html b/src/app/pages/simulation-wizard/existing-simulations/existing-simulations.component.html index 034dc8a78eaa6f113a1a9ee6dae6219e4e00cd62..34332bf652a96f7c9660ed1ee29bd79014defcc6 100644 --- a/src/app/pages/simulation-wizard/existing-simulations/existing-simulations.component.html +++ b/src/app/pages/simulation-wizard/existing-simulations/existing-simulations.component.html @@ -29,7 +29,7 @@ " > <nb-card-body class="single-sim"> - <span> + <span class="text-name"> {{ simulation.name }} <nb-icon [icon]=" @@ -53,9 +53,7 @@ > </nb-icon> </span> - <span class="subtitle-2 text-description">{{ - simulation.description - }}</span> + <span class="text-description">{{ simulation.description }}</span> <button *ngIf="selectedSimulation == simulation; else elseBlock" nbButton @@ -65,17 +63,23 @@ > selected </button> - <span - class="subtitle-2 text-hint" - [@socketStatusAnimation]="simulation.animationState" - (@socketStatusAnimation.done)="onAnimationEventDone($event, i)" - (@socketStatusAnimation.start)="onAnimationEventStart($event, i)" - ></span> <ng-template #elseBlock> <button nbButton status="primary" (click)="onSelect(simulation)"> select </button> </ng-template> + <span + class="text-duration" + *ngIf=" + simulation.duration != undefined; + else elseSimulationDurationBlock + " + > + {{ simulation.duration }} + </span> + <ng-template #elseSimulationDurationBlock> + <span class="text-duration"> no data about duration </span> + </ng-template> </nb-card-body> </nb-card> </section> @@ -308,8 +312,9 @@ nbTooltip="This button will run Preprocess Data, Generate Population, Generate Travel Demand Model and Run the Simulation. GET http://localhost:8082/traffic-simulation/simulation/{id}/run" [disabled]="!selectedSimulation || runSimulationBtnDisabled" > - Run simulation</button - ><nb-icon + Run simulation + </button> + <!-- <nb-icon [icon]=" runSimulation.status == 'running' ? 'loader-outline' @@ -329,7 +334,7 @@ [ngClass]="{ 'icon-spin': runSimulation.status == 'running' }" class="icon" > - </nb-icon> + </nb-icon> --> </div> <div class="mb-2 button-envelope"> <button diff --git a/src/app/pages/simulation-wizard/existing-simulations/existing-simulations.component.scss b/src/app/pages/simulation-wizard/existing-simulations/existing-simulations.component.scss index 94921191dab37f1b6e86e07de4982388c79ca1ba..1abd4b9e4d12340dd35fe4905d7a21c629e00d38 100644 --- a/src/app/pages/simulation-wizard/existing-simulations/existing-simulations.component.scss +++ b/src/app/pages/simulation-wizard/existing-simulations/existing-simulations.component.scss @@ -100,20 +100,22 @@ align-items: center; padding-top: 0.25rem; padding-bottom: 0.25rem; - span { - margin-right: 15px; + span.text-name { min-width: 280px; - } - span.text-hint { - min-width: 210px; + margin-right: 15px; } span.text-description { min-width: 220px; + margin-right: 15px; } button { margin-right: 15px; min-width: 112px; } + span.text-duration { + min-width: 220px; + flex-grow: 1; + } } span.text-hint, span.text-description { @@ -153,6 +155,34 @@ } } +@media screen and (max-width: 1000px) { + .nb-card { + margin-top: 0.75rem !important; + .single-sim { + display: flex; + flex-wrap: wrap; + > * { + margin-bottom: 0.25rem; + } + span { + width: 100%; + } + span.text-name { + margin-right: 0px; + } + span.text-description { + margin-right: 0px; + } + button { + margin-right: 0px; + } + button { + order: 4; + } + } + } +} + .icon { margin-left: 0.25em; margin-right: 0.3em; diff --git a/src/app/pages/simulation-wizard/existing-simulations/existing-simulations.component.ts b/src/app/pages/simulation-wizard/existing-simulations/existing-simulations.component.ts index cb186bdd8bcfb6004ff71e96e89a33d306eb006f..440df5c8aa304247367c06c7b1ce6510fdd16f93 100644 --- a/src/app/pages/simulation-wizard/existing-simulations/existing-simulations.component.ts +++ b/src/app/pages/simulation-wizard/existing-simulations/existing-simulations.component.ts @@ -372,12 +372,10 @@ export class ExistingSimulationsComponent implements OnInit { ); let startTime, endTime; startTime = new Date(); - console.log("🚀☢ ~ this.selectedSimulation", this.selectedSimulation); this.simulationService .getCalculateKPIs(this.selectedCity.cityId, this.selectedSimulation.id) .subscribe( (res) => { - console.log("🚀☢ ~ res", res); this.calculateKPIS.status = ""; endTime = new Date(); let timeDiff = endTime - startTime; @@ -425,10 +423,6 @@ export class ExistingSimulationsComponent implements OnInit { // rudimentary way of concincing our-spider-chart to redownload evaluated json this.selectedSimulationToEmit.emit(undefined); setTimeout(() => { - console.log( - "🚀☢ ~ this.selectedSimulation.id.toString()", - this.selectedSimulation - ); this.selectedSimulationToEmit.emit(this.selectedSimulation); this.showToast(`Updating spider chart.`, "Info", "info"); }, 0); diff --git a/src/app/pages/simulation-wizard/ml-module/ml-module.component.scss b/src/app/pages/simulation-wizard/ml-module/ml-module.component.scss index 119bac56c891fe19015a45efc4905c964bbc0465..0c7af6efce54b09ec0b6bbdab7daa408afed799f 100644 --- a/src/app/pages/simulation-wizard/ml-module/ml-module.component.scss +++ b/src/app/pages/simulation-wizard/ml-module/ml-module.component.scss @@ -27,4 +27,7 @@ } } } + a { + text-decoration: none; + } } diff --git a/src/app/pages/simulation-wizard/our-spider-chart/our-spider-chart.component.ts b/src/app/pages/simulation-wizard/our-spider-chart/our-spider-chart.component.ts index 3d8db60aa3502d952a15600990695086dc404a10..ca1c8f45fecb3167a39aeec90d20881cfece75a6 100644 --- a/src/app/pages/simulation-wizard/our-spider-chart/our-spider-chart.component.ts +++ b/src/app/pages/simulation-wizard/our-spider-chart/our-spider-chart.component.ts @@ -98,7 +98,7 @@ export class OurSpiderChartComponent implements OnChanges { values_B.push(entry[1] as string); } } else { - console.log("🚀☢ Setting 0"); + console.log("🚀☢ Setting 0 for ", entry[0]); if (j == 0) { values_A.push(0); } else if (j == 1) { diff --git a/src/app/pages/simulation-wizard/results-map/results-map-settings.ts b/src/app/pages/simulation-wizard/results-map/results-map-settings.ts new file mode 100644 index 0000000000000000000000000000000000000000..d33a51bde0050dca2eef2164f5507b4421af9e17 --- /dev/null +++ b/src/app/pages/simulation-wizard/results-map/results-map-settings.ts @@ -0,0 +1,7 @@ +// legendInverted are those who 'more is better' +export const legendInverted: string[] = [ + 'infra', 'speed', 'bikeability_safety', 'capacity' +] + +// ratiosBetweenGrades are used for legend +export const ratiosBetweenGrades: number[] = [25.6, 12.8, 6.4, 3.2, 1.6]; diff --git a/src/app/pages/simulation-wizard/results-map/results-map.component.html b/src/app/pages/simulation-wizard/results-map/results-map.component.html index 3595642f2d36f3aba9db6fe9f8813ecb94fa2cc6..e1c6c6f0a0e88ed64bd83fac52721355b5ea22f9 100644 --- a/src/app/pages/simulation-wizard/results-map/results-map.component.html +++ b/src/app/pages/simulation-wizard/results-map/results-map.component.html @@ -14,18 +14,46 @@ <div id="loadGeojsonButtonsContainer"> <button nbButton - status="primary" size="small" - (click)="onLoad(l)" + (click)="onLoadClick(l.buttonLabel)" nbTooltip="Select a simulation in order to use this button. GET http://localhost:8083/dss/geojson/{id}/selectedKpi" [disabled]="selectedSimulation == undefined" [nbSpinner]="geojsonLoading" - [status]="clickedButton == l ? 'control' : 'primary'" - *ngFor="let l of loadGeojsonButtons" + [status]="selectedGeojson == l.buttonLabel ? 'control' : 'primary'" + *ngFor="let l of loadGeojsons" > - load {{ l }} geojson + load {{ l.buttonLabel }} geojson + </button> + <button + nbButton + (click)="openOverviewOfIndicators(dialog)" + nbTooltip="click for overview of indicators" + [disabled]="selectedSimulation == undefined" + > + <nb-icon icon="info-outline"></nb-icon> </button> </div> + <ng-template #dialog let-data let-ref="dialogRef"> + <nb-card> + <nb-card-header + >Overview of Indicators for {{ data | titlecase }} + </nb-card-header> + <nb-card-body> + <img + src="{{ + 'assets/images/overviewOfIndicators' + + data[0].toUpperCase() + + data.slice(1) + + '.png' + }}" + alt="" + /> + </nb-card-body> + <nb-card-footer> + <button nbButton (click)="ref.close()">Close</button> + </nb-card-footer> + </nb-card> + </ng-template> </div> <div id="grayscaleInput"> <input diff --git a/src/app/pages/simulation-wizard/results-map/results-map.component.scss b/src/app/pages/simulation-wizard/results-map/results-map.component.scss index ffe1fa9d54b1384c9b4b99362c4b5630ef504831..8541f1068723f0048c0224f085fa3100577b162e 100644 --- a/src/app/pages/simulation-wizard/results-map/results-map.component.scss +++ b/src/app/pages/simulation-wizard/results-map/results-map.component.scss @@ -16,7 +16,7 @@ } ::ng-deep .leaflet-top.leaflet-right { position: relative; - top: 37px; + top: 42px; } #grayscaleInput { background: #fffd; diff --git a/src/app/pages/simulation-wizard/results-map/results-map.component.ts b/src/app/pages/simulation-wizard/results-map/results-map.component.ts index 253f14e5b00347c10251e8ec588540ff85bf577f..c5584b286657216b23e33e2c23fa510c8e7c5526 100644 --- a/src/app/pages/simulation-wizard/results-map/results-map.component.ts +++ b/src/app/pages/simulation-wizard/results-map/results-map.component.ts @@ -1,8 +1,9 @@ -import { Component, Input } from "@angular/core"; +import { Component, Input, TemplateRef, OnChanges } from "@angular/core"; import * as L from "leaflet"; import { SimulationService } from "../utils/services/simulation.service"; import * as MapColors from "./map-colors-local"; -import { NbToastrService } from "@nebular/theme"; +import { legendInverted, ratiosBetweenGrades } from "./results-map-settings"; +import { NbToastrService, NbDialogService } from "@nebular/theme"; import { Simulation } from "../utils/data/simulation"; @Component({ @@ -10,7 +11,7 @@ import { Simulation } from "../utils/data/simulation"; templateUrl: "./results-map.component.html", styleUrls: ["./results-map.component.scss"], }) -export class ResultsMapComponent { +export class ResultsMapComponent implements OnChanges { public map: L.Map; options = { layers: [ @@ -24,25 +25,37 @@ export class ResultsMapComponent { }; mapLegend = new L.Control({ position: "bottomright" }); radioButtonLayersControl: any; + loadGeojsons: Object[] = [ + { + response: undefined, + buttonLabel: "bikeability", + }, + { + response: undefined, + buttonLabel: "bikeIntensity", + }, + { + response: undefined, + buttonLabel: "bikeSafety", + }, + { + response: undefined, + buttonLabel: "pollution", + }, + ]; checkedRadioButton: string = ""; geoJsonStyleWeight: number = 5; geoJsonStyleOpacity: number = 0.8; maxKeyValues: Object = {}; - ratiosBetweenGrades: number[] = [25.6, 12.8, 6.4, 3.2, 1.6]; grayscale: any = 50; geojsonLoading: boolean = false; @Input() selectedSimulation: Simulation; - clickedButton: string = ""; - loadGeojsonButtons: string[] = [ - "bikeability", - "bikeIntensity", - "bikeSafety", - "pollution", - ]; + selectedGeojson: string = ""; constructor( private simulationService: SimulationService, - private toastrService: NbToastrService + private toastrService: NbToastrService, + private dialogService: NbDialogService ) {} onMapReady(map: L.Map) { this.map = map; @@ -57,7 +70,7 @@ export class ResultsMapComponent { // ); // const celkomplet: HTMLElement = document.querySelectorAll( // ".ng-tns-c441-0.appearance-filled.size-medium.shape-rectangle.status-primary.ng-star-inserted.nb-transition" - // )[6] as HTMLElement; + // )[1] as HTMLElement; // celkomplet.click(); // }, 995); // setTimeout(() => { @@ -72,116 +85,137 @@ export class ResultsMapComponent { // }, 1000); } - onLoad(selectedKpi: string) { - this.clickedButton = selectedKpi; + onLoadClick(selectedKpi: string) { + this.selectedGeojson = selectedKpi; + this.resetLayersAndButton(); this.setMapZoom(); if (this.radioButtonLayersControl) this.radioButtonLayersControl.remove(this.map); - this.toastrService.show("This might take a while", "Info", { - status: "info", + this.loadGeojsons.forEach((geojson, index) => { + if (geojson["buttonLabel"] == selectedKpi) { + if (this.loadGeojsons[index]["response"] == undefined) { + this.toastrService.show("This might take a while", "Info", { + status: "info", + }); + this.geojsonLoading = true; + this.simulationService + .getGeojson(this.selectedSimulation["id"].toString(), selectedKpi) + .subscribe((res) => { + this.loadGeojsons[index]["response"] = res; + this.handleResponse( + selectedKpi, + this.loadGeojsons[index]["response"] + ); + }), + (error) => { + this.toastrService.show( + error["message"], + "Error Getting Geojson", + { + status: "danger", + } + ); + this.geojsonLoading = false; + }; + } else { + this.handleResponse( + selectedKpi, + this.loadGeojsons[index]["response"] + ); + } + } }); - this.geojsonLoading = true; - this.simulationService - .getGeojson(this.selectedSimulation["id"].toString(), selectedKpi) - .subscribe( - (res) => { - if (res["message"] == "Calculating...") { - this.toastrService.show( - "Server says: Calculating the KPI visualization. GEOJSON loading will not be completed.", - "Geojson not ready", - { - status: "danger", - duration: 10000, - } - ); - this.geojsonLoading = false; - return; - } else if (res["message"] == "Calculating the KPI visualization.") { - this.toastrService.show( - "Server says: Calculating the KPI visualization. GEOJSON loading will not be completed.", - "Geojson not ready", - { - status: "danger", - duration: 10000, - } - ); - this.geojsonLoading = false; - return; - } else if (res["message"] == "Please prepare visualizations first.") { - this.toastrService.show( - "The visualization is not prepared yet, try again in a few minutes.", - "Geojson not ready", - { - status: "danger", - duration: 10000, - } - ); - this.geojsonLoading = false; - return; - } else if (res["message"] && res["message"].length > 0) { - this.toastrService.show( - "Geojson might not be ready", - "API response contains a message", - { - status: "warning", - } - ); - } + } - this.toastrService.show("", "Geojson Loaded", { - status: "success", - }); + handleResponse(selectedKpi, res) { + this.loadGeojsons.forEach((geojson, index) => { + if (geojson["buttonLabel"] == selectedKpi) { + this.loadGeojsons[index]["response"] = res; + } + }); - const keys = this.extractKeys(res); - const propertyGeojsons = this.populatePropertyGeojsons(res, keys); - let obj = {}; - - for (let i = 0; i < propertyGeojsons.length; i++) { - if ( - propertyGeojsons[i].myKey == "link_id" || - propertyGeojsons[i].myKey == "modes" || - propertyGeojsons[i].myKey == "internal_travel_by_mode" - ) - continue; - obj[`${keys[i]}`] = propertyGeojsons[i]; - } - this.radioButtonLayersControl = new L.Control.Layers(obj, null, { - collapsed: false, - }); - this.map.addControl(this.radioButtonLayersControl); - this.addListenerToRadioButtonLayersControl(); - this.geojsonLoading = false; - }, - (error) => { - this.toastrService.show(error["message"], "Error Getting Geojson", { - status: "danger", - }); - this.geojsonLoading = false; + if (res["message"] == "Calculating...") { + this.toastrService.show( + "Server says: Calculating the KPI visualization. GEOJSON loading will not be completed.", + "Geojson not ready", + { + status: "danger", + duration: 10000, } ); + this.geojsonLoading = false; + return; + } else if (res["message"] == "Calculating the KPI visualization.") { + this.toastrService.show( + "Server says: Calculating the KPI visualization. GEOJSON loading will not be completed.", + "Geojson not ready", + { + status: "danger", + duration: 10000, + } + ); + this.geojsonLoading = false; + return; + } else if (res["message"] == "Please prepare visualizations first.") { + this.toastrService.show( + "The visualization is not prepared yet, try again in a few minutes.", + "Geojson not ready", + { + status: "danger", + duration: 10000, + } + ); + this.geojsonLoading = false; + return; + } else if (res["message"] && res["message"].length > 0) { + this.toastrService.show( + "Geojson might not be ready", + "API response contains a message", + { + status: "warning", + } + ); + } + + this.toastrService.show("", "Geojson Loaded", { + status: "success", + }); + + const keys = this.extractKeys(res); + const propertyGeojsons = this.populatePropertyGeojsons(res, keys); + let obj = {}; + + for (let i = 0; i < propertyGeojsons.length; i++) { + if ( + propertyGeojsons[i].myKey == "link_id" || + propertyGeojsons[i].myKey == "modes" || + propertyGeojsons[i].myKey == "internal_travel_by_mode" + ) + continue; + obj[`${keys[i]}`] = propertyGeojsons[i]; + } + this.radioButtonLayersControl = new L.Control.Layers(obj, null, { + collapsed: false, + }); + this.map.addControl(this.radioButtonLayersControl); + this.addListenerToRadioButtonLayersControl(); + this.geojsonLoading = false; } - // LEGEND setLegend(legendType) { + if (this.map != undefined && legendType == undefined) { + this.map.removeControl(this.mapLegend); + return; + } + if (this.map == undefined) { + return; + } + this.mapLegend.onAdd = (map) => { let direction: string; - if ( - legendType == "PM" || - legendType == "CO2_rep" || - legendType == "CO" || - legendType == "CO2_TOTAL" || - legendType == "HC" || - legendType == "NOx" || - legendType == "pedestrianTravelTime" || - legendType == "bike_count" || - legendType == "bus_count" || - legendType == "car_count" || - legendType == "infra" || - legendType == "speed" || - legendType == "bikeability_safety" - ) { + if (legendInverted.indexOf(legendType) == -1) { direction = "lowToHigh"; } else { direction = "highToLow"; @@ -191,6 +225,10 @@ export class ResultsMapComponent { this.maxKeyValues["maxValue_" + legendType] == undefined || this.maxKeyValues["maxValue_" + legendType] == 0 ) { + this.toastrService.info( + "Geojson not displayed because all values are undefined or zero!", + "Geojson not displayed" + ); let div = L.DomUtil.create("div"); div.innerHTML += `<p style='background:white; display: inline; font-size:17px; padding: 0 7px; background: #ff3d71'>Values for ${legendType} kpi are undefined or zero!</p>`; return div; @@ -200,24 +238,19 @@ export class ResultsMapComponent { const grades = [ 0, this.limitMyDigits( - this.maxKeyValues["maxValue_" + legendType] / - this.ratiosBetweenGrades[0] + this.maxKeyValues["maxValue_" + legendType] / ratiosBetweenGrades[0] ), this.limitMyDigits( - this.maxKeyValues["maxValue_" + legendType] / - this.ratiosBetweenGrades[1] + this.maxKeyValues["maxValue_" + legendType] / ratiosBetweenGrades[1] ), this.limitMyDigits( - this.maxKeyValues["maxValue_" + legendType] / - this.ratiosBetweenGrades[2] + this.maxKeyValues["maxValue_" + legendType] / ratiosBetweenGrades[2] ), this.limitMyDigits( - this.maxKeyValues["maxValue_" + legendType] / - this.ratiosBetweenGrades[3] + this.maxKeyValues["maxValue_" + legendType] / ratiosBetweenGrades[3] ), this.limitMyDigits( - this.maxKeyValues["maxValue_" + legendType] / - this.ratiosBetweenGrades[4] + this.maxKeyValues["maxValue_" + legendType] / ratiosBetweenGrades[4] ), ]; @@ -372,86 +405,105 @@ export class ResultsMapComponent { for (let f = 0; f < keys.length; f++) { let tmp: Object = {}; - if (keys[f] == "capacity") { - tmp = L.geoJSON(<any>jsonFile, { - style: (feature) => ({ - weight: this.geoJsonStyleWeight, - color: MapColors.getColorHighToLow( - feature["properties"]["capacity"], - keys[f], - this.maxKeyValues[`maxValue_${keys[f]}`], - this.ratiosBetweenGrades, - parseInt(feature["properties"]["capacity"]) == 9999 ? true : false - ), - opacity: this.geoJsonStyleOpacity, - }), - onEachFeature: (feature, layer) => - layer.on({ - mouseover: (e) => this.highlightFeature(e, feature.properties), - mouseout: (e) => this.resetFeature(e, feature.properties), - }), + + if ( + this.maxKeyValues["maxValue_" + keys[f]] == undefined || + this.maxKeyValues["maxValue_" + keys[f]] == 0 + ) { + tmp = L.geoJSON(<any>{ + type: "FeatureCollection", + features: [], }); - } else if (keys[f] == "dailyInternalBikeTravels") { - tmp = L.geoJSON(<any>jsonFile, { - style: (feature) => ({ - weight: this.geoJsonStyleWeight, - color: MapColors.getColorHighToLow( - feature["properties"]["cityWide"]["traffic"] - .dailyInternalBikeTravels || - feature["properties"].dailyInternalBikeTravels, - keys[f], - this.maxKeyValues[`maxValue_${keys[f]}`], - this.ratiosBetweenGrades, - parseInt(feature["properties"]["capacity"]) == 9999 ? true : false - ), - opacity: this.geoJsonStyleOpacity, - }), - onEachFeature: (feature, layer) => - layer.on({ - mouseover: (e) => this.highlightFeature(e, feature.properties), - mouseout: (e) => this.resetFeature(e, feature.properties), + } else { + if (keys[f] == "capacity") { + tmp = L.geoJSON(<any>jsonFile, { + style: (feature) => ({ + weight: this.geoJsonStyleWeight, + color: MapColors.getColorHighToLow( + feature["properties"]["capacity"], + keys[f], + this.maxKeyValues[`maxValue_${keys[f]}`], + ratiosBetweenGrades, + parseInt(feature["properties"]["capacity"]) == 9999 + ? true + : false + ), + opacity: this.geoJsonStyleOpacity, }), - }); - } else if (keys[f] == "pedestrianTravelTime") { - tmp = L.geoJSON(<any>jsonFile, { - style: (feature) => ({ - weight: this.geoJsonStyleWeight, - color: MapColors.getColor( - feature["properties"]["cityWide"]["traffic"] - .pedestrianTravelTime || - feature["properties"].pedestrianTravelTime, - keys[f], - this.maxKeyValues[`maxValue_${keys[f]}`], - this.ratiosBetweenGrades, - parseInt(feature["properties"]["capacity"]) == 9999 ? true : false - ), - opacity: this.geoJsonStyleOpacity, - }), - onEachFeature: (feature, layer) => - layer.on({ - mouseover: (e) => this.highlightFeature(e, feature.properties), - mouseout: (e) => this.resetFeature(e, feature.properties), + onEachFeature: (feature, layer) => + layer.on({ + mouseover: (e) => this.highlightFeature(e, feature.properties), + mouseout: (e) => this.resetFeature(e, feature.properties), + }), + }); + } else if (keys[f] == "dailyInternalBikeTravels") { + tmp = L.geoJSON(<any>jsonFile, { + style: (feature) => ({ + weight: this.geoJsonStyleWeight, + color: MapColors.getColorHighToLow( + feature["properties"]["cityWide"]["traffic"] + .dailyInternalBikeTravels || + feature["properties"].dailyInternalBikeTravels, + keys[f], + this.maxKeyValues[`maxValue_${keys[f]}`], + ratiosBetweenGrades, + parseInt(feature["properties"]["capacity"]) == 9999 + ? true + : false + ), + opacity: this.geoJsonStyleOpacity, }), - }); - } else { - tmp = L.geoJSON(<any>jsonFile, { - style: (feature) => ({ - weight: this.geoJsonStyleWeight, - color: MapColors.getColor( - feature["properties"], - keys[f], - this.maxKeyValues[`maxValue_${keys[f]}`], - this.ratiosBetweenGrades, - parseInt(feature["properties"]["capacity"]) == 9999 ? true : false - ), - opacity: this.geoJsonStyleOpacity, - }), - onEachFeature: (feature, layer) => - layer.on({ - mouseover: (e) => this.highlightFeature(e, feature.properties), - mouseout: (e) => this.resetFeature(e, feature.properties), + onEachFeature: (feature, layer) => + layer.on({ + mouseover: (e) => this.highlightFeature(e, feature.properties), + mouseout: (e) => this.resetFeature(e, feature.properties), + }), + }); + } else if (keys[f] == "pedestrianTravelTime") { + tmp = L.geoJSON(<any>jsonFile, { + style: (feature) => ({ + weight: this.geoJsonStyleWeight, + color: MapColors.getColor( + feature["properties"]["cityWide"]["traffic"] + .pedestrianTravelTime || + feature["properties"].pedestrianTravelTime, + keys[f], + this.maxKeyValues[`maxValue_${keys[f]}`], + ratiosBetweenGrades, + parseInt(feature["properties"]["capacity"]) == 9999 + ? true + : false + ), + opacity: this.geoJsonStyleOpacity, }), - }); + onEachFeature: (feature, layer) => + layer.on({ + mouseover: (e) => this.highlightFeature(e, feature.properties), + mouseout: (e) => this.resetFeature(e, feature.properties), + }), + }); + } else { + tmp = L.geoJSON(<any>jsonFile, { + style: (feature) => ({ + weight: this.geoJsonStyleWeight, + color: MapColors.getColor( + feature["properties"], + keys[f], + this.maxKeyValues[`maxValue_${keys[f]}`], + ratiosBetweenGrades, + parseInt(feature["properties"]["capacity"]) == 9999 + ? true + : false + ), + opacity: this.geoJsonStyleOpacity, + }), + onEachFeature: (feature, layer) => + layer.on({ + mouseover: (e) => this.highlightFeature(e, feature.properties), + mouseout: (e) => this.resetFeature(e, feature.properties), + }), + }); + } } tmp["myKey"] = keys[f]; res.push(tmp); @@ -587,4 +639,37 @@ export class ResultsMapComponent { }); } } + + openOverviewOfIndicators(dialog: TemplateRef<any>) { + this.dialogService.open(dialog, { + context: this.selectedSimulation["city"]["cityId"], + }); + } + + resetLayersAndButton() { + let timeout = 100; + if (this.map != undefined) { + this.map.eachLayer((layer) => { + if (layer["feature"] != undefined) { + setTimeout(() => { + this.map.removeLayer(layer); + timeout += 50; + }, timeout); + } + }); + + if (this.radioButtonLayersControl) + this.radioButtonLayersControl.remove(this.map); + } + this.setLegend(undefined); + } + + ngOnChanges() { + this.resetLayersAndButton(); + this.selectedGeojson = ""; + + Object.entries(this.loadGeojsons).forEach((entry) => { + entry[1]["response"] = undefined; + }); + } } diff --git a/src/assets/images/overviewOfIndicatorsAmsterdam.png b/src/assets/images/overviewOfIndicatorsAmsterdam.png new file mode 100644 index 0000000000000000000000000000000000000000..06b8ff8eadfc3d28210c222b8bf1f0e182406e3d Binary files /dev/null and b/src/assets/images/overviewOfIndicatorsAmsterdam.png differ diff --git a/src/assets/images/overviewOfIndicatorsBilbao.png b/src/assets/images/overviewOfIndicatorsBilbao.png new file mode 100644 index 0000000000000000000000000000000000000000..f1412b8aa99c3db2cf2de7f32d5325b671984f91 Binary files /dev/null and b/src/assets/images/overviewOfIndicatorsBilbao.png differ diff --git a/src/assets/images/overviewOfIndicatorsHelsinki.png b/src/assets/images/overviewOfIndicatorsHelsinki.png new file mode 100644 index 0000000000000000000000000000000000000000..97521a8252ce50e181a6f27038f572721380d81b Binary files /dev/null and b/src/assets/images/overviewOfIndicatorsHelsinki.png differ diff --git a/src/assets/images/overviewOfIndicatorsMessina.png b/src/assets/images/overviewOfIndicatorsMessina.png new file mode 100644 index 0000000000000000000000000000000000000000..12900cd5021e9868289266dc067dda3a3da74b66 Binary files /dev/null and b/src/assets/images/overviewOfIndicatorsMessina.png differ