From 5ace1565f3fd4e9221cde517e266409511df9814 Mon Sep 17 00:00:00 2001 From: "oier.beaskoetxea" <oier.beaskoetxea@tecnalia.com> Date: Mon, 20 Mar 2023 15:44:16 +0100 Subject: [PATCH] Modifications into de UI per nathaly and thomas requests --- .../services/datastorage.service.ts | 14 +- src/app/pages/pages-menu.ts | 12 +- src/app/pages/pages.component.ts | 5 + .../bike-analysis_AMS.component.ts | 2 +- .../bike-trajectory.component.html | 82 ++++- .../bike-trajectory.component.ts | 316 ++++++++++++------ .../noise-comp/noise-comp.component.ts | 2 +- .../services/put-geojson.service.ts | 6 +- .../tecnalia-module/tecnalia-module.module.ts | 2 + 9 files changed, 314 insertions(+), 127 deletions(-) diff --git a/src/app/pages/dashboard-management/services/datastorage.service.ts b/src/app/pages/dashboard-management/services/datastorage.service.ts index 0e5e88c0..2b416cf0 100644 --- a/src/app/pages/dashboard-management/services/datastorage.service.ts +++ b/src/app/pages/dashboard-management/services/datastorage.service.ts @@ -19,12 +19,18 @@ export class DatastorageService { // https://messina.urbanite.esilab.org/data/getTData/ } - getMapLayers(id:string = undefined): Observable<any> { + getMapLayers(id:string = undefined, filters: string = undefined): Observable<any> { + let ep = `https://${this.city}.urbanite.esilab.org/data/getTData/mapLayer/${this.city}`; + if (id !== undefined){ - return this.http.get<any>(`https://${this.city}.urbanite.esilab.org/data/getTData/mapLayer/${this.city}/${id}`); - } else{ - return this.http.get<any>(`https://${this.city}.urbanite.esilab.org/data/getTData/mapLayer/${this.city}`); + ep += "/" + id; + } + + if (filters !== undefined) { + ep += "?filters=" + encodeURI(filters) } + + return this.http.get<any>(ep); } getMessinaCycling(): Observable<any> { diff --git a/src/app/pages/pages-menu.ts b/src/app/pages/pages-menu.ts index d7379f97..0d047fec 100644 --- a/src/app/pages/pages-menu.ts +++ b/src/app/pages/pages-menu.ts @@ -66,19 +66,19 @@ export const MENU_ITEMS: NbMenuItem[] = [ }, }, { - title: "Bike OD Matrix", - link: "/pages/tecnalia/bike_AMS", + title: "Bike Trajectories", + link: "/pages/tecnalia/biketrajectories", data: { name: "tecnalia", - key: "bike_analysis_AMS", + key: "bike_trajectories", }, }, { - title: "Bike Trajectories", - link: "/pages/tecnalia/biketrajectories", + title: "Bike OD Matrix", + link: "/pages/tecnalia/bike_AMS", data: { name: "tecnalia", - key: "bike_trajectories", + key: "bike_analysis_AMS", }, }, { diff --git a/src/app/pages/pages.component.ts b/src/app/pages/pages.component.ts index 0870ac01..958fdb09 100644 --- a/src/app/pages/pages.component.ts +++ b/src/app/pages/pages.component.ts @@ -125,6 +125,11 @@ export class PagesComponent implements OnInit { } else{ x.hidden = true; } + + // When the city is AMSTERDAM the Bike Trajectories option is called Bike Data + if (this.default_pilot === "AMSTERDAM" && x.title === "Bike Trajectories") { + x.title = "Bike Data"; + } }) } } diff --git a/src/app/pages/tecnalia-module/bike-analysis_AMS/bike-analysis_AMS.component.ts b/src/app/pages/tecnalia-module/bike-analysis_AMS/bike-analysis_AMS.component.ts index 1903fd40..97f3fd4b 100644 --- a/src/app/pages/tecnalia-module/bike-analysis_AMS/bike-analysis_AMS.component.ts +++ b/src/app/pages/tecnalia-module/bike-analysis_AMS/bike-analysis_AMS.component.ts @@ -620,7 +620,7 @@ export class BikeAnalysisAMSComponent implements OnInit { let city = 'amsterdam'; let name = "bike_analysis_"+dt.getTime(); console.log("upload_geojson::: name="+name); - this.putGeoJSONService.putGeoJSON(geojson,name,city).subscribe( + this.putGeoJSONService.putGeoJSON(geojson,name,city,name, name).subscribe( res => {alert('geojson '+name+' added to storage.'); console.log("putGeoJSONService: SUCESS::: res="+JSON.stringify(res))}, err => {alert('ERROR!!!\ngeojson '+name+' NOT added to storage.');console.log("putGeoJSONService: ERROR::: err="+JSON.stringify(err));} ); diff --git a/src/app/pages/tecnalia-module/bike-trajectory/bike-trajectory.component.html b/src/app/pages/tecnalia-module/bike-trajectory/bike-trajectory.component.html index dbc53910..b30f0303 100644 --- a/src/app/pages/tecnalia-module/bike-trajectory/bike-trajectory.component.html +++ b/src/app/pages/tecnalia-module/bike-trajectory/bike-trajectory.component.html @@ -2,7 +2,7 @@ <div class="row"> <div class="row" style="display:flex"> - <div class="control_box" id='define_sims' style='width:450px;position:relative'> + <div class="control_box" id='define_sims' style='width:380px;position:relative'> <div id="vel_tab" style="margin-left:20px;display:none"> # Trajs <material-slide-toggle [(checked)]="toggleLbls" (change)="tooltipChange();">Sensor Labels</material-slide-toggle> Speed @@ -76,6 +76,18 @@ <button id="download_run_btn2" (click)="download_values();">Download Values</button> </div> + <div class="control_box button_box" id="" style='width:300px;' *ngIf="city == '1' && viz_type == 2"> + <button (click)="openUploadModal()">Upload from computer to Storage</button> + + <select name="selected_si" [(ngModel)]="selected_si" #selectedSI> + <!--<option [ngValue]="undefined"></option>--> + <option [value]="item.id" *ngFor="let item of safetyIndexGeoJsons" title="{{item.description}}">{{item.name}}</option> + </select> + + <button (click)="load_safe_index(selectedSI.value)" style="display: inline-block">Show</button> + <button (click)="clear_safety_index_map()" style="display: inline-block">Clear</button> + </div> + </div> </div> <div id='top-right' style='height:700px;width:100%;margin-top:5px'> @@ -85,6 +97,7 @@ </div> </div> + <div class="modal" id="instructionModal" style="display:none;z-index:1000"> <div class="modal-content" style="width:80%;height:60%"> <button type="button" class="close" data-dismiss="modal" aria-label="Close" @@ -98,10 +111,7 @@ <div class="form-title mb-2" style="width:100%;height:80%;overflow-y:auto"> <p>The component shows the most popular locations for bikes travelling within the city. The locations are painted with different colors from white (less popular) to dark red (more popular). In the case - there is no information the points are painted in blue. - </p> - <h5>Bilbao Use Case</h5> - In the case of Bilbao use case, the data used are the trajectories obtained from the bicycle rental service of the city. Each trajectory has been matched to points in the + there is no information the pointsopenUploadModalata used are the trajectories obtained from the bicycle rental service of the city. Each trajectory has been matched to points in the road network of the city. This module has two modes of operation: <ul> <li><b>Per Day:</b>The points are aggregated by days and each day can be choosen with the slider @@ -126,4 +136,66 @@ </div> </div> </div> +</div> + +<div class="modal" id="uploadModal" style="display:none;z-index:1000"> + <div class="modal-content" style="width:80%"> + <button type="button" class="close" data-dismiss="modal" aria-label="Close" + (click)="closeUploadModal();"> + <span aria-hidden="true">×</span> + </button> + <div class="modal-header"> + <h1 class="modal-title" id="instructionTitle">Upload GEOJSON file from computer to Storage</h1> + </div> + <div class="modal-body" style="width:100%;height:100%"> + <form> + <div class="form-group"> + <label for="description">GEOJSON File</label><br> + <input type="file" name="file" class = "form-control" (change)="onFileSelected($event.target.files)" accept=".geojson" required> + </div> + <pre></pre> + <div class="form-group"> + <label for="name">Name</label><br> + <span>safety_index_ </span> + <input type="text" name="name" class = "form-control" style="display: inline-block; width: 93%" + ngModel [(ngModel)]="geoJsonData.name" required> + </div> + + <!-- + <pre></pre> + <div class="form-group"> + <label for="alternateName">Altername name</label><br> + <input type="text" name="alternateName" class = "form-control" ngModel [(ngModel)]="geoJsonData.alternateName"> + </div> + --> + + <pre></pre> + <div class="form-group"> + <label for="description">Description</label><br> + <textarea name="description" placeholder="Description" class = "form-control" [(ngModel)]="geoJsonData.description"></textarea> + </div> + + + <button *ngIf="isValidModalForm(); else elseBlockShow" class="btn btn-primary" (click)="uploadFile()">Submit</button> + + <ng-template #elseBlockShow> + <div class="alert alert-danger" > + <div *ngIf="geoJsonData.file === null"> + A GEOJSON file must be selected. + </div> + <div *ngIf="geoJsonData.name === ''"> + Name is required. + </div> + <div *ngIf="geoJsonData.alternateName === ''"> + Alternate name is required. + </div> + <div *ngIf="geoJsonData.description === ''"> + Description is required. + </div> + + </div> + </ng-template> + </form> + </div> + </div> </div> \ No newline at end of file diff --git a/src/app/pages/tecnalia-module/bike-trajectory/bike-trajectory.component.ts b/src/app/pages/tecnalia-module/bike-trajectory/bike-trajectory.component.ts index 9bf37c1e..faa5d3c4 100644 --- a/src/app/pages/tecnalia-module/bike-trajectory/bike-trajectory.component.ts +++ b/src/app/pages/tecnalia-module/bike-trajectory/bike-trajectory.component.ts @@ -4,6 +4,7 @@ import { ConfigService } from '@ngx-config/core'; import { BikeTrajectoryService } from '../services/bike-trajectory.service'; import { Options, LabelType } from '@angular-slider/ngx-slider'; import { PutGeoJsonService } from '../services/put-geojson.service'; +import { DatastorageService } from '../../dashboard-management/services/datastorage.service'; @Component({ @@ -17,12 +18,38 @@ export class BikeTrajectoryComponent implements OnInit { constructor( private bikeTrajectoryService: BikeTrajectoryService, private putGeoJSONService: PutGeoJsonService, - private configService: ConfigService, - ) { this.apiURL = configService.getSettings("biketrajectory_api_base_url"); } + private configService: ConfigService, + private dataStorageService: DatastorageService + ) { + this.apiURL = configService.getSettings("biketrajectory_api_base_url"); + } private apiURL: any; - private city: string = "0"; + + private static readonly CITY_AMS = "1"; + + private static readonly AMS_LEGEND_MAP = [ + { value: 1, label: 'Safe', color: 'darkgreen' }, + { value: 1.1, label: 'Low Risk', color: 'green' }, + { value: 1.175, label: 'Medium Risk', color: 'yellow' }, + { value: 1.25, label: 'High Risk', color: 'orange' }, + { value: 1.4, label: 'Unsafe', color: 'red' }, + { value: -1, label: 'No data', color: 'white' }, + { value: -2, label: '', color: 'black' }, + ]; + + public geoJsonData = { + name: "", + alternateName: "safety_index", + description: "", + file: null + } + + public safetyIndexGeoJsons = []; + public selected_si = null; + + public city: string = "0"; public lat:number = 0; public lon:number = 0; public zoom:number = 14; @@ -103,7 +130,7 @@ export class BikeTrajectoryComponent implements OnInit { } radio2_change(){ - let eles:any = document.getElementsByName('biker_type'); + let eles:any = document.getElementsByName('biker_type');this this.biker_type = -1; for(let i=0;i<3;i++){ let isChecked = eles[i].checked; @@ -115,7 +142,53 @@ export class BikeTrajectoryComponent implements OnInit { this.load_safe_index(); } - load_safe_index(){ + static get_ams_mapping_index(val: number|null): number { + let out = -1; + if ( val == null ) { return out; } + + if ( val == BikeTrajectoryComponent.AMS_LEGEND_MAP[6].value ) { out = 6; } + else if ( val == BikeTrajectoryComponent.AMS_LEGEND_MAP[5].value ) { out = 5; } + else if ( val > BikeTrajectoryComponent.AMS_LEGEND_MAP[4].value ) { out = 4; } + else if ( val > BikeTrajectoryComponent.AMS_LEGEND_MAP[3].value ) { out = 3; } + else if ( val > BikeTrajectoryComponent.AMS_LEGEND_MAP[2].value ) { out = 2; } + else if ( val > BikeTrajectoryComponent.AMS_LEGEND_MAP[1].value ) { out = 1; } + else { out = 0; } + + return out; + } + + static get_trajectory_map_pop_up_info(props) { + const name = props.name ?? '--'; + + const normal_index = BikeTrajectoryComponent.get_ams_mapping_index(props.v_normal2); + const vuln_index = BikeTrajectoryComponent.get_ams_mapping_index(props.v_vuln); + const fast_index = BikeTrajectoryComponent.get_ams_mapping_index(props.v_fast); + + const normal_label = BikeTrajectoryComponent.AMS_LEGEND_MAP[normal_index]?.label; + const vuln_label = BikeTrajectoryComponent.AMS_LEGEND_MAP[vuln_index]?.label; + const fast_label = BikeTrajectoryComponent.AMS_LEGEND_MAP[fast_index]?.label; + + return `<table style=\"width:100%\"> + <tr> + <th>name</th> + <th>${name}</th> + </tr> + <tr> + <td>normal</td> + <td>${normal_label} (${props.v_normal2})</td> + </tr> + <tr> + <td>vulnerable</td> + <td>${vuln_label} (${props.v_vuln})</td> + </tr> + <tr> + <td>fast</td> + <td>${fast_label} (${props.v_fast})</td> + </tr> + </table>`; + } + + load_safe_index(sf_id?: string){ for( let m in this.markers){ this.map.removeLayer(this.markers[m]); } @@ -125,88 +198,49 @@ export class BikeTrajectoryComponent implements OnInit { }catch(e){ console.log("e="+e); } + let linksFile = '/assets/geojsons/safety_index_AMS.geojson'; - if ( this.biker_type == 0 ){ - fetch(linksFile).then(res => res.text()).then(data => { - let geojson = JSON.parse(data); - this.links = L.geoJSON(geojson, { - pane: 'paneHigh', - style: function(feature) { - let val = feature.properties.v_vuln; - let out = { color: '#FFFFFF' , opacity: 1.0}; - if ( val ==null ) { out = { color: '#000000', opacity: 1.0 } } - else if ( val < BikeTrajectoryComponent.vals_L[0] ) { out = { color: BikeTrajectoryComponent.clrs[0], opacity: 1.0 } } - else if ( val < BikeTrajectoryComponent.vals_L[1] ) { out = { color: BikeTrajectoryComponent.clrs[1], opacity: 1.0 } } - else if ( val < BikeTrajectoryComponent.vals_L[2] ) { out = { color: BikeTrajectoryComponent.clrs[2], opacity: 1.0 } } - else if ( val < BikeTrajectoryComponent.vals_L[3] ) { out = { color: BikeTrajectoryComponent.clrs[3], opacity: 1.0 } } - else if ( val < BikeTrajectoryComponent.vals_L[4] ) { out = { color: BikeTrajectoryComponent.clrs[4], opacity: 1.0 } } - else if ( val < BikeTrajectoryComponent.vals_L[5] ) { out = { color: BikeTrajectoryComponent.clrs[5], opacity: 1.0 } } - else if ( val < BikeTrajectoryComponent.vals_L[6] ) { out = { color: BikeTrajectoryComponent.clrs[6], opacity: 1.0 } } - else if ( val < BikeTrajectoryComponent.vals_L[7] ) { out = { color: BikeTrajectoryComponent.clrs[7], opacity: 1.0 } } - else if ( val < BikeTrajectoryComponent.vals_L[8] ) { out = { color: BikeTrajectoryComponent.clrs[8], opacity: 1.0 } } - return out; - }, - onEachFeature: function(feature, layer){ - layer.bindPopup("<table style=\"width:100%\"><tr><th>id</th><th>"+feature.properties.id+"</th></tr><tr><td>v_normal</td><td>"+feature.properties.v_normal2+"</td></tr><tr><td>v_vuln</td><td>"+feature.properties.v_vuln+"</td></tr><tr><td>v_fast</td> <td>"+feature.properties.v_fast+"</td></tr></table>"); - } - }).addTo(this.map); - }); - }else if ( this.biker_type == 1 ){ - fetch(linksFile).then(res => res.text()).then(data => { - let geojson = JSON.parse(data); - this.links = L.geoJSON(geojson, { - pane: 'paneHigh', - style: function(feature) { - let val = feature.properties.v_normal2; - let out = { color: '#FFFFFF' , opacity: 1.0}; - if ( val ==null ) { out = { color: '#000000', opacity: 1.0 } } - else if ( val < BikeTrajectoryComponent.vals_L[0] ) { out = { color: BikeTrajectoryComponent.clrs[0], opacity: 1.0 } } - else if ( val < BikeTrajectoryComponent.vals_L[1] ) { out = { color: BikeTrajectoryComponent.clrs[1], opacity: 1.0 } } - else if ( val < BikeTrajectoryComponent.vals_L[2] ) { out = { color: BikeTrajectoryComponent.clrs[2], opacity: 1.0 } } - else if ( val < BikeTrajectoryComponent.vals_L[3] ) { out = { color: BikeTrajectoryComponent.clrs[3], opacity: 1.0 } } - else if ( val < BikeTrajectoryComponent.vals_L[4] ) { out = { color: BikeTrajectoryComponent.clrs[4], opacity: 1.0 } } - else if ( val < BikeTrajectoryComponent.vals_L[5] ) { out = { color: BikeTrajectoryComponent.clrs[5], opacity: 1.0 } } - else if ( val < BikeTrajectoryComponent.vals_L[6] ) { out = { color: BikeTrajectoryComponent.clrs[6], opacity: 1.0 } } - else if ( val < BikeTrajectoryComponent.vals_L[7] ) { out = { color: BikeTrajectoryComponent.clrs[7], opacity: 1.0 } } - else if ( val < BikeTrajectoryComponent.vals_L[8] ) { out = { color: BikeTrajectoryComponent.clrs[8], opacity: 1.0 } } - return out; - }, - onEachFeature: function(feature, layer){ - layer.bindPopup("<table style=\"width:100%\"><tr><th>id</th><th>"+feature.properties.id+"</th></tr><tr><td>v_normal</td><td>"+feature.properties.v_normal2+"</td></tr><tr><td>v_vuln</td><td>"+feature.properties.v_vuln+"</td></tr><tr><td>v_fast</td> <td>"+feature.properties.v_fast+"</td></tr></table>"); - } - }).addTo(this.map); - }); - }else if( this.biker_type == 2){ - fetch(linksFile).then(res => res.text()).then(data => { - let geojson = JSON.parse(data); - this.links = L.geoJSON(geojson, { - pane: 'paneHigh', - style: function(feature) { - let val = feature.properties.v_fast; - let out = { color: '#FFFFFF' , opacity: 1.0}; - if ( val ==null ) { out = { color: '#000000', opacity: 1.0 } } - else if ( val < BikeTrajectoryComponent.vals_L[0] ) { out = { color: BikeTrajectoryComponent.clrs[0], opacity: 1.0 } } - else if ( val < BikeTrajectoryComponent.vals_L[1] ) { out = { color: BikeTrajectoryComponent.clrs[1], opacity: 1.0 } } - else if ( val < BikeTrajectoryComponent.vals_L[2] ) { out = { color: BikeTrajectoryComponent.clrs[2], opacity: 1.0 } } - else if ( val < BikeTrajectoryComponent.vals_L[3] ) { out = { color: BikeTrajectoryComponent.clrs[3], opacity: 1.0 } } - else if ( val < BikeTrajectoryComponent.vals_L[4] ) { out = { color: BikeTrajectoryComponent.clrs[4], opacity: 1.0 } } - else if ( val < BikeTrajectoryComponent.vals_L[5] ) { out = { color: BikeTrajectoryComponent.clrs[5], opacity: 1.0 } } - else if ( val < BikeTrajectoryComponent.vals_L[6] ) { out = { color: BikeTrajectoryComponent.clrs[6], opacity: 1.0 } } - else if ( val < BikeTrajectoryComponent.vals_L[7] ) { out = { color: BikeTrajectoryComponent.clrs[7], opacity: 1.0 } } - else if ( val < BikeTrajectoryComponent.vals_L[8] ) { out = { color: BikeTrajectoryComponent.clrs[8], opacity: 1.0 } } - return out; - }, - onEachFeature: function(feature, layer){ - layer.bindPopup("<table style=\"width:100%\"><tr><th>id</th><th>"+feature.properties.id+"</th></tr><tr><td>v_normal</td><td>"+feature.properties.v_normal2+"</td></tr><tr><td>v_vuln</td><td>"+feature.properties.v_vuln+"</td></tr><tr><td>v_fast</td> <td>"+feature.properties.v_fast+"</td></tr></table>"); - } - }).addTo(this.map); - }); + if (this.biker_type >= 0 && this.biker_type <= 2) { + if (sf_id === undefined) { + fetch(linksFile).then(res => res.text()).then(data => { + const geojson = JSON.parse(data); + this.load_safe_index_data(geojson); + }); + } else { + const safety_index = this.safetyIndexGeoJsons.find(elem => elem.id == sf_id); + if (safety_index) { + const geojson = safety_index.map; + this.load_safe_index_data(geojson); + } + } } + if ( this.legend != null ){this.map.removeControl(this.legend);} this.create_legend2(); } + private load_safe_index_data(geojson) { + const biker_type = this.biker_type; + + this.links = L.geoJSON(geojson, { + pane: 'paneHigh', + style: function(feature) { + const valTypes = ['v_vuln', 'v_normal2', 'v_fast']; + const val = feature.properties[valTypes[biker_type]]; + const legend_index = BikeTrajectoryComponent.get_ams_mapping_index(val); + + return { + color: legend_index < 0 ? '#ff00ff00' : BikeTrajectoryComponent.AMS_LEGEND_MAP[legend_index].color, + opacity: legend_index == 6 ? 0.0 : 1.0 + }; + }, + onEachFeature: function(feature, layer){ + layer.bindPopup(BikeTrajectoryComponent.get_trajectory_map_pop_up_info(feature.properties)); + } + }).addTo(this.map); + } + tooltipChange() { console.log("tooltipChange::: this.toggleLbs="+this.toggleLbls); this.toggleLbls = !this.toggleLbls; @@ -285,12 +319,14 @@ export class BikeTrajectoryComponent implements OnInit { document.getElementById('info').style.display="none"; } else if (pilotName === "AMSTERDAM") { - this.city = "1"; + this.city = "1"; document.getElementById('controls').style.display='block'; document.getElementById('vel_tab').style.display="none"; document.getElementById('radio_button_div').style.display="block"; document.getElementById('day_tab').style.display="none"; document.getElementById('info').style.display="block"; + + this.loadSafetyIndex(); } else if (pilotName === "HELSINKI") { this.city = "2"; } else if (pilotName === "MESSINA") { this.city = "3"; } @@ -574,7 +610,7 @@ export class BikeTrajectoryComponent implements OnInit { html = html + "<div style='height:200px;width:200px;border-style:solid;border-width:1px'>"; html = html + "<chart style='height:200px;width:200px' type='bar' [data]='this.chart_configs[id].data' [options]='this.chart_configs[id].options'></chart>" html = html + "</div>" */ - this.markers[id].bindPopup(html); + this.markers[id].bindPopup(html); } @@ -606,9 +642,7 @@ export class BikeTrajectoryComponent implements OnInit { let vv = BikeTrajectoryComponent.qs[0].toFixed(1) + ' - ' + BikeTrajectoryComponent.qs[1].toFixed(1); div.innerHTML += labels.push('<div style="width:25px;height:14px;padding-left:10px;white-space:nowrap;"><div style="width:25px;height:23px;background:' + 'white' + '"></div><label style="position:absolute;left:45px;top:' + 5 + 'px">' + vv + '</label></div>'); - }else{ - let minVal = 0.0; - //let vv = minVal.toFixed(1) + ' - ' + BikeTrajectoryComponent.qs[0].toFixed(1); + }else{safety_index_+ BikeTrajectoryComponent.qs[0].toFixed(1); let vv = BikeTrajectoryComponent.qs[0].toFixed(1) + ' - ' + BikeTrajectoryComponent.qs[1].toFixed(1); div.innerHTML += labels.push('<div style="width:25px;height:14px;padding-left:10px;white-space:nowrap;"><div style="width:25px;height:23px;background:' + 'white' + '"></div><label style="position:absolute;left:45px;top:' + 5 + 'px">' + vv + '</label></div>'); @@ -626,7 +660,7 @@ export class BikeTrajectoryComponent implements OnInit { } else { let maxvalS = BikeTrajectoryComponent.qs[BikeTrajectoryComponent.qs.length-1]; if (BikeTrajectoryComponent.qs[BikeTrajectoryComponent.qs.length-1] < 0) { maxvalS = '0'; } - vv = vv.toFixed(1) + ' - ' + maxvalS.toFixed(1); + vv = vv.toFixed(1) + ' - ' + maxvasafety_index_lS.toFixed(1); } if (vv < 0) { vv = 0; } if ( clr_idx == 0 ){ @@ -680,33 +714,41 @@ export class BikeTrajectoryComponent implements OnInit { this.legend.onAdd = function (map: object) { var div = L.DomUtil.create('div', 'info legend'); div.style.background = '#C0C0C0DD'; - div.style.width = '150px'; - div.style.height = '260px'; - let labels = []; - let minVal = 5.0; + div.style.width = '200px'; + div.style.height = '190px'; + let labels = []; + //console.log('create_legend2::: vals_L='+BikeTrajectoryComponent.vals_L); - let vv = " None" + /*let vv = " None" div.innerHTML += labels.push('<div style="width:25px;height:14px;padding-left:10px;padding-top:12px;white-space:nowrap;"><div style="width:25px;height:3px;background:' + 'black' + '"></div><label style="position:absolute;left:45px;top:' + 5 + 'px">' + vv + '</label></div>'); - for (let i = 0; i < BikeTrajectoryComponent.vals_L.length-1; i++) { - let vv = BikeTrajectoryComponent.vals_L[i]; + */ + + for (let i = 0; i < BikeTrajectoryComponent.AMS_LEGEND_MAP.length-1; i++) { + const value = BikeTrajectoryComponent.AMS_LEGEND_MAP[i].value; + let vv = value.toString(); //console.log('create_legend2::: i='+i+' vv='+vv);//.toFixed(1)); - if (vv < 0) { vv = 0; } - if (i < BikeTrajectoryComponent.vals_L.length - 1) { - if (BikeTrajectoryComponent.vals_L[i + 1] > 0) { - vv = vv.toFixed(1) + ' - ' + BikeTrajectoryComponent.vals_L[i + 1].toFixed(1); - } else { - vv = vv.toFixed(1) + ' - 0'; - } + if (value < 0) { + vv = BikeTrajectoryComponent.AMS_LEGEND_MAP[i].label; } else { - let maxvalS = BikeTrajectoryComponent.vals_L[BikeTrajectoryComponent.vals_L.length-1]; - if (BikeTrajectoryComponent.qs[BikeTrajectoryComponent.vals_L.length-1] < 0) { maxvalS = '0'; } - vv = vv.toFixed(1) + ' - ' + maxvalS.toFixed(1); + // if (i < BikeTrajectoryComponent.vals_L.length - 1) { + if (BikeTrajectoryComponent.AMS_LEGEND_MAP[i + 1].value > 0) { + vv = value.toFixed(3) + ' - ' + BikeTrajectoryComponent.AMS_LEGEND_MAP[i + 1].value.toFixed(3); + } else { + vv = '> ' + value.toFixed(1); + } + + vv = BikeTrajectoryComponent.AMS_LEGEND_MAP[i].label + ' (' + vv + ')'; } - if (vv < 0) { vv = 0; } + // } else { + // let maxvalS = BikeTrajectoryComponent.vals_L[BikeTrajectoryComponent.vals_L.length-1]; + // if (BikeTrajectoryComponent.qs[BikeTrajectoryComponent.vals_L.length-1] < 0) { maxvalS = '0'; } + // vv = vv.toFixed(3) + ' - ' + maxvalS.toFixed(3); + //} + // if (value < 0) { vv = '0'; } div.innerHTML += - labels.push('<div style="width:25px;height:14px;padding-left:10px;padding-top:12px;white-space:nowrap;"><div style="width:25px;height:3px;background:' + BikeTrajectoryComponent.clrs[i] + '"></div><label style="position:absolute;left:45px;top:' + (5 + 32 * (i+1)) + 'px">' + vv + '</label></div>'); + labels.push('<div style="width:25px;height:14px;padding-left:10px;padding-top:12px;white-space:nowrap;"><div style="width:25px;height:3px;background:' + BikeTrajectoryComponent.AMS_LEGEND_MAP[i].color + '"></div><label style="position:absolute;left:45px;top:' + (5 + 32 * (i)) + 'px">' + vv + '</label></div>'); } div.innerHTML = labels.join('<br>'); return div; @@ -779,12 +821,72 @@ export class BikeTrajectoryComponent implements OnInit { let dt = new Date(); let name = "bike_trajectory_"+this.viz_type+"_"+dt.getTime(); console.log("upload_geojson::: name="+name); - this.putGeoJSONService.putGeoJSON(geojson,name,this.city).subscribe( + this.putGeoJSONService.putGeoJSON(geojson,name,this.city, name, name).subscribe( res => {alert('geojson '+name+' added to storage.'); console.log("putGeoJSONService: SUCESS::: res="+JSON.stringify(res))}, err => {alert('ERROR!!!\ngeojson '+name+' NOT added to storage.');console.log("putGeoJSONService: ERROR::: err="+JSON.stringify(err));} ); } - + + openUploadModal() { + document.getElementById('uploadModal').style.display = 'block'; + } + + closeUploadModal() { + document.getElementById('uploadModal').style.display = 'none'; + this.geoJsonData = { + name: "", + alternateName: "safety_index", + description: "", + file: null + }; + } + + onFileSelected(files: FileList): void { + this.geoJsonData.file = files.item(0); + } + + isValidModalForm(): boolean { + return this.geoJsonData.file !== null && this.geoJsonData.name !== '' + && this.geoJsonData.alternateName !== '' && this.geoJsonData.description !== ''; + } + + uploadFile() { + const current = new Date(); + const name = "safety_index_" + this.geoJsonData.name + "_" + current.getTime(); + const alternateName = this.geoJsonData.alternateName; + const desc = this.geoJsonData.description; + + const reader = new FileReader(); + reader.onload = () => { + const geojson = JSON.parse(reader.result.toString()); + + this.putGeoJSONService.putGeoJSON(geojson, name, this.city, alternateName, desc).subscribe( + res => { + alert('geojson '+name+' added to storage.'); + console.log("putGeoJSONService: SUCESS::: res="+JSON.stringify(res)) + this.loadSafetyIndex(); + }, + err => {alert('ERROR!!!\ngeojson '+name+' NOT added to storage.');console.log("putGeoJSONService: ERROR::: err="+JSON.stringify(err));} + ); + + this.closeUploadModal(); + }; + + reader.readAsText(this.geoJsonData.file); + } + + loadSafetyIndex() { + const id = undefined; + const filters = "{\"alternateName\": \"safety_index\"}"; + this.dataStorageService.getMapLayers(id, filters).subscribe(res => { + this.safetyIndexGeoJsons = res; + }); + } + + clear_safety_index_map() { + this.selected_si = null; + this.load_safe_index('') + } } diff --git a/src/app/pages/tecnalia-module/noise-comp/noise-comp.component.ts b/src/app/pages/tecnalia-module/noise-comp/noise-comp.component.ts index 984d4b4c..5f9f3753 100644 --- a/src/app/pages/tecnalia-module/noise-comp/noise-comp.component.ts +++ b/src/app/pages/tecnalia-module/noise-comp/noise-comp.component.ts @@ -754,7 +754,7 @@ export class NoiseCompComponent implements OnInit { let name = "noise_computation_"+sel.value+"_"+dt.getTime(); console.log("upload_geojson::: name="+name); console.log("upload_geojson::: this.geojson="+JSON.stringify(this.geojson)); - this.putGeoJSONService.putGeoJSON(this.geojson,name,this.city).subscribe( + this.putGeoJSONService.putGeoJSON(this.geojson,name,this.city, name, name).subscribe( res => { document.getElementById('nameNGJ').innerHTML = name; document.getElementById('newNewGeoJSONModal').style.display = "block"; diff --git a/src/app/pages/tecnalia-module/services/put-geojson.service.ts b/src/app/pages/tecnalia-module/services/put-geojson.service.ts index da36c424..cfc96d05 100644 --- a/src/app/pages/tecnalia-module/services/put-geojson.service.ts +++ b/src/app/pages/tecnalia-module/services/put-geojson.service.ts @@ -14,12 +14,12 @@ export class PutGeoJsonService{ console.log("put-geojson.service::: apiURL="+this.apiURL); } - putGeoJSON(geojson:any, name:string, city:string): Observable<any> { + putGeoJSON(geojson:any, name:string, city:string, alternateName: string, desc: string): Observable<any> { let input = [{ "id": "urn:ngsi-ld:MapLayer:"+city+":zone:"+name, - "alternateName": name, - "description": name, + "alternateName": alternateName, + "description": desc, "name": name, "type": "MapLayer", "@context": [ diff --git a/src/app/pages/tecnalia-module/tecnalia-module.module.ts b/src/app/pages/tecnalia-module/tecnalia-module.module.ts index 9b698d60..ffb05819 100644 --- a/src/app/pages/tecnalia-module/tecnalia-module.module.ts +++ b/src/app/pages/tecnalia-module/tecnalia-module.module.ts @@ -17,6 +17,7 @@ import { BikeTrajectoryComponent } from './bike-trajectory/bike-trajectory. import { NoiseCompComponent } from './noise-comp/noise-comp.component'; import { LeafletDrawModule } from '@asymmetrik/ngx-leaflet-draw'; import { OdFromCountsComponent } from './od-from-counts/od-from-counts.component'; +import { FormsModule } from '@angular/forms'; @NgModule({ declarations: [TrafficPredictionComponent, @@ -28,6 +29,7 @@ import { OdFromCountsComponent } from './od-from-counts/od-from-counts.component NoiseCompComponent, OdFromCountsComponent], imports: [ + FormsModule, CommonModule, LeafletModule, LeafletDrawModule, -- GitLab