diff --git a/src/app/pages/dashboard-management/services/datastorage.service.ts b/src/app/pages/dashboard-management/services/datastorage.service.ts index 0e5e88c0c8b1026eba3f720f896fa302d7461895..2b416cf05ffe1f0ab44b62a3637ec261c306d587 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 d7379f9714532c34b0d363d99aeb94b6096660a2..0d047fec507451c3e8932a408af57305549ae440 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 0870ac010bbea02dd48061a907fcd2f7ac4bbc3b..958fdb09bc0c32303820cdf27e5e583dcb18bfb4 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 1903fd40eb6c053f286b1a53f915d7ace1f5cd8f..97f3fd4b81f98d8b6cc12f1a0db9e81ad72b87fe 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 dbc5391087d400cada0f70e2112e70c96aeae908..b30f03032c339697bd21b70ddc40a4d3e0f857e4 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 9bf37c1e69f0af705972dcf4ddd8b29c0ac73660..faa5d3c46cd6c68a2d71511a64f5f464ea9cc199 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 984d4b4cb77b3f28ecb396a243f4839a6975b4ae..5f9f3753cabd9eae900a1b65c284838c0cd9b5ca 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 da36c424036701c054352ef04f1781eba60d1e19..cfc96d05cb5013fe223f0aa4c6b9b83c9ec59ae5 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 9b698d60fbeedf15333b385eea194e10904f2960..ffb058194b072b254ac528acdced41599deaa3d1 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,