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