From 041530756690d0b17816900d0e8405947b82f7d9 Mon Sep 17 00:00:00 2001 From: Hugo SUBTIL <ext.sopra.husubtil@grandlyon.com> Date: Mon, 23 Nov 2020 11:55:14 +0100 Subject: [PATCH 1/4] fix: change endpoint for categories --- src/app/structure-list/services/search.service.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/app/structure-list/services/search.service.ts b/src/app/structure-list/services/search.service.ts index 3f57cd50f..2c2b58e37 100644 --- a/src/app/structure-list/services/search.service.ts +++ b/src/app/structure-list/services/search.service.ts @@ -14,17 +14,17 @@ export class SearchService { public getCategoriesTraining(): Observable<Category[]> { return this.http - .get('/api/CategoriesFormations') + .get('/api/categories/categoriesFormations') .pipe(map((data: any[]) => data.map((item) => new Category(item)))); } public getCategoriesAccompaniment(): Observable<Category[]> { return this.http - .get('/api/CategoriesAccompagnement') + .get('/api/categories/categoriesAccompagnement') .pipe(map((data: any[]) => data.map((item) => new Category(item)))); } public getCategoriesMoreFilters(): Observable<Category[]> { return this.http - .get('/api/CategoriesPlusDeFiltres') + .get('/api/categories/categoriesOthers') .pipe(map((data: any[]) => data.map((item) => new Category(item)))); } -- GitLab From 1a9e1263c3a2155b383602ccbfbe1eb6212f51b3 Mon Sep 17 00:00:00 2001 From: Hugo SUBTIL <ext.sopra.husubtil@grandlyon.com> Date: Tue, 24 Nov 2020 14:08:56 +0100 Subject: [PATCH 2/4] fix: filters refacto for backend --- src/app/home/home.component.ts | 25 +------------------ src/app/services/structure-list.service.ts | 22 +++++++++++++++- .../search/search.component.spec.ts | 2 +- .../components/search/search.component.ts | 2 +- 4 files changed, 24 insertions(+), 27 deletions(-) diff --git a/src/app/home/home.component.ts b/src/app/home/home.component.ts index 873be218a..40033bd4c 100644 --- a/src/app/home/home.component.ts +++ b/src/app/home/home.component.ts @@ -41,7 +41,6 @@ export class HomeComponent implements OnInit { this.structuresChunked = []; } this.structureService.getStructures(filters).subscribe((structures) => { - filters ? (structures = this.applyFilters(structures, filters)) : structures; if (structures) { Promise.all( structures.map((structure) => { @@ -55,7 +54,7 @@ export class HomeComponent implements OnInit { }) ).then((structureList) => { structureList = _.sortBy(structureList, ['distance']); - if (this.pageStructures == 0) { + if (this.pageStructures === 0) { for (let i = 0; i < structureList.length; i += this.chunck) { this.structuresChunked.push(structureList.slice(i, i + this.chunck)); } @@ -68,28 +67,6 @@ export class HomeComponent implements OnInit { }); } - /** - * Delete when we have back-end - * Fix a bug with Json-server request - */ - private applyFilters(structures, filters): Structure[] { - let structuresFiltered = []; - structures.forEach((s: Structure) => { - let count = 0; - filters.forEach((filter: Filter) => { - let properties: string[] = []; - properties = s[filter.name]; - if (properties && properties.includes(filter.value)) { - count++; - } - }); - if (count === filters.length) { - structuresFiltered.push(s); - } - }); - return structuresFiltered; - } - /** * Get structures positions and add marker corresponding to those positons on the map */ diff --git a/src/app/services/structure-list.service.ts b/src/app/services/structure-list.service.ts index faf14254c..3224f378a 100644 --- a/src/app/services/structure-list.service.ts +++ b/src/app/services/structure-list.service.ts @@ -3,6 +3,7 @@ import { Injectable } from '@angular/core'; import { WeekDay } from '@angular/common'; import { Observable } from 'rxjs'; import { map } from 'rxjs/operators'; +import * as _ from 'lodash'; import { Structure } from '../models/structure.model'; import { Day } from '../models/day.model'; @@ -18,7 +19,26 @@ export class StructureService { constructor(private http: HttpClient) {} public getStructures(filters: Filter[]): Observable<Structure[]> { - return this.http.get('/api/structures').pipe(map((data: any[]) => data.map((item) => new Structure(item)))); + if (filters && filters.length > 0) { + let requestUrl = '/api/structures/search'; + const queryString = _.find(filters, { name: 'query' }); + if (queryString) { + _.remove(filters, { name: 'query' }); + requestUrl += `?query=${queryString.value}`; + } + const formatedFilters = this.formatFilters(filters); + return this.http + .post(requestUrl, { filters: formatedFilters }) + .pipe(map((data: any[]) => data.map((item) => new Structure(item)))); + } else { + return this.http.get('/api/structures').pipe(map((data: any[]) => data.map((item) => new Structure(item)))); + } + } + + private formatFilters(filters: Filter[]): object { + return filters.map((filter) => { + return { [filter.name]: filter.value }; + }); } /** diff --git a/src/app/structure-list/components/search/search.component.spec.ts b/src/app/structure-list/components/search/search.component.spec.ts index 647c986a8..be7013937 100644 --- a/src/app/structure-list/components/search/search.component.spec.ts +++ b/src/app/structure-list/components/search/search.component.spec.ts @@ -33,7 +33,7 @@ describe('SearchComponent', () => { // applyFilter function it('should emit filters', () => { - const filter: Filter[] = [new Filter('nomDeVotreStructure', 'valInput')]; + const filter: Filter[] = [new Filter('query', 'valInput')]; spyOn(component.searchEvent, 'emit'); component.applyFilter('valInput'); expect(component.searchEvent.emit).toHaveBeenCalled(); diff --git a/src/app/structure-list/components/search/search.component.ts b/src/app/structure-list/components/search/search.component.ts index 39a0f9eaa..6149a0fd9 100644 --- a/src/app/structure-list/components/search/search.component.ts +++ b/src/app/structure-list/components/search/search.component.ts @@ -64,7 +64,7 @@ export class SearchComponent implements OnInit { // Add search input filter const filters: Filter[] = []; if (term) { - filters.push(new Filter('nomDeVotreStructure', term)); + filters.push(new Filter('query', term)); } // Add checked box filter this.checkedModulesFilter.forEach((cm) => { -- GitLab From bfca4a17f76aa36d9f19bcb3047bcc8afb1e691b Mon Sep 17 00:00:00 2001 From: Hugo SUBTIL <ext.sopra.husubtil@grandlyon.com> Date: Thu, 26 Nov 2020 08:44:28 +0100 Subject: [PATCH 3/4] feat: move structure location call to backend --- proxy.conf.json | 6 ---- src/app/home/home.component.spec.ts | 14 -------- src/app/home/home.component.ts | 44 ++++++++---------------- src/app/map/components/map.component.ts | 38 ++++++++------------ src/app/models/structure.model.ts | 9 +++++ src/app/services/geojson.service.spec.ts | 15 -------- src/app/services/geojson.service.ts | 10 ------ 7 files changed, 37 insertions(+), 99 deletions(-) diff --git a/proxy.conf.json b/proxy.conf.json index 70c21305f..cc19a8115 100644 --- a/proxy.conf.json +++ b/proxy.conf.json @@ -14,12 +14,6 @@ "changeOrigin": true, "logLevel": "info" }, - "/geocoding/photon/api": { - "target": "https://download.data.grandlyon.com", - "secure": false, - "changeOrigin": true, - "logLevel": "info" - }, "/wfs/grandlyon": { "target": "https://download.data.grandlyon.com", "secure": false, diff --git a/src/app/home/home.component.spec.ts b/src/app/home/home.component.spec.ts index d389cc50d..4bc5950f6 100644 --- a/src/app/home/home.component.spec.ts +++ b/src/app/home/home.component.spec.ts @@ -31,20 +31,6 @@ describe('HomeComponent', () => { it('should create', () => { expect(component).toBeTruthy(); }); - - it('getCoord(): should get coord', async () => { - await new Promise((resolve) => { - component.getCoord('Rue de la Mairie ', 'Feyzin').subscribe( - (val) => { - expect(val.geometry.getLat()).toEqual(4.8591584); - expect(val.geometry.getLon()).toEqual(45.6727968); - resolve(); - }, - (err) => { - resolve(); - } - ); - }); }); it('getAddress(): should getAddress', () => { diff --git a/src/app/home/home.component.ts b/src/app/home/home.component.ts index 0f968db5b..265131817 100644 --- a/src/app/home/home.component.ts +++ b/src/app/home/home.component.ts @@ -38,12 +38,9 @@ export class HomeComponent implements OnInit { Promise.all( structures.map((structure) => { if (this.geolocation) { - return this.getStructurePosition(structure).then((val) => { - return this.structureService.updateOpeningStructure(val, DateTime.local()); - }); - } else { - return this.structureService.updateOpeningStructure(structure, DateTime.local()); + structure = this.getStructurePosition(structure); } + return this.structureService.updateOpeningStructure(structure, DateTime.local()); }) ).then((structureList) => { structureList = _.sortBy(structureList, ['distance']); @@ -58,31 +55,18 @@ export class HomeComponent implements OnInit { /** * Get structures positions and add marker corresponding to those positons on the map */ - private getStructurePosition(structure: Structure): Promise<Structure> { - return new Promise((resolve, reject) => { - this.getCoord(structure.n, structure.voie, structure.commune).subscribe((coord: GeoJson) => { - structure.address = structure.voie + ' - ' + coord.properties.postcode + ' ' + coord.properties.city; - structure.distance = parseInt( - this.geoJsonService.getDistance( - coord.geometry.getLon(), - coord.geometry.getLat(), - this.currentLocation.geometry.getLon(), - this.currentLocation.geometry.getLat(), - 'M' - ), - 10 - ); - resolve(structure); - }); - }); - } - - /** - * Get coord with a street reference - * @param idVoie Street reference - */ - public getCoord(numero: string, voie: string, zipcode: string): Observable<GeoJson> { - return this.geoJsonService.getCoord(numero, voie, zipcode); + private getStructurePosition(structure: Structure): Structure { + structure.distance = parseInt( + this.geoJsonService.getDistance( + structure.getLon(), + structure.getLat(), + this.currentLocation.geometry.getLon(), + this.currentLocation.geometry.getLat(), + 'M' + ), + 10 + ); + return structure; } public getLocation(): void { diff --git a/src/app/map/components/map.component.ts b/src/app/map/components/map.component.ts index 84a68b693..6bccd2d44 100644 --- a/src/app/map/components/map.component.ts +++ b/src/app/map/components/map.component.ts @@ -108,22 +108,20 @@ export class MapComponent implements OnChanges { } private getStructuresPositions(structureListe: Structure[]): void { - structureListe.forEach((element: Structure) => { - this.getCoord(element.n, element.voie, element.commune).subscribe((coord: GeoJson) => { - this.mapService - .createMarker( - coord.geometry.getLon(), - coord.geometry.getLat(), - MarkerType.structure, - element.id, - this.buildToolTip(element) - ) - .addTo(this.map) - // store structure before user click on button - .on('popupopen', () => { - this.currentStructure = element; - }); - }); + structureListe.forEach((structure: Structure) => { + this.mapService + .createMarker( + structure.getLon(), + structure.getLat(), + MarkerType.structure, + structure.id, + this.buildToolTip(structure) + ) + .addTo(this.map) + // store structure before user click on button + .on('popupopen', () => { + this.currentStructure = structure; + }); }); } @@ -159,14 +157,6 @@ export class MapComponent implements OnChanges { return `<h1>${mdmProperties.nom}</h1><p>${mdmProperties.adresse}</p>`; } - /** - * Get coord with a street reference - * @param idVoie Street reference - */ - public getCoord(numero: string, voie: string, zipcode: string): Observable<GeoJson> { - return this.geoJsonService.getCoord(numero, voie, zipcode); - } - /** * Add marker when map is ready to be showned * @param map map diff --git a/src/app/models/structure.model.ts b/src/app/models/structure.model.ts index 221dd15cf..bcc5b4a08 100644 --- a/src/app/models/structure.model.ts +++ b/src/app/models/structure.model.ts @@ -40,6 +40,7 @@ export class Structure { public accesAuxDroits: string[]; public distance?: number; public address?: string; + public coord?: number[]; constructor(obj?: any) { Object.assign(this, obj, { @@ -109,4 +110,12 @@ export class Structure { } } } + + public getLat(): number { + return this.coord[0]; + } + + public getLon(): number { + return this.coord[1]; + } } diff --git a/src/app/services/geojson.service.spec.ts b/src/app/services/geojson.service.spec.ts index a947152a8..71045a64d 100644 --- a/src/app/services/geojson.service.spec.ts +++ b/src/app/services/geojson.service.spec.ts @@ -21,19 +21,4 @@ describe('GeojsonService', () => { it('should be created', () => { expect(service).toBeTruthy(); }); - - it('should get coord with query string Rue de la Mairie Feyzin ', async () => { - await new Promise((resolve) => { - service.getCoord('Rue de la Mairie', 'Feyzin').subscribe( - (val) => { - expect(val.geometry.getLat()).toEqual(4.8591584); - expect(val.geometry.getLon()).toEqual(45.6727968); - resolve(); - }, - (err) => { - resolve(); - } - ); - }); - }); }); diff --git a/src/app/services/geojson.service.ts b/src/app/services/geojson.service.ts index 5f15ae6d8..befafee6c 100644 --- a/src/app/services/geojson.service.ts +++ b/src/app/services/geojson.service.ts @@ -43,16 +43,6 @@ export class GeojsonService { .pipe(map((data: { features: any[] }) => _.map(data.features, this.parseToGeoJson))); } - /** - * Get GeoLocation with an address - * @param address Address - */ - public getCoord(numero: string, address: string, zipcode: string): Observable<GeoJson> { - return this.http - .get('/geocoding/photon/api' + '?q=' + numero + ' ' + address + ' ' + zipcode) - .pipe(map((data: { features: any[]; type: string }) => new GeoJson(data.features[0]))); - } - // ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: // ::: ::: // ::: This routine calculates the distance between two points (given the ::: -- GitLab From 3407dfc81528f22b9bf7efcefdf44e4e2e79f736 Mon Sep 17 00:00:00 2001 From: Hugo SUBTIL <ext.sopra.husubtil@grandlyon.com> Date: Fri, 27 Nov 2020 10:19:15 +0100 Subject: [PATCH 4/4] feat: add location search --- proxy.conf.json | 6 ++ src/app/home/home.component.ts | 102 +++++++++++++++----- src/app/map/components/map.component.ts | 2 +- src/app/map/models/addressGeometry.model.ts | 4 +- src/app/models/structure.model.ts | 4 +- src/app/services/geojson.service.ts | 10 ++ 6 files changed, 99 insertions(+), 29 deletions(-) diff --git a/proxy.conf.json b/proxy.conf.json index cc19a8115..f5d918024 100644 --- a/proxy.conf.json +++ b/proxy.conf.json @@ -25,5 +25,11 @@ "secure": false, "changeOrigin": true, "logLevel": "info" + }, + "/geocoding/photon/api": { + "target": "https://download.data.grandlyon.com", + "secure": false, + "changeOrigin": true, + "logLevel": "info" } } diff --git a/src/app/home/home.component.ts b/src/app/home/home.component.ts index 265131817..ce2ef32e6 100644 --- a/src/app/home/home.component.ts +++ b/src/app/home/home.component.ts @@ -22,6 +22,8 @@ export class HomeComponent implements OnInit { public geolocation = false; public currentLocation: GeoJson; public currentStructure: Structure; + public userLatitude: number; + public userLongitude: number; constructor(private structureService: StructureService, private geoJsonService: GeojsonService) {} ngOnInit(): void { @@ -33,37 +35,84 @@ export class HomeComponent implements OnInit { } public getStructures(filters: Filter[]): void { - this.structureService.getStructures(filters).subscribe((structures) => { - if (structures) { - Promise.all( - structures.map((structure) => { - if (this.geolocation) { - structure = this.getStructurePosition(structure); - } - return this.structureService.updateOpeningStructure(structure, DateTime.local()); - }) - ).then((structureList) => { - structureList = _.sortBy(structureList, ['distance']); - this.structures = structureList; + const queryString = _.find(filters, { name: 'query' }); + if (queryString) { + if (this.isLocationRequest(queryString.value)) { + this.getCoordByAddress(queryString.value).then((res) => { + this.currentLocation = res; + this.updateStructuresdistance( + this.structures, + this.currentLocation.geometry.getLon(), + this.currentLocation.geometry.getLat() + ); }); } else { - this.structures = null; + this.structureService.getStructures(filters).subscribe((structures) => { + if (structures) { + this.updateStructuresdistance(structures, this.userLongitude, this.userLatitude); + } else { + this.structures = null; + } + }); } + } else { + this.structureService.getStructures(filters).subscribe((structures) => { + if (structures) { + this.updateStructuresdistance(structures, this.userLongitude, this.userLatitude); + } else { + this.structures = null; + } + }); + } + } + + private updateStructuresdistance(structures: Structure[], lon: number, lat: number): void { + Promise.all( + structures.map((structure) => { + if (this.geolocation) { + structure = this.getStructurePosition(structure, lon, lat); + } + return this.structureService.updateOpeningStructure(structure, DateTime.local()); + }) + ).then((structureList) => { + structureList = _.sortBy(structureList, ['distance']); + this.structures = structureList; }); } + /** + * Retrive GeoJson for a given address + * @param address string + */ + private getCoordByAddress(address: string): Promise<GeoJson> { + return new Promise((resolve) => { + this.geoJsonService.getCoord(address, '', '69000').subscribe((res) => { + resolve(res); + }); + }); + } + + /** + * Check with a regex that an address is request + * @param value string + */ + private isLocationRequest(value: string): boolean { + const regex = /^\d+\s[A-z]+\s[A-z]+/g; + if (value.match(regex)) { + return true; + } + return false; + } + /** * Get structures positions and add marker corresponding to those positons on the map + * @param structure Structure + * @param lon number + * @param lat number */ - private getStructurePosition(structure: Structure): Structure { + private getStructurePosition(structure: Structure, lon: number, lat: number): Structure { structure.distance = parseInt( - this.geoJsonService.getDistance( - structure.getLon(), - structure.getLat(), - this.currentLocation.geometry.getLon(), - this.currentLocation.geometry.getLat(), - 'M' - ), + this.geoJsonService.getDistance(structure.getLat(), structure.getLon(), lat, lon, 'M'), 10 ); return structure; @@ -72,13 +121,18 @@ export class HomeComponent implements OnInit { public getLocation(): void { navigator.geolocation.getCurrentPosition((position) => { this.geolocation = true; - const longitude = position.coords.longitude; - const latitude = position.coords.latitude; - this.getAddress(longitude, latitude); + this.userLongitude = position.coords.longitude; + this.userLatitude = position.coords.latitude; + this.getAddress(position.coords.longitude, position.coords.latitude); this.getStructures(null); }); } + /** + * Get an address by coord + * @param longitude number + * @param latitude number + */ private getAddress(longitude: number, latitude: number): void { this.geoJsonService.getAddressByCoord(longitude, latitude).subscribe( (location) => { diff --git a/src/app/map/components/map.component.ts b/src/app/map/components/map.component.ts index 6bccd2d44..875be42c0 100644 --- a/src/app/map/components/map.component.ts +++ b/src/app/map/components/map.component.ts @@ -111,8 +111,8 @@ export class MapComponent implements OnChanges { structureListe.forEach((structure: Structure) => { this.mapService .createMarker( - structure.getLon(), structure.getLat(), + structure.getLon(), MarkerType.structure, structure.id, this.buildToolTip(structure) diff --git a/src/app/map/models/addressGeometry.model.ts b/src/app/map/models/addressGeometry.model.ts index 71e1ce346..b7612f2fc 100644 --- a/src/app/map/models/addressGeometry.model.ts +++ b/src/app/map/models/addressGeometry.model.ts @@ -7,10 +7,10 @@ export class AddressGeometry { } public getLat(): number { - return this.coordinates[0]; + return this.coordinates[1]; } public getLon(): number { - return this.coordinates[1]; + return this.coordinates[0]; } } diff --git a/src/app/models/structure.model.ts b/src/app/models/structure.model.ts index bcc5b4a08..597234630 100644 --- a/src/app/models/structure.model.ts +++ b/src/app/models/structure.model.ts @@ -112,10 +112,10 @@ export class Structure { } public getLat(): number { - return this.coord[0]; + return this.coord[1]; } public getLon(): number { - return this.coord[1]; + return this.coord[0]; } } diff --git a/src/app/services/geojson.service.ts b/src/app/services/geojson.service.ts index befafee6c..5f15ae6d8 100644 --- a/src/app/services/geojson.service.ts +++ b/src/app/services/geojson.service.ts @@ -43,6 +43,16 @@ export class GeojsonService { .pipe(map((data: { features: any[] }) => _.map(data.features, this.parseToGeoJson))); } + /** + * Get GeoLocation with an address + * @param address Address + */ + public getCoord(numero: string, address: string, zipcode: string): Observable<GeoJson> { + return this.http + .get('/geocoding/photon/api' + '?q=' + numero + ' ' + address + ' ' + zipcode) + .pipe(map((data: { features: any[]; type: string }) => new GeoJson(data.features[0]))); + } + // ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: // ::: ::: // ::: This routine calculates the distance between two points (given the ::: -- GitLab