Skip to content
Snippets Groups Projects
Commit 397fb5f7 authored by Hugo SUBTIL's avatar Hugo SUBTIL
Browse files

feat(map): merge structre and map.

Remove useless components and structure refacto
parent 6295b528
No related branches found
No related tags found
2 merge requests!11Recette,!5Map poc
Showing
with 273 additions and 28 deletions
......@@ -1902,6 +1902,14 @@
"webpack-sources": "1.4.3"
}
},
"@ngx-translate/core": {
"version": "13.0.0",
"resolved": "https://registry.npmjs.org/@ngx-translate/core/-/core-13.0.0.tgz",
"integrity": "sha512-+tzEp8wlqEnw0Gc7jtVRAJ6RteUjXw6JJR4O65KlnxOmJrCGPI0xjV/lKRnQeU0w4i96PQs/jtpL921Wrb7PWg==",
"requires": {
"tslib": "^2.0.0"
}
},
"@nodelib/fs.scandir": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.3.tgz",
......
......@@ -3,14 +3,14 @@
"version": "0.0.3",
"scripts": {
"ng": "ng",
"start": "ng serve --configuration=fr",
"start": "ng serve --configuration=fr --proxy-config proxy.conf.json",
"build:prod": "ng build --configuration=production,fr --output-path=dist",
"build:dev": "ng build --configuration=fr --output-path=dist",
"test": "ng test",
"lint": "ng lint",
"e2e": "ng e2e",
"release": "standard-version",
"translate": "ng xi18n --output-path src/locale --out-file messages.en.xlf",
"translate": "ng xi18n --ivy --output-path src/locale --out-file messages.en.xlf",
"api": "json-server api/db.json --routes api/routes.json --no-cors=true"
},
"private": true,
......@@ -26,10 +26,11 @@
"@angular/platform-browser-dynamic": "~10.1.3",
"@angular/router": "~10.1.3",
"@asymmetrik/ngx-leaflet": "^8.1.0",
"@ngx-translate/core": "^13.0.0",
"@runette/ngx-leaflet-locate": "^1.0.3",
"json-server": "^0.16.2",
"leaflet": "^1.7.1",
"leaflet.locatecontrol": "^0.72.0",
"json-server": "^0.16.2",
"luxon": "^1.25.0",
"rxjs": "~6.6.0",
"tslib": "^2.0.0",
......
{
"/api": {
"target": "http://localhost:3000"
},
"/base-adresse/base-adresse-nationale/streets": {
"target": "https://passerelle.formulaireextranet.grandlyon.com",
"secure": false,
"changeOrigin": true,
"logLevel": "info"
},
"/geocoding/photon/api": {
"target": "https://download.data.grandlyon.com",
"secure": false,
"changeOrigin": true,
"logLevel": "info"
}
}
import { LOCALE_ID, NgModule } from '@angular/core';
import { AppRoutingModule } from './app-routing.module';
import { HttpClientModule } from '@angular/common/http';
import { BrowserModule } from '@angular/platform-browser';
import { FlexLayoutModule } from '@angular/flex-layout';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { HomeComponent } from './home/home.component';
import { CustomBreakPointsProvider } from './config/custom-breakpoint';
import { FooterComponent } from './footer/footer.component';
import { HeaderComponent } from './header/header.component';
import { SharedModule } from './shared/shared.module';
import { StructureListModule } from './structure-list/structure-list.module';
import { MapModule } from './map/map.module';
import { RechercheComponent } from './structure-list/components/recherche/recherche.component';
import { StructureListComponent } from './structure-list/structure-list.component';
import { CardComponent } from './structure-list/components/card/card.component';
@NgModule({
declarations: [AppComponent, HeaderComponent, FooterComponent, HomeComponent],
imports: [BrowserModule, AppRoutingModule, FlexLayoutModule, SharedModule, StructureListModule, MapModule],
declarations: [
AppComponent,
HeaderComponent,
FooterComponent,
HomeComponent,
StructureListComponent,
CardComponent,
RechercheComponent,
],
imports: [BrowserModule, HttpClientModule, AppRoutingModule, FlexLayoutModule, SharedModule, MapModule],
providers: [{ provide: LOCALE_ID, useValue: 'fr' }, CustomBreakPointsProvider],
bootstrap: [AppComponent],
})
......
<div fxLayout="row">
<app-structure-list class="left-pane" fxFlex="30%"></app-structure-list>
<app-map fxFlex="70%" [toogleToolTipIds]="[1, 2]"></app-map>
<app-structure-list [structureList]="structures" class="left-pane" fxFlex="30%"></app-structure-list>
<app-map fxFlex="70%" [structures]="structures"></app-map>
</div>
import { Component, OnInit } from '@angular/core';
import { mergeMap } from 'rxjs/operators';
import { Structure } from '../models/structure.model';
import { StructureService } from '../services/structure-list.service';
const { DateTime } = require('luxon');
@Component({
selector: 'app-home',
......@@ -6,7 +10,14 @@ import { Component, OnInit } from '@angular/core';
styleUrls: ['./home.component.scss'],
})
export class HomeComponent implements OnInit {
constructor() {}
public structures: Structure[] = [];
constructor(private structureService: StructureService) {}
ngOnInit(): void {}
ngOnInit(): void {
this.structureService.getStructures().subscribe((structures) => {
this.structures = structures.map((structure) =>
this.structureService.updateOpeningStructure(structure, DateTime.local())
);
});
}
}
@import '../../../assets/scss/color';
@import '../../../assets/scss/layout';
@import '../../../assets/scss/icons';
@import '../../../assets/scss/typography';
#map {
height: calc(100vh - #{$header-height} - #{$footer-height});
......@@ -48,3 +50,36 @@
}
}
}
::ng-deep .leaflet-tooltip {
padding: 8px 10px 8px 10px;
h1 {
color: $purple;
@include cn-bold-20;
margin: 0;
}
p {
color: $grey-3;
@include cn-regular-16;
margin: 0 0 13px 0;
}
div {
align-items: center;
display: flex;
}
// Find somthing better than redeclare class. Mixins ?
.ico-dot-available {
height: 12px;
width: 12px;
background-color: $green;
border-radius: 50%;
margin-right: 8px;
}
.ico-dot-unavailable {
height: 12px;
width: 12px;
background-color: $grey;
border-radius: 50%;
margin-right: 8px;
}
}
import { Component, Input, OnInit } from '@angular/core';
import { Component, Input, OnChanges, OnInit, SimpleChanges } from '@angular/core';
import { latLng, MapOptions, tileLayer, Map, CRS, TileLayer, LatLngBounds } from 'leaflet';
import { Observable } from 'rxjs';
import { mergeMap } from 'rxjs/operators';
import { Structure } from '../../models/structure.model';
import { GeoJson } from '../models/geojson.model';
import { GeojsonService } from '../services/geojson.service';
import { MapService } from '../services/map.service';
@Component({
......@@ -7,7 +12,8 @@ import { MapService } from '../services/map.service';
templateUrl: './map.component.html',
styleUrls: ['./map.component.scss'],
})
export class MapComponent implements OnInit {
export class MapComponent implements OnChanges {
@Input() public structures: Structure[] = [];
@Input() public toogleToolTipIds: Array<number> = [];
public map: Map;
public mapOptions: MapOptions;
......@@ -22,19 +28,64 @@ export class MapComponent implements OnInit {
clickBehavior: { inView: 'stop', outOfView: 'setView', inViewNotFollowing: 'setView' },
};
constructor(private mapService: MapService) {}
ngOnInit(): void {
constructor(private mapService: MapService, private geoJsonService: GeojsonService) {
this.initializeMapOptions();
}
ngOnChanges(changes: SimpleChanges): void {
if (changes.structures) {
this.getStructurePosition();
}
}
/**
* Get structures positions and add marker corresponding to those positons on the map
*/
private getStructurePosition(): void {
this.structures.forEach((element: Structure) => {
this.getCoord(element.voie).subscribe((coord: GeoJson) => {
this.mapService
.createMarker(coord.geometry.getLon(), coord.geometry.getLat(), 1, this.buildToolTip(element))
.addTo(this.map);
});
});
}
/**
* Create tooltip for display
* @param structure Structure
*/
private buildToolTip(structure: Structure): string {
const cssAvailabilityClass = structure.isOpen ? 'available' : 'unavailable';
return (
'<h1>' +
structure.nomDeVotreStructure +
'</h1>' +
'<p>' +
structure.typeDeStructure +
'</p><div>' +
'<span class="ico-dot-' +
cssAvailabilityClass +
'"></span><span>' +
structure.openDisplay() +
'</span></div>'
);
}
/**
* Get coord with a street reference
* @param idVoie Street reference
*/
public getCoord(idVoie: number): Observable<GeoJson> {
return this.geoJsonService.getAddress(idVoie).pipe(mergeMap((res) => this.geoJsonService.getCoord(res)));
}
/**
* Add marker when map is ready to be showned
* @param map map
*/
public onMapReady(map: Map): void {
this.map = map;
this.addMarker();
}
/**
......@@ -84,11 +135,4 @@ export class MapComponent implements OnInit {
this.mapService.toogleToolTip(id);
});
}
private addMarker(): void {
//TODO: Replace with real data
this.mapService.createMarker(45.764043, 4.835659, 1, '<p>Hello <br/>World !</p>').addTo(this.map);
this.mapService.createMarker(45.764043, 4.935659, 2, '<p>Hello <br/>World 2!</p>').addTo(this.map);
this.mapService.createMarker(45.664043, 4.835659, 3).addTo(this.map);
}
}
export class Address {
public id: number;
public text: string;
public type: string;
public city: string;
public citycode: string;
public zipcode: string;
constructor(obj?: any) {
Object.assign(this, obj);
}
public queryString(): string {
return this.text + ' ' + this.citycode;
}
}
export class AddressGeometry {
public coordinates: Array<number>;
public type: string;
constructor(obj?: any) {
Object.assign(this, obj);
}
public getLat(): number {
return this.coordinates[0];
}
public getLon(): number {
return this.coordinates[1];
}
}
import { AddressGeometry } from './addressGeometry.model';
export class GeoJson {
public geometry: AddressGeometry;
public type: string;
public properties: object;
constructor(obj?: any) {
Object.assign(this, obj, {
geometry: obj && obj.geometry ? new AddressGeometry(obj.geometry) : null,
});
}
}
import { TestBed } from '@angular/core/testing';
import { Address } from '../models/address.model';
import { GeojsonService } from './geojson.service';
describe('GeojsonService', () => {
let service: GeojsonService;
beforeEach(() => {
TestBed.configureTestingModule({});
service = TestBed.inject(GeojsonService);
});
it('should be created', () => {
expect(service).toBeTruthy();
});
it('should get address for id 26061 ', () => {
service.getAddress(26061).subscribe((val) => {
expect(val.zipcode).toEqual('69800');
expect(val.text).toEqual('13ème Rue Cité Berliet');
});
});
it('should get coord with query string avenue foch 69006 ', () => {
service.getCoord(new Address({ text: 'avenue foch', citycode: '69006' })).subscribe((val) => {
expect(val.geometry.getLat()).toEqual(4.8429024);
expect(val.geometry.getLon()).toEqual(45.7733884);
});
});
});
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import { Address } from '../models/address.model';
import { GeoJson } from '../models/geojson.model';
@Injectable({
providedIn: 'root',
})
export class GeojsonService {
constructor(private http: HttpClient) {}
/**
* Retrive an address with a street national reference
* @param idVoie Number
*/
public getAddress(idVoie: number): Observable<Address> {
return this.http
.get('/base-adresse/base-adresse-nationale/streets' + '?id=' + idVoie)
.pipe(map((data: { data: any[]; err: number }) => new Address(data.data[0])));
}
/**
* Get GeoLocation with an address
* @param address Address
*/
public getCoord(address: Address): Observable<GeoJson> {
return this.http
.get('/geocoding/photon/api' + '?q=' + address.queryString())
.pipe(map((data: { features: any[]; type: string }) => new GeoJson(data.features[0])));
}
}
......@@ -21,6 +21,9 @@ export class MapService {
marker.bindTooltip(tooltip);
}
this.markersList[id] = marker;
console.log('marker lat', lat);
console.log('marker lon', lon);
console.log('marker', marker);
return marker;
}
......
import { TranslateService } from '@ngx-translate/core';
import { Weekday } from '../structure-list/enum/weekday.enum';
import { Day } from './day.model';
import { OpeningDay } from './openingDay.model';
import { Weekday } from '../enum/weekday.enum';
import { Week } from './week.model';
export class Structure {
......@@ -13,7 +14,7 @@ export class Structure {
public typeDeStructure: string;
public description: string;
public n: string;
public voie: string;
public voie: number;
public telephone: string;
public courriel: string;
public siteWeb: string;
......@@ -32,7 +33,7 @@ export class Structure {
public isOpen: boolean;
public openedOn: OpeningDay;
constructor(obj?: any) {
constructor(obj?: any, private translateService: TranslateService) {
Object.assign(this, obj, {
hours: obj && obj.hours ? new Week(obj.hours) : null,
});
......@@ -58,4 +59,14 @@ export class Structure {
return null;
}
}
public openDisplay(): string {
if (this.isOpen) {
return 'Ouvert actuellement ';
} else if (this.openedOn.day) {
return 'Fermé - Ouvre ' + this.openedOn.day + ' à ' + this.openedOn.schedule;
} else {
return 'Fermé - Aucun horaire disponible ';
}
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment