From d5b012236c287f47c085bbec1b38ea6c8629fd0b Mon Sep 17 00:00:00 2001 From: Jeremie BRISON <ext.sopra.jbrison@grandlyon.com> Date: Thu, 8 Oct 2020 10:31:10 +0200 Subject: [PATCH 01/50] init --- src/app/app.module.ts | 3 ++- src/app/home/home.component.html | 2 +- .../components/card/card.component.html | 1 + .../components/card/card.component.scss | 0 .../components/card/card.component.spec.ts | 25 +++++++++++++++++++ .../components/card/card.component.ts | 15 +++++++++++ .../recherche/recherche.component.html | 1 + .../recherche/recherche.component.scss | 0 .../recherche/recherche.component.spec.ts | 25 +++++++++++++++++++ .../recherche/recherche.component.ts | 15 +++++++++++ .../services/structure.service.spec.ts | 16 ++++++++++++ .../structure/services/structure.service.ts | 9 +++++++ src/app/structure/structure.component.html | 2 ++ src/app/structure/structure.component.scss | 0 src/app/structure/structure.component.spec.ts | 25 +++++++++++++++++++ src/app/structure/structure.component.ts | 15 +++++++++++ src/app/structure/structure.module.ts | 12 +++++++++ 17 files changed, 164 insertions(+), 2 deletions(-) create mode 100644 src/app/structure/components/card/card.component.html create mode 100644 src/app/structure/components/card/card.component.scss create mode 100644 src/app/structure/components/card/card.component.spec.ts create mode 100644 src/app/structure/components/card/card.component.ts create mode 100644 src/app/structure/components/recherche/recherche.component.html create mode 100644 src/app/structure/components/recherche/recherche.component.scss create mode 100644 src/app/structure/components/recherche/recherche.component.spec.ts create mode 100644 src/app/structure/components/recherche/recherche.component.ts create mode 100644 src/app/structure/services/structure.service.spec.ts create mode 100644 src/app/structure/services/structure.service.ts create mode 100644 src/app/structure/structure.component.html create mode 100644 src/app/structure/structure.component.scss create mode 100644 src/app/structure/structure.component.spec.ts create mode 100644 src/app/structure/structure.component.ts create mode 100644 src/app/structure/structure.module.ts diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 4ad3e8861..9d221fe1a 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -11,10 +11,11 @@ import { StructureListComponent } from './structure-list/structure-list.componen import { FooterComponent } from './footer/footer.component'; import { HeaderComponent } from './header/header.component'; import { SharedModule } from './shared/shared.module'; +import { StructureModule } from './structure/structure.module'; @NgModule({ declarations: [AppComponent, HeaderComponent, FooterComponent, HomeComponent, StructureListComponent], - imports: [BrowserModule, AppRoutingModule, FlexLayoutModule, SharedModule], + imports: [BrowserModule, AppRoutingModule, FlexLayoutModule, SharedModule, StructureModule], providers: [{ provide: LOCALE_ID, useValue: 'fr' }, CustomBreakPointsProvider], bootstrap: [AppComponent], }) diff --git a/src/app/home/home.component.html b/src/app/home/home.component.html index 4f2ba48bc..a1abb68dc 100644 --- a/src/app/home/home.component.html +++ b/src/app/home/home.component.html @@ -1,5 +1,5 @@ <div class="content-container"> <div class="section-container"> - <p>Home works!</p> + <app-structure></app-structure> </div> </div> diff --git a/src/app/structure/components/card/card.component.html b/src/app/structure/components/card/card.component.html new file mode 100644 index 000000000..8071bfcce --- /dev/null +++ b/src/app/structure/components/card/card.component.html @@ -0,0 +1 @@ +<p>card wsdorks!</p> diff --git a/src/app/structure/components/card/card.component.scss b/src/app/structure/components/card/card.component.scss new file mode 100644 index 000000000..e69de29bb diff --git a/src/app/structure/components/card/card.component.spec.ts b/src/app/structure/components/card/card.component.spec.ts new file mode 100644 index 000000000..3093fd5a3 --- /dev/null +++ b/src/app/structure/components/card/card.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { CardComponent } from './card.component'; + +describe('CardComponent', () => { + let component: CardComponent; + let fixture: ComponentFixture<CardComponent>; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ CardComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(CardComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/structure/components/card/card.component.ts b/src/app/structure/components/card/card.component.ts new file mode 100644 index 000000000..07a9ab07e --- /dev/null +++ b/src/app/structure/components/card/card.component.ts @@ -0,0 +1,15 @@ +import { Component, OnInit } from '@angular/core'; + +@Component({ + selector: 'app-card', + templateUrl: './card.component.html', + styleUrls: ['./card.component.scss'] +}) +export class CardComponent implements OnInit { + + constructor() { } + + ngOnInit(): void { + } + +} diff --git a/src/app/structure/components/recherche/recherche.component.html b/src/app/structure/components/recherche/recherche.component.html new file mode 100644 index 000000000..63c7b1a72 --- /dev/null +++ b/src/app/structure/components/recherche/recherche.component.html @@ -0,0 +1 @@ +<p>recherche works!</p> diff --git a/src/app/structure/components/recherche/recherche.component.scss b/src/app/structure/components/recherche/recherche.component.scss new file mode 100644 index 000000000..e69de29bb diff --git a/src/app/structure/components/recherche/recherche.component.spec.ts b/src/app/structure/components/recherche/recherche.component.spec.ts new file mode 100644 index 000000000..e38e4d4e8 --- /dev/null +++ b/src/app/structure/components/recherche/recherche.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { RechercheComponent } from './recherche.component'; + +describe('RechercheComponent', () => { + let component: RechercheComponent; + let fixture: ComponentFixture<RechercheComponent>; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ RechercheComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(RechercheComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/structure/components/recherche/recherche.component.ts b/src/app/structure/components/recherche/recherche.component.ts new file mode 100644 index 000000000..b37a52c87 --- /dev/null +++ b/src/app/structure/components/recherche/recherche.component.ts @@ -0,0 +1,15 @@ +import { Component, OnInit } from '@angular/core'; + +@Component({ + selector: 'app-recherche', + templateUrl: './recherche.component.html', + styleUrls: ['./recherche.component.scss'] +}) +export class RechercheComponent implements OnInit { + + constructor() { } + + ngOnInit(): void { + } + +} diff --git a/src/app/structure/services/structure.service.spec.ts b/src/app/structure/services/structure.service.spec.ts new file mode 100644 index 000000000..d44ef8feb --- /dev/null +++ b/src/app/structure/services/structure.service.spec.ts @@ -0,0 +1,16 @@ +import { TestBed } from '@angular/core/testing'; + +import { StructureService } from './structure.service'; + +describe('StructureService', () => { + let service: StructureService; + + beforeEach(() => { + TestBed.configureTestingModule({}); + service = TestBed.inject(StructureService); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); +}); diff --git a/src/app/structure/services/structure.service.ts b/src/app/structure/services/structure.service.ts new file mode 100644 index 000000000..8a09d6adb --- /dev/null +++ b/src/app/structure/services/structure.service.ts @@ -0,0 +1,9 @@ +import { Injectable } from '@angular/core'; + +@Injectable({ + providedIn: 'root' +}) +export class StructureService { + + constructor() { } +} diff --git a/src/app/structure/structure.component.html b/src/app/structure/structure.component.html new file mode 100644 index 000000000..8688da6ce --- /dev/null +++ b/src/app/structure/structure.component.html @@ -0,0 +1,2 @@ +<app-card></app-card> +<app-recherche></app-recherche> diff --git a/src/app/structure/structure.component.scss b/src/app/structure/structure.component.scss new file mode 100644 index 000000000..e69de29bb diff --git a/src/app/structure/structure.component.spec.ts b/src/app/structure/structure.component.spec.ts new file mode 100644 index 000000000..47da9d53d --- /dev/null +++ b/src/app/structure/structure.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { StructureComponent } from './structure.component'; + +describe('StructureComponent', () => { + let component: StructureComponent; + let fixture: ComponentFixture<StructureComponent>; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ StructureComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(StructureComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/structure/structure.component.ts b/src/app/structure/structure.component.ts new file mode 100644 index 000000000..c74423ddc --- /dev/null +++ b/src/app/structure/structure.component.ts @@ -0,0 +1,15 @@ +import { Component, OnInit } from '@angular/core'; + +@Component({ + selector: 'app-structure', + templateUrl: './structure.component.html', + styleUrls: ['./structure.component.scss'] +}) +export class StructureComponent implements OnInit { + + constructor() { } + + ngOnInit(): void { + } + +} diff --git a/src/app/structure/structure.module.ts b/src/app/structure/structure.module.ts new file mode 100644 index 000000000..902f040cd --- /dev/null +++ b/src/app/structure/structure.module.ts @@ -0,0 +1,12 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { StructureComponent } from './structure.component'; +import { CardComponent } from './components/card/card.component'; +import { RechercheComponent } from './components/recherche/recherche.component'; + +@NgModule({ + declarations: [StructureComponent, CardComponent, RechercheComponent], + imports: [CommonModule], + exports: [StructureComponent], +}) +export class StructureModule {} -- GitLab From 960ae5df57c60ef44f486d077078fe1876092163 Mon Sep 17 00:00:00 2001 From: Jeremie BRISON <ext.sopra.jbrison@grandlyon.com> Date: Thu, 8 Oct 2020 10:47:14 +0200 Subject: [PATCH 02/50] feat(api): Mise en place d'une solution mock --- angular.json | 3 +- api/db.json | 58 + api/routes.json | 3 + package-lock.json | 1195 ++++++++++++++--- package.json | 4 +- proxy.conf.json | 5 + .../components/card/card.component.html | 18 +- .../components/card/card.component.scss | 22 + .../components/card/card.component.ts | 17 +- src/app/structure/models/structure.model.ts | 27 + src/app/structure/structure.component.html | 2 +- src/app/structure/structure.module.ts | 3 +- 12 files changed, 1187 insertions(+), 170 deletions(-) create mode 100644 api/db.json create mode 100644 api/routes.json create mode 100644 proxy.conf.json create mode 100644 src/app/structure/models/structure.model.ts diff --git a/angular.json b/angular.json index 79beada28..1761772a3 100644 --- a/angular.json +++ b/angular.json @@ -74,7 +74,8 @@ "serve": { "builder": "@angular-devkit/build-angular:dev-server", "options": { - "browserTarget": "pamn:build" + "browserTarget": "pamn:build", + "proxyConfig": "proxy.conf.json" }, "configurations": { "production": { diff --git a/api/db.json b/api/db.json new file mode 100644 index 000000000..e41fd2d32 --- /dev/null +++ b/api/db.json @@ -0,0 +1,58 @@ +{ + "structure": [ + { + "id": "26-28", + "created_on": "22/09/2020 16:01", + "last_modif": "22/09/2020 16:01", + "owner": "-", + "status": "Un établissement principal (siège social)", + "nom": "Labit", + "type_structure": "MDM", + "description": "Ouvert à toute heure", + "num": "12", + "voie": "27838 Avenue Lacassagne", + "telephone": "0134257645", + "courriel": "coop.labit@gmail.com", + "site_web": "", + "facebook": "", + "twitter": "", + "instagram": "", + "civilite_contact": "Madame", + "nom_contact": "Labit", + "prenom_contact": "Valentine", + "email_contact": "coop.labit@gmail.com", + "fonction_contact": "Président de l'association", + "pmr": true, + "je_fais_a_la_place_de_lusager": true, + "accompagnement_aux_demarches": ["Pôle Emploi", "CPAM", "Impôts", "Logement"], + "wifi": true + }, + { + "id": "26-10", + "created_on": "03/09/2020 14:14", + "last_modif": "03/09/2020 14:15", + "owner": "Marlène Simondant", + "status": "Un établissement principal (siège social)", + "nom": "fgh", + "type_structure": "Bibliothèque", + "description": "", + "num": "", + "voie": "26061 13ème Rue Cité Berliet", + "telephone": "0659856235", + "courriel": "test@test.te", + "site_web": "", + "facebook": "", + "twitter": "", + "instagram": "", + "civilite_contact": "", + "nom_contact": "dh", + "prenom_contact": "fxh", + "email_contact": "test@test.te", + "fonction_contact": "Bénévole", + "pmr": false, + "je_fais_a_la_place_de_lusager": false, + "accompagnement_aux_demarches": ["CPAM"], + "wifi": false + } + ] +} diff --git a/api/routes.json b/api/routes.json new file mode 100644 index 000000000..6a7af55fa --- /dev/null +++ b/api/routes.json @@ -0,0 +1,3 @@ +{ + "/api/*": "/$1" +} diff --git a/package-lock.json b/package-lock.json index 3cc3d6852..b09f84a5a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1967,6 +1967,19 @@ "semver-intersect": "1.4.0" } }, + "@sindresorhus/is": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", + "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==" + }, + "@szmarczak/http-timer": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz", + "integrity": "sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==", + "requires": { + "defer-to-connect": "^1.0.1" + } + }, "@types/color-name": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz", @@ -2278,7 +2291,6 @@ "version": "1.3.7", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", - "dev": true, "requires": { "mime-types": "~2.1.24", "negotiator": "0.6.2" @@ -2413,6 +2425,14 @@ "integrity": "sha1-l6ERlkmyEa0zaR2fn0hqjsn74KM=", "dev": true }, + "ansi-align": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.0.tgz", + "integrity": "sha512-ZpClVKqXN3RGBmKibdfWzqCY4lnjEuoNzU5T0oEFpfd/z5qJHVarukridD4juLO2FXMiwUQxr9WqQtaYa8XRYw==", + "requires": { + "string-width": "^3.0.0" + } + }, "ansi-colors": { "version": "3.2.4", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.4.tgz", @@ -2839,6 +2859,14 @@ "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==", "dev": true }, + "basic-auth": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz", + "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==", + "requires": { + "safe-buffer": "5.1.2" + } + }, "batch": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", @@ -2906,7 +2934,6 @@ "version": "1.19.0", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", - "dev": true, "requires": { "bytes": "3.1.0", "content-type": "~1.0.4", @@ -2923,14 +2950,12 @@ "bytes": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", - "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", - "dev": true + "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==" }, "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, "requires": { "ms": "2.0.0" } @@ -2939,7 +2964,6 @@ "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dev": true, "requires": { "safer-buffer": ">= 2.1.2 < 3" } @@ -2947,8 +2971,7 @@ "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" } } }, @@ -2972,6 +2995,109 @@ "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=", "dev": true }, + "boxen": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-4.2.0.tgz", + "integrity": "sha512-eB4uT9RGzg2odpER62bBwSLvUeGC+WbRjjyyFhGsKnc8wp/m0+hQsMUvUe3H2V0D5vw0nBdO1hCJoZo5mKeuIQ==", + "requires": { + "ansi-align": "^3.0.0", + "camelcase": "^5.3.1", + "chalk": "^3.0.0", + "cli-boxes": "^2.2.0", + "string-width": "^4.1.0", + "term-size": "^2.1.0", + "type-fest": "^0.8.1", + "widest-line": "^3.1.0" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==" + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==" + }, + "chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" + }, + "string-width": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", + "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + } + }, + "strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "requires": { + "ansi-regex": "^5.0.0" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "requires": { + "has-flag": "^4.0.0" + } + }, + "type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==" + } + } + }, "brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -3168,8 +3294,7 @@ "bytes": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", - "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=", - "dev": true + "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=" }, "cacache": { "version": "15.0.5", @@ -3221,6 +3346,45 @@ "unset-value": "^1.0.0" } }, + "cacheable-request": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz", + "integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==", + "requires": { + "clone-response": "^1.0.2", + "get-stream": "^5.1.0", + "http-cache-semantics": "^4.0.0", + "keyv": "^3.0.0", + "lowercase-keys": "^2.0.0", + "normalize-url": "^4.1.0", + "responselike": "^1.0.2" + }, + "dependencies": { + "get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "requires": { + "pump": "^3.0.0" + } + }, + "http-cache-semantics": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", + "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==" + }, + "lowercase-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", + "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==" + }, + "normalize-url": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.0.tgz", + "integrity": "sha512-2s47yzUxdexf1OhyRi4Em83iQk0aPvwTddtFz4hnSSw9dCEsLEGf6SwIO8ss/19S9iBb5sJaOuTvTGDeZI00BQ==" + } + } + }, "caller-callsite": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/caller-callsite/-/caller-callsite-2.0.0.tgz", @@ -3362,6 +3526,11 @@ } } }, + "ci-info": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", + "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==" + }, "cipher-base": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", @@ -3407,6 +3576,11 @@ "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", "dev": true }, + "cli-boxes": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.1.tgz", + "integrity": "sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==" + }, "cli-cursor": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", @@ -3462,6 +3636,14 @@ "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=", "dev": true }, + "clone-response": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", + "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=", + "requires": { + "mimic-response": "^1.0.0" + } + }, "coa": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/coa/-/coa-2.0.2.tgz", @@ -3646,7 +3828,6 @@ "version": "2.0.18", "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", - "dev": true, "requires": { "mime-db": ">= 1.43.0 < 2" } @@ -3655,7 +3836,6 @@ "version": "1.7.4", "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", - "dev": true, "requires": { "accepts": "~1.3.5", "bytes": "3.0.0", @@ -3670,7 +3850,6 @@ "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, "requires": { "ms": "2.0.0" } @@ -3678,8 +3857,7 @@ "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" } } }, @@ -3701,6 +3879,34 @@ "typedarray": "^0.0.6" } }, + "configstore": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/configstore/-/configstore-5.0.1.tgz", + "integrity": "sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA==", + "requires": { + "dot-prop": "^5.2.0", + "graceful-fs": "^4.1.2", + "make-dir": "^3.0.0", + "unique-string": "^2.0.0", + "write-file-atomic": "^3.0.0", + "xdg-basedir": "^4.0.0" + }, + "dependencies": { + "make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "requires": { + "semver": "^6.0.0" + } + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" + } + } + }, "connect": { "version": "3.7.0", "resolved": "https://registry.npmjs.org/connect/-/connect-3.7.0.tgz", @@ -3736,6 +3942,11 @@ "integrity": "sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg==", "dev": true }, + "connect-pause": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/connect-pause/-/connect-pause-0.1.1.tgz", + "integrity": "sha1-smmyu4Ldsaw9tQmcD7WCq6mfs3o=" + }, "console-browserify": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.2.0.tgz", @@ -3752,7 +3963,6 @@ "version": "0.5.3", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", - "dev": true, "requires": { "safe-buffer": "5.1.2" } @@ -3760,8 +3970,7 @@ "content-type": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", - "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", - "dev": true + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" }, "conventional-changelog": { "version": "3.1.23", @@ -4040,14 +4249,12 @@ "cookie": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", - "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==", - "dev": true + "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==" }, "cookie-signature": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=", - "dev": true + "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" }, "copy-concurrently": { "version": "1.0.5", @@ -4140,6 +4347,15 @@ "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", "dev": true }, + "cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "requires": { + "object-assign": "^4", + "vary": "^1" + } + }, "cosmiconfig": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.2.1.tgz", @@ -4237,6 +4453,11 @@ "randomfill": "^1.0.3" } }, + "crypto-random-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", + "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==" + }, "css": { "version": "2.2.4", "resolved": "https://registry.npmjs.org/css/-/css-2.2.4.tgz", @@ -4561,7 +4782,6 @@ "version": "4.2.0", "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz", "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==", - "dev": true, "requires": { "ms": "2.1.2" } @@ -4575,8 +4795,7 @@ "decamelize": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", - "dev": true + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" }, "decamelize-keys": { "version": "1.1.0", @@ -4602,6 +4821,14 @@ "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", "dev": true }, + "decompress-response": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", + "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", + "requires": { + "mimic-response": "^1.0.0" + } + }, "deep-equal": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.1.tgz", @@ -4616,6 +4843,11 @@ "regexp.prototype.flags": "^1.2.0" } }, + "deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==" + }, "default-gateway": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-4.2.0.tgz", @@ -4643,6 +4875,11 @@ } } }, + "defer-to-connect": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz", + "integrity": "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==" + }, "define-properties": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", @@ -4764,8 +5001,7 @@ "depd": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", - "dev": true + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" }, "dependency-graph": { "version": "0.7.2", @@ -4786,8 +5022,7 @@ "destroy": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", - "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=", - "dev": true + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" }, "detect-indent": { "version": "6.0.0", @@ -4938,7 +5173,6 @@ "version": "5.3.0", "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", - "dev": true, "requires": { "is-obj": "^2.0.0" } @@ -4953,6 +5187,11 @@ "minimatch": "^3.0.4" } }, + "duplexer3": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", + "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=" + }, "duplexify": { "version": "3.7.1", "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", @@ -4978,8 +5217,7 @@ "ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", - "dev": true + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" }, "electron-to-chromium": { "version": "1.3.573", @@ -5013,8 +5251,7 @@ "emoji-regex": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", - "dev": true + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==" }, "emojis-list": { "version": "3.0.0", @@ -5025,8 +5262,7 @@ "encodeurl": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", - "dev": true + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" }, "encoding": { "version": "0.1.13", @@ -5041,7 +5277,6 @@ "version": "1.4.4", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "dev": true, "requires": { "once": "^1.4.0" } @@ -5182,6 +5417,15 @@ "is-arrayish": "^0.2.1" } }, + "errorhandler": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/errorhandler/-/errorhandler-1.5.1.tgz", + "integrity": "sha512-rcOwbfvP1WTViVoUjcfZicVzjhjTuhSMntHh6mW3IrEiyE6mJyXvsToJUJGlGlw/2xU9P5whlWNGlIDVeCiT4A==", + "requires": { + "accepts": "~1.3.7", + "escape-html": "~1.0.3" + } + }, "es-abstract": { "version": "1.18.0-next.0", "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.0.tgz", @@ -5266,11 +5510,15 @@ "integrity": "sha512-mAk+hPSO8fLDkhV7V0dXazH5pDc6MrjBTPyD3VeKzxnVFjH1MIxbCdqGZB9O8+EwWakZs3ZCbDS4IpRt79V1ig==", "dev": true }, + "escape-goat": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/escape-goat/-/escape-goat-2.1.1.tgz", + "integrity": "sha512-8/uIhbG12Csjy2JEW7D9pHbreaVaS/OpN3ycnyvElTdwM5n6GY6W6e2IPemfvGZeUMqZ9A/3GqIZMgKnBhAw/Q==" + }, "escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=", - "dev": true + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" }, "escape-string-regexp": { "version": "1.0.5", @@ -5326,8 +5574,7 @@ "etag": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", - "dev": true + "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" }, "eventemitter3": { "version": "4.0.7", @@ -5435,7 +5682,6 @@ "version": "4.17.1", "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", - "dev": true, "requires": { "accepts": "~1.3.7", "array-flatten": "1.1.1", @@ -5472,14 +5718,12 @@ "array-flatten": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=", - "dev": true + "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" }, "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, "requires": { "ms": "2.0.0" } @@ -5487,8 +5731,31 @@ "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + } + } + }, + "express-urlrewrite": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/express-urlrewrite/-/express-urlrewrite-1.3.0.tgz", + "integrity": "sha512-xy3WZqA9EIfb51FkL1R0EqW91Z8lMi9ohp/WrNxKukvQulybqvh7+OsGiw9JOD51NrGsSuWi2hqOv7GW+DGz1w==", + "requires": { + "debug": "*", + "path-to-regexp": "^1.0.3" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + }, + "path-to-regexp": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", + "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", + "requires": { + "isarray": "0.0.1" + } } } }, @@ -5717,7 +5984,6 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", - "dev": true, "requires": { "debug": "2.6.9", "encodeurl": "~1.0.2", @@ -5732,7 +5998,6 @@ "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, "requires": { "ms": "2.0.0" } @@ -5740,8 +6005,7 @@ "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" } } }, @@ -5873,8 +6137,7 @@ "forwarded": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", - "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=", - "dev": true + "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=" }, "fragment-cache": { "version": "0.2.1", @@ -5888,8 +6151,7 @@ "fresh": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", - "dev": true + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" }, "from2": { "version": "2.3.0", @@ -5976,8 +6238,7 @@ "get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==" }, "get-pkg-repo": { "version": "1.4.0", @@ -6141,7 +6402,6 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", - "dev": true, "requires": { "pump": "^3.0.0" } @@ -6328,6 +6588,14 @@ "is-glob": "^4.0.1" } }, + "global-dirs": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-2.0.1.tgz", + "integrity": "sha512-5HqUqdhkEovj2Of/ms3IeS/EekcO54ytHRLV4PEY2rhRwrHXLQjeVEES0Lhka0xwNDtGYn58wyC4s5+MHsOO6A==", + "requires": { + "ini": "^1.3.5" + } + }, "globals": { "version": "11.12.0", "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", @@ -6348,11 +6616,28 @@ "slash": "^3.0.0" } }, + "got": { + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", + "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==", + "requires": { + "@sindresorhus/is": "^0.14.0", + "@szmarczak/http-timer": "^1.1.2", + "cacheable-request": "^6.0.0", + "decompress-response": "^3.3.0", + "duplexer3": "^0.1.4", + "get-stream": "^4.1.0", + "lowercase-keys": "^1.0.1", + "mimic-response": "^1.0.1", + "p-cancelable": "^1.0.0", + "to-readable-stream": "^1.0.0", + "url-parse-lax": "^3.0.0" + } + }, "graceful-fs": { "version": "4.2.4", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", - "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", - "dev": true + "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==" }, "handle-thing": { "version": "2.0.1", @@ -6508,6 +6793,11 @@ } } }, + "has-yarn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/has-yarn/-/has-yarn-2.1.0.tgz", + "integrity": "sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw==" + }, "hash-base": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", @@ -6632,7 +6922,6 @@ "version": "1.7.2", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", - "dev": true, "requires": { "depd": "~1.1.2", "inherits": "2.0.3", @@ -6644,8 +6933,7 @@ "inherits": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", - "dev": true + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" } } }, @@ -6937,6 +7225,11 @@ "resolve-from": "^3.0.0" } }, + "import-lazy": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz", + "integrity": "sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM=" + }, "import-local": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/import-local/-/import-local-2.0.0.tgz", @@ -6950,8 +7243,7 @@ "imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", - "dev": true + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=" }, "indent-string": { "version": "4.0.0", @@ -6996,8 +7288,7 @@ "ini": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", - "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", - "dev": true + "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==" }, "inquirer": { "version": "7.3.3", @@ -7150,8 +7441,7 @@ "ipaddr.js": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", - "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", - "dev": true + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" }, "is-absolute-url": { "version": "2.1.0", @@ -7212,6 +7502,14 @@ "integrity": "sha512-dnMqspv5nU3LoewK2N/y7KLtxtakvTuaCsU9FU50/QDmdbHNy/4/JuRtMHqRU22o3q+W89YQndQEeCVwK+3qrA==", "dev": true }, + "is-ci": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", + "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==", + "requires": { + "ci-info": "^2.0.0" + } + }, "is-color-stop": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-color-stop/-/is-color-stop-1.1.0.tgz", @@ -7304,8 +7602,7 @@ "is-fullwidth-code-point": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" }, "is-glob": { "version": "4.0.1", @@ -7316,6 +7613,22 @@ "is-extglob": "^2.1.1" } }, + "is-installed-globally": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.3.2.tgz", + "integrity": "sha512-wZ8x1js7Ia0kecP/CHM/3ABkAmujX7WPvQk6uu3Fly/Mk44pySulQpnHG46OMjHGXApINnV4QhY3SWnECO2z5g==", + "requires": { + "global-dirs": "^2.0.1", + "is-path-inside": "^3.0.1" + }, + "dependencies": { + "is-path-inside": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.2.tgz", + "integrity": "sha512-/2UGPSgmtqwo1ktx8NDHjuPwZWmHhO+gj0f93EkhLB5RgW9RZevWYYlIkS6zePc6U2WpOdQYIwHe9YC4DWEBVg==" + } + } + }, "is-interactive": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", @@ -7328,6 +7641,11 @@ "integrity": "sha1-lVOxIbD6wohp2p7UWeIMdUN4hGE=", "dev": true }, + "is-npm": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-4.0.0.tgz", + "integrity": "sha512-96ECIfh9xtDDlPylNPXhzjsykHsMJZ18ASpaWzQyBr4YRTcVjUvzaHayDAES2oU/3KpljhHUjtSRNiDwi0F0ig==" + }, "is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", @@ -7337,8 +7655,7 @@ "is-obj": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", - "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", - "dev": true + "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==" }, "is-path-cwd": { "version": "2.2.0", @@ -7379,6 +7696,11 @@ "isobject": "^3.0.1" } }, + "is-promise": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", + "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==" + }, "is-regex": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz", @@ -7430,8 +7752,7 @@ "is-typedarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", - "dev": true + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" }, "is-utf8": { "version": "0.2.1", @@ -7454,6 +7775,11 @@ "is-docker": "^2.0.0" } }, + "is-yarn-global": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/is-yarn-global/-/is-yarn-global-0.3.0.tgz", + "integrity": "sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw==" + }, "isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", @@ -7667,6 +7993,11 @@ } } }, + "jju": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/jju/-/jju-1.4.0.tgz", + "integrity": "sha1-o6vicYryQaKykE+EpiWXDzia4yo=" + }, "js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -7695,6 +8026,11 @@ "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", "dev": true }, + "json-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", + "integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=" + }, "json-parse-better-errors": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", @@ -7707,6 +8043,14 @@ "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", "dev": true }, + "json-parse-helpfulerror": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/json-parse-helpfulerror/-/json-parse-helpfulerror-1.0.3.tgz", + "integrity": "sha1-E/FM4C7tTpgSl7ZOueO5MuLdE9w=", + "requires": { + "jju": "^1.1.0" + } + }, "json-schema": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", @@ -7719,6 +8063,193 @@ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", "dev": true }, + "json-server": { + "version": "0.16.2", + "resolved": "https://registry.npmjs.org/json-server/-/json-server-0.16.2.tgz", + "integrity": "sha512-USmSODvmBvt9Z7M3e4AHGHzLBcFlNkQMVOOqtB/h/k79JQI4saPcWniYvD5zf0kE3oGNR9VJzcHKzT8fZ9kEtw==", + "requires": { + "body-parser": "^1.19.0", + "chalk": "^3.0.0", + "compression": "^1.7.4", + "connect-pause": "^0.1.1", + "cors": "^2.8.5", + "errorhandler": "^1.5.1", + "express": "^4.17.1", + "express-urlrewrite": "^1.2.0", + "json-parse-helpfulerror": "^1.0.3", + "lodash": "^4.17.15", + "lodash-id": "^0.14.0", + "lowdb": "^1.0.0", + "method-override": "^3.0.0", + "morgan": "^1.9.1", + "nanoid": "^2.1.11", + "please-upgrade-node": "^3.2.0", + "pluralize": "^8.0.0", + "server-destroy": "^1.0.1", + "update-notifier": "^4.0.0", + "yargs": "^15.1.0" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==" + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==" + }, + "chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "cliui": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "requires": { + "p-locate": "^4.1.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "requires": { + "p-limit": "^2.2.0" + } + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==" + }, + "string-width": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", + "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + } + }, + "strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "requires": { + "ansi-regex": "^5.0.0" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "requires": { + "has-flag": "^4.0.0" + } + }, + "wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + }, + "yargs": { + "version": "15.4.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", + "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", + "requires": { + "cliui": "^6.0.0", + "decamelize": "^1.2.0", + "find-up": "^4.1.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^4.2.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^18.1.2" + } + }, + "yargs-parser": { + "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + } + } + }, "json-stringify-safe": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", @@ -8040,6 +8571,14 @@ "source-map-support": "^0.5.5" } }, + "keyv": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz", + "integrity": "sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==", + "requires": { + "json-buffer": "3.0.0" + } + }, "killable": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/killable/-/killable-1.0.1.tgz", @@ -8058,6 +8597,14 @@ "integrity": "sha512-ZRbnvdg/NxqzC7L9Uyqzf4psi1OM4Cuc+sJAkQPjO6XkQIJTNbfK2Rsmbw8fx1p2mkZdp2FZYo2+LwXYY/uwIA==", "dev": true }, + "latest-version": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-5.1.0.tgz", + "integrity": "sha512-weT+r0kTkRQdCdYCNtkMwWXQTMEswKrFBkm4ckQOMVhhqhIMI1UT2hMj+1iigIhgSZm5gTmrRXBNoGUgaTY1xA==", + "requires": { + "package-json": "^6.3.0" + } + }, "less": { "version": "3.12.2", "resolved": "https://registry.npmjs.org/less/-/less-3.12.2.tgz", @@ -8201,8 +8748,12 @@ "lodash": { "version": "4.17.20", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", - "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==", - "dev": true + "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==" + }, + "lodash-id": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/lodash-id/-/lodash-id-0.14.0.tgz", + "integrity": "sha1-uvSJNOVDobXWNG+MhGmLGoyAOJY=" }, "lodash._reinterpolate": { "version": "3.0.0", @@ -8358,6 +8909,30 @@ "signal-exit": "^3.0.0" } }, + "lowdb": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lowdb/-/lowdb-1.0.0.tgz", + "integrity": "sha512-2+x8esE/Wb9SQ1F9IHaYWfsC9FIecLOPrK4g17FGEayjUWH172H6nwicRovGvSE2CPZouc2MCIqCI7h9d+GftQ==", + "requires": { + "graceful-fs": "^4.1.3", + "is-promise": "^2.1.0", + "lodash": "4", + "pify": "^3.0.0", + "steno": "^0.4.1" + }, + "dependencies": { + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=" + } + } + }, + "lowercase-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", + "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==" + }, "lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", @@ -8524,8 +9099,7 @@ "media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", - "dev": true + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" }, "memory-fs": { "version": "0.5.0", @@ -8668,8 +9242,7 @@ "merge-descriptors": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=", - "dev": true + "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" }, "merge-source-map": { "version": "1.1.0", @@ -8700,11 +9273,36 @@ "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", "dev": true }, + "method-override": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/method-override/-/method-override-3.0.0.tgz", + "integrity": "sha512-IJ2NNN/mSl9w3kzWB92rcdHpz+HjkxhDJWNDBqSlas+zQdP8wBiJzITPg08M/k2uVvMow7Sk41atndNtt/PHSA==", + "requires": { + "debug": "3.1.0", + "methods": "~1.1.2", + "parseurl": "~1.3.2", + "vary": "~1.1.2" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + } + } + }, "methods": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", - "dev": true + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" }, "micromatch": { "version": "4.0.2", @@ -8737,20 +9335,17 @@ "mime": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "dev": true + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" }, "mime-db": { "version": "1.44.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz", - "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==", - "dev": true + "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==" }, "mime-types": { "version": "2.1.27", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz", "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==", - "dev": true, "requires": { "mime-db": "1.44.0" } @@ -8761,6 +9356,11 @@ "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", "dev": true }, + "mimic-response": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==" + }, "min-indent": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", @@ -8848,8 +9448,7 @@ "minimist": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", - "dev": true + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" }, "minimist-options": { "version": "4.1.0", @@ -8962,6 +9561,38 @@ "integrity": "sha512-xV2bxeN6F7oYjZWTe/YPAy6MN2M+sL4u/Rlm2AHCIVGfo2p1yGmBHQ6vHehl4bRTZBdHu3TSkWdYgkwpYzAGSw==", "dev": true }, + "morgan": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.10.0.tgz", + "integrity": "sha512-AbegBVI4sh6El+1gNwvD5YIck7nSA36weD7xvIxG4in80j/UoK8AEGaWnnz8v1GxonMCltmlNs5ZKbGvl9b1XQ==", + "requires": { + "basic-auth": "~2.0.1", + "debug": "2.6.9", + "depd": "~2.0.0", + "on-finished": "~2.3.0", + "on-headers": "~1.0.2" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + } + } + }, "move-concurrently": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", @@ -8990,8 +9621,7 @@ "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "multicast-dns": { "version": "6.2.3", @@ -9015,6 +9645,11 @@ "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", "dev": true }, + "nanoid": { + "version": "2.1.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-2.1.11.tgz", + "integrity": "sha512-s/snB+WGm6uwi0WjsZdaVcuf3KJXlfGl2LcxgwkEwJF0D/BWzVWAZW/XY4bFaiR7s0Jk3FPvlnepg1H1b1UwlA==" + }, "nanomatch": { "version": "1.2.13", "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", @@ -9044,8 +9679,7 @@ "negotiator": { "version": "0.6.2", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", - "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==", - "dev": true + "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==" }, "neo-async": { "version": "2.6.2", @@ -9350,8 +9984,7 @@ "object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "dev": true + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" }, "object-component": { "version": "0.0.3", @@ -9543,7 +10176,6 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", - "dev": true, "requires": { "ee-first": "1.1.1" } @@ -9551,14 +10183,12 @@ "on-headers": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", - "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", - "dev": true + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==" }, "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, "requires": { "wrappy": "1" } @@ -9719,6 +10349,11 @@ "os-tmpdir": "^1.0.0" } }, + "p-cancelable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz", + "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==" + }, "p-finally": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", @@ -9729,7 +10364,6 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, "requires": { "p-try": "^2.0.0" } @@ -9764,8 +10398,25 @@ "p-try": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==" + }, + "package-json": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/package-json/-/package-json-6.5.0.tgz", + "integrity": "sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ==", + "requires": { + "got": "^9.6.0", + "registry-auth-token": "^4.0.0", + "registry-url": "^5.0.0", + "semver": "^6.2.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" + } + } }, "pacote": { "version": "9.5.12", @@ -10029,8 +10680,7 @@ "parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", - "dev": true + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" }, "pascalcase": { "version": "0.1.1", @@ -10083,8 +10733,7 @@ "path-to-regexp": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=", - "dev": true + "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" }, "path-type": { "version": "4.0.0", @@ -10147,6 +10796,19 @@ "find-up": "^3.0.0" } }, + "please-upgrade-node": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/please-upgrade-node/-/please-upgrade-node-3.2.0.tgz", + "integrity": "sha512-gQR3WpIgNIKwBMVLkpMUeR3e1/E1y42bqDQZfql+kDeXd8COYfM8PQA4X6y7a8u9Ua9FHmsrrmirW2vHs45hWg==", + "requires": { + "semver-compare": "^1.0.0" + } + }, + "pluralize": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", + "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==" + }, "pnp-webpack-plugin": { "version": "1.6.4", "resolved": "https://registry.npmjs.org/pnp-webpack-plugin/-/pnp-webpack-plugin-1.6.4.tgz", @@ -11227,7 +11889,6 @@ "version": "2.0.6", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz", "integrity": "sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw==", - "dev": true, "requires": { "forwarded": "~0.1.2", "ipaddr.js": "1.9.1" @@ -11271,7 +11932,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "dev": true, "requires": { "end-of-stream": "^1.1.0", "once": "^1.3.1" @@ -11306,6 +11966,14 @@ "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", "dev": true }, + "pupa": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pupa/-/pupa-2.0.1.tgz", + "integrity": "sha512-hEJH0s8PXLY/cdXh66tNEQGndDrIKNqNC5xmrysZy3i5C3oEoLna7YAOad+7u125+zH1HNXUmGEkrhb3c2VriA==", + "requires": { + "escape-goat": "^2.0.0" + } + }, "q": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", @@ -11321,8 +11989,7 @@ "qs": { "version": "6.7.0", "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", - "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==", - "dev": true + "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==" }, "query-string": { "version": "4.3.4", @@ -11380,14 +12047,12 @@ "range-parser": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", - "dev": true + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" }, "raw-body": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", - "dev": true, "requires": { "bytes": "3.1.0", "http-errors": "1.7.2", @@ -11398,14 +12063,12 @@ "bytes": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", - "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", - "dev": true + "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==" }, "iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dev": true, "requires": { "safer-buffer": ">= 2.1.2 < 3" } @@ -11422,6 +12085,17 @@ "schema-utils": "^2.6.5" } }, + "rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + } + }, "read-cache": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", @@ -11715,6 +12389,22 @@ "unicode-match-property-value-ecmascript": "^1.2.0" } }, + "registry-auth-token": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-4.2.0.tgz", + "integrity": "sha512-P+lWzPrsgfN+UEpDS3U8AQKg/UjZX6mQSJueZj3EK+vNESoqBSpBUD3gmu4sF9lOsjXWjF11dQKUqemf3veq1w==", + "requires": { + "rc": "^1.2.8" + } + }, + "registry-url": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-5.1.0.tgz", + "integrity": "sha512-8acYXXTI0AkQv6RAOjE3vOaIXZkT9wo4LOFbBKYQEEnnMNBpKqdUrI6S4NT0KPIo/WVvJ5tE/X5LF/TQUf0ekw==", + "requires": { + "rc": "^1.2.8" + } + }, "regjsgen": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.5.2.tgz", @@ -11804,14 +12494,12 @@ "require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", - "dev": true + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=" }, "require-main-filename": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", - "dev": true + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==" }, "requires-port": { "version": "1.0.0", @@ -11927,6 +12615,14 @@ } } }, + "responselike": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", + "integrity": "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=", + "requires": { + "lowercase-keys": "^1.0.0" + } + }, "restore-cursor": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", @@ -12064,8 +12760,7 @@ "safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" }, "safe-regex": { "version": "1.1.0", @@ -12079,8 +12774,7 @@ "safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, "sass": { "version": "1.26.10", @@ -12183,6 +12877,26 @@ "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==", "dev": true }, + "semver-compare": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", + "integrity": "sha1-De4hahyUGrN+nvsXiPavxf9VN/w=" + }, + "semver-diff": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-3.1.1.tgz", + "integrity": "sha512-GX0Ix/CJcHyB8c4ykpHGIAvLyOwOobtM/8d+TQkAd81/bEjgPHrfba41Vpesr7jX/t8Uh+R3EX9eAS5be+jQYg==", + "requires": { + "semver": "^6.3.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" + } + } + }, "semver-dsl": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/semver-dsl/-/semver-dsl-1.0.1.tgz", @@ -12221,7 +12935,6 @@ "version": "0.17.1", "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", - "dev": true, "requires": { "debug": "2.6.9", "depd": "~1.1.2", @@ -12242,7 +12955,6 @@ "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, "requires": { "ms": "2.0.0" }, @@ -12250,16 +12962,14 @@ "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" } } }, "ms": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", - "dev": true + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" } } }, @@ -12332,7 +13042,6 @@ "version": "1.14.1", "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", - "dev": true, "requires": { "encodeurl": "~1.0.2", "escape-html": "~1.0.3", @@ -12340,11 +13049,15 @@ "send": "0.17.1" } }, + "server-destroy": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/server-destroy/-/server-destroy-1.0.1.tgz", + "integrity": "sha1-8Tv5KOQrnD55OD5hzDmYtdFObN0=" + }, "set-blocking": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", - "dev": true + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" }, "set-immediate-shim": { "version": "1.0.1", @@ -12384,8 +13097,7 @@ "setprototypeof": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", - "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==", - "dev": true + "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" }, "sha.js": { "version": "2.4.11", @@ -12426,8 +13138,7 @@ "signal-exit": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", - "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==", - "dev": true + "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==" }, "simple-swizzle": { "version": "0.2.2", @@ -13234,8 +13945,15 @@ "statuses": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", - "dev": true + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" + }, + "steno": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/steno/-/steno-0.4.4.tgz", + "integrity": "sha1-BxEFvfwobmYVwEA8J+nXtdy4Vcs=", + "requires": { + "graceful-fs": "^4.1.3" + } }, "stream-browserify": { "version": "2.0.2", @@ -13316,7 +14034,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, "requires": { "emoji-regex": "^7.0.1", "is-fullwidth-code-point": "^2.0.0", @@ -13326,14 +14043,12 @@ "ansi-regex": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==" }, "strip-ansi": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, "requires": { "ansi-regex": "^4.1.0" } @@ -13450,6 +14165,11 @@ "min-indent": "^1.0.0" } }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" + }, "style-loader": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-1.2.1.tgz", @@ -13626,6 +14346,11 @@ } } }, + "term-size": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/term-size/-/term-size-2.2.0.tgz", + "integrity": "sha512-a6sumDlzyHVJWb8+YofY4TW112G6p2FCPEAFk+59gIYHv3XHRhm9ltVQ9kli4hNWeQBwSpe8cRN25x0ROunMOw==" + }, "terser": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/terser/-/terser-5.3.0.tgz", @@ -13769,6 +14494,11 @@ } } }, + "to-readable-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz", + "integrity": "sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q==" + }, "to-regex": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", @@ -13793,8 +14523,7 @@ "toidentifier": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", - "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==", - "dev": true + "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==" }, "tough-cookie": { "version": "2.5.0", @@ -13946,7 +14675,6 @@ "version": "1.6.18", "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", - "dev": true, "requires": { "media-typer": "0.3.0", "mime-types": "~2.1.24" @@ -13958,6 +14686,14 @@ "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", "dev": true }, + "typedarray-to-buffer": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", + "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", + "requires": { + "is-typedarray": "^1.0.0" + } + }, "typescript": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.0.3.tgz", @@ -14047,6 +14783,14 @@ "imurmurhash": "^0.1.4" } }, + "unique-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", + "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==", + "requires": { + "crypto-random-string": "^2.0.0" + } + }, "universal-analytics": { "version": "0.4.23", "resolved": "https://registry.npmjs.org/universal-analytics/-/universal-analytics-0.4.23.tgz", @@ -14067,8 +14811,7 @@ "unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", - "dev": true + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" }, "unquote": { "version": "1.1.1", @@ -14122,6 +14865,71 @@ "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==", "dev": true }, + "update-notifier": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-4.1.3.tgz", + "integrity": "sha512-Yld6Z0RyCYGB6ckIjffGOSOmHXj1gMeE7aROz4MG+XMkmixBX4jUngrGXNYz7wPKBmtoD4MnBa2Anu7RSKht/A==", + "requires": { + "boxen": "^4.2.0", + "chalk": "^3.0.0", + "configstore": "^5.0.1", + "has-yarn": "^2.1.0", + "import-lazy": "^2.1.0", + "is-ci": "^2.0.0", + "is-installed-globally": "^0.3.1", + "is-npm": "^4.0.0", + "is-yarn-global": "^0.3.0", + "latest-version": "^5.0.0", + "pupa": "^2.0.1", + "semver-diff": "^3.1.1", + "xdg-basedir": "^4.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, "uri-js": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.0.tgz", @@ -14165,6 +14973,21 @@ "requires-port": "^1.0.0" } }, + "url-parse-lax": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", + "integrity": "sha1-FrXK/Afb42dsGxmZF3gj1lA6yww=", + "requires": { + "prepend-http": "^2.0.0" + }, + "dependencies": { + "prepend-http": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", + "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=" + } + } + }, "use": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", @@ -14239,8 +15062,7 @@ "utils-merge": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", - "dev": true + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" }, "uuid": { "version": "3.4.0", @@ -14270,8 +15092,7 @@ "vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", - "dev": true + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" }, "vendors": { "version": "1.0.4", @@ -15264,8 +16085,50 @@ "which-module": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", - "dev": true + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=" + }, + "widest-line": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", + "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==", + "requires": { + "string-width": "^4.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==" + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" + }, + "string-width": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", + "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + } + }, + "strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "requires": { + "ansi-regex": "^5.0.0" + } + } + } }, "wordwrap": { "version": "1.0.0", @@ -15344,8 +16207,18 @@ "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "write-file-atomic": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", + "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", + "requires": { + "imurmurhash": "^0.1.4", + "is-typedarray": "^1.0.0", + "signal-exit": "^3.0.2", + "typedarray-to-buffer": "^3.1.5" + } }, "ws": { "version": "6.2.1", @@ -15356,6 +16229,11 @@ "async-limiter": "~1.0.0" } }, + "xdg-basedir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz", + "integrity": "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==" + }, "xml2js": { "version": "0.4.23", "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.23.tgz", @@ -15387,8 +16265,7 @@ "y18n": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", - "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", - "dev": true + "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==" }, "yallist": { "version": "4.0.0", diff --git a/package.json b/package.json index 5a8956c0f..97ef23241 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,8 @@ "lint": "ng lint", "e2e": "ng e2e", "release": "standard-version", - "translate": "ng xi18n --output-path src/locale --out-file messages.en.xlf" + "translate": "ng xi18n --output-path src/locale --out-file messages.en.xlf", + "api": "json-server api/db.json --routes api/routes.json --no-cors=true" }, "private": true, "dependencies": { @@ -24,6 +25,7 @@ "@angular/platform-browser": "~10.1.3", "@angular/platform-browser-dynamic": "~10.1.3", "@angular/router": "~10.1.3", + "json-server": "^0.16.2", "rxjs": "~6.6.0", "tslib": "^2.0.0", "zone.js": "~0.10.2" diff --git a/proxy.conf.json b/proxy.conf.json new file mode 100644 index 000000000..c394a84fb --- /dev/null +++ b/proxy.conf.json @@ -0,0 +1,5 @@ +{ + "/api": { + "target": "http://localhost:3000" + } +} diff --git a/src/app/structure/components/card/card.component.html b/src/app/structure/components/card/card.component.html index 8071bfcce..db49c0aef 100644 --- a/src/app/structure/components/card/card.component.html +++ b/src/app/structure/components/card/card.component.html @@ -1 +1,17 @@ -<p>card wsdorks!</p> +<span class="divider"></span> +<span class="nbStructuresLabel">140 structures</span> + +<div class="structure"> + <span class="typeStructure">Bibliothèque</span> + <div class="headerStructure" fxLayout="row" fxLayoutAlign="space-between center"> + <span class="nomStructure">Nom de la structure</span> + <div class="distanceStructure"> + <span>|-----| 63 m</span> + </div> + </div> + <br /> + <div class="statusStructure" fxLayout="row" fxLayoutAlign="start center" fxLayoutGap="1vw"> + <span class="dot"></span> + <span>Ouvert actuellement</span> + </div> +</div> diff --git a/src/app/structure/components/card/card.component.scss b/src/app/structure/components/card/card.component.scss index e69de29bb..18648a329 100644 --- a/src/app/structure/components/card/card.component.scss +++ b/src/app/structure/components/card/card.component.scss @@ -0,0 +1,22 @@ +.nbStructuresLabel { + color: #828282; + padding: 10px; + font-size: 14px; +} +.structure { + padding: 12px 0 12px 0; + border-bottom: 1px dashed #bdbdbd; + .typeStructure { + color: #828282; + } + .headerStructure { + .nomStructure { + font-weight: bold; + color: #594d59; + font-size: 22px; + } + } + &:last-child { + border-bottom: none; + } +} diff --git a/src/app/structure/components/card/card.component.ts b/src/app/structure/components/card/card.component.ts index 07a9ab07e..57820f6a3 100644 --- a/src/app/structure/components/card/card.component.ts +++ b/src/app/structure/components/card/card.component.ts @@ -1,15 +1,20 @@ import { Component, OnInit } from '@angular/core'; +import { Structure } from '../../models/structure.model'; @Component({ selector: 'app-card', templateUrl: './card.component.html', - styleUrls: ['./card.component.scss'] + styleUrls: ['./card.component.scss'], }) export class CardComponent implements OnInit { + structure: Structure[] = []; + servicesProposes: any = [ + { val: 'CAF', text: 'Droits à la CAF' }, + { val: 'Pôle Emploi', text: 'Droits à Pôle Emploi' }, + { val: 'Impôts', text: 'Droits aux Impots' }, + { val: 'CPAM', text: 'Droits à la CPAM (AMELI)' }, + ]; + constructor() {} - constructor() { } - - ngOnInit(): void { - } - + ngOnInit(): void {} } diff --git a/src/app/structure/models/structure.model.ts b/src/app/structure/models/structure.model.ts new file mode 100644 index 000000000..bf0a5b70a --- /dev/null +++ b/src/app/structure/models/structure.model.ts @@ -0,0 +1,27 @@ +export class Structure { + id: string; + created_on: string; + last_modif: string; + owner: string; + status: string; + nom: string; + type_structure: string; + description: string; + num: string; + voie: string; + telephone: string; + courriel: string; + site_web: string; + facebook: string; + twitter: string; + instagram: string; + civilite_contact: string; + nom_contact: string; + prenom_contact: string; + email_contact: string; + fonction_contact: string; + pmr: boolean; + je_fais_a_la_place_de_lusager: boolean; + accompagnement_aux_demarches: string[]; + wifi: boolean; +} diff --git a/src/app/structure/structure.component.html b/src/app/structure/structure.component.html index 8688da6ce..a6dbe19b7 100644 --- a/src/app/structure/structure.component.html +++ b/src/app/structure/structure.component.html @@ -1,2 +1,2 @@ -<app-card></app-card> <app-recherche></app-recherche> +<app-card></app-card> diff --git a/src/app/structure/structure.module.ts b/src/app/structure/structure.module.ts index 902f040cd..027e62301 100644 --- a/src/app/structure/structure.module.ts +++ b/src/app/structure/structure.module.ts @@ -3,10 +3,11 @@ import { CommonModule } from '@angular/common'; import { StructureComponent } from './structure.component'; import { CardComponent } from './components/card/card.component'; import { RechercheComponent } from './components/recherche/recherche.component'; +import { HttpClientModule } from '@angular/common/http'; @NgModule({ declarations: [StructureComponent, CardComponent, RechercheComponent], - imports: [CommonModule], + imports: [CommonModule, HttpClientModule], exports: [StructureComponent], }) export class StructureModule {} -- GitLab From f0ec840d63e785d9128024875f9b1b0c553cfbf8 Mon Sep 17 00:00:00 2001 From: Jeremie BRISON <ext.sopra.jbrison@grandlyon.com> Date: Fri, 9 Oct 2020 14:05:02 +0200 Subject: [PATCH 03/50] feat(card): ajout template + logique structures --- .gitignore | 3 + package-lock.json | 5 + package.json | 1 + .../components/card/card.component.html | 28 ++-- .../components/card/card.component.scss | 46 +++++- .../components/card/card.component.ts | 19 +-- src/app/structure/models/structure.model.ts | 47 ++++-- .../structure/services/structure.service.ts | 139 +++++++++++++++++- src/app/structure/structure.module.ts | 3 +- src/assets/scss/_icons.scss | 14 ++ 10 files changed, 260 insertions(+), 45 deletions(-) diff --git a/.gitignore b/.gitignore index 86d943a9b..b1b6bcc81 100644 --- a/.gitignore +++ b/.gitignore @@ -44,3 +44,6 @@ testem.log # System Files .DS_Store Thumbs.db + +# apiMock +api/db.json diff --git a/package-lock.json b/package-lock.json index b09f84a5a..da8384e00 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8942,6 +8942,11 @@ "yallist": "^4.0.0" } }, + "luxon": { + "version": "1.25.0", + "resolved": "https://registry.npmjs.org/luxon/-/luxon-1.25.0.tgz", + "integrity": "sha512-hEgLurSH8kQRjY6i4YLey+mcKVAWXbDNlZRmM6AgWDJ1cY3atl8Ztf5wEY7VBReFbmGnwQPz7KYJblL8B2k0jQ==" + }, "magic-string": { "version": "0.25.7", "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.7.tgz", diff --git a/package.json b/package.json index 97ef23241..fe8dccab6 100644 --- a/package.json +++ b/package.json @@ -26,6 +26,7 @@ "@angular/platform-browser-dynamic": "~10.1.3", "@angular/router": "~10.1.3", "json-server": "^0.16.2", + "luxon": "^1.25.0", "rxjs": "~6.6.0", "tslib": "^2.0.0", "zone.js": "~0.10.2" diff --git a/src/app/structure/components/card/card.component.html b/src/app/structure/components/card/card.component.html index db49c0aef..e2443b8c8 100644 --- a/src/app/structure/components/card/card.component.html +++ b/src/app/structure/components/card/card.component.html @@ -1,17 +1,25 @@ -<span class="divider"></span> -<span class="nbStructuresLabel">140 structures</span> +<span class="nbStructuresLabel">{{ structures.length }} structures</span> +<div class="structure" fxLayout="column" *ngFor="let structure of structures"> + <span class="nomStructure">{{ structure.nom }}</span> -<div class="structure"> - <span class="typeStructure">Bibliothèque</span> <div class="headerStructure" fxLayout="row" fxLayoutAlign="space-between center"> - <span class="nomStructure">Nom de la structure</span> - <div class="distanceStructure"> - <span>|-----| 63 m</span> - </div> + <span class="typeStructure">{{ structure.type_de_structure }}</span> + <span class="distanceStructure">|-| 63 m</span> </div> <br /> <div class="statusStructure" fxLayout="row" fxLayoutAlign="start center" fxLayoutGap="1vw"> - <span class="dot"></span> - <span>Ouvert actuellement</span> + <div *ngIf="structure.estOuvert; else closed"> + <span class="ico-dot-available"></span> + <span> Ouvert actuellement</span> + </div> + <ng-template #closed> + <span class="ico-dot-unavailable"></span> + <span *ngIf="structure.ouvreLe.jour; else noTime"> + Fermé - Ouvre {{ structure.ouvreLe.jour }} à {{ structure.ouvreLe.horaire }}</span + > + </ng-template> </div> </div> +<ng-template #noTime> + <span> Fermé - Aucun horaire disponible</span> +</ng-template> diff --git a/src/app/structure/components/card/card.component.scss b/src/app/structure/components/card/card.component.scss index 18648a329..f3f374801 100644 --- a/src/app/structure/components/card/card.component.scss +++ b/src/app/structure/components/card/card.component.scss @@ -1,22 +1,52 @@ +@import '../../../../assets/scss/icons'; .nbStructuresLabel { color: #828282; - padding: 10px; - font-size: 14px; + font-family: Trebuchet MS; + font-style: normal; + font-weight: normal; + font-size: 16px; + line-height: 19px; + display: flex; + align-items: center; } .structure { padding: 12px 0 12px 0; border-bottom: 1px dashed #bdbdbd; .typeStructure { color: #828282; + font-family: Times New Roman; + font-style: normal; + font-weight: normal; + font-size: 16px; + line-height: 100%; } - .headerStructure { - .nomStructure { - font-weight: bold; - color: #594d59; - font-size: 22px; - } + .nomStructure { + padding-top: 13px; + color: #594d59; + font-family: Trebuchet MS; + font-style: normal; + font-weight: bold; + font-size: 20px; + line-height: 103%; + padding-bottom: 5px; + } + .distanceStructure { + font-family: Times New Roman; + font-style: normal; + font-size: 16px; + line-height: 103%; + color: #594d59; } &:last-child { border-bottom: none; } } +.statusStructure { + span { + font-family: Trebuchet MS; + font-style: normal; + font-weight: normal; + font-size: 15px; + line-height: 103%; + } +} diff --git a/src/app/structure/components/card/card.component.ts b/src/app/structure/components/card/card.component.ts index 57820f6a3..093bdde33 100644 --- a/src/app/structure/components/card/card.component.ts +++ b/src/app/structure/components/card/card.component.ts @@ -1,5 +1,6 @@ import { Component, OnInit } from '@angular/core'; import { Structure } from '../../models/structure.model'; +import { StructureService } from '../../services/structure.service'; @Component({ selector: 'app-card', @@ -7,14 +8,14 @@ import { Structure } from '../../models/structure.model'; styleUrls: ['./card.component.scss'], }) export class CardComponent implements OnInit { - structure: Structure[] = []; - servicesProposes: any = [ - { val: 'CAF', text: 'Droits à la CAF' }, - { val: 'Pôle Emploi', text: 'Droits à Pôle Emploi' }, - { val: 'Impôts', text: 'Droits aux Impots' }, - { val: 'CPAM', text: 'Droits à la CPAM (AMELI)' }, - ]; - constructor() {} + structures: Structure[] = []; + constructor(private _structureService: StructureService) {} - ngOnInit(): void {} + ngOnInit(): void { + this._structureService.recupererStructures().subscribe((structures: Structure[]) => { + structures.forEach((s: Structure) => { + this.structures.push(this._structureService.majOuvertureStructure(s)); + }); + }); + } } diff --git a/src/app/structure/models/structure.model.ts b/src/app/structure/models/structure.model.ts index bf0a5b70a..d64b5b3ad 100644 --- a/src/app/structure/models/structure.model.ts +++ b/src/app/structure/models/structure.model.ts @@ -1,13 +1,13 @@ export class Structure { - id: string; - created_on: string; - last_modif: string; - owner: string; - status: string; - nom: string; - type_structure: string; + numero: string; + date_de_creation: string; + derniere_modification: string; + nom_de_lusager: string; + votre_structure_est_elle: string; + nom_de_votre_structure: string; + type_de_structure: string; description: string; - num: string; + n: string; voie: string; telephone: string; courriel: string; @@ -15,13 +15,30 @@ export class Structure { facebook: string; twitter: string; instagram: string; - civilite_contact: string; - nom_contact: string; - prenom_contact: string; + civilite: string; + nom: string; + prenom: string; email_contact: string; - fonction_contact: string; - pmr: boolean; - je_fais_a_la_place_de_lusager: boolean; - accompagnement_aux_demarches: string[]; + fonction: string; + accessibilite_personnes_a_mobilite_reduite_pmr: boolean; + jaccompagne_les_usagers_dans_leurs_demarches_en_ligne: boolean; + accompagnement_des_demarches: string[]; wifi: boolean; + horaires: horaireStructure; + estOuvert: boolean; + ouvreLe: { jour: string; horaire: string }; +} + +export class horaireStructure { + lundi: Jour; + mardi: Jour; + mercredi: Jour; + jeudi: Jour; + vendredi: Jour; + samedi: Jour; + dimanche: Jour; +} +export class Jour { + open: boolean; + time: [{ openning: number; closing: number }]; } diff --git a/src/app/structure/services/structure.service.ts b/src/app/structure/services/structure.service.ts index 8a09d6adb..a72138d7e 100644 --- a/src/app/structure/services/structure.service.ts +++ b/src/app/structure/services/structure.service.ts @@ -1,9 +1,144 @@ +import { HttpClient } from '@angular/common/http'; import { Injectable } from '@angular/core'; +import { Jour, Structure } from '../models/structure.model'; +const { DateTime } = require('luxon'); @Injectable({ - providedIn: 'root' + providedIn: 'root', }) export class StructureService { + constructor(private http: HttpClient) {} - constructor() { } + recupererStructures() { + return this.http.get('/api/Structures'); + } + + majOuvertureStructure(structure: Structure) { + //Récupère le jour de la semaine. + var dt = DateTime.local(); + var jourSemaine: number = dt.weekday; + + //Vérifie si les minutes commencent par zéro pour éviter la suppression. + var now: number; + if (dt.minute.toString().length != 1) { + now = parseInt('' + dt.hour + dt.minute, 10); + } else { + now = parseInt('' + dt.hour + 0 + dt.minute, 10); + } + + //Récupérer les horaires d'une structure en fonction de son jour pour indiquer si elle est ouverte. + var horaireStructure: Jour = this.recupererHoraire(structure, jourSemaine); + structure.estOuvert = false; + if (horaireStructure.open) { + horaireStructure.time.forEach((periode) => { + if (this.comparerHoraire(periode.openning, periode.closing, now)) { + structure.estOuvert = true; + } + }); + } + structure.ouvreLe = this.recupererProchaineOuverture(structure, jourSemaine, jourSemaine, now); + + return structure; + } + + //Récupère les horaires d'une structure en fonction du jour de la semaine + recupererHoraire(structure: Structure, jourActuel: number) { + switch (jourActuel) { + case 1: + return structure.horaires.lundi; + case 2: + return structure.horaires.mardi; + case 3: + return structure.horaires.mercredi; + case 4: + return structure.horaires.jeudi; + case 5: + return structure.horaires.vendredi; + case 6: + return structure.horaires.samedi; + case 7: + return structure.horaires.dimanche; + } + } + //Vérifie si l'heure actuelle est dans l'interval des horaires de la structure + comparerHoraire(heureDeb: number, heureFin: number, heureActuelle: number) { + return heureActuelle >= heureDeb && heureActuelle <= heureFin; + } + + recupererProchaineOuverture(s: Structure, j: number, baseJour: number, baseHeure: number) { + //Récupérer horaire du jour en cours + var horaires = this.recupererHoraire(s, j); + //Condition pour stopper la récursion (Si le jour du compteur est égal au jour en cours) + if (j + 1 != baseJour) { + if (horaires.open) { + //Vérifie si le compteur correspond au jour en cours pour éviter de proposer + //les horaires déjà passés. + if (j != baseJour) { + var jourOuverture = null; + horaires.time.every((periode) => { + if (periode.openning) { + jourOuverture = { jour: this.numberToDay(j), horaire: this.numberToHour(periode.openning) }; + return false; + } + return true; + }); + //Si pas de période trouvée, on réitère. + if (!jourOuverture) { + return this.recupererProchaineOuverture(s, j + 1, baseJour, baseHeure); + } + return jourOuverture; + } else { + var jourOuverture = null; + horaires.time.every((periode) => { + if (periode.openning >= baseHeure) { + jourOuverture = { jour: ' ', horaire: this.numberToHour(periode.openning) }; + return false; + } + return true; + }); + //Si pas de période trouvée, on réitère. + if (!jourOuverture) { + return this.recupererProchaineOuverture(s, j + 1, baseJour, baseHeure); + } + return jourOuverture; + } + } else { + //Si le jour est égal à Dimanche, on le positionne sur Lundi. + if (j != 7) { + return this.recupererProchaineOuverture(s, j + 1, baseJour, baseHeure); + } + return this.recupererProchaineOuverture(s, 1, baseJour, baseHeure); + } + } + return 'Aucun horaire disponible'; + } + + numberToDay(n: number) { + switch (n) { + case 1: + return 'lundi'; + case 2: + return 'mardi'; + case 3: + return 'mercredi'; + case 4: + return 'jeudi'; + case 5: + return 'vendredi'; + case 6: + return 'samedi'; + case 7: + return 'dimanche'; + } + } + + numberToHour(n: number) { + if (n.toString().length == 3) { + var tabNum = n.toString().match(/.{1,1}/g); + return tabNum[0] + 'h' + tabNum[1] + tabNum[2]; + } else if (n.toString().length == 4) { + var tabNum = n.toString().match(/.{1,2}/g); + return tabNum[0] + 'h' + tabNum[1]; + } + } } diff --git a/src/app/structure/structure.module.ts b/src/app/structure/structure.module.ts index 027e62301..335604aef 100644 --- a/src/app/structure/structure.module.ts +++ b/src/app/structure/structure.module.ts @@ -4,10 +4,11 @@ import { StructureComponent } from './structure.component'; import { CardComponent } from './components/card/card.component'; import { RechercheComponent } from './components/recherche/recherche.component'; import { HttpClientModule } from '@angular/common/http'; +import { FlexLayoutModule } from '@angular/flex-layout'; @NgModule({ declarations: [StructureComponent, CardComponent, RechercheComponent], - imports: [CommonModule, HttpClientModule], + imports: [CommonModule, HttpClientModule, FlexLayoutModule], exports: [StructureComponent], }) export class StructureModule {} diff --git a/src/assets/scss/_icons.scss b/src/assets/scss/_icons.scss index b1dcb9ac7..a44fae8f2 100644 --- a/src/assets/scss/_icons.scss +++ b/src/assets/scss/_icons.scss @@ -64,3 +64,17 @@ background: $orange; } } +.ico-dot-available { + height: 12px; + width: 12px; + background-color: #41c29c; + border-radius: 50%; + display: inline-block; +} +.ico-dot-unavailable { + height: 12px; + width: 12px; + background-color: #b7b7b7; + border-radius: 50%; + display: inline-block; +} -- GitLab From 2cd65e469fe4fe12ff8000ed6e330b34fb09d07e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9mie=20BRISON?= <ext.sopra.jbrison@grandlyon.com> Date: Fri, 9 Oct 2020 14:10:29 +0200 Subject: [PATCH 04/50] Delete db.json --- api/db.json | 58 ----------------------------------------------------- 1 file changed, 58 deletions(-) delete mode 100644 api/db.json diff --git a/api/db.json b/api/db.json deleted file mode 100644 index e41fd2d32..000000000 --- a/api/db.json +++ /dev/null @@ -1,58 +0,0 @@ -{ - "structure": [ - { - "id": "26-28", - "created_on": "22/09/2020 16:01", - "last_modif": "22/09/2020 16:01", - "owner": "-", - "status": "Un établissement principal (siège social)", - "nom": "Labit", - "type_structure": "MDM", - "description": "Ouvert à toute heure", - "num": "12", - "voie": "27838 Avenue Lacassagne", - "telephone": "0134257645", - "courriel": "coop.labit@gmail.com", - "site_web": "", - "facebook": "", - "twitter": "", - "instagram": "", - "civilite_contact": "Madame", - "nom_contact": "Labit", - "prenom_contact": "Valentine", - "email_contact": "coop.labit@gmail.com", - "fonction_contact": "Président de l'association", - "pmr": true, - "je_fais_a_la_place_de_lusager": true, - "accompagnement_aux_demarches": ["Pôle Emploi", "CPAM", "Impôts", "Logement"], - "wifi": true - }, - { - "id": "26-10", - "created_on": "03/09/2020 14:14", - "last_modif": "03/09/2020 14:15", - "owner": "Marlène Simondant", - "status": "Un établissement principal (siège social)", - "nom": "fgh", - "type_structure": "Bibliothèque", - "description": "", - "num": "", - "voie": "26061 13ème Rue Cité Berliet", - "telephone": "0659856235", - "courriel": "test@test.te", - "site_web": "", - "facebook": "", - "twitter": "", - "instagram": "", - "civilite_contact": "", - "nom_contact": "dh", - "prenom_contact": "fxh", - "email_contact": "test@test.te", - "fonction_contact": "Bénévole", - "pmr": false, - "je_fais_a_la_place_de_lusager": false, - "accompagnement_aux_demarches": ["CPAM"], - "wifi": false - } - ] -} -- GitLab From c9686d31d0b03b57e3e43a0458a9830b03441991 Mon Sep 17 00:00:00 2001 From: Jeremie BRISON <ext.sopra.jbrison@grandlyon.com> Date: Fri, 9 Oct 2020 15:00:31 +0200 Subject: [PATCH 05/50] fix(test) : add type 'node' for jasmine test + fix import test --- src/app/app.component.spec.ts | 12 ++++-------- src/app/header/header.component.spec.ts | 7 ++++--- .../components/card/card.component.spec.ts | 8 ++++---- .../structure/services/structure.service.spec.ts | 5 ++++- tsconfig.spec.json | 14 +++----------- 5 files changed, 19 insertions(+), 27 deletions(-) diff --git a/src/app/app.component.spec.ts b/src/app/app.component.spec.ts index f8649a882..3ccaf52ed 100644 --- a/src/app/app.component.spec.ts +++ b/src/app/app.component.spec.ts @@ -5,12 +5,8 @@ import { AppComponent } from './app.component'; describe('AppComponent', () => { beforeEach(async () => { await TestBed.configureTestingModule({ - imports: [ - RouterTestingModule - ], - declarations: [ - AppComponent - ], + imports: [RouterTestingModule], + declarations: [AppComponent], }).compileComponents(); }); @@ -26,10 +22,10 @@ describe('AppComponent', () => { expect(app.title).toEqual('pamn'); }); - it('should render title', () => { + /*it('should render title', () => { const fixture = TestBed.createComponent(AppComponent); fixture.detectChanges(); const compiled = fixture.nativeElement; expect(compiled.querySelector('.content span').textContent).toContain('pamn app is running!'); - }); + });*/ }); diff --git a/src/app/header/header.component.spec.ts b/src/app/header/header.component.spec.ts index 381e8e80c..6e760707f 100644 --- a/src/app/header/header.component.spec.ts +++ b/src/app/header/header.component.spec.ts @@ -1,4 +1,5 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { RouterTestingModule } from '@angular/router/testing'; import { HeaderComponent } from './header.component'; @@ -8,9 +9,9 @@ describe('HeaderComponent', () => { beforeEach(async () => { await TestBed.configureTestingModule({ - declarations: [ HeaderComponent ] - }) - .compileComponents(); + imports: [RouterTestingModule], + declarations: [HeaderComponent], + }).compileComponents(); }); beforeEach(() => { diff --git a/src/app/structure/components/card/card.component.spec.ts b/src/app/structure/components/card/card.component.spec.ts index 3093fd5a3..c0787da7b 100644 --- a/src/app/structure/components/card/card.component.spec.ts +++ b/src/app/structure/components/card/card.component.spec.ts @@ -1,16 +1,16 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { CardComponent } from './card.component'; - +import { HttpClientModule } from '@angular/common/http'; describe('CardComponent', () => { let component: CardComponent; let fixture: ComponentFixture<CardComponent>; beforeEach(async () => { await TestBed.configureTestingModule({ - declarations: [ CardComponent ] - }) - .compileComponents(); + imports: [HttpClientModule], + declarations: [CardComponent], + }).compileComponents(); }); beforeEach(() => { diff --git a/src/app/structure/services/structure.service.spec.ts b/src/app/structure/services/structure.service.spec.ts index d44ef8feb..8048236e0 100644 --- a/src/app/structure/services/structure.service.spec.ts +++ b/src/app/structure/services/structure.service.spec.ts @@ -1,3 +1,4 @@ +import { HttpClientModule } from '@angular/common/http'; import { TestBed } from '@angular/core/testing'; import { StructureService } from './structure.service'; @@ -6,7 +7,9 @@ describe('StructureService', () => { let service: StructureService; beforeEach(() => { - TestBed.configureTestingModule({}); + TestBed.configureTestingModule({ + imports: [HttpClientModule], + }); service = TestBed.inject(StructureService); }); diff --git a/tsconfig.spec.json b/tsconfig.spec.json index 092345b02..6c31866e9 100644 --- a/tsconfig.spec.json +++ b/tsconfig.spec.json @@ -3,16 +3,8 @@ "extends": "./tsconfig.json", "compilerOptions": { "outDir": "./out-tsc/spec", - "types": [ - "jasmine" - ] + "types": ["jasmine", "node"] }, - "files": [ - "src/test.ts", - "src/polyfills.ts" - ], - "include": [ - "src/**/*.spec.ts", - "src/**/*.d.ts" - ] + "files": ["src/test.ts", "src/polyfills.ts"], + "include": ["src/**/*.spec.ts", "src/**/*.d.ts"] } -- GitLab From e15e5dc6ea5d7a97ade2d21ddd2b20fcb557d100 Mon Sep 17 00:00:00 2001 From: Jeremie BRISON <ext.sopra.jbrison@grandlyon.com> Date: Fri, 9 Oct 2020 17:40:17 +0200 Subject: [PATCH 06/50] fix(test) : add test functions + fix model --- src/app/structure/models/structure.model.ts | 2 +- .../services/structure.service.spec.ts | 171 +++++++++++++++++- .../structure/services/structure.service.ts | 20 +- 3 files changed, 182 insertions(+), 11 deletions(-) diff --git a/src/app/structure/models/structure.model.ts b/src/app/structure/models/structure.model.ts index d64b5b3ad..5617a7948 100644 --- a/src/app/structure/models/structure.model.ts +++ b/src/app/structure/models/structure.model.ts @@ -40,5 +40,5 @@ export class horaireStructure { } export class Jour { open: boolean; - time: [{ openning: number; closing: number }]; + time: { openning: number; closing: number }[]; } diff --git a/src/app/structure/services/structure.service.spec.ts b/src/app/structure/services/structure.service.spec.ts index 8048236e0..e4f26a5ac 100644 --- a/src/app/structure/services/structure.service.spec.ts +++ b/src/app/structure/services/structure.service.spec.ts @@ -1,19 +1,174 @@ -import { HttpClientModule } from '@angular/common/http'; -import { TestBed } from '@angular/core/testing'; - +import { HttpClient, HttpClientModule } from '@angular/common/http'; +import { inject, TestBed } from '@angular/core/testing'; +import { horaireStructure, Jour, Structure } from '../models/structure.model'; import { StructureService } from './structure.service'; +const { DateTime } = require('luxon'); describe('StructureService', () => { - let service: StructureService; - beforeEach(() => { TestBed.configureTestingModule({ imports: [HttpClientModule], }); - service = TestBed.inject(StructureService); }); + let _structureService: StructureService; + beforeEach(inject([StructureService], (_s: StructureService) => { + _structureService = _s; + })); + it('should return an hour string', () => { + const result = _structureService.numberToHour(928); + expect(result).toBe('9h28'); + }); + + it('should return a day string', () => { + const result = _structureService.numberToDay(1); + expect(result).toBe('lundi'); + }); + it('should return null', () => { + const result = _structureService.numberToDay(8); + expect(result).toBeNull(); + }); + + it('Comparer Horaire : should return true', () => { + const result = _structureService.comparerHoraire(830, 1200, 900); + expect(result).toBeTrue(); + }); + + it('Comparer Horaire : should return false', () => { + const result = _structureService.comparerHoraire(830, 1200, 800); + expect(result).toBeFalse(); + }); + + it('Recuperer Horaire : should return an object (Jour)', () => { + const s: Structure = new Structure(); + var horaire = [ + { openning: 800, closing: 1200 }, + { openning: 1400, closing: 1600 }, + ]; + s.horaires = new horaireStructure(); + s.horaires.mardi = new Jour(); + s.horaires.mardi.open = true; + s.horaires.mardi.time = horaire; + const jour: Jour = new Jour(); + jour.open = true; + jour.time = horaire; + const result = _structureService.recupererHoraire(s, 2); + expect(result).toEqual(jour); + }); + + it('Recuperer Horaire : should return undefined', () => { + const s: Structure = new Structure(); + var horaire = [ + { openning: 800, closing: 1200 }, + { openning: 1400, closing: 1600 }, + ]; + s.horaires = new horaireStructure(); + s.horaires.lundi = new Jour(); + s.horaires.lundi.open = true; + s.horaires.lundi.time = horaire; + const jour: Jour = new Jour(); + jour.open = true; + jour.time = horaire; + const result = _structureService.recupererHoraire(s, 2); + expect(result).toBeUndefined(); + }); + + it('Recuperer Horaire : should return null', () => { + const s: Structure = new Structure(); + var horaire = [ + { openning: 800, closing: 1200 }, + { openning: 1400, closing: 1600 }, + ]; + s.horaires = new horaireStructure(); + s.horaires.mardi = new Jour(); + s.horaires.mardi.open = true; + s.horaires.mardi.time = horaire; + const result = _structureService.recupererHoraire(s, 8); + expect(result).toBeNull(); + }); + + it('Recuperer Prochaine Ouverture : should return an object ({Jour/Horaire})', () => { + //Init structure + const s: Structure = new Structure(); + var horaire = [ + { openning: 805, closing: 1200 }, + { openning: 1400, closing: 1600 }, + ]; + s.horaires = new horaireStructure(); + s.horaires.lundi = new Jour(); + s.horaires.mardi = new Jour(); + s.horaires.mercredi = new Jour(); + s.horaires.jeudi = new Jour(); + s.horaires.vendredi = new Jour(); + s.horaires.samedi = new Jour(); + s.horaires.dimanche = new Jour(); + s.horaires.mardi.open = true; + s.horaires.mardi.time = horaire; + + //Init sur vendredi à 14h00 + const result = _structureService.recupererProchaineOuverture(s, 5, 5, 1400); + expect(result).toEqual({ jour: 'mardi', horaire: '8h05' }); + }); + + it('Recuperer Prochaine Ouverture dans la journée : should return an object ({Jour/Horaire})', () => { + //Init structure + const s: Structure = new Structure(); + var horaire = [ + { openning: 805, closing: 1200 }, + { openning: 1400, closing: 1600 }, + ]; + s.horaires = new horaireStructure(); + s.horaires.lundi = new Jour(); + s.horaires.mardi = new Jour(); + s.horaires.mercredi = new Jour(); + s.horaires.jeudi = new Jour(); + s.horaires.vendredi = new Jour(); + s.horaires.samedi = new Jour(); + s.horaires.dimanche = new Jour(); + s.horaires.mardi.open = true; + s.horaires.mardi.time = horaire; + + //Init sur mardi à 12h06 + const result = _structureService.recupererProchaineOuverture(s, 2, 2, 1206); + expect(result).toEqual({ jour: ' ', horaire: '14h00' }); + }); + + it('Recuperer Prochaine Ouverture pour la semaine prochaine sur le même jour : should return an object ({Jour/Horaire})', () => { + //Init structure + const s: Structure = new Structure(); + var horaire = [ + { openning: 805, closing: 1200 }, + { openning: 1400, closing: 1600 }, + ]; + s.horaires = new horaireStructure(); + s.horaires.lundi = new Jour(); + s.horaires.mardi = new Jour(); + s.horaires.mercredi = new Jour(); + s.horaires.jeudi = new Jour(); + s.horaires.vendredi = new Jour(); + s.horaires.samedi = new Jour(); + s.horaires.dimanche = new Jour(); + s.horaires.mardi.open = true; + s.horaires.mardi.time = horaire; + + //Init sur mardi à 15h15 + const result = _structureService.recupererProchaineOuverture(s, 2, 2, 1515); + expect(result).toEqual({ jour: 'mardi', horaire: '8h05' }); + }); + + it('Recuperer Prochaine Ouverture : should return an error string', () => { + //Init structure + const s: Structure = new Structure(); + s.horaires = new horaireStructure(); + s.horaires.lundi = new Jour(); + s.horaires.mardi = new Jour(); + s.horaires.mercredi = new Jour(); + s.horaires.jeudi = new Jour(); + s.horaires.vendredi = new Jour(); + s.horaires.samedi = new Jour(); + s.horaires.dimanche = new Jour(); - it('should be created', () => { - expect(service).toBeTruthy(); + //Init sur jeudi à 12h06 + const result = _structureService.recupererProchaineOuverture(s, 4, 2, 1206); + expect(result).toEqual('Aucun horaire disponible'); }); }); diff --git a/src/app/structure/services/structure.service.ts b/src/app/structure/services/structure.service.ts index a72138d7e..dc5803152 100644 --- a/src/app/structure/services/structure.service.ts +++ b/src/app/structure/services/structure.service.ts @@ -37,7 +37,6 @@ export class StructureService { }); } structure.ouvreLe = this.recupererProchaineOuverture(structure, jourSemaine, jourSemaine, now); - return structure; } @@ -58,6 +57,8 @@ export class StructureService { return structure.horaires.samedi; case 7: return structure.horaires.dimanche; + default: + return null; } } //Vérifie si l'heure actuelle est dans l'interval des horaires de la structure @@ -110,7 +111,20 @@ export class StructureService { return this.recupererProchaineOuverture(s, 1, baseJour, baseHeure); } } - return 'Aucun horaire disponible'; + var lastChancehoraire = this.recupererHoraire(s, j + 1); + var lastJour: any; + if (lastChancehoraire.open) { + lastChancehoraire.time.every((periode) => { + if (periode.openning && periode.openning < baseHeure) { + lastJour = { jour: this.numberToDay(j + 1), horaire: this.numberToHour(periode.openning) }; + return false; + } + lastJour = 'Aucun horaire disponible'; + }); + } else { + lastJour = 'Aucun horaire disponible'; + } + return lastJour; } numberToDay(n: number) { @@ -129,6 +143,8 @@ export class StructureService { return 'samedi'; case 7: return 'dimanche'; + default: + return null; } } -- GitLab From c5b1c9d732c5db6497ee66bf6fef51c242da0ce2 Mon Sep 17 00:00:00 2001 From: Jeremie BRISON <ext.sopra.jbrison@grandlyon.com> Date: Mon, 12 Oct 2020 10:21:45 +0200 Subject: [PATCH 07/50] fix(card) : add condition for monday problem + export date from service to component MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Condition supplémentaire sur la fonction récursive pour gérer le cas d'un Lundi. Suppression de l'import Luxon dans le service. --- .../components/card/card.component.ts | 4 +- .../services/structure.service.spec.ts | 51 ++++++++++++++++++- .../structure/services/structure.service.ts | 19 ++++--- 3 files changed, 63 insertions(+), 11 deletions(-) diff --git a/src/app/structure/components/card/card.component.ts b/src/app/structure/components/card/card.component.ts index 093bdde33..ad3154950 100644 --- a/src/app/structure/components/card/card.component.ts +++ b/src/app/structure/components/card/card.component.ts @@ -1,6 +1,7 @@ import { Component, OnInit } from '@angular/core'; import { Structure } from '../../models/structure.model'; import { StructureService } from '../../services/structure.service'; +const { DateTime } = require('luxon'); @Component({ selector: 'app-card', @@ -12,9 +13,10 @@ export class CardComponent implements OnInit { constructor(private _structureService: StructureService) {} ngOnInit(): void { + var dt = DateTime.local(); this._structureService.recupererStructures().subscribe((structures: Structure[]) => { structures.forEach((s: Structure) => { - this.structures.push(this._structureService.majOuvertureStructure(s)); + this.structures.push(this._structureService.majOuvertureStructure(s, dt)); }); }); } diff --git a/src/app/structure/services/structure.service.spec.ts b/src/app/structure/services/structure.service.spec.ts index e4f26a5ac..7c885d669 100644 --- a/src/app/structure/services/structure.service.spec.ts +++ b/src/app/structure/services/structure.service.spec.ts @@ -133,7 +133,7 @@ describe('StructureService', () => { }); it('Recuperer Prochaine Ouverture pour la semaine prochaine sur le même jour : should return an object ({Jour/Horaire})', () => { - //Init structure + //Init structure avec deux horaires le mardi const s: Structure = new Structure(); var horaire = [ { openning: 805, closing: 1200 }, @@ -156,7 +156,7 @@ describe('StructureService', () => { }); it('Recuperer Prochaine Ouverture : should return an error string', () => { - //Init structure + //Init structure avec aucun horaire const s: Structure = new Structure(); s.horaires = new horaireStructure(); s.horaires.lundi = new Jour(); @@ -171,4 +171,51 @@ describe('StructureService', () => { const result = _structureService.recupererProchaineOuverture(s, 4, 2, 1206); expect(result).toEqual('Aucun horaire disponible'); }); + + it('Mise à jour ouverture de la structure : should return true', () => { + var horaire = [ + { openning: 805, closing: 1200 }, + { openning: 1400, closing: 1600 }, + ]; + //Init structure avec aucun horaire + const s: Structure = new Structure(); + s.horaires = new horaireStructure(); + s.horaires.lundi = new Jour(); + s.horaires.mardi = new Jour(); + s.horaires.mercredi = new Jour(); + s.horaires.jeudi = new Jour(); + s.horaires.vendredi = new Jour(); + s.horaires.samedi = new Jour(); + s.horaires.dimanche = new Jour(); + + s.horaires.jeudi.open = true; + s.horaires.jeudi.time = horaire; + + //Init date sur un jeudi à 9h05 + var dt = new DateTime.local(2020, 10, 8, 9, 5); + const result = _structureService.majOuvertureStructure(s, dt); + expect(result.estOuvert).toEqual(true); + }); + + it('Mise à jour ouverture de la structure : should return false', () => { + var horaire = [{ openning: 1400, closing: 1600 }]; + //Init structure avec aucun horaire + const s: Structure = new Structure(); + s.horaires = new horaireStructure(); + s.horaires.lundi = new Jour(); + s.horaires.mardi = new Jour(); + s.horaires.mercredi = new Jour(); + s.horaires.jeudi = new Jour(); + s.horaires.vendredi = new Jour(); + s.horaires.samedi = new Jour(); + s.horaires.dimanche = new Jour(); + + s.horaires.jeudi.open = true; + s.horaires.jeudi.time = horaire; + + //Init date sur un jeudi à 9h05 + var dt = new DateTime.local(2020, 10, 8, 9, 5); + const result = _structureService.majOuvertureStructure(s, dt); + expect(result.estOuvert).toEqual(false); + }); }); diff --git a/src/app/structure/services/structure.service.ts b/src/app/structure/services/structure.service.ts index dc5803152..f18978024 100644 --- a/src/app/structure/services/structure.service.ts +++ b/src/app/structure/services/structure.service.ts @@ -1,7 +1,6 @@ import { HttpClient } from '@angular/common/http'; import { Injectable } from '@angular/core'; import { Jour, Structure } from '../models/structure.model'; -const { DateTime } = require('luxon'); @Injectable({ providedIn: 'root', @@ -13,17 +12,16 @@ export class StructureService { return this.http.get('/api/Structures'); } - majOuvertureStructure(structure: Structure) { + majOuvertureStructure(structure: Structure, dateActuelle: any) { //Récupère le jour de la semaine. - var dt = DateTime.local(); - var jourSemaine: number = dt.weekday; + var jourSemaine: number = dateActuelle.weekday; //Vérifie si les minutes commencent par zéro pour éviter la suppression. var now: number; - if (dt.minute.toString().length != 1) { - now = parseInt('' + dt.hour + dt.minute, 10); + if (dateActuelle.minute.toString().length != 1) { + now = parseInt('' + dateActuelle.hour + dateActuelle.minute, 10); } else { - now = parseInt('' + dt.hour + 0 + dt.minute, 10); + now = parseInt('' + dateActuelle.hour + 0 + dateActuelle.minute, 10); } //Récupérer les horaires d'une structure en fonction de son jour pour indiquer si elle est ouverte. @@ -104,10 +102,15 @@ export class StructureService { return jourOuverture; } } else { - //Si le jour est égal à Dimanche, on le positionne sur Lundi. + //Si le jour n'est pas égal à Dimanche, on l'incrémente de 1. if (j != 7) { return this.recupererProchaineOuverture(s, j + 1, baseJour, baseHeure); } + //Si le jour est égal à Lundi, on le positionne sur 0 pour activer la condition d'arrêt. + if (baseJour == 1) { + return this.recupererProchaineOuverture(s, 0, baseJour, baseHeure); + } + //Si le jour est égal à Dimanche, on le positionne sur Lundi. return this.recupererProchaineOuverture(s, 1, baseJour, baseHeure); } } -- GitLab From aa7cac38b2ab92413058db0a90392657cc0f88ba Mon Sep 17 00:00:00 2001 From: Jeremie BRISON <ext.sopra.jbrison@grandlyon.com> Date: Mon, 12 Oct 2020 14:48:54 +0200 Subject: [PATCH 08/50] feat(search) : add html style + icon search --- .../recherche/recherche.component.html | 38 +++- .../recherche/recherche.component.scss | 172 ++++++++++++++++++ src/app/structure/structure.component.html | 7 +- src/app/structure/structure.component.scss | 11 ++ src/assets/scss/_icons.scss | 20 ++ 5 files changed, 245 insertions(+), 3 deletions(-) diff --git a/src/app/structure/components/recherche/recherche.component.html b/src/app/structure/components/recherche/recherche.component.html index 63c7b1a72..bca3c4b6f 100644 --- a/src/app/structure/components/recherche/recherche.component.html +++ b/src/app/structure/components/recherche/recherche.component.html @@ -1 +1,37 @@ -<p>recherche works!</p> +<div class="header"> + <span class="title">Acteurs de la médiation</span> +</div> +<div class="content" fxLayout="column"> + <div class="searchSection" fxLayout="row" fxLayoutGap="1.5vw"> + <div class="icon"> + <div class="ico-pin-search grey"></div> + </div> + <input type="text" placeholder="Rechercher une adresse, une association..." /> + <button type="button">Rechercher</button> + </div> + + <div class="btnSection" fxLayout="row" fxLayoutAlign="space-between center"> + <button type="button"> + <span class="btnText">Services</span> + <div class="arrow"></div> + </button> + <button type="button"> + <span class="btnText">Accueil</span> + <div class="arrow"></div> + </button> + <button type="button"> + <span class="btnText">Plus de filtres</span> + <div class="arrow"></div> + </button> + </div> +</div> +<div class="footer" fxLayout="row" fxLayoutAlign="space-between center"> + <div class="checkbox"> + <label> + <input type="checkbox" /> + <span class="customCheck"></span> + Pass numérique + </label> + </div> + <a href="">Ajouter une structure</a> +</div> diff --git a/src/app/structure/components/recherche/recherche.component.scss b/src/app/structure/components/recherche/recherche.component.scss index e69de29bb..41a606c70 100644 --- a/src/app/structure/components/recherche/recherche.component.scss +++ b/src/app/structure/components/recherche/recherche.component.scss @@ -0,0 +1,172 @@ +@import '../../../../assets/scss/icons'; +@import '../../../../assets/scss/color'; +.header { + .title { + font-family: Times New Roman; + font-style: normal; + font-weight: bold; + font-size: 20px; + line-height: 103%; + padding: 16px 0 16px 0; + + display: flex; + align-items: center; + text-transform: uppercase; + } +} +.content { + margin: 10px 0 0px 0; + .icon { + border: 1px solid $grey; + padding: 4px 6px 8px 6px; + border-radius: 4px; + cursor: pointer; + } + input { + width: 100%; + background-color: $grey-4; + border: none; + font-family: Trebuchet MS; + font-style: normal; + font-weight: normal; + font-size: 12px; + line-height: 17px; + display: flex; + align-items: center; + padding-left: 10px; + text-overflow: ellipsis; + color: $grey-1; + outline: none; + } + .searchSection { + button { + border: none; + cursor: pointer; + background-color: $purple; + font-family: Trebuchet MS; + font-style: normal; + font-weight: bold; + font-size: 13px; + line-height: 100%; + align-items: center; + text-align: center; + color: $white; + padding: 0 10px 0 10px; + outline: none; + } + } + .btnSection { + padding: 16px 0 16px 0; + button { + border: 1px solid $grey; + border-radius: 33px; + background-color: $white; + padding: 2px 6px 2px 13px; + align-items: center; + display: flex; + cursor: pointer; + + .btnText { + justify-content: center; + font-family: Trebuchet MS; + font-style: normal; + font-weight: normal; + font-size: 13px; + line-height: 19px; + display: flex; + align-items: center; + } + &:focus { + border: 1px solid $orange-light; + color: $orange-light; + outline: none; + .arrow { + background-color: transparent; + border-bottom: 1px solid $orange-light; + border-right: 1px solid $orange-light; + transform: translateY(25%) rotate(-135deg); + margin: 0 5px 0 10px; + height: 7px; + width: 7px; + } + } + } + .arrow { + background-color: transparent; + border-bottom: 1px solid $grey; + border-right: 1px solid $grey; + transform: translateY(-25%) rotate(45deg); + margin: 0 5px 0 10px; + height: 7px; + width: 7px; + } + } +} +.footer { + margin: 0px 0 16px 0; + a { + font-family: Trebuchet MS; + font-style: normal; + font-weight: bold; + font-size: 13px; + line-height: 18px; + /* or 120% */ + + display: flex; + align-items: center; + text-decoration-line: underline; + } + .checkbox { + position: relative; + padding-left: 27px; + label { + font-family: Trebuchet MS; + font-style: normal; + font-weight: normal; + font-size: 15px; + line-height: 21px; + } + input { + position: absolute; + opacity: 0; + height: 0; + width: 0; + &:checked ~ .customCheck { + background-color: $orange-light; + border-color: transparent; + } + &:checked ~ .customCheck:after { + display: block; + } + } + .customCheck { + position: absolute; + height: 18px; + width: 18px; + background-color: $white; + border: 1px solid $grey; + cursor: pointer; + top: 0; + left: 0; + &:hover { + background-color: $grey-4; + } + &:after { + content: ''; + position: absolute; + display: none; + } + &:after { + left: 6.5px; + top: 3px; + width: 4px; + height: 8px; + border: solid white; + border-width: 0 2px 2px 0; + transform: rotate(45deg); + -webkit-transform: rotate(45deg); + -ms-transform: rotate(45deg); + } + } + } +} diff --git a/src/app/structure/structure.component.html b/src/app/structure/structure.component.html index a6dbe19b7..86c8f6308 100644 --- a/src/app/structure/structure.component.html +++ b/src/app/structure/structure.component.html @@ -1,2 +1,5 @@ -<app-recherche></app-recherche> -<app-card></app-card> +<div class="container"> + <app-recherche></app-recherche> + <div class="divider"></div> + <app-card></app-card> +</div> diff --git a/src/app/structure/structure.component.scss b/src/app/structure/structure.component.scss index e69de29bb..2d506b58d 100644 --- a/src/app/structure/structure.component.scss +++ b/src/app/structure/structure.component.scss @@ -0,0 +1,11 @@ +@import '../../assets/scss/color'; + +.divider { + width: 100%; + height: 1px; + background-color: $grey-4; +} +//En attendant de l'intégrer avec la map +.container { + width: 320px; +} diff --git a/src/assets/scss/_icons.scss b/src/assets/scss/_icons.scss index a44fae8f2..54bf61acf 100644 --- a/src/assets/scss/_icons.scss +++ b/src/assets/scss/_icons.scss @@ -64,6 +64,26 @@ background: $orange; } } +.ico-pin-search { + width: 18px; + height: 18px; + border-radius: 50% 50% 50% 0; + -webkit-transform: rotate(-45deg); + transform: rotate(-45deg); + &:before { + content: ''; + position: absolute; + left: 5px; + top: 6px; + width: 7px; + height: 7px; + border-radius: 4px; + background-color: white; + } + &.grey { + background-color: #828282; + } +} .ico-dot-available { height: 12px; width: 12px; -- GitLab From 4dd91784c1d12a3866de6d54b71c5b5e874c0e58 Mon Sep 17 00:00:00 2001 From: Jeremie BRISON <ext.sopra.jbrison@grandlyon.com> Date: Mon, 12 Oct 2020 15:40:03 +0200 Subject: [PATCH 09/50] fix(search) : Fix btn design clicked + init modal MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Utilisation du TS plutôt que des propriétés CSS pour la gestion Activé/Désactivé des filtres --- .../recherche/recherche.component.html | 7 ++-- .../recherche/recherche.component.scss | 39 ++++++++++++------- .../recherche/recherche.component.ts | 37 ++++++++++++++++-- 3 files changed, 62 insertions(+), 21 deletions(-) diff --git a/src/app/structure/components/recherche/recherche.component.html b/src/app/structure/components/recherche/recherche.component.html index bca3c4b6f..a1e2b199d 100644 --- a/src/app/structure/components/recherche/recherche.component.html +++ b/src/app/structure/components/recherche/recherche.component.html @@ -11,19 +11,20 @@ </div> <div class="btnSection" fxLayout="row" fxLayoutAlign="space-between center"> - <button type="button"> + <button type="button" [className]="btnServicesChecked ? 'selected' : ''" (click)="openModal(this.modalType[0])"> <span class="btnText">Services</span> <div class="arrow"></div> </button> - <button type="button"> + <button type="button" [className]="btnHomeChecked ? 'selected' : ''" (click)="openModal(this.modalType[1])"> <span class="btnText">Accueil</span> <div class="arrow"></div> </button> - <button type="button"> + <button type="button" [className]="btnMoreFilterchecked ? 'selected' : ''" (click)="openModal(this.modalType[2])"> <span class="btnText">Plus de filtres</span> <div class="arrow"></div> </button> </div> + <div *ngIf="modalOpened" class="modal"></div> </div> <div class="footer" fxLayout="row" fxLayoutAlign="space-between center"> <div class="checkbox"> diff --git a/src/app/structure/components/recherche/recherche.component.scss b/src/app/structure/components/recherche/recherche.component.scss index 41a606c70..b1e1cac04 100644 --- a/src/app/structure/components/recherche/recherche.component.scss +++ b/src/app/structure/components/recherche/recherche.component.scss @@ -58,6 +58,8 @@ .btnSection { padding: 16px 0 16px 0; button { + outline: none; + border: 1px solid $grey; border-radius: 33px; background-color: $white; @@ -65,7 +67,6 @@ align-items: center; display: flex; cursor: pointer; - .btnText { justify-content: center; font-family: Trebuchet MS; @@ -76,19 +77,18 @@ display: flex; align-items: center; } - &:focus { - border: 1px solid $orange-light; - color: $orange-light; - outline: none; - .arrow { - background-color: transparent; - border-bottom: 1px solid $orange-light; - border-right: 1px solid $orange-light; - transform: translateY(25%) rotate(-135deg); - margin: 0 5px 0 10px; - height: 7px; - width: 7px; - } + } + .selected { + border: 1px solid $orange-light; + color: $orange-light; + .arrow { + background-color: transparent; + border-bottom: 1px solid $orange-light; + border-right: 1px solid $orange-light; + transform: translateY(25%) rotate(-135deg); + margin: 0 5px 0 10px; + height: 7px; + width: 7px; } } .arrow { @@ -170,3 +170,14 @@ } } } +.modal { + height: 500px; + width: 1100px; + background: $white; + border: 1px solid $purple; + box-sizing: border-box; + border-radius: 8px; + z-index: 1; + position: fixed; + margin-top: 80px; +} diff --git a/src/app/structure/components/recherche/recherche.component.ts b/src/app/structure/components/recherche/recherche.component.ts index b37a52c87..f47084959 100644 --- a/src/app/structure/components/recherche/recherche.component.ts +++ b/src/app/structure/components/recherche/recherche.component.ts @@ -3,13 +3,42 @@ import { Component, OnInit } from '@angular/core'; @Component({ selector: 'app-recherche', templateUrl: './recherche.component.html', - styleUrls: ['./recherche.component.scss'] + styleUrls: ['./recherche.component.scss'], }) export class RechercheComponent implements OnInit { - - constructor() { } - + constructor() {} + modalOpened: string; + modalType: string[] = ['services', 'accueil', 'plusFiltres']; + btnServicesChecked: boolean; + btnHomeChecked: boolean; + btnMoreFilterchecked: boolean; ngOnInit(): void { + this.modalOpened = null; + this.btnServicesChecked = false; } + openModal(option: string) { + this.modalOpened = null; + switch (option) { + case this.modalType[0]: + this.btnServicesChecked = !this.btnServicesChecked; + this.btnHomeChecked = false; + this.btnMoreFilterchecked = false; + if (this.btnServicesChecked) this.modalOpened = this.modalType[0]; + + break; + case this.modalType[1]: + this.btnHomeChecked = !this.btnHomeChecked; + this.btnMoreFilterchecked = false; + this.btnServicesChecked = false; + if (this.btnHomeChecked) this.modalOpened = this.modalType[1]; + break; + case this.modalType[2]: + this.btnMoreFilterchecked = !this.btnMoreFilterchecked; + this.btnServicesChecked = false; + this.btnHomeChecked = false; + if (this.btnMoreFilterchecked) this.modalOpened = this.modalType[2]; + break; + } + } } -- GitLab From 2f26a9680a3df06fd520bcd73c84b0d703890d33 Mon Sep 17 00:00:00 2001 From: Jeremie BRISON <ext.sopra.jbrison@grandlyon.com> Date: Tue, 13 Oct 2020 09:14:28 +0200 Subject: [PATCH 10/50] fix(search) : add modal + module list --- .../recherche/recherche.component.html | 30 ++- .../recherche/recherche.component.scss | 171 ++++++++++++------ .../recherche/recherche.component.ts | 45 ++++- src/app/structure/models/recherche.model.ts | 5 + 4 files changed, 192 insertions(+), 59 deletions(-) create mode 100644 src/app/structure/models/recherche.model.ts diff --git a/src/app/structure/components/recherche/recherche.component.html b/src/app/structure/components/recherche/recherche.component.html index a1e2b199d..b5b6f48af 100644 --- a/src/app/structure/components/recherche/recherche.component.html +++ b/src/app/structure/components/recherche/recherche.component.html @@ -24,7 +24,35 @@ <div class="arrow"></div> </button> </div> - <div *ngIf="modalOpened" class="modal"></div> + <div *ngIf="modalOpened" class="modal" fxLayout="column" fxLayoutAlign="space-between"> + <div class="contentModal" fxLayout="row wrap"> + <!--<div class="blockFiltre" *ngFor="let s of services">--> + <div class="blockFiltre" *ngFor="let s of services"> + <div class="blockLigne"> + <h4>{{ s.titre }}</h4> + <div + fxLayout="row" + class="ligneFiltre" + fxLayoutAlign="space-between center" + *ngFor="let categ of s.categories" + > + <div class="checkbox"> + <label> + <input type="checkbox" /> + <span class="customCheck"></span> + {{ categ }} + </label> + </div> + <span class="nbResult">34</span> + </div> + </div> + </div> + </div> + <div class="footer" fxLayout="row" fxLayoutAlign="end center" fxLayoutGap="3vw"> + <a href="">Effacer</a> + <button type="button" (click)="applyFilter()">Appliquer</button> + </div> + </div> </div> <div class="footer" fxLayout="row" fxLayoutAlign="space-between center"> <div class="checkbox"> diff --git a/src/app/structure/components/recherche/recherche.component.scss b/src/app/structure/components/recherche/recherche.component.scss index b1e1cac04..81da77faf 100644 --- a/src/app/structure/components/recherche/recherche.component.scss +++ b/src/app/structure/components/recherche/recherche.component.scss @@ -1,5 +1,6 @@ @import '../../../../assets/scss/icons'; @import '../../../../assets/scss/color'; + .header { .title { font-family: Times New Roman; @@ -51,7 +52,7 @@ align-items: center; text-align: center; color: $white; - padding: 0 10px 0 10px; + padding: 3px 16px 3px 16px; outline: none; } } @@ -116,68 +117,126 @@ align-items: center; text-decoration-line: underline; } - .checkbox { - position: relative; - padding-left: 27px; - label { +} +.modal { + height: 654px; + max-width: 1100px; + background: $white; + border: 1px solid $purple; + box-sizing: border-box; + border-radius: 8px; + z-index: 1; + position: absolute; + margin-top: 80px; + .contentModal { + writing-mode: vertical-lr; + padding: 20px 5px 10px 5px; + overflow-y: hidden; + max-width: 1100px; + .blockFiltre { + writing-mode: horizontal-tb; + max-width: 320px; + padding: 0 10px 10px 10px; + } + .ligneFiltre { + margin: 5px 0 5px 0; + } + h4 { + font-family: Trebuchet MS; + font-style: normal; + font-weight: bold; + font-size: 13px; + line-height: 17px; + display: flex; + align-items: center; + margin: 0; + } + .nbResult { font-family: Trebuchet MS; font-style: normal; font-weight: normal; - font-size: 15px; - line-height: 21px; + font-size: 13px; + line-height: 15px; } - input { - position: absolute; - opacity: 0; - height: 0; - width: 0; - &:checked ~ .customCheck { - background-color: $orange-light; - border-color: transparent; - } - &:checked ~ .customCheck:after { - display: block; - } + label { + font-family: Trebuchet MS; + font-style: normal; + font-weight: normal; + font-size: 14px; + line-height: 16px; } - .customCheck { - position: absolute; - height: 18px; - width: 18px; - background-color: $white; - border: 1px solid $grey; + } + .footer { + height: 32px; + padding-right: 24px; + button { + height: 100%; + border: none; cursor: pointer; - top: 0; - left: 0; - &:hover { - background-color: $grey-4; - } - &:after { - content: ''; - position: absolute; - display: none; - } - &:after { - left: 6.5px; - top: 3px; - width: 4px; - height: 8px; - border: solid white; - border-width: 0 2px 2px 0; - transform: rotate(45deg); - -webkit-transform: rotate(45deg); - -ms-transform: rotate(45deg); - } + background-color: $purple; + font-family: Trebuchet MS; + font-style: normal; + font-weight: bold; + font-size: 13px; + line-height: 100%; + align-items: center; + text-align: center; + color: $white; + padding: 3px 16px 3px 16px; + outline: none; } } } -.modal { - height: 500px; - width: 1100px; - background: $white; - border: 1px solid $purple; - box-sizing: border-box; - border-radius: 8px; - z-index: 1; - position: fixed; - margin-top: 80px; +.checkbox { + position: relative; + padding-left: 27px; + label { + font-family: Trebuchet MS; + font-style: normal; + font-weight: normal; + font-size: 15px; + line-height: 21px; + } + input { + position: absolute; + opacity: 0; + height: 0; + width: 0; + &:checked ~ .customCheck { + background-color: $orange-light; + border-color: transparent; + } + &:checked ~ .customCheck:after { + display: block; + } + } + .customCheck { + position: absolute; + height: 18px; + width: 18px; + background-color: $white; + border: 1px solid $grey; + cursor: pointer; + top: 0; + left: 0; + &:hover { + background-color: $grey-4; + } + &:after { + content: ''; + position: absolute; + display: none; + } + &:after { + left: 6.5px; + top: 3px; + width: 4px; + height: 8px; + border: solid white; + border-width: 0 2px 2px 0; + transform: rotate(45deg); + -webkit-transform: rotate(45deg); + -ms-transform: rotate(45deg); + } + } } diff --git a/src/app/structure/components/recherche/recherche.component.ts b/src/app/structure/components/recherche/recherche.component.ts index f47084959..15fb2c9cf 100644 --- a/src/app/structure/components/recherche/recherche.component.ts +++ b/src/app/structure/components/recherche/recherche.component.ts @@ -1,4 +1,5 @@ import { Component, OnInit } from '@angular/core'; +import { Service } from '../../models/recherche.model'; @Component({ selector: 'app-recherche', @@ -12,11 +13,32 @@ export class RechercheComponent implements OnInit { btnServicesChecked: boolean; btnHomeChecked: boolean; btnMoreFilterchecked: boolean; + test = '50%'; + services: Service[]; + ngOnInit(): void { - this.modalOpened = null; + this.modalOpened = 'services'; this.btnServicesChecked = false; + this.services = []; + this.mockService('Accompagnement aux démarches en ligne', 'CAF', 7); + this.mockService('Insertion sociale et professionnelle', 'Diffuser son CV en ligne', 5); + this.mockService('Accès aux droits', 'Déclarer ses revenus en ligne et découvertes des services proposés', 8); + this.mockService('Aide à la parentalité/éducation', 'Découvrir l’univers des jeux vidéos', 4); + this.mockService('Compétences de base', 'Faire un diagnostic des compétences', 8); + this.mockService('Culture et sécurité numérique', 'Traitement de texte : découverte', 4); + console.log(this.services); + this.calcSizeCol(this.services); } + mockService(titre: string, categ: string, nbCateg: number) { + var service1 = new Service(); + service1.titre = titre; + service1.categories = []; + for (var i = 0; i < nbCateg; i++) { + service1.categories.push(categ + '_' + i); + } + this.services.push(service1); + } openModal(option: string) { this.modalOpened = null; switch (option) { @@ -25,7 +47,6 @@ export class RechercheComponent implements OnInit { this.btnHomeChecked = false; this.btnMoreFilterchecked = false; if (this.btnServicesChecked) this.modalOpened = this.modalType[0]; - break; case this.modalType[1]: this.btnHomeChecked = !this.btnHomeChecked; @@ -41,4 +62,24 @@ export class RechercheComponent implements OnInit { break; } } + applyFilter() { + this.openModal(this.modalOpened); + } + + calcSizeCol(services: Service[]) { + for (var i = 0; i < services.length; i++) { + if (services[i + 1]) { + var nb1, nb2: number; + nb1 = services[i].categories.length; + nb2 = services[i + 1].categories.length; + if (nb1 + nb2 <= 13) { + services[i].size = parseFloat((nb1 / 13).toPrecision(2)) * 100; + services[i + 1].size = parseFloat((1 - services[i].size / 100).toPrecision(2)) * 100; + i++; + } else { + services[i].size = 100; + } + } + } + } } diff --git a/src/app/structure/models/recherche.model.ts b/src/app/structure/models/recherche.model.ts new file mode 100644 index 000000000..5904abd46 --- /dev/null +++ b/src/app/structure/models/recherche.model.ts @@ -0,0 +1,5 @@ +export class Service { + titre: string; + categories: string[]; + size: number; +} -- GitLab From 74601392794bfbe07e66ae53bcf29fa65b673d05 Mon Sep 17 00:00:00 2001 From: Jeremie BRISON <ext.sopra.jbrison@grandlyon.com> Date: Tue, 13 Oct 2020 09:55:55 +0200 Subject: [PATCH 11/50] fix(checkbox) : fix checkbox display checked --- .../recherche/recherche.component.html | 12 +++++-- .../recherche/recherche.component.scss | 32 +++++++++++-------- 2 files changed, 28 insertions(+), 16 deletions(-) diff --git a/src/app/structure/components/recherche/recherche.component.html b/src/app/structure/components/recherche/recherche.component.html index b5b6f48af..d5174958b 100644 --- a/src/app/structure/components/recherche/recherche.component.html +++ b/src/app/structure/components/recherche/recherche.component.html @@ -1,3 +1,11 @@ +<div class="checkbox"> + <label> + <input type="checkbox" /> + <span class="customCheck"></span> + </label> + <div class="test">text ici</div> +</div> + <div class="header"> <span class="title">Acteurs de la médiation</span> </div> @@ -40,8 +48,8 @@ <label> <input type="checkbox" /> <span class="customCheck"></span> - {{ categ }} </label> + <div class="label">{{ categ }}</div> </div> <span class="nbResult">34</span> </div> @@ -59,8 +67,8 @@ <label> <input type="checkbox" /> <span class="customCheck"></span> - Pass numérique </label> + <div class="label">Pass numérique</div> </div> <a href="">Ajouter une structure</a> </div> diff --git a/src/app/structure/components/recherche/recherche.component.scss b/src/app/structure/components/recherche/recherche.component.scss index 81da77faf..fa45288d7 100644 --- a/src/app/structure/components/recherche/recherche.component.scss +++ b/src/app/structure/components/recherche/recherche.component.scss @@ -189,19 +189,12 @@ } .checkbox { position: relative; - padding-left: 27px; - label { - font-family: Trebuchet MS; - font-style: normal; - font-weight: normal; - font-size: 15px; - line-height: 21px; - } + display: grid; + align-items: center; + grid-template-columns: min-content auto; input { - position: absolute; opacity: 0; - height: 0; - width: 0; + display: none; &:checked ~ .customCheck { background-color: $orange-light; border-color: transparent; @@ -210,13 +203,24 @@ display: block; } } + .label { + padding-left: 15px; + + font-family: Trebuchet MS; + font-style: normal; + font-weight: normal; + font-size: 15px; + line-height: 21px; + } .customCheck { - position: absolute; - height: 18px; + display: inline-grid; width: 18px; + height: 18px; background-color: $white; border: 1px solid $grey; cursor: pointer; + position: relative; + top: 0; left: 0; &:hover { @@ -228,7 +232,7 @@ display: none; } &:after { - left: 6.5px; + left: 7px; top: 3px; width: 4px; height: 8px; -- GitLab From 046684b4a75808fee6ee1fa882dd701d6ed0c467 Mon Sep 17 00:00:00 2001 From: Jeremie BRISON <ext.sopra.jbrison@grandlyon.com> Date: Tue, 13 Oct 2020 10:46:03 +0200 Subject: [PATCH 12/50] fix(checkbox) : add btn + form + clear --- .../recherche/recherche.component.html | 31 +++++----- .../recherche/recherche.component.scss | 20 ++++--- .../recherche/recherche.component.ts | 57 +++++++++++++------ src/app/structure/structure.module.ts | 3 +- 4 files changed, 71 insertions(+), 40 deletions(-) diff --git a/src/app/structure/components/recherche/recherche.component.html b/src/app/structure/components/recherche/recherche.component.html index d5174958b..7c5564162 100644 --- a/src/app/structure/components/recherche/recherche.component.html +++ b/src/app/structure/components/recherche/recherche.component.html @@ -1,11 +1,3 @@ -<div class="checkbox"> - <label> - <input type="checkbox" /> - <span class="customCheck"></span> - </label> - <div class="test">text ici</div> -</div> - <div class="header"> <span class="title">Acteurs de la médiation</span> </div> @@ -32,7 +24,15 @@ <div class="arrow"></div> </button> </div> - <div *ngIf="modalOpened" class="modal" fxLayout="column" fxLayoutAlign="space-between"> + <form + [formGroup]="form" + (ngSubmit)="applyFilter()" + novalidate + *ngIf="modalOpened" + class="modal" + fxLayout="column" + fxLayoutAlign="space-between" + > <div class="contentModal" fxLayout="row wrap"> <!--<div class="blockFiltre" *ngFor="let s of services">--> <div class="blockFiltre" *ngFor="let s of services"> @@ -46,7 +46,12 @@ > <div class="checkbox"> <label> - <input type="checkbox" /> + <input + type="checkbox" + [checked]="isChecked(categ)" + [value]="categ" + (change)="onCheckboxChange($event, true)" + /> <span class="customCheck"></span> </label> <div class="label">{{ categ }}</div> @@ -57,10 +62,10 @@ </div> </div> <div class="footer" fxLayout="row" fxLayoutAlign="end center" fxLayoutGap="3vw"> - <a href="">Effacer</a> - <button type="button" (click)="applyFilter()">Appliquer</button> + <a (click)="onCheckboxChange($event, false)">Effacer</a> + <button type="submit" value="Submit">Appliquer</button> </div> - </div> + </form> </div> <div class="footer" fxLayout="row" fxLayoutAlign="space-between center"> <div class="checkbox"> diff --git a/src/app/structure/components/recherche/recherche.component.scss b/src/app/structure/components/recherche/recherche.component.scss index fa45288d7..9ea829dac 100644 --- a/src/app/structure/components/recherche/recherche.component.scss +++ b/src/app/structure/components/recherche/recherche.component.scss @@ -128,15 +128,17 @@ z-index: 1; position: absolute; margin-top: 80px; + padding: 20px 16px 10px 16px; .contentModal { writing-mode: vertical-lr; - padding: 20px 5px 10px 5px; overflow-y: hidden; max-width: 1100px; + border-bottom: 1px solid grey; + margin-bottom: 10px; .blockFiltre { writing-mode: horizontal-tb; max-width: 320px; - padding: 0 10px 10px 10px; + padding: 0 30px 10px 10px; } .ligneFiltre { margin: 5px 0 5px 0; @@ -149,7 +151,7 @@ line-height: 17px; display: flex; align-items: center; - margin: 0; + margin-top: 0; } .nbResult { font-family: Trebuchet MS; @@ -168,7 +170,6 @@ } .footer { height: 32px; - padding-right: 24px; button { height: 100%; border: none; @@ -203,14 +204,17 @@ display: block; } } + label { + display: inline-grid; + } .label { - padding-left: 15px; - + padding-left: 8px; font-family: Trebuchet MS; font-style: normal; font-weight: normal; - font-size: 15px; - line-height: 21px; + font-size: 14px; + line-height: 17px; + padding: 0 16px 0 16px; } .customCheck { display: inline-grid; diff --git a/src/app/structure/components/recherche/recherche.component.ts b/src/app/structure/components/recherche/recherche.component.ts index 15fb2c9cf..5aaac22ef 100644 --- a/src/app/structure/components/recherche/recherche.component.ts +++ b/src/app/structure/components/recherche/recherche.component.ts @@ -1,5 +1,6 @@ import { Component, OnInit } from '@angular/core'; import { Service } from '../../models/recherche.model'; +import { FormBuilder, FormGroup, FormArray, FormControl } from '@angular/forms'; @Component({ selector: 'app-recherche', @@ -7,7 +8,12 @@ import { Service } from '../../models/recherche.model'; styleUrls: ['./recherche.component.scss'], }) export class RechercheComponent implements OnInit { - constructor() {} + constructor(private fb: FormBuilder) { + this.form = this.fb.group({ + checkArray: this.fb.array([]), + }); + } + form: FormGroup; modalOpened: string; modalType: string[] = ['services', 'accueil', 'plusFiltres']; btnServicesChecked: boolean; @@ -17,19 +23,19 @@ export class RechercheComponent implements OnInit { services: Service[]; ngOnInit(): void { - this.modalOpened = 'services'; + this.modalOpened = null; this.btnServicesChecked = false; this.services = []; + //Block en attendant this.mockService('Accompagnement aux démarches en ligne', 'CAF', 7); - this.mockService('Insertion sociale et professionnelle', 'Diffuser son CV en ligne', 5); + this.mockService('Insertion sociale et professionnelle', ' Diffuser son CV en ligne', 5); this.mockService('Accès aux droits', 'Déclarer ses revenus en ligne et découvertes des services proposés', 8); this.mockService('Aide à la parentalité/éducation', 'Découvrir l’univers des jeux vidéos', 4); this.mockService('Compétences de base', 'Faire un diagnostic des compétences', 8); this.mockService('Culture et sécurité numérique', 'Traitement de texte : découverte', 4); - console.log(this.services); - this.calcSizeCol(this.services); + //Fin block en attendant } - + //Fonction en attendant mockService(titre: string, categ: string, nbCateg: number) { var service1 = new Service(); service1.titre = titre; @@ -39,6 +45,7 @@ export class RechercheComponent implements OnInit { } this.services.push(service1); } + //Fin fonction en attendant openModal(option: string) { this.modalOpened = null; switch (option) { @@ -64,22 +71,36 @@ export class RechercheComponent implements OnInit { } applyFilter() { this.openModal(this.modalOpened); + console.log(this.form.value); } - calcSizeCol(services: Service[]) { - for (var i = 0; i < services.length; i++) { - if (services[i + 1]) { - var nb1, nb2: number; - nb1 = services[i].categories.length; - nb2 = services[i + 1].categories.length; - if (nb1 + nb2 <= 13) { - services[i].size = parseFloat((nb1 / 13).toPrecision(2)) * 100; - services[i + 1].size = parseFloat((1 - services[i].size / 100).toPrecision(2)) * 100; + onCheckboxChange(e, reset: boolean) { + const checkArray: FormArray = this.form.get('checkArray') as FormArray; + if (reset) { + if (e.target.checked) { + checkArray.push(new FormControl(e.target.value)); + } else { + let i: number = 0; + checkArray.controls.forEach((item: FormControl) => { + if (item.value == e.target.value) { + checkArray.removeAt(i); + return; + } i++; - } else { - services[i].size = 100; - } + }); } + } else { + checkArray.clear(); } } + isChecked(module: string) { + const checkArray: FormArray = this.form.get('checkArray') as FormArray; + var bool: boolean = false; + checkArray.controls.forEach((item: FormControl) => { + if (item.value == module) { + bool = true; + } + }); + return bool; + } } diff --git a/src/app/structure/structure.module.ts b/src/app/structure/structure.module.ts index 335604aef..fdc77203d 100644 --- a/src/app/structure/structure.module.ts +++ b/src/app/structure/structure.module.ts @@ -5,10 +5,11 @@ import { CardComponent } from './components/card/card.component'; import { RechercheComponent } from './components/recherche/recherche.component'; import { HttpClientModule } from '@angular/common/http'; import { FlexLayoutModule } from '@angular/flex-layout'; +import { FormsModule, ReactiveFormsModule } from '@angular/forms'; @NgModule({ declarations: [StructureComponent, CardComponent, RechercheComponent], - imports: [CommonModule, HttpClientModule, FlexLayoutModule], + imports: [CommonModule, HttpClientModule, FlexLayoutModule, ReactiveFormsModule], exports: [StructureComponent], }) export class StructureModule {} -- GitLab From 8120b0a3ba74c06e8d9008b56c85fbefe05ff2af Mon Sep 17 00:00:00 2001 From: Jeremie BRISON <ext.sopra.jbrison@grandlyon.com> Date: Tue, 13 Oct 2020 17:08:25 +0200 Subject: [PATCH 13/50] fix(checkbox) : fix checkbox + clean/maj code Etat stable des checkbox multiples dans les modals --- .../recherche/recherche.component.html | 44 +++-- .../recherche/recherche.component.scss | 9 +- .../recherche/recherche.component.ts | 174 +++++++++++------- src/app/structure/models/recherche.model.ts | 2 +- 4 files changed, 137 insertions(+), 92 deletions(-) diff --git a/src/app/structure/components/recherche/recherche.component.html b/src/app/structure/components/recherche/recherche.component.html index 7c5564162..00eecd6da 100644 --- a/src/app/structure/components/recherche/recherche.component.html +++ b/src/app/structure/components/recherche/recherche.component.html @@ -11,46 +11,50 @@ </div> <div class="btnSection" fxLayout="row" fxLayoutAlign="space-between center"> - <button type="button" [className]="btnServicesChecked ? 'selected' : ''" (click)="openModal(this.modalType[0])"> + <button + type="button" + [className]="modalOpened == modalType[0] ? 'selected' : ''" + (click)="openModal(this.modalType[0])" + > <span class="btnText">Services</span> <div class="arrow"></div> </button> - <button type="button" [className]="btnHomeChecked ? 'selected' : ''" (click)="openModal(this.modalType[1])"> + <button + type="button" + [className]="modalOpened == modalType[1] ? 'selected' : ''" + (click)="openModal(this.modalType[1])" + > <span class="btnText">Accueil</span> <div class="arrow"></div> </button> - <button type="button" [className]="btnMoreFilterchecked ? 'selected' : ''" (click)="openModal(this.modalType[2])"> + <button + type="button" + [className]="modalOpened == modalType[2] ? 'selected' : ''" + (click)="openModal(this.modalType[2])" + > <span class="btnText">Plus de filtres</span> <div class="arrow"></div> </button> </div> - <form - [formGroup]="form" - (ngSubmit)="applyFilter()" - novalidate - *ngIf="modalOpened" - class="modal" - fxLayout="column" - fxLayoutAlign="space-between" - > + <div *ngIf="modalOpened" fxLayout="column" fxLayoutAlign="space-between" [ngClass]="['modal', 'modal' + modalOpened]"> <div class="contentModal" fxLayout="row wrap"> <!--<div class="blockFiltre" *ngFor="let s of services">--> - <div class="blockFiltre" *ngFor="let s of services"> + <div class="blockFiltre" *ngFor="let m of modules"> <div class="blockLigne"> - <h4>{{ s.titre }}</h4> + <h4>{{ m.titre }}</h4> <div fxLayout="row" class="ligneFiltre" fxLayoutAlign="space-between center" - *ngFor="let categ of s.categories" + *ngFor="let categ of m.categories" > <div class="checkbox"> <label> <input type="checkbox" - [checked]="isChecked(categ)" + [checked]="this.checkedTab.indexOf(categ) > -1" [value]="categ" - (change)="onCheckboxChange($event, true)" + (change)="onCheckboxChange($event, false)" /> <span class="customCheck"></span> </label> @@ -62,10 +66,10 @@ </div> </div> <div class="footer" fxLayout="row" fxLayoutAlign="end center" fxLayoutGap="3vw"> - <a (click)="onCheckboxChange($event, false)">Effacer</a> - <button type="submit" value="Submit">Appliquer</button> + <a (click)="onCheckboxChange($event, true)">Effacer</a> + <button type="button" (click)="applyFilter(modalOpened)">Appliquer</button> </div> - </form> + </div> </div> <div class="footer" fxLayout="row" fxLayoutAlign="space-between center"> <div class="checkbox"> diff --git a/src/app/structure/components/recherche/recherche.component.scss b/src/app/structure/components/recherche/recherche.component.scss index 9ea829dac..e1ac58b8d 100644 --- a/src/app/structure/components/recherche/recherche.component.scss +++ b/src/app/structure/components/recherche/recherche.component.scss @@ -118,8 +118,14 @@ text-decoration-line: underline; } } +.modalaccueil { + margin-left: 100px; +} +.modalplusFiltres { + margin-left: 196px; +} .modal { - height: 654px; + max-height: 654px; max-width: 1100px; background: $white; border: 1px solid $purple; @@ -193,6 +199,7 @@ display: grid; align-items: center; grid-template-columns: min-content auto; + min-height: 25px; input { opacity: 0; display: none; diff --git a/src/app/structure/components/recherche/recherche.component.ts b/src/app/structure/components/recherche/recherche.component.ts index 5aaac22ef..34881d906 100644 --- a/src/app/structure/components/recherche/recherche.component.ts +++ b/src/app/structure/components/recherche/recherche.component.ts @@ -1,6 +1,5 @@ import { Component, OnInit } from '@angular/core'; -import { Service } from '../../models/recherche.model'; -import { FormBuilder, FormGroup, FormArray, FormControl } from '@angular/forms'; +import { Module } from '../../models/recherche.model'; @Component({ selector: 'app-recherche', @@ -8,99 +7,134 @@ import { FormBuilder, FormGroup, FormArray, FormControl } from '@angular/forms'; styleUrls: ['./recherche.component.scss'], }) export class RechercheComponent implements OnInit { - constructor(private fb: FormBuilder) { - this.form = this.fb.group({ - checkArray: this.fb.array([]), - }); - } - form: FormGroup; - modalOpened: string; + constructor() {} + //Variables btn filtres modalType: string[] = ['services', 'accueil', 'plusFiltres']; - btnServicesChecked: boolean; - btnHomeChecked: boolean; - btnMoreFilterchecked: boolean; - test = '50%'; - services: Service[]; + + //Variable gestion liste modal + servicesCategories: Module[]; + modaliteCategories: Module[]; + modules: Module[]; + filtresCategories: Module[]; + modalOpened: string; + + //Variable gestion Checkbox + checkedTab: string[]; + filterCheck: string[]; ngOnInit(): void { + //Sert à afficher la modal et indiquer le type de filtre choisit this.modalOpened = null; - this.btnServicesChecked = false; - this.services = []; - //Block en attendant - this.mockService('Accompagnement aux démarches en ligne', 'CAF', 7); - this.mockService('Insertion sociale et professionnelle', ' Diffuser son CV en ligne', 5); - this.mockService('Accès aux droits', 'Déclarer ses revenus en ligne et découvertes des services proposés', 8); - this.mockService('Aide à la parentalité/éducation', 'Découvrir l’univers des jeux vidéos', 4); - this.mockService('Compétences de base', 'Faire un diagnostic des compétences', 8); - this.mockService('Culture et sécurité numérique', 'Traitement de texte : découverte', 4); - //Fin block en attendant - } - //Fonction en attendant - mockService(titre: string, categ: string, nbCateg: number) { - var service1 = new Service(); - service1.titre = titre; - service1.categories = []; - for (var i = 0; i < nbCateg; i++) { - service1.categories.push(categ + '_' + i); - } - this.services.push(service1); + + //Sert à stocker les différentes catégories + this.servicesCategories = []; + this.modaliteCategories = []; + this.modules = []; + this.filtresCategories = []; + + //Sert à gérer la checkbox multiple + this.checkedTab = new Array(); + this.filterCheck = new Array(); } - //Fin fonction en attendant + + //Ouvrir la modal et afficher la liste en fonction du btn de filtre appuyé openModal(option: string) { - this.modalOpened = null; + this.modules = []; switch (option) { case this.modalType[0]: - this.btnServicesChecked = !this.btnServicesChecked; - this.btnHomeChecked = false; - this.btnMoreFilterchecked = false; - if (this.btnServicesChecked) this.modalOpened = this.modalType[0]; + //Vérifie si le btn n'est pas actif + if (this.modalOpened != this.modalType[0]) { + this.modalOpened = this.modalType[0]; + this.fakeDataServices(); + } else { + this.modalOpened = null; + } break; case this.modalType[1]: - this.btnHomeChecked = !this.btnHomeChecked; - this.btnMoreFilterchecked = false; - this.btnServicesChecked = false; - if (this.btnHomeChecked) this.modalOpened = this.modalType[1]; + //Vérifie si le btn n'est pas actif + if (this.modalOpened != this.modalType[1]) { + this.modalOpened = this.modalType[1]; + this.fakeDataModalite(); + } else { + this.modalOpened = null; + } break; case this.modalType[2]: - this.btnMoreFilterchecked = !this.btnMoreFilterchecked; - this.btnServicesChecked = false; - this.btnHomeChecked = false; - if (this.btnMoreFilterchecked) this.modalOpened = this.modalType[2]; + //Vérifie si le btn n'est pas actif + if (this.modalOpened != this.modalType[2]) { + this.modalOpened = this.modalType[2]; + this.fakeDataFiltres(); + } else { + this.modalOpened = null; + } break; } + //Initialisation de la liste temporaire + this.checkedTab = this.filterCheck.slice(); } + + //Envoie d'un tableau contenant tous les filtres applyFilter() { + this.filterCheck = this.checkedTab.slice(); this.openModal(this.modalOpened); - console.log(this.form.value); + console.log(this.filterCheck); } + //Gestion de l'evenement checkbox(Cocher/Décocher) onCheckboxChange(e, reset: boolean) { - const checkArray: FormArray = this.form.get('checkArray') as FormArray; - if (reset) { + //Condition btn effacer filtre d'une liste + if (!reset) { if (e.target.checked) { - checkArray.push(new FormControl(e.target.value)); + this.checkedTab.push(e.target.value); } else { - let i: number = 0; - checkArray.controls.forEach((item: FormControl) => { - if (item.value == e.target.value) { - checkArray.removeAt(i); - return; - } - i++; - }); + //Vérifie si la case décochée est présente dans la liste temporaire et la supprime + if (this.checkedTab.indexOf(e.target.value) > -1) { + this.checkedTab.splice(this.checkedTab.indexOf(e.target.value), 1); + } } } else { - checkArray.clear(); + //Efface uniquement les éléments de la liste en cours + this.modules.forEach((m) => { + m.categories.forEach((categ) => { + if (this.checkedTab.indexOf(categ) > -1) this.checkedTab.splice(this.checkedTab.indexOf(categ), 1); + }); + }); } } - isChecked(module: string) { - const checkArray: FormArray = this.form.get('checkArray') as FormArray; - var bool: boolean = false; - checkArray.controls.forEach((item: FormControl) => { - if (item.value == module) { - bool = true; - } - }); - return bool; + + /** + * En attendant les apis + */ + mockService(module: Module[], titre: string, categ: string, nbCateg: number) { + var m = new Module(); + m.titre = titre; + m.categories = []; + for (var i = 0; i < nbCateg; i++) { + m.categories.push(categ + i); + } + module.push(m); + } + fakeDataServices() { + this.mockService(this.modules, 'Accompagnement aux démarches en ligne', 'CAF', 7); + this.mockService(this.modules, 'Insertion sociale et professionnelle', ' Diffuser son CV en ligne', 5); + this.mockService( + this.modules, + 'Accès aux droits', + 'Déclarer ses revenus en ligne et découvertes des services proposés', + 8 + ); + this.mockService(this.modules, 'Aide à la parentalité/éducation', 'Découvrir l’univers des jeux vidéos', 4); + this.mockService(this.modules, 'Compétences de base', 'Faire un diagnostic des compétences', 8); + this.mockService(this.modules, 'Culture et sécurité numérique', 'Traitement de texte : découverte', 4); + } + fakeDataModalite() { + this.mockService(this.modules, "Modalité d'accueil", 'Matériel mis à dispostion', 6); + } + fakeDataFiltres() { + this.mockService(this.modules, 'Équipements', 'Accès à des revues ou livres infoirmatiques numériques', 8); + this.mockService(this.modules, "Type d'acteurs", 'Lieux de médiation (Pimms, assos...)', 5); + this.mockService(this.modules, 'Publics', 'Langues étrangères autres qu’anglais', 12); + this.mockService(this.modules, 'Labelisation', 'Prescripteur du Pass Numérique', 6); + this.mockService(this.modules, 'Type de structure', 'Espace de co-working', 6); } } diff --git a/src/app/structure/models/recherche.model.ts b/src/app/structure/models/recherche.model.ts index 5904abd46..a498b7318 100644 --- a/src/app/structure/models/recherche.model.ts +++ b/src/app/structure/models/recherche.model.ts @@ -1,4 +1,4 @@ -export class Service { +export class Module { titre: string; categories: string[]; size: number; -- GitLab From 62be28151167b6e6b9bcbe44fab751852a992da0 Mon Sep 17 00:00:00 2001 From: Jeremie BRISON <ext.sopra.jbrison@grandlyon.com> Date: Thu, 15 Oct 2020 17:06:47 +0200 Subject: [PATCH 14/50] fix(search) : Fix merge problem --- .../recherche/recherche.component.html | 79 +++++- .../recherche/recherche.component.scss | 257 ++++++++++++++++++ .../recherche/recherche.component.spec.ts | 5 +- .../recherche/recherche.component.ts | 130 ++++++++- .../structure-list/models/category.model.ts | 5 + .../structure-list.component.html | 7 +- .../structure-list.component.scss | 11 + .../structure-list.component.ts | 1 + 8 files changed, 488 insertions(+), 7 deletions(-) create mode 100644 src/app/structure-list/models/category.model.ts create mode 100644 src/app/structure-list/structure-list.component.scss diff --git a/src/app/structure-list/components/recherche/recherche.component.html b/src/app/structure-list/components/recherche/recherche.component.html index 63c7b1a72..211a03bea 100644 --- a/src/app/structure-list/components/recherche/recherche.component.html +++ b/src/app/structure-list/components/recherche/recherche.component.html @@ -1 +1,78 @@ -<p>recherche works!</p> +<div class="header"> + <span class="title">Acteurs de la médiation</span> +</div> +<div class="content" fxLayout="column"> + <div class="searchSection" fxLayout="row" fxLayoutGap="1.5vw"> + <div class="icon"> + <div class="ico-pin-search grey"></div> + </div> + <input type="text" placeholder="Rechercher une adresse, une association..." /> + <button type="button">Rechercher</button> + </div> + + <div class="btnSection" fxLayout="row" fxLayoutAlign="space-between center"> + <button + type="button" + [className]="modalOpened == modalType[0] ? 'selected' : ''" + (click)="openModal(this.modalType[0])" + > + <span class="btnText">Services</span> + <div class="arrow"></div> + </button> + <button + type="button" + [className]="modalOpened == modalType[1] ? 'selected' : ''" + (click)="openModal(this.modalType[1])" + > + <span class="btnText">Accueil</span> + <div class="arrow"></div> + </button> + <button + type="button" + [className]="modalOpened == modalType[2] ? 'selected' : ''" + (click)="openModal(this.modalType[2])" + > + <span class="btnText">Plus de filtres</span> + <div class="arrow"></div> + </button> + </div> + <div *ngIf="modalOpened" fxLayout="column" fxLayoutAlign="space-between" [ngClass]="['modal', 'modal' + modalOpened]"> + <div class="contentModal" fxLayout="row wrap"> + <!--<div class="blockFiltre" *ngFor="let s of services">--> + <div class="blockFiltre" *ngFor="let c of categories"> + <div class="blockLigne"> + <h4>{{ c.titre }}</h4> + <div fxLayout="row" class="ligneFiltre" fxLayoutAlign="space-between center" *ngFor="let module of c.modules"> + <div class="checkbox"> + <label> + <input + type="checkbox" + [checked]="this.checkedTab.indexOf(module) > -1" + [value]="module" + (change)="onCheckboxChange($event, false)" + /> + <span class="customCheck"></span> + </label> + <div class="label">{{ module }}</div> + </div> + <span class="nbResult">34</span> + </div> + </div> + </div> + </div> + <div class="footer" fxLayout="row" fxLayoutAlign="end center" fxLayoutGap="3vw"> + <a (click)="onCheckboxChange($event, true)">Effacer</a> + <button type="button" (click)="applyFilter(modalOpened)">Appliquer</button> + </div> + </div> +</div> +<div class="footer" fxLayout="row" fxLayoutAlign="space-between center"> + <div class="checkbox"> + <label> + <input type="checkbox" /> + <span class="customCheck"></span> + </label> + <div class="label">Pass numérique</div> + </div> + <a href="">Ajouter une structure</a> +</div> diff --git a/src/app/structure-list/components/recherche/recherche.component.scss b/src/app/structure-list/components/recherche/recherche.component.scss index e69de29bb..e1ac58b8d 100644 --- a/src/app/structure-list/components/recherche/recherche.component.scss +++ b/src/app/structure-list/components/recherche/recherche.component.scss @@ -0,0 +1,257 @@ +@import '../../../../assets/scss/icons'; +@import '../../../../assets/scss/color'; + +.header { + .title { + font-family: Times New Roman; + font-style: normal; + font-weight: bold; + font-size: 20px; + line-height: 103%; + padding: 16px 0 16px 0; + + display: flex; + align-items: center; + text-transform: uppercase; + } +} +.content { + margin: 10px 0 0px 0; + .icon { + border: 1px solid $grey; + padding: 4px 6px 8px 6px; + border-radius: 4px; + cursor: pointer; + } + input { + width: 100%; + background-color: $grey-4; + border: none; + font-family: Trebuchet MS; + font-style: normal; + font-weight: normal; + font-size: 12px; + line-height: 17px; + display: flex; + align-items: center; + padding-left: 10px; + text-overflow: ellipsis; + color: $grey-1; + outline: none; + } + .searchSection { + button { + border: none; + cursor: pointer; + background-color: $purple; + font-family: Trebuchet MS; + font-style: normal; + font-weight: bold; + font-size: 13px; + line-height: 100%; + align-items: center; + text-align: center; + color: $white; + padding: 3px 16px 3px 16px; + outline: none; + } + } + .btnSection { + padding: 16px 0 16px 0; + button { + outline: none; + + border: 1px solid $grey; + border-radius: 33px; + background-color: $white; + padding: 2px 6px 2px 13px; + align-items: center; + display: flex; + cursor: pointer; + .btnText { + justify-content: center; + font-family: Trebuchet MS; + font-style: normal; + font-weight: normal; + font-size: 13px; + line-height: 19px; + display: flex; + align-items: center; + } + } + .selected { + border: 1px solid $orange-light; + color: $orange-light; + .arrow { + background-color: transparent; + border-bottom: 1px solid $orange-light; + border-right: 1px solid $orange-light; + transform: translateY(25%) rotate(-135deg); + margin: 0 5px 0 10px; + height: 7px; + width: 7px; + } + } + .arrow { + background-color: transparent; + border-bottom: 1px solid $grey; + border-right: 1px solid $grey; + transform: translateY(-25%) rotate(45deg); + margin: 0 5px 0 10px; + height: 7px; + width: 7px; + } + } +} +.footer { + margin: 0px 0 16px 0; + a { + font-family: Trebuchet MS; + font-style: normal; + font-weight: bold; + font-size: 13px; + line-height: 18px; + /* or 120% */ + + display: flex; + align-items: center; + text-decoration-line: underline; + } +} +.modalaccueil { + margin-left: 100px; +} +.modalplusFiltres { + margin-left: 196px; +} +.modal { + max-height: 654px; + max-width: 1100px; + background: $white; + border: 1px solid $purple; + box-sizing: border-box; + border-radius: 8px; + z-index: 1; + position: absolute; + margin-top: 80px; + padding: 20px 16px 10px 16px; + .contentModal { + writing-mode: vertical-lr; + overflow-y: hidden; + max-width: 1100px; + border-bottom: 1px solid grey; + margin-bottom: 10px; + .blockFiltre { + writing-mode: horizontal-tb; + max-width: 320px; + padding: 0 30px 10px 10px; + } + .ligneFiltre { + margin: 5px 0 5px 0; + } + h4 { + font-family: Trebuchet MS; + font-style: normal; + font-weight: bold; + font-size: 13px; + line-height: 17px; + display: flex; + align-items: center; + margin-top: 0; + } + .nbResult { + font-family: Trebuchet MS; + font-style: normal; + font-weight: normal; + font-size: 13px; + line-height: 15px; + } + label { + font-family: Trebuchet MS; + font-style: normal; + font-weight: normal; + font-size: 14px; + line-height: 16px; + } + } + .footer { + height: 32px; + button { + height: 100%; + border: none; + cursor: pointer; + background-color: $purple; + font-family: Trebuchet MS; + font-style: normal; + font-weight: bold; + font-size: 13px; + line-height: 100%; + align-items: center; + text-align: center; + color: $white; + padding: 3px 16px 3px 16px; + outline: none; + } + } +} +.checkbox { + position: relative; + display: grid; + align-items: center; + grid-template-columns: min-content auto; + min-height: 25px; + input { + opacity: 0; + display: none; + &:checked ~ .customCheck { + background-color: $orange-light; + border-color: transparent; + } + &:checked ~ .customCheck:after { + display: block; + } + } + label { + display: inline-grid; + } + .label { + padding-left: 8px; + font-family: Trebuchet MS; + font-style: normal; + font-weight: normal; + font-size: 14px; + line-height: 17px; + padding: 0 16px 0 16px; + } + .customCheck { + display: inline-grid; + width: 18px; + height: 18px; + background-color: $white; + border: 1px solid $grey; + cursor: pointer; + position: relative; + + top: 0; + left: 0; + &:hover { + background-color: $grey-4; + } + &:after { + content: ''; + position: absolute; + display: none; + } + &:after { + left: 7px; + top: 3px; + width: 4px; + height: 8px; + border: solid white; + border-width: 0 2px 2px 0; + transform: rotate(45deg); + -webkit-transform: rotate(45deg); + -ms-transform: rotate(45deg); + } + } +} diff --git a/src/app/structure-list/components/recherche/recherche.component.spec.ts b/src/app/structure-list/components/recherche/recherche.component.spec.ts index e38e4d4e8..211150ab6 100644 --- a/src/app/structure-list/components/recherche/recherche.component.spec.ts +++ b/src/app/structure-list/components/recherche/recherche.component.spec.ts @@ -8,9 +8,8 @@ describe('RechercheComponent', () => { beforeEach(async () => { await TestBed.configureTestingModule({ - declarations: [ RechercheComponent ] - }) - .compileComponents(); + declarations: [RechercheComponent], + }).compileComponents(); }); beforeEach(() => { diff --git a/src/app/structure-list/components/recherche/recherche.component.ts b/src/app/structure-list/components/recherche/recherche.component.ts index 7754a323b..94e354989 100644 --- a/src/app/structure-list/components/recherche/recherche.component.ts +++ b/src/app/structure-list/components/recherche/recherche.component.ts @@ -1,4 +1,5 @@ import { Component, OnInit } from '@angular/core'; +import { Category } from '../../models/category.model'; @Component({ selector: 'app-recherche', @@ -7,6 +8,133 @@ import { Component, OnInit } from '@angular/core'; }) export class RechercheComponent implements OnInit { constructor() {} + //Variables btn filtres + modalType: string[] = ['services', 'accueil', 'plusFiltres']; - ngOnInit(): void {} + //Variable gestion liste modal + servicesCategories: Category[]; + modaliteCategories: Category[]; + categories: Category[]; + filtresCategories: Category[]; + modalOpened: string; + + //Variable gestion Checkbox + checkedTab: string[]; + filterCheck: string[]; + + ngOnInit(): void { + //Sert à afficher la modal et indiquer le type de filtre choisit + this.modalOpened = null; + + //Sert à stocker les différentes catégories + this.servicesCategories = []; + this.modaliteCategories = []; + this.categories = []; + this.filtresCategories = []; + + //Sert à gérer la checkbox multiple + this.checkedTab = new Array(); + this.filterCheck = new Array(); + } + + //Ouvrir la modal et afficher la liste en fonction du btn de filtre appuyé + openModal(option: string) { + this.categories = []; + switch (option) { + case this.modalType[0]: + //Vérifie si le btn n'est pas actif + if (this.modalOpened != this.modalType[0]) { + this.modalOpened = this.modalType[0]; + this.fakeDataServices(); + } else { + this.modalOpened = null; + } + break; + case this.modalType[1]: + //Vérifie si le btn n'est pas actif + if (this.modalOpened != this.modalType[1]) { + this.modalOpened = this.modalType[1]; + this.fakeDataModalite(); + } else { + this.modalOpened = null; + } + break; + case this.modalType[2]: + //Vérifie si le btn n'est pas actif + if (this.modalOpened != this.modalType[2]) { + this.modalOpened = this.modalType[2]; + this.fakeDataFiltres(); + } else { + this.modalOpened = null; + } + break; + } + //Initialisation de la liste temporaire + this.checkedTab = this.filterCheck.slice(); + } + + //Envoie d'un tableau contenant tous les filtres + applyFilter() { + this.filterCheck = this.checkedTab.slice(); + this.openModal(this.modalOpened); + console.log(this.filterCheck); + } + + //Gestion de l'evenement checkbox(Cocher/Décocher) + onCheckboxChange(e, reset: boolean) { + //Condition btn effacer filtre d'une liste + if (!reset) { + if (e.target.checked) { + this.checkedTab.push(e.target.value); + } else { + //Vérifie si la case décochée est présente dans la liste temporaire et la supprime + if (this.checkedTab.indexOf(e.target.value) > -1) { + this.checkedTab.splice(this.checkedTab.indexOf(e.target.value), 1); + } + } + } else { + //Efface uniquement les éléments de la liste en cours + this.categories.forEach((m) => { + m.modules.forEach((categ) => { + if (this.checkedTab.indexOf(categ) > -1) this.checkedTab.splice(this.checkedTab.indexOf(categ), 1); + }); + }); + } + } + + /** + * En attendant les apis + */ + mockService(module: Category[], titre: string, categ: string, nbCateg: number) { + var m = new Category(); + m.titre = titre; + m.modules = []; + for (var i = 0; i < nbCateg; i++) { + m.modules.push(categ + i); + } + module.push(m); + } + fakeDataServices() { + this.mockService(this.categories, 'Accompagnement aux démarches en ligne', 'CAF', 7); + this.mockService(this.categories, 'Insertion sociale et professionnelle', ' Diffuser son CV en ligne', 5); + this.mockService( + this.categories, + 'Accès aux droits', + 'Déclarer ses revenus en ligne et découvertes des services proposés', + 8 + ); + this.mockService(this.categories, 'Aide à la parentalité/éducation', 'Découvrir l’univers des jeux vidéos', 4); + this.mockService(this.categories, 'Compétences de base', 'Faire un diagnostic des compétences', 8); + this.mockService(this.categories, 'Culture et sécurité numérique', 'Traitement de texte : découverte', 4); + } + fakeDataModalite() { + this.mockService(this.categories, "Modalité d'accueil", 'Matériel mis à dispostion', 6); + } + fakeDataFiltres() { + this.mockService(this.categories, 'Équipements', 'Accès à des revues ou livres infoirmatiques numériques', 8); + this.mockService(this.categories, "Type d'acteurs", 'Lieux de médiation (Pimms, assos...)', 5); + this.mockService(this.categories, 'Publics', 'Langues étrangères autres qu’anglais', 12); + this.mockService(this.categories, 'Labelisation', 'Prescripteur du Pass Numérique', 6); + this.mockService(this.categories, 'Type de structure', 'Espace de co-working', 6); + } } diff --git a/src/app/structure-list/models/category.model.ts b/src/app/structure-list/models/category.model.ts new file mode 100644 index 000000000..5610acca0 --- /dev/null +++ b/src/app/structure-list/models/category.model.ts @@ -0,0 +1,5 @@ +export class Category { + titre: string; + modules: string[]; + size: number; +} diff --git a/src/app/structure-list/structure-list.component.html b/src/app/structure-list/structure-list.component.html index a6dbe19b7..86c8f6308 100644 --- a/src/app/structure-list/structure-list.component.html +++ b/src/app/structure-list/structure-list.component.html @@ -1,2 +1,5 @@ -<app-recherche></app-recherche> -<app-card></app-card> +<div class="container"> + <app-recherche></app-recherche> + <div class="divider"></div> + <app-card></app-card> +</div> diff --git a/src/app/structure-list/structure-list.component.scss b/src/app/structure-list/structure-list.component.scss new file mode 100644 index 000000000..2d506b58d --- /dev/null +++ b/src/app/structure-list/structure-list.component.scss @@ -0,0 +1,11 @@ +@import '../../assets/scss/color'; + +.divider { + width: 100%; + height: 1px; + background-color: $grey-4; +} +//En attendant de l'intégrer avec la map +.container { + width: 320px; +} diff --git a/src/app/structure-list/structure-list.component.ts b/src/app/structure-list/structure-list.component.ts index 276b325e4..6ea9c6fde 100644 --- a/src/app/structure-list/structure-list.component.ts +++ b/src/app/structure-list/structure-list.component.ts @@ -3,6 +3,7 @@ import { Component, OnInit } from '@angular/core'; @Component({ selector: 'app-structure-list', templateUrl: './structure-list.component.html', + styleUrls: ['./structure-list.component.scss'], }) export class StructureListComponent implements OnInit { constructor() {} -- GitLab From 3917bb881cf333801fd8365f00cd75c8595d7d5d Mon Sep 17 00:00:00 2001 From: Jeremie BRISON <ext.sopra.jbrison@grandlyon.com> Date: Thu, 15 Oct 2020 17:10:37 +0200 Subject: [PATCH 15/50] fix(search) : rename component --- .../search.component.html} | 2 +- .../search.component.scss} | 0 .../search.component.spec.ts} | 10 +++++----- .../search.component.ts} | 10 +++++----- src/app/structure-list/models/category.model.ts | 2 +- src/app/structure-list/structure-list.component.html | 2 +- src/app/structure-list/structure-list.module.ts | 4 ++-- 7 files changed, 15 insertions(+), 15 deletions(-) rename src/app/structure-list/components/{recherche/recherche.component.html => search/search.component.html} (98%) rename src/app/structure-list/components/{recherche/recherche.component.scss => search/search.component.scss} (100%) rename src/app/structure-list/components/{recherche/recherche.component.spec.ts => search/search.component.spec.ts} (60%) rename src/app/structure-list/components/{recherche/recherche.component.ts => search/search.component.ts} (96%) diff --git a/src/app/structure-list/components/recherche/recherche.component.html b/src/app/structure-list/components/search/search.component.html similarity index 98% rename from src/app/structure-list/components/recherche/recherche.component.html rename to src/app/structure-list/components/search/search.component.html index 211a03bea..3b769e950 100644 --- a/src/app/structure-list/components/recherche/recherche.component.html +++ b/src/app/structure-list/components/search/search.component.html @@ -41,7 +41,7 @@ <!--<div class="blockFiltre" *ngFor="let s of services">--> <div class="blockFiltre" *ngFor="let c of categories"> <div class="blockLigne"> - <h4>{{ c.titre }}</h4> + <h4>{{ c.title }}</h4> <div fxLayout="row" class="ligneFiltre" fxLayoutAlign="space-between center" *ngFor="let module of c.modules"> <div class="checkbox"> <label> diff --git a/src/app/structure-list/components/recherche/recherche.component.scss b/src/app/structure-list/components/search/search.component.scss similarity index 100% rename from src/app/structure-list/components/recherche/recherche.component.scss rename to src/app/structure-list/components/search/search.component.scss diff --git a/src/app/structure-list/components/recherche/recherche.component.spec.ts b/src/app/structure-list/components/search/search.component.spec.ts similarity index 60% rename from src/app/structure-list/components/recherche/recherche.component.spec.ts rename to src/app/structure-list/components/search/search.component.spec.ts index 211150ab6..56e05f1d6 100644 --- a/src/app/structure-list/components/recherche/recherche.component.spec.ts +++ b/src/app/structure-list/components/search/search.component.spec.ts @@ -1,19 +1,19 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; -import { RechercheComponent } from './recherche.component'; +import { SearchComponent } from './search.component'; describe('RechercheComponent', () => { - let component: RechercheComponent; - let fixture: ComponentFixture<RechercheComponent>; + let component: SearchComponent; + let fixture: ComponentFixture<SearchComponent>; beforeEach(async () => { await TestBed.configureTestingModule({ - declarations: [RechercheComponent], + declarations: [SearchComponent], }).compileComponents(); }); beforeEach(() => { - fixture = TestBed.createComponent(RechercheComponent); + fixture = TestBed.createComponent(SearchComponent); component = fixture.componentInstance; fixture.detectChanges(); }); diff --git a/src/app/structure-list/components/recherche/recherche.component.ts b/src/app/structure-list/components/search/search.component.ts similarity index 96% rename from src/app/structure-list/components/recherche/recherche.component.ts rename to src/app/structure-list/components/search/search.component.ts index 94e354989..c9d533d63 100644 --- a/src/app/structure-list/components/recherche/recherche.component.ts +++ b/src/app/structure-list/components/search/search.component.ts @@ -2,11 +2,11 @@ import { Component, OnInit } from '@angular/core'; import { Category } from '../../models/category.model'; @Component({ - selector: 'app-recherche', - templateUrl: './recherche.component.html', - styleUrls: ['./recherche.component.scss'], + selector: 'app-search', + templateUrl: './search.component.html', + styleUrls: ['./search.component.scss'], }) -export class RechercheComponent implements OnInit { +export class SearchComponent implements OnInit { constructor() {} //Variables btn filtres modalType: string[] = ['services', 'accueil', 'plusFiltres']; @@ -107,7 +107,7 @@ export class RechercheComponent implements OnInit { */ mockService(module: Category[], titre: string, categ: string, nbCateg: number) { var m = new Category(); - m.titre = titre; + m.title = titre; m.modules = []; for (var i = 0; i < nbCateg; i++) { m.modules.push(categ + i); diff --git a/src/app/structure-list/models/category.model.ts b/src/app/structure-list/models/category.model.ts index 5610acca0..102ac062a 100644 --- a/src/app/structure-list/models/category.model.ts +++ b/src/app/structure-list/models/category.model.ts @@ -1,5 +1,5 @@ export class Category { - titre: string; + title: string; modules: string[]; size: number; } diff --git a/src/app/structure-list/structure-list.component.html b/src/app/structure-list/structure-list.component.html index 86c8f6308..ade358e27 100644 --- a/src/app/structure-list/structure-list.component.html +++ b/src/app/structure-list/structure-list.component.html @@ -1,5 +1,5 @@ <div class="container"> - <app-recherche></app-recherche> + <app-search></app-search> <div class="divider"></div> <app-card></app-card> </div> diff --git a/src/app/structure-list/structure-list.module.ts b/src/app/structure-list/structure-list.module.ts index 7067e0fef..7fe5bcf83 100644 --- a/src/app/structure-list/structure-list.module.ts +++ b/src/app/structure-list/structure-list.module.ts @@ -2,12 +2,12 @@ import { NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; import { StructureListComponent } from './structure-list.component'; import { CardComponent } from './components/card/card.component'; -import { RechercheComponent } from './components/recherche/recherche.component'; +import { SearchComponent } from './components/search/search.component'; import { HttpClientModule } from '@angular/common/http'; import { FlexLayoutModule } from '@angular/flex-layout'; @NgModule({ - declarations: [StructureListComponent, CardComponent, RechercheComponent], + declarations: [StructureListComponent, CardComponent, SearchComponent], imports: [CommonModule, HttpClientModule, FlexLayoutModule], exports: [StructureListComponent], }) -- GitLab From 577b48167dc7f89141b03d9cdaa922af17c3c175 Mon Sep 17 00:00:00 2001 From: Jeremie BRISON <ext.sopra.jbrison@grandlyon.com> Date: Thu, 15 Oct 2020 17:45:40 +0200 Subject: [PATCH 16/50] fix(search) : french to english + clean code --- .../components/search/search.component.html | 19 +- .../components/search/search.component.ts | 164 ++++++++---------- 2 files changed, 80 insertions(+), 103 deletions(-) diff --git a/src/app/structure-list/components/search/search.component.html b/src/app/structure-list/components/search/search.component.html index 3b769e950..15cadf914 100644 --- a/src/app/structure-list/components/search/search.component.html +++ b/src/app/structure-list/components/search/search.component.html @@ -13,7 +13,7 @@ <div class="btnSection" fxLayout="row" fxLayoutAlign="space-between center"> <button type="button" - [className]="modalOpened == modalType[0] ? 'selected' : ''" + [className]="modalTypeOpened == modalType[0] ? 'selected' : ''" (click)="openModal(this.modalType[0])" > <span class="btnText">Services</span> @@ -21,7 +21,7 @@ </button> <button type="button" - [className]="modalOpened == modalType[1] ? 'selected' : ''" + [className]="modalTypeOpened == modalType[1] ? 'selected' : ''" (click)="openModal(this.modalType[1])" > <span class="btnText">Accueil</span> @@ -29,14 +29,19 @@ </button> <button type="button" - [className]="modalOpened == modalType[2] ? 'selected' : ''" + [className]="modalTypeOpened == modalType[2] ? 'selected' : ''" (click)="openModal(this.modalType[2])" > <span class="btnText">Plus de filtres</span> <div class="arrow"></div> </button> </div> - <div *ngIf="modalOpened" fxLayout="column" fxLayoutAlign="space-between" [ngClass]="['modal', 'modal' + modalOpened]"> + <div + *ngIf="modalTypeOpened" + fxLayout="column" + fxLayoutAlign="space-between" + [ngClass]="['modal', 'modal' + modalTypeOpened]" + > <div class="contentModal" fxLayout="row wrap"> <!--<div class="blockFiltre" *ngFor="let s of services">--> <div class="blockFiltre" *ngFor="let c of categories"> @@ -47,7 +52,7 @@ <label> <input type="checkbox" - [checked]="this.checkedTab.indexOf(module) > -1" + [checked]="this.checkedModules.indexOf(module) > -1" [value]="module" (change)="onCheckboxChange($event, false)" /> @@ -61,8 +66,8 @@ </div> </div> <div class="footer" fxLayout="row" fxLayoutAlign="end center" fxLayoutGap="3vw"> - <a (click)="onCheckboxChange($event, true)">Effacer</a> - <button type="button" (click)="applyFilter(modalOpened)">Appliquer</button> + <a (click)="clearFilters()">Effacer</a> + <button type="button" (click)="applyFilter(modalTypeOpened)">Appliquer</button> </div> </div> </div> diff --git a/src/app/structure-list/components/search/search.component.ts b/src/app/structure-list/components/search/search.component.ts index c9d533d63..634973a08 100644 --- a/src/app/structure-list/components/search/search.component.ts +++ b/src/app/structure-list/components/search/search.component.ts @@ -8,102 +8,74 @@ import { Category } from '../../models/category.model'; }) export class SearchComponent implements OnInit { constructor() {} - //Variables btn filtres - modalType: string[] = ['services', 'accueil', 'plusFiltres']; - //Variable gestion liste modal - servicesCategories: Category[]; - modaliteCategories: Category[]; + // button variable + modalType: string[] = ['services', 'modalite', 'plusFiltres']; + + // Modal variable categories: Category[]; - filtresCategories: Category[]; - modalOpened: string; + modalTypeOpened: string; - //Variable gestion Checkbox - checkedTab: string[]; - filterCheck: string[]; + // Checkbox variable + checkedModules: string[]; + checkedModulesFilter: string[]; ngOnInit(): void { - //Sert à afficher la modal et indiquer le type de filtre choisit - this.modalOpened = null; - - //Sert à stocker les différentes catégories - this.servicesCategories = []; - this.modaliteCategories = []; + // Store the different categories this.categories = []; - this.filtresCategories = []; - //Sert à gérer la checkbox multiple - this.checkedTab = new Array(); - this.filterCheck = new Array(); + // Manage checkbox + this.checkedModules = new Array(); + this.checkedModulesFilter = new Array(); } - //Ouvrir la modal et afficher la liste en fonction du btn de filtre appuyé + // Open the modal and display the list according to the right filter button openModal(option: string) { this.categories = []; - switch (option) { - case this.modalType[0]: - //Vérifie si le btn n'est pas actif - if (this.modalOpened != this.modalType[0]) { - this.modalOpened = this.modalType[0]; - this.fakeDataServices(); - } else { - this.modalOpened = null; - } - break; - case this.modalType[1]: - //Vérifie si le btn n'est pas actif - if (this.modalOpened != this.modalType[1]) { - this.modalOpened = this.modalType[1]; - this.fakeDataModalite(); - } else { - this.modalOpened = null; - } - break; - case this.modalType[2]: - //Vérifie si le btn n'est pas actif - if (this.modalOpened != this.modalType[2]) { - this.modalOpened = this.modalType[2]; - this.fakeDataFiltres(); - } else { - this.modalOpened = null; - } - break; + if (this.modalTypeOpened !== option) { + this.modalTypeOpened = option; + this.fakeData(option); + } else { + this.modalTypeOpened = null; } - //Initialisation de la liste temporaire - this.checkedTab = this.filterCheck.slice(); + + // Init checked list modules + this.checkedModules = this.checkedModulesFilter.slice(); } - //Envoie d'un tableau contenant tous les filtres + // Sends an array containing all filters applyFilter() { - this.filterCheck = this.checkedTab.slice(); - this.openModal(this.modalOpened); - console.log(this.filterCheck); + this.checkedModulesFilter = this.checkedModules.slice(); + this.openModal(this.modalTypeOpened); + + // Simulation send filter + console.log(this.checkedModulesFilter); } - //Gestion de l'evenement checkbox(Cocher/Décocher) - onCheckboxChange(e, reset: boolean) { - //Condition btn effacer filtre d'une liste - if (!reset) { - if (e.target.checked) { - this.checkedTab.push(e.target.value); - } else { - //Vérifie si la case décochée est présente dans la liste temporaire et la supprime - if (this.checkedTab.indexOf(e.target.value) > -1) { - this.checkedTab.splice(this.checkedTab.indexOf(e.target.value), 1); - } - } + // Management of the checkbox event (Check / Uncheck) + onCheckboxChange(event) { + if (event.target.checked) { + this.checkedModules.push(event.target.value); } else { - //Efface uniquement les éléments de la liste en cours - this.categories.forEach((m) => { - m.modules.forEach((categ) => { - if (this.checkedTab.indexOf(categ) > -1) this.checkedTab.splice(this.checkedTab.indexOf(categ), 1); - }); - }); + // Check if the unchecked module is present in the list and remove it + if (this.checkedModules.indexOf(event.target.value) > -1) { + this.checkedModules.splice(this.checkedModules.indexOf(event.target.value), 1); + } } } + // Clear only filters in the current modal + clearFilters() { + this.categories.forEach((categ) => { + categ.modules.forEach((module) => { + if (this.checkedModules.indexOf(module) > -1) + this.checkedModules.splice(this.checkedModules.indexOf(module), 1); + }); + }); + } + /** - * En attendant les apis + * En attendant l'api */ mockService(module: Category[], titre: string, categ: string, nbCateg: number) { var m = new Category(); @@ -114,27 +86,27 @@ export class SearchComponent implements OnInit { } module.push(m); } - fakeDataServices() { - this.mockService(this.categories, 'Accompagnement aux démarches en ligne', 'CAF', 7); - this.mockService(this.categories, 'Insertion sociale et professionnelle', ' Diffuser son CV en ligne', 5); - this.mockService( - this.categories, - 'Accès aux droits', - 'Déclarer ses revenus en ligne et découvertes des services proposés', - 8 - ); - this.mockService(this.categories, 'Aide à la parentalité/éducation', 'Découvrir l’univers des jeux vidéos', 4); - this.mockService(this.categories, 'Compétences de base', 'Faire un diagnostic des compétences', 8); - this.mockService(this.categories, 'Culture et sécurité numérique', 'Traitement de texte : découverte', 4); - } - fakeDataModalite() { - this.mockService(this.categories, "Modalité d'accueil", 'Matériel mis à dispostion', 6); - } - fakeDataFiltres() { - this.mockService(this.categories, 'Équipements', 'Accès à des revues ou livres infoirmatiques numériques', 8); - this.mockService(this.categories, "Type d'acteurs", 'Lieux de médiation (Pimms, assos...)', 5); - this.mockService(this.categories, 'Publics', 'Langues étrangères autres qu’anglais', 12); - this.mockService(this.categories, 'Labelisation', 'Prescripteur du Pass Numérique', 6); - this.mockService(this.categories, 'Type de structure', 'Espace de co-working', 6); + fakeData(option: string) { + if (option === this.modalType[0]) { + this.mockService(this.categories, 'Accompagnement aux démarches en ligne', 'CAF', 7); + this.mockService(this.categories, 'Insertion sociale et professionnelle', ' Diffuser son CV en ligne', 5); + this.mockService( + this.categories, + 'Accès aux droits', + 'Déclarer ses revenus en ligne et découvertes des services proposés', + 8 + ); + this.mockService(this.categories, 'Aide à la parentalité/éducation', 'Découvrir l’univers des jeux vidéos', 4); + this.mockService(this.categories, 'Compétences de base', 'Faire un diagnostic des compétences', 8); + this.mockService(this.categories, 'Culture et sécurité numérique', 'Traitement de texte : découverte', 4); + } else if (option === this.modalType[1]) { + this.mockService(this.categories, "Modalité d'accueil", 'Matériel mis à dispostion', 6); + } else if (option === this.modalType[2]) { + this.mockService(this.categories, 'Équipements', 'Accès à des revues ou livres infoirmatiques numériques', 8); + this.mockService(this.categories, "Type d'acteurs", 'Lieux de médiation (Pimms, assos...)', 5); + this.mockService(this.categories, 'Publics', 'Langues étrangères autres qu’anglais', 12); + this.mockService(this.categories, 'Labelisation', 'Prescripteur du Pass Numérique', 6); + this.mockService(this.categories, 'Type de structure', 'Espace de co-working', 6); + } } } -- GitLab From d9afa82ce8b4900c5e6ed1323d3e64d5a11af191 Mon Sep 17 00:00:00 2001 From: Jeremie BRISON <ext.sopra.jbrison@grandlyon.com> Date: Thu, 15 Oct 2020 18:11:17 +0200 Subject: [PATCH 17/50] fix(search) : fix scss using defined variables --- .../components/search/search.component.scss | 68 ++++--------------- 1 file changed, 13 insertions(+), 55 deletions(-) diff --git a/src/app/structure-list/components/search/search.component.scss b/src/app/structure-list/components/search/search.component.scss index e1ac58b8d..6f46f7690 100644 --- a/src/app/structure-list/components/search/search.component.scss +++ b/src/app/structure-list/components/search/search.component.scss @@ -1,15 +1,11 @@ @import '../../../../assets/scss/icons'; @import '../../../../assets/scss/color'; +@import '../../../../assets/scss/typography'; .header { .title { - font-family: Times New Roman; - font-style: normal; - font-weight: bold; - font-size: 20px; - line-height: 103%; + @include cn-bold-20; padding: 16px 0 16px 0; - display: flex; align-items: center; text-transform: uppercase; @@ -27,11 +23,7 @@ width: 100%; background-color: $grey-4; border: none; - font-family: Trebuchet MS; - font-style: normal; - font-weight: normal; - font-size: 12px; - line-height: 17px; + @include cn-regular-14; display: flex; align-items: center; padding-left: 10px; @@ -44,11 +36,7 @@ border: none; cursor: pointer; background-color: $purple; - font-family: Trebuchet MS; - font-style: normal; - font-weight: bold; - font-size: 13px; - line-height: 100%; + @include cn-bold-14; align-items: center; text-align: center; color: $white; @@ -60,7 +48,6 @@ padding: 16px 0 16px 0; button { outline: none; - border: 1px solid $grey; border-radius: 33px; background-color: $white; @@ -70,11 +57,7 @@ cursor: pointer; .btnText { justify-content: center; - font-family: Trebuchet MS; - font-style: normal; - font-weight: normal; - font-size: 13px; - line-height: 19px; + @include cn-regular-14; display: flex; align-items: center; } @@ -106,13 +89,7 @@ .footer { margin: 0px 0 16px 0; a { - font-family: Trebuchet MS; - font-style: normal; - font-weight: bold; - font-size: 13px; - line-height: 18px; - /* or 120% */ - + @include cn-bold-14; display: flex; align-items: center; text-decoration-line: underline; @@ -139,7 +116,7 @@ writing-mode: vertical-lr; overflow-y: hidden; max-width: 1100px; - border-bottom: 1px solid grey; + border-bottom: 1px solid $grey; margin-bottom: 10px; .blockFiltre { writing-mode: horizontal-tb; @@ -150,28 +127,16 @@ margin: 5px 0 5px 0; } h4 { - font-family: Trebuchet MS; - font-style: normal; - font-weight: bold; - font-size: 13px; - line-height: 17px; + @include cn-bold-14; display: flex; align-items: center; margin-top: 0; } .nbResult { - font-family: Trebuchet MS; - font-style: normal; - font-weight: normal; - font-size: 13px; - line-height: 15px; + @include cn-regular-14; } label { - font-family: Trebuchet MS; - font-style: normal; - font-weight: normal; - font-size: 14px; - line-height: 16px; + @include cn-regular-14; } } .footer { @@ -181,10 +146,7 @@ border: none; cursor: pointer; background-color: $purple; - font-family: Trebuchet MS; - font-style: normal; - font-weight: bold; - font-size: 13px; + @include cn-bold-14; line-height: 100%; align-items: center; text-align: center; @@ -216,11 +178,7 @@ } .label { padding-left: 8px; - font-family: Trebuchet MS; - font-style: normal; - font-weight: normal; - font-size: 14px; - line-height: 17px; + @include cn-regular-14; padding: 0 16px 0 16px; } .customCheck { @@ -247,7 +205,7 @@ top: 3px; width: 4px; height: 8px; - border: solid white; + border: solid $white; border-width: 0 2px 2px 0; transform: rotate(45deg); -webkit-transform: rotate(45deg); -- GitLab From f410599698b70808a87d609a0c5cbac8dfdebe3c Mon Sep 17 00:00:00 2001 From: Jeremie BRISON <ext.sopra.jbrison@grandlyon.com> Date: Fri, 16 Oct 2020 10:28:10 +0200 Subject: [PATCH 18/50] fix(search) : fix search input + list --- .../components/card/card.component.ts | 16 +++++++++++++-- .../components/search/search.component.html | 4 ++-- .../components/search/search.component.ts | 20 ++++++++++++------- src/app/structure-list/models/filter.model.ts | 9 +++++++++ .../services/structure-list.service.ts | 20 +++++++++++++++++-- .../structure-list.component.html | 4 ++-- .../structure-list.component.ts | 6 +++++- .../structure-list/structure-list.module.ts | 3 ++- 8 files changed, 65 insertions(+), 17 deletions(-) create mode 100644 src/app/structure-list/models/filter.model.ts diff --git a/src/app/structure-list/components/card/card.component.ts b/src/app/structure-list/components/card/card.component.ts index 5594b507f..5a255e1e1 100644 --- a/src/app/structure-list/components/card/card.component.ts +++ b/src/app/structure-list/components/card/card.component.ts @@ -1,4 +1,5 @@ -import { Component, OnInit } from '@angular/core'; +import { Component, Input, OnInit } from '@angular/core'; +import { Filter } from '../../models/filter.model'; import { Structure } from '../../models/structure.model'; import { StructureService } from '../../services/structure-list.service'; const { DateTime } = require('luxon'); @@ -10,10 +11,21 @@ const { DateTime } = require('luxon'); }) export class CardComponent implements OnInit { structures: Structure[] = []; + @Input() filter: string; constructor(private structureService: StructureService) {} ngOnInit(): void { - this.structureService.getStructures().subscribe((structures) => { + this.getStructures(null); + } + ngOnChanges(): void { + let filters: Filter[] = []; + filters.push(new Filter('nom', this.filter)); + this.getStructures(filters); + } + + public getStructures(filters): void { + this.structureService.getStructures(filters).subscribe((structures) => { + this.structures = []; structures.forEach((s: Structure) => { this.structures.push(this.structureService.updateOpeningStructure(s, DateTime.local())); }); diff --git a/src/app/structure-list/components/search/search.component.html b/src/app/structure-list/components/search/search.component.html index 15cadf914..0beaafe5d 100644 --- a/src/app/structure-list/components/search/search.component.html +++ b/src/app/structure-list/components/search/search.component.html @@ -6,8 +6,8 @@ <div class="icon"> <div class="ico-pin-search grey"></div> </div> - <input type="text" placeholder="Rechercher une adresse, une association..." /> - <button type="button">Rechercher</button> + <input type="text" [(ngModel)]="searchTerm" placeholder="Rechercher une adresse, une association..." /> + <button type="button" (click)="submitSearch(searchTerm)">Rechercher</button> </div> <div class="btnSection" fxLayout="row" fxLayoutAlign="space-between center"> diff --git a/src/app/structure-list/components/search/search.component.ts b/src/app/structure-list/components/search/search.component.ts index 634973a08..13c3c7ebd 100644 --- a/src/app/structure-list/components/search/search.component.ts +++ b/src/app/structure-list/components/search/search.component.ts @@ -1,4 +1,4 @@ -import { Component, OnInit } from '@angular/core'; +import { Component, EventEmitter, OnInit, Output } from '@angular/core'; import { Category } from '../../models/category.model'; @Component({ @@ -9,6 +9,8 @@ import { Category } from '../../models/category.model'; export class SearchComponent implements OnInit { constructor() {} + @Output() searchEvent = new EventEmitter(); + searchTerm: string = ''; // button variable modalType: string[] = ['services', 'modalite', 'plusFiltres']; @@ -30,7 +32,7 @@ export class SearchComponent implements OnInit { } // Open the modal and display the list according to the right filter button - openModal(option: string) { + private openModal(option: string): void { this.categories = []; if (this.modalTypeOpened !== option) { this.modalTypeOpened = option; @@ -44,7 +46,7 @@ export class SearchComponent implements OnInit { } // Sends an array containing all filters - applyFilter() { + private applyFilter(): void { this.checkedModulesFilter = this.checkedModules.slice(); this.openModal(this.modalTypeOpened); @@ -53,7 +55,7 @@ export class SearchComponent implements OnInit { } // Management of the checkbox event (Check / Uncheck) - onCheckboxChange(event) { + private onCheckboxChange(event): void { if (event.target.checked) { this.checkedModules.push(event.target.value); } else { @@ -65,7 +67,7 @@ export class SearchComponent implements OnInit { } // Clear only filters in the current modal - clearFilters() { + private clearFilters(): void { this.categories.forEach((categ) => { categ.modules.forEach((module) => { if (this.checkedModules.indexOf(module) > -1) @@ -74,10 +76,14 @@ export class SearchComponent implements OnInit { }); } + private submitSearch(searchTerm: string): void { + this.searchEvent.emit(searchTerm); + } + /** * En attendant l'api */ - mockService(module: Category[], titre: string, categ: string, nbCateg: number) { + private mockService(module: Category[], titre: string, categ: string, nbCateg: number): void { var m = new Category(); m.title = titre; m.modules = []; @@ -86,7 +92,7 @@ export class SearchComponent implements OnInit { } module.push(m); } - fakeData(option: string) { + private fakeData(option: string): void { if (option === this.modalType[0]) { this.mockService(this.categories, 'Accompagnement aux démarches en ligne', 'CAF', 7); this.mockService(this.categories, 'Insertion sociale et professionnelle', ' Diffuser son CV en ligne', 5); diff --git a/src/app/structure-list/models/filter.model.ts b/src/app/structure-list/models/filter.model.ts new file mode 100644 index 000000000..1cee683bd --- /dev/null +++ b/src/app/structure-list/models/filter.model.ts @@ -0,0 +1,9 @@ +export class Filter { + name: string; + value: string; + + constructor(name: string, value: string) { + this.name = name; + this.value = value; + } +} diff --git a/src/app/structure-list/services/structure-list.service.ts b/src/app/structure-list/services/structure-list.service.ts index 9394b38c1..6ac879463 100644 --- a/src/app/structure-list/services/structure-list.service.ts +++ b/src/app/structure-list/services/structure-list.service.ts @@ -11,6 +11,7 @@ import { Time } from '../models/time.model'; import { Weekday } from '../enum/weekday.enum'; import { Week } from '../models/week.model'; import { WeekDay } from '@angular/common'; +import { Filter } from '../models/filter.model'; @Injectable({ providedIn: 'root', @@ -18,8 +19,23 @@ import { WeekDay } from '@angular/common'; export class StructureService { constructor(private http: HttpClient) {} - public getStructures(): Observable<Structure[]> { - return this.http.get('/api/Structures').pipe(map((data: any[]) => data.map((item) => new Structure(item)))); + public getStructures(filters: Filter[]): Observable<Structure[]> { + return this.http + .get('/api/Structures?' + this.constructApi(filters)) + .pipe(map((data: any[]) => data.map((item) => new Structure(item)))); + } + + private constructApi(filters: Filter[]): string { + let api: string = ''; + if (filters) { + filters.forEach((filter) => { + if (api) { + api = api + '&'; + } + api = api + filter.name + '_like=' + filter.value; + }); + } + return api; } /** diff --git a/src/app/structure-list/structure-list.component.html b/src/app/structure-list/structure-list.component.html index ade358e27..38562830e 100644 --- a/src/app/structure-list/structure-list.component.html +++ b/src/app/structure-list/structure-list.component.html @@ -1,5 +1,5 @@ <div class="container"> - <app-search></app-search> + <app-search (searchEvent)="fetchResults($event)"></app-search> <div class="divider"></div> - <app-card></app-card> + <app-card [filter]="currentFilter"></app-card> </div> diff --git a/src/app/structure-list/structure-list.component.ts b/src/app/structure-list/structure-list.component.ts index 6ea9c6fde..8db285d5f 100644 --- a/src/app/structure-list/structure-list.component.ts +++ b/src/app/structure-list/structure-list.component.ts @@ -7,6 +7,10 @@ import { Component, OnInit } from '@angular/core'; }) export class StructureListComponent implements OnInit { constructor() {} - + currentFilter: string; ngOnInit(): void {} + + fetchResults(filter: string) { + this.currentFilter = filter; + } } diff --git a/src/app/structure-list/structure-list.module.ts b/src/app/structure-list/structure-list.module.ts index 7fe5bcf83..9947bca5b 100644 --- a/src/app/structure-list/structure-list.module.ts +++ b/src/app/structure-list/structure-list.module.ts @@ -5,10 +5,11 @@ import { CardComponent } from './components/card/card.component'; import { SearchComponent } from './components/search/search.component'; import { HttpClientModule } from '@angular/common/http'; import { FlexLayoutModule } from '@angular/flex-layout'; +import { FormsModule } from '@angular/forms'; @NgModule({ declarations: [StructureListComponent, CardComponent, SearchComponent], - imports: [CommonModule, HttpClientModule, FlexLayoutModule], + imports: [CommonModule, HttpClientModule, FlexLayoutModule, FormsModule], exports: [StructureListComponent], }) export class StructureListModule {} -- GitLab From 89839b8f970db79d39b34d15f4e21375c6eb7de7 Mon Sep 17 00:00:00 2001 From: Jeremie BRISON <ext.sopra.jbrison@grandlyon.com> Date: Fri, 16 Oct 2020 14:32:45 +0200 Subject: [PATCH 19/50] fix(search) : design scroll bar + fix modal design --- .../components/search/search.component.html | 39 ++++++----- .../components/search/search.component.scss | 68 +++++++++++++------ .../components/search/search.component.ts | 15 ++-- 3 files changed, 76 insertions(+), 46 deletions(-) diff --git a/src/app/structure-list/components/search/search.component.html b/src/app/structure-list/components/search/search.component.html index 0beaafe5d..ab6ba5235 100644 --- a/src/app/structure-list/components/search/search.component.html +++ b/src/app/structure-list/components/search/search.component.html @@ -16,7 +16,7 @@ [className]="modalTypeOpened == modalType[0] ? 'selected' : ''" (click)="openModal(this.modalType[0])" > - <span class="btnText">Services</span> + <span class="btnText">Accompagnement</span> <div class="arrow"></div> </button> <button @@ -24,7 +24,7 @@ [className]="modalTypeOpened == modalType[1] ? 'selected' : ''" (click)="openModal(this.modalType[1])" > - <span class="btnText">Accueil</span> + <span class="btnText">Formations</span> <div class="arrow"></div> </button> <button @@ -42,27 +42,30 @@ fxLayoutAlign="space-between" [ngClass]="['modal', 'modal' + modalTypeOpened]" > - <div class="contentModal" fxLayout="row wrap"> + <div class="contentModal" fxLayout="row wrap" fxLayoutAlign="flex-start"> <!--<div class="blockFiltre" *ngFor="let s of services">--> <div class="blockFiltre" *ngFor="let c of categories"> - <div class="blockLigne"> - <h4>{{ c.title }}</h4> + <h4>{{ c.title }}</h4> + + <ul class="blockLigne"> <div fxLayout="row" class="ligneFiltre" fxLayoutAlign="space-between center" *ngFor="let module of c.modules"> - <div class="checkbox"> - <label> - <input - type="checkbox" - [checked]="this.checkedModules.indexOf(module) > -1" - [value]="module" - (change)="onCheckboxChange($event, false)" - /> - <span class="customCheck"></span> - </label> - <div class="label">{{ module }}</div> - </div> + <li class="checkbox"> + <div class="testBox"> + <label> + <input + type="checkbox" + [checked]="this.checkedModules.indexOf(module) > -1" + [value]="module" + (change)="onCheckboxChange($event, false)" + /> + <span class="customCheck"></span> + </label> + <div class="label">{{ module }}</div> + </div> + </li> <span class="nbResult">34</span> </div> - </div> + </ul> </div> </div> <div class="footer" fxLayout="row" fxLayoutAlign="end center" fxLayoutGap="3vw"> diff --git a/src/app/structure-list/components/search/search.component.scss b/src/app/structure-list/components/search/search.component.scss index 6f46f7690..2a64a6845 100644 --- a/src/app/structure-list/components/search/search.component.scss +++ b/src/app/structure-list/components/search/search.component.scss @@ -86,15 +86,6 @@ } } } -.footer { - margin: 0px 0 16px 0; - a { - @include cn-bold-14; - display: flex; - align-items: center; - text-decoration-line: underline; - } -} .modalaccueil { margin-left: 100px; } @@ -103,28 +94,48 @@ } .modal { max-height: 654px; - max-width: 1100px; + max-width: 754px; background: $white; - border: 1px solid $purple; + border: 1px solid $grey; box-sizing: border-box; - border-radius: 8px; z-index: 1; position: absolute; margin-top: 80px; - padding: 20px 16px 10px 16px; + + ::-webkit-scrollbar { + width: 10px; + } + ::-webkit-scrollbar-track { + background: $grey-4; + } + ::-webkit-scrollbar-thumb { + background: $grey; + border-radius: 6px; + } + .contentModal { - writing-mode: vertical-lr; - overflow-y: hidden; + overflow-y: auto; max-width: 1100px; border-bottom: 1px solid $grey; margin-bottom: 10px; + .blockFiltre { - writing-mode: horizontal-tb; - max-width: 320px; - padding: 0 30px 10px 10px; + width: 100%; + padding: 32px 40px 10px 40px; + min-width: 450px; + } + .blockLigne { + padding-left: 0; + -moz-column-count: 2; + -moz-column-gap: 46px; + -webkit-column-count: 2; + -webkit-column-gap: 46px; + column-count: 1; + column-gap: 46px; + column-rule: dashed 1px $grey; } .ligneFiltre { - margin: 5px 0 5px 0; + padding: 5px 0 5px 0; } h4 { @include cn-bold-14; @@ -140,6 +151,13 @@ } } .footer { + margin: 0px 20px 16px 0; + a { + @include cn-bold-14; + display: flex; + align-items: center; + text-decoration-line: underline; + } height: 32px; button { height: 100%; @@ -157,11 +175,19 @@ } } .checkbox { - position: relative; + .testBox { + position: relative; + display: inline-grid; + align-items: center; + grid-template-columns: min-content auto; + min-height: 25px; + } + /*position: relative; display: grid; align-items: center; grid-template-columns: min-content auto; - min-height: 25px; + min-height: 25px;*/ + list-style-type: none; input { opacity: 0; display: none; diff --git a/src/app/structure-list/components/search/search.component.ts b/src/app/structure-list/components/search/search.component.ts index 13c3c7ebd..9c3694255 100644 --- a/src/app/structure-list/components/search/search.component.ts +++ b/src/app/structure-list/components/search/search.component.ts @@ -32,7 +32,7 @@ export class SearchComponent implements OnInit { } // Open the modal and display the list according to the right filter button - private openModal(option: string): void { + public openModal(option: string): void { this.categories = []; if (this.modalTypeOpened !== option) { this.modalTypeOpened = option; @@ -46,7 +46,7 @@ export class SearchComponent implements OnInit { } // Sends an array containing all filters - private applyFilter(): void { + public applyFilter(): void { this.checkedModulesFilter = this.checkedModules.slice(); this.openModal(this.modalTypeOpened); @@ -55,7 +55,7 @@ export class SearchComponent implements OnInit { } // Management of the checkbox event (Check / Uncheck) - private onCheckboxChange(event): void { + public onCheckboxChange(event): void { if (event.target.checked) { this.checkedModules.push(event.target.value); } else { @@ -76,7 +76,7 @@ export class SearchComponent implements OnInit { }); } - private submitSearch(searchTerm: string): void { + public submitSearch(searchTerm: string): void { this.searchEvent.emit(searchTerm); } @@ -95,6 +95,8 @@ export class SearchComponent implements OnInit { private fakeData(option: string): void { if (option === this.modalType[0]) { this.mockService(this.categories, 'Accompagnement aux démarches en ligne', 'CAF', 7); + } else if (option === this.modalType[1]) { + this.mockService(this.categories, 'Compétences de base', 'Faire un diagnostic des compétences', 8); this.mockService(this.categories, 'Insertion sociale et professionnelle', ' Diffuser son CV en ligne', 5); this.mockService( this.categories, @@ -103,12 +105,11 @@ export class SearchComponent implements OnInit { 8 ); this.mockService(this.categories, 'Aide à la parentalité/éducation', 'Découvrir l’univers des jeux vidéos', 4); - this.mockService(this.categories, 'Compétences de base', 'Faire un diagnostic des compétences', 8); this.mockService(this.categories, 'Culture et sécurité numérique', 'Traitement de texte : découverte', 4); - } else if (option === this.modalType[1]) { - this.mockService(this.categories, "Modalité d'accueil", 'Matériel mis à dispostion', 6); } else if (option === this.modalType[2]) { this.mockService(this.categories, 'Équipements', 'Accès à des revues ou livres infoirmatiques numériques', 8); + this.mockService(this.categories, "Modalité d'accueil", 'Matériel mis à dispostion', 6); + this.mockService(this.categories, "Type d'acteurs", 'Lieux de médiation (Pimms, assos...)', 5); this.mockService(this.categories, 'Publics', 'Langues étrangères autres qu’anglais', 12); this.mockService(this.categories, 'Labelisation', 'Prescripteur du Pass Numérique', 6); -- GitLab From c83eac6e7538bd18bb5a18cd21bb9da89f59561c Mon Sep 17 00:00:00 2001 From: Jeremie BRISON <ext.sopra.jbrison@grandlyon.com> Date: Mon, 19 Oct 2020 17:04:53 +0200 Subject: [PATCH 20/50] fix(search) : Add checkbox filter + clean code --- .../components/card/card.component.ts | 8 +- .../components/search/search.component.html | 80 +++--- .../components/search/search.component.scss | 21 +- .../components/search/search.component.ts | 106 +++++--- .../structure-list/models/category.model.ts | 7 +- src/app/structure-list/models/filter.model.ts | 6 +- src/app/structure-list/models/module.model.ts | 9 + .../services/search.service.spec.ts | 16 ++ .../structure-list/services/search.service.ts | 14 + .../services/structure-list.service.ts | 7 +- .../structure-list.component.ts | 5 +- .../components/card/card.component.html | 25 -- .../components/card/card.component.scss | 52 ---- .../components/card/card.component.spec.ts | 25 -- .../components/card/card.component.ts | 23 -- .../recherche/recherche.component.html | 83 ------ .../recherche/recherche.component.scss | 257 ------------------ .../recherche/recherche.component.spec.ts | 25 -- .../recherche/recherche.component.ts | 140 ---------- src/app/structure/models/recherche.model.ts | 5 - src/app/structure/models/structure.model.ts | 44 --- .../services/structure.service.spec.ts | 221 --------------- .../structure/services/structure.service.ts | 163 ----------- src/app/structure/structure.component.html | 5 - src/app/structure/structure.component.scss | 11 - src/app/structure/structure.component.spec.ts | 25 -- src/app/structure/structure.component.ts | 15 - src/app/structure/structure.module.ts | 15 - 28 files changed, 184 insertions(+), 1229 deletions(-) create mode 100644 src/app/structure-list/models/module.model.ts create mode 100644 src/app/structure-list/services/search.service.spec.ts create mode 100644 src/app/structure-list/services/search.service.ts delete mode 100644 src/app/structure/components/card/card.component.html delete mode 100644 src/app/structure/components/card/card.component.scss delete mode 100644 src/app/structure/components/card/card.component.spec.ts delete mode 100644 src/app/structure/components/card/card.component.ts delete mode 100644 src/app/structure/components/recherche/recherche.component.html delete mode 100644 src/app/structure/components/recherche/recherche.component.scss delete mode 100644 src/app/structure/components/recherche/recherche.component.spec.ts delete mode 100644 src/app/structure/components/recherche/recherche.component.ts delete mode 100644 src/app/structure/models/recherche.model.ts delete mode 100644 src/app/structure/models/structure.model.ts delete mode 100644 src/app/structure/services/structure.service.spec.ts delete mode 100644 src/app/structure/services/structure.service.ts delete mode 100644 src/app/structure/structure.component.html delete mode 100644 src/app/structure/structure.component.scss delete mode 100644 src/app/structure/structure.component.spec.ts delete mode 100644 src/app/structure/structure.component.ts delete mode 100644 src/app/structure/structure.module.ts diff --git a/src/app/structure-list/components/card/card.component.ts b/src/app/structure-list/components/card/card.component.ts index 5a255e1e1..a54d92069 100644 --- a/src/app/structure-list/components/card/card.component.ts +++ b/src/app/structure-list/components/card/card.component.ts @@ -11,7 +11,7 @@ const { DateTime } = require('luxon'); }) export class CardComponent implements OnInit { structures: Structure[] = []; - @Input() filter: string; + @Input() filter: Filter[]; constructor(private structureService: StructureService) {} ngOnInit(): void { @@ -19,8 +19,10 @@ export class CardComponent implements OnInit { } ngOnChanges(): void { let filters: Filter[] = []; - filters.push(new Filter('nom', this.filter)); - this.getStructures(filters); + if (this.filter) { + filters = this.filter; + this.getStructures(filters); + } } public getStructures(filters): void { diff --git a/src/app/structure-list/components/search/search.component.html b/src/app/structure-list/components/search/search.component.html index ab6ba5235..8236e0fcd 100644 --- a/src/app/structure-list/components/search/search.component.html +++ b/src/app/structure-list/components/search/search.component.html @@ -7,34 +7,36 @@ <div class="ico-pin-search grey"></div> </div> <input type="text" [(ngModel)]="searchTerm" placeholder="Rechercher une adresse, une association..." /> - <button type="button" (click)="submitSearch(searchTerm)">Rechercher</button> + <button type="button" (click)="applyFilter()">Rechercher</button> </div> - <div class="btnSection" fxLayout="row" fxLayoutAlign="space-between center"> - <button - type="button" - [className]="modalTypeOpened == modalType[0] ? 'selected' : ''" - (click)="openModal(this.modalType[0])" - > - <span class="btnText">Accompagnement</span> - <div class="arrow"></div> - </button> - <button - type="button" - [className]="modalTypeOpened == modalType[1] ? 'selected' : ''" - (click)="openModal(this.modalType[1])" - > - <span class="btnText">Formations</span> - <div class="arrow"></div> - </button> - <button - type="button" - [className]="modalTypeOpened == modalType[2] ? 'selected' : ''" - (click)="openModal(this.modalType[2])" - > - <span class="btnText">Plus de filtres</span> - <div class="arrow"></div> - </button> + <div class="btnSection"> + <div class="phoneSection" fxLayout="row" fxLayoutAlign="center center"> + <button + type="button" + [className]="modalTypeOpened === modalType[0] ? 'selected' : ''" + (click)="openModal(this.modalType[0])" + > + <span class="btnText">Accompagnement</span> + <div class="arrow"></div> + </button> + <button + type="button" + [className]="modalTypeOpened === modalType[1] ? 'selected' : ''" + (click)="openModal(this.modalType[1])" + > + <span class="btnText">Formations</span> + <div class="arrow"></div> + </button> + <button + type="button" + [className]="modalTypeOpened === modalType[2] ? 'selected' : ''" + (click)="openModal(this.modalType[2])" + > + <span class="btnText">Plus de filtres</span> + <div class="arrow"></div> + </button> + </div> </div> <div *ngIf="modalTypeOpened" @@ -42,25 +44,25 @@ fxLayoutAlign="space-between" [ngClass]="['modal', 'modal' + modalTypeOpened]" > - <div class="contentModal" fxLayout="row wrap" fxLayoutAlign="flex-start"> + <div class="contentModal" fxLayout="row wrap" fxLayoutAlign="flex-start" *ngIf="categories.length > 0"> <!--<div class="blockFiltre" *ngFor="let s of services">--> <div class="blockFiltre" *ngFor="let c of categories"> - <h4>{{ c.title }}</h4> + <h4>{{ c.name }}</h4> <ul class="blockLigne"> <div fxLayout="row" class="ligneFiltre" fxLayoutAlign="space-between center" *ngFor="let module of c.modules"> <li class="checkbox"> - <div class="testBox"> + <div class="checkboxItem"> <label> <input type="checkbox" - [checked]="this.checkedModules.indexOf(module) > -1" - [value]="module" - (change)="onCheckboxChange($event, false)" + [checked]="getIndex(module.id, c.name) > -1" + [value]="module.id" + (change)="onCheckboxChange($event, c.name)" /> <span class="customCheck"></span> </label> - <div class="label">{{ module }}</div> + <div class="label">{{ module.text }}</div> </div> </li> <span class="nbResult">34</span> @@ -76,11 +78,13 @@ </div> <div class="footer" fxLayout="row" fxLayoutAlign="space-between center"> <div class="checkbox"> - <label> - <input type="checkbox" /> - <span class="customCheck"></span> - </label> - <div class="label">Pass numérique</div> + <div class="checkboxItem"> + <label> + <input type="checkbox" /> + <span class="customCheck"></span> + </label> + <div class="label">Pass numérique</div> + </div> </div> <a href="">Ajouter une structure</a> </div> diff --git a/src/app/structure-list/components/search/search.component.scss b/src/app/structure-list/components/search/search.component.scss index 2a64a6845..cbe065b6c 100644 --- a/src/app/structure-list/components/search/search.component.scss +++ b/src/app/structure-list/components/search/search.component.scss @@ -1,6 +1,7 @@ @import '../../../../assets/scss/icons'; @import '../../../../assets/scss/color'; @import '../../../../assets/scss/typography'; +@import '../../../../assets/scss/breakpoint'; .header { .title { @@ -46,6 +47,9 @@ } .btnSection { padding: 16px 0 16px 0; + .phoneSection { + display: none; + } button { outline: none; border: 1px solid $grey; @@ -130,7 +134,7 @@ -moz-column-gap: 46px; -webkit-column-count: 2; -webkit-column-gap: 46px; - column-count: 1; + column-count: 2; column-gap: 46px; column-rule: dashed 1px $grey; } @@ -175,18 +179,13 @@ } } .checkbox { - .testBox { + .checkboxItem { position: relative; display: inline-grid; align-items: center; grid-template-columns: min-content auto; min-height: 25px; } - /*position: relative; - display: grid; - align-items: center; - grid-template-columns: min-content auto; - min-height: 25px;*/ list-style-type: none; input { opacity: 0; @@ -239,3 +238,11 @@ } } } +/*@media #{$phone} { + .allSection { + display: none !important; + } + .phoneSection { + display: flex; + } +}*/ diff --git a/src/app/structure-list/components/search/search.component.ts b/src/app/structure-list/components/search/search.component.ts index 9c3694255..86550580e 100644 --- a/src/app/structure-list/components/search/search.component.ts +++ b/src/app/structure-list/components/search/search.component.ts @@ -1,5 +1,8 @@ import { Component, EventEmitter, OnInit, Output } from '@angular/core'; import { Category } from '../../models/category.model'; +import { Filter } from '../../models/filter.model'; +import { Module } from '../../models/module.model'; +import { SearchService } from '../../services/search.service'; @Component({ selector: 'app-search', @@ -7,11 +10,14 @@ import { Category } from '../../models/category.model'; styleUrls: ['./search.component.scss'], }) export class SearchComponent implements OnInit { - constructor() {} + constructor(private searchService: SearchService) {} @Output() searchEvent = new EventEmitter(); + + // Search input variable searchTerm: string = ''; - // button variable + + // Button variable modalType: string[] = ['services', 'modalite', 'plusFiltres']; // Modal variable @@ -19,11 +25,11 @@ export class SearchComponent implements OnInit { modalTypeOpened: string; // Checkbox variable - checkedModules: string[]; - checkedModulesFilter: string[]; + checkedModules: Module[]; + checkedModulesFilter: Module[]; ngOnInit(): void { - // Store the different categories + // Will store the different categories this.categories = []; // Manage checkbox @@ -31,6 +37,11 @@ export class SearchComponent implements OnInit { this.checkedModulesFilter = new Array(); } + // Delete when getting back-end + private mockApiNumber(nb: number): string { + return ('00' + nb).slice(-3); + } + // Open the modal and display the list according to the right filter button public openModal(option: string): void { this.categories = []; @@ -50,62 +61,81 @@ export class SearchComponent implements OnInit { this.checkedModulesFilter = this.checkedModules.slice(); this.openModal(this.modalTypeOpened); - // Simulation send filter - console.log(this.checkedModulesFilter); + // Send search input filter + let filters: Filter[] = []; + if (this.searchTerm) { + filters.push(new Filter('nom', this.searchTerm, false)); + } + + // Send checked box filter + this.checkedModulesFilter.forEach((cm) => { + filters.push(new Filter(this.fromStringToIdExcel(cm.text), this.mockApiNumber(cm.id), false)); + }); + this.searchEvent.emit(filters); } // Management of the checkbox event (Check / Uncheck) - public onCheckboxChange(event): void { + public onCheckboxChange(event, categ: string): void { + const checkValue: number = parseInt(event.target.value); if (event.target.checked) { - this.checkedModules.push(event.target.value); + this.checkedModules.push(new Module(checkValue, categ)); } else { // Check if the unchecked module is present in the list and remove it - if (this.checkedModules.indexOf(event.target.value) > -1) { - this.checkedModules.splice(this.checkedModules.indexOf(event.target.value), 1); + if (this.getIndex(checkValue, categ) > -1) { + this.checkedModules.splice(this.getIndex(checkValue, categ), 1); } } } + // Return index of a specific module in array modules + public getIndex(id: number, categ: string): number { + return this.checkedModules.findIndex((m: Module) => m.id === id && m.text === categ); + } + // Clear only filters in the current modal - private clearFilters(): void { - this.categories.forEach((categ) => { - categ.modules.forEach((module) => { - if (this.checkedModules.indexOf(module) > -1) - this.checkedModules.splice(this.checkedModules.indexOf(module), 1); + public clearFilters(): void { + this.categories.forEach((categ: Category) => { + categ.modules.forEach((module: Module) => { + if (this.getIndex(module.id, categ.name) > -1) + this.checkedModules.splice(this.getIndex(module.id, categ.name), 1); }); }); } - public submitSearch(searchTerm: string): void { - this.searchEvent.emit(searchTerm); + // Format title of category to id of excel category + private fromStringToIdExcel(categ: string): string { + let splitStr = categ.toLowerCase().split(' '); + for (let i = 1; i < splitStr.length; i++) { + splitStr[i] = splitStr[i].charAt(0).toUpperCase() + splitStr[i].substring(1); + } + return splitStr + .join('') + .normalize('NFD') + .replace(/[\u0300-\u036f'’°()]/g, '') + .replace(/[\s-]/g, ' ') + .replace('?', ''); } - - /** - * En attendant l'api - */ - private mockService(module: Category[], titre: string, categ: string, nbCateg: number): void { - var m = new Category(); - m.title = titre; + // Fake service api + private mockService(module: Category[], titre: string, categ: any, nbCateg: number): void { + let m = new Category(); + m.name = titre; m.modules = []; - for (var i = 0; i < nbCateg; i++) { - m.modules.push(categ + i); + for (let i = 0; i < nbCateg; i++) { + m.modules.push(new Module(categ.id, categ.name + i)); } module.push(m); } + + // Fake data private fakeData(option: string): void { if (option === this.modalType[0]) { - this.mockService(this.categories, 'Accompagnement aux démarches en ligne', 'CAF', 7); + this.mockService(this.categories, 'Accompagnement des démarches', { name: 'CAF', id: '' }, 7); } else if (option === this.modalType[1]) { - this.mockService(this.categories, 'Compétences de base', 'Faire un diagnostic des compétences', 8); - this.mockService(this.categories, 'Insertion sociale et professionnelle', ' Diffuser son CV en ligne', 5); - this.mockService( - this.categories, - 'Accès aux droits', - 'Déclarer ses revenus en ligne et découvertes des services proposés', - 8 - ); - this.mockService(this.categories, 'Aide à la parentalité/éducation', 'Découvrir l’univers des jeux vidéos', 4); - this.mockService(this.categories, 'Culture et sécurité numérique', 'Traitement de texte : découverte', 4); + this.searchService.getCategories().subscribe((d) => { + d.forEach((element) => { + this.categories.push(element); + }); + }); } else if (option === this.modalType[2]) { this.mockService(this.categories, 'Équipements', 'Accès à des revues ou livres infoirmatiques numériques', 8); this.mockService(this.categories, "Modalité d'accueil", 'Matériel mis à dispostion', 6); diff --git a/src/app/structure-list/models/category.model.ts b/src/app/structure-list/models/category.model.ts index 102ac062a..f6c60e54e 100644 --- a/src/app/structure-list/models/category.model.ts +++ b/src/app/structure-list/models/category.model.ts @@ -1,5 +1,6 @@ +import { Module } from './module.model'; + export class Category { - title: string; - modules: string[]; - size: number; + name: string; + modules: Module[]; } diff --git a/src/app/structure-list/models/filter.model.ts b/src/app/structure-list/models/filter.model.ts index 1cee683bd..826633f50 100644 --- a/src/app/structure-list/models/filter.model.ts +++ b/src/app/structure-list/models/filter.model.ts @@ -1,9 +1,11 @@ export class Filter { name: string; value: string; + isStrict: boolean; - constructor(name: string, value: string) { + constructor(name: string, value: any, isStrict: boolean) { this.name = name; - this.value = value; + this.value = value.toString(); + this.isStrict = isStrict; } } diff --git a/src/app/structure-list/models/module.model.ts b/src/app/structure-list/models/module.model.ts new file mode 100644 index 000000000..83d025356 --- /dev/null +++ b/src/app/structure-list/models/module.model.ts @@ -0,0 +1,9 @@ +export class Module { + id: number; + text: string; + + constructor(id: number, text: string) { + this.id = id; + this.text = text; + } +} diff --git a/src/app/structure-list/services/search.service.spec.ts b/src/app/structure-list/services/search.service.spec.ts new file mode 100644 index 000000000..23c42c7bb --- /dev/null +++ b/src/app/structure-list/services/search.service.spec.ts @@ -0,0 +1,16 @@ +import { TestBed } from '@angular/core/testing'; + +import { SearchService } from './search.service'; + +describe('SearchService', () => { + let service: SearchService; + + beforeEach(() => { + TestBed.configureTestingModule({}); + service = TestBed.inject(SearchService); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); +}); diff --git a/src/app/structure-list/services/search.service.ts b/src/app/structure-list/services/search.service.ts new file mode 100644 index 000000000..d48c602e1 --- /dev/null +++ b/src/app/structure-list/services/search.service.ts @@ -0,0 +1,14 @@ +import { HttpClient } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { Observable } from 'rxjs'; + +@Injectable({ + providedIn: 'root', +}) +export class SearchService { + constructor(private http: HttpClient) {} + + public getCategories(): Observable<any> { + return this.http.get('/api/Categories'); + } +} diff --git a/src/app/structure-list/services/structure-list.service.ts b/src/app/structure-list/services/structure-list.service.ts index 6ac879463..0a1d1e34a 100644 --- a/src/app/structure-list/services/structure-list.service.ts +++ b/src/app/structure-list/services/structure-list.service.ts @@ -9,7 +9,6 @@ import { OpeningDay } from '../models/openingDay.model'; import { Structure } from '../models/structure.model'; import { Time } from '../models/time.model'; import { Weekday } from '../enum/weekday.enum'; -import { Week } from '../models/week.model'; import { WeekDay } from '@angular/common'; import { Filter } from '../models/filter.model'; @@ -32,7 +31,11 @@ export class StructureService { if (api) { api = api + '&'; } - api = api + filter.name + '_like=' + filter.value; + if (filter.isStrict) { + api = api + filter.name + '=' + filter.value; + } else { + api = api + filter.name + '_like=' + filter.value; + } }); } return api; diff --git a/src/app/structure-list/structure-list.component.ts b/src/app/structure-list/structure-list.component.ts index 8db285d5f..e62cff38c 100644 --- a/src/app/structure-list/structure-list.component.ts +++ b/src/app/structure-list/structure-list.component.ts @@ -1,4 +1,5 @@ import { Component, OnInit } from '@angular/core'; +import { Filter } from './models/filter.model'; @Component({ selector: 'app-structure-list', @@ -7,10 +8,10 @@ import { Component, OnInit } from '@angular/core'; }) export class StructureListComponent implements OnInit { constructor() {} - currentFilter: string; + currentFilter: Filter[]; ngOnInit(): void {} - fetchResults(filter: string) { + fetchResults(filter: Filter[]) { this.currentFilter = filter; } } diff --git a/src/app/structure/components/card/card.component.html b/src/app/structure/components/card/card.component.html deleted file mode 100644 index e2443b8c8..000000000 --- a/src/app/structure/components/card/card.component.html +++ /dev/null @@ -1,25 +0,0 @@ -<span class="nbStructuresLabel">{{ structures.length }} structures</span> -<div class="structure" fxLayout="column" *ngFor="let structure of structures"> - <span class="nomStructure">{{ structure.nom }}</span> - - <div class="headerStructure" fxLayout="row" fxLayoutAlign="space-between center"> - <span class="typeStructure">{{ structure.type_de_structure }}</span> - <span class="distanceStructure">|-| 63 m</span> - </div> - <br /> - <div class="statusStructure" fxLayout="row" fxLayoutAlign="start center" fxLayoutGap="1vw"> - <div *ngIf="structure.estOuvert; else closed"> - <span class="ico-dot-available"></span> - <span> Ouvert actuellement</span> - </div> - <ng-template #closed> - <span class="ico-dot-unavailable"></span> - <span *ngIf="structure.ouvreLe.jour; else noTime"> - Fermé - Ouvre {{ structure.ouvreLe.jour }} à {{ structure.ouvreLe.horaire }}</span - > - </ng-template> - </div> -</div> -<ng-template #noTime> - <span> Fermé - Aucun horaire disponible</span> -</ng-template> diff --git a/src/app/structure/components/card/card.component.scss b/src/app/structure/components/card/card.component.scss deleted file mode 100644 index f3f374801..000000000 --- a/src/app/structure/components/card/card.component.scss +++ /dev/null @@ -1,52 +0,0 @@ -@import '../../../../assets/scss/icons'; -.nbStructuresLabel { - color: #828282; - font-family: Trebuchet MS; - font-style: normal; - font-weight: normal; - font-size: 16px; - line-height: 19px; - display: flex; - align-items: center; -} -.structure { - padding: 12px 0 12px 0; - border-bottom: 1px dashed #bdbdbd; - .typeStructure { - color: #828282; - font-family: Times New Roman; - font-style: normal; - font-weight: normal; - font-size: 16px; - line-height: 100%; - } - .nomStructure { - padding-top: 13px; - color: #594d59; - font-family: Trebuchet MS; - font-style: normal; - font-weight: bold; - font-size: 20px; - line-height: 103%; - padding-bottom: 5px; - } - .distanceStructure { - font-family: Times New Roman; - font-style: normal; - font-size: 16px; - line-height: 103%; - color: #594d59; - } - &:last-child { - border-bottom: none; - } -} -.statusStructure { - span { - font-family: Trebuchet MS; - font-style: normal; - font-weight: normal; - font-size: 15px; - line-height: 103%; - } -} diff --git a/src/app/structure/components/card/card.component.spec.ts b/src/app/structure/components/card/card.component.spec.ts deleted file mode 100644 index c0787da7b..000000000 --- a/src/app/structure/components/card/card.component.spec.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { ComponentFixture, TestBed } from '@angular/core/testing'; - -import { CardComponent } from './card.component'; -import { HttpClientModule } from '@angular/common/http'; -describe('CardComponent', () => { - let component: CardComponent; - let fixture: ComponentFixture<CardComponent>; - - beforeEach(async () => { - await TestBed.configureTestingModule({ - imports: [HttpClientModule], - declarations: [CardComponent], - }).compileComponents(); - }); - - beforeEach(() => { - fixture = TestBed.createComponent(CardComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }); -}); diff --git a/src/app/structure/components/card/card.component.ts b/src/app/structure/components/card/card.component.ts deleted file mode 100644 index ad3154950..000000000 --- a/src/app/structure/components/card/card.component.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { Component, OnInit } from '@angular/core'; -import { Structure } from '../../models/structure.model'; -import { StructureService } from '../../services/structure.service'; -const { DateTime } = require('luxon'); - -@Component({ - selector: 'app-card', - templateUrl: './card.component.html', - styleUrls: ['./card.component.scss'], -}) -export class CardComponent implements OnInit { - structures: Structure[] = []; - constructor(private _structureService: StructureService) {} - - ngOnInit(): void { - var dt = DateTime.local(); - this._structureService.recupererStructures().subscribe((structures: Structure[]) => { - structures.forEach((s: Structure) => { - this.structures.push(this._structureService.majOuvertureStructure(s, dt)); - }); - }); - } -} diff --git a/src/app/structure/components/recherche/recherche.component.html b/src/app/structure/components/recherche/recherche.component.html deleted file mode 100644 index 00eecd6da..000000000 --- a/src/app/structure/components/recherche/recherche.component.html +++ /dev/null @@ -1,83 +0,0 @@ -<div class="header"> - <span class="title">Acteurs de la médiation</span> -</div> -<div class="content" fxLayout="column"> - <div class="searchSection" fxLayout="row" fxLayoutGap="1.5vw"> - <div class="icon"> - <div class="ico-pin-search grey"></div> - </div> - <input type="text" placeholder="Rechercher une adresse, une association..." /> - <button type="button">Rechercher</button> - </div> - - <div class="btnSection" fxLayout="row" fxLayoutAlign="space-between center"> - <button - type="button" - [className]="modalOpened == modalType[0] ? 'selected' : ''" - (click)="openModal(this.modalType[0])" - > - <span class="btnText">Services</span> - <div class="arrow"></div> - </button> - <button - type="button" - [className]="modalOpened == modalType[1] ? 'selected' : ''" - (click)="openModal(this.modalType[1])" - > - <span class="btnText">Accueil</span> - <div class="arrow"></div> - </button> - <button - type="button" - [className]="modalOpened == modalType[2] ? 'selected' : ''" - (click)="openModal(this.modalType[2])" - > - <span class="btnText">Plus de filtres</span> - <div class="arrow"></div> - </button> - </div> - <div *ngIf="modalOpened" fxLayout="column" fxLayoutAlign="space-between" [ngClass]="['modal', 'modal' + modalOpened]"> - <div class="contentModal" fxLayout="row wrap"> - <!--<div class="blockFiltre" *ngFor="let s of services">--> - <div class="blockFiltre" *ngFor="let m of modules"> - <div class="blockLigne"> - <h4>{{ m.titre }}</h4> - <div - fxLayout="row" - class="ligneFiltre" - fxLayoutAlign="space-between center" - *ngFor="let categ of m.categories" - > - <div class="checkbox"> - <label> - <input - type="checkbox" - [checked]="this.checkedTab.indexOf(categ) > -1" - [value]="categ" - (change)="onCheckboxChange($event, false)" - /> - <span class="customCheck"></span> - </label> - <div class="label">{{ categ }}</div> - </div> - <span class="nbResult">34</span> - </div> - </div> - </div> - </div> - <div class="footer" fxLayout="row" fxLayoutAlign="end center" fxLayoutGap="3vw"> - <a (click)="onCheckboxChange($event, true)">Effacer</a> - <button type="button" (click)="applyFilter(modalOpened)">Appliquer</button> - </div> - </div> -</div> -<div class="footer" fxLayout="row" fxLayoutAlign="space-between center"> - <div class="checkbox"> - <label> - <input type="checkbox" /> - <span class="customCheck"></span> - </label> - <div class="label">Pass numérique</div> - </div> - <a href="">Ajouter une structure</a> -</div> diff --git a/src/app/structure/components/recherche/recherche.component.scss b/src/app/structure/components/recherche/recherche.component.scss deleted file mode 100644 index e1ac58b8d..000000000 --- a/src/app/structure/components/recherche/recherche.component.scss +++ /dev/null @@ -1,257 +0,0 @@ -@import '../../../../assets/scss/icons'; -@import '../../../../assets/scss/color'; - -.header { - .title { - font-family: Times New Roman; - font-style: normal; - font-weight: bold; - font-size: 20px; - line-height: 103%; - padding: 16px 0 16px 0; - - display: flex; - align-items: center; - text-transform: uppercase; - } -} -.content { - margin: 10px 0 0px 0; - .icon { - border: 1px solid $grey; - padding: 4px 6px 8px 6px; - border-radius: 4px; - cursor: pointer; - } - input { - width: 100%; - background-color: $grey-4; - border: none; - font-family: Trebuchet MS; - font-style: normal; - font-weight: normal; - font-size: 12px; - line-height: 17px; - display: flex; - align-items: center; - padding-left: 10px; - text-overflow: ellipsis; - color: $grey-1; - outline: none; - } - .searchSection { - button { - border: none; - cursor: pointer; - background-color: $purple; - font-family: Trebuchet MS; - font-style: normal; - font-weight: bold; - font-size: 13px; - line-height: 100%; - align-items: center; - text-align: center; - color: $white; - padding: 3px 16px 3px 16px; - outline: none; - } - } - .btnSection { - padding: 16px 0 16px 0; - button { - outline: none; - - border: 1px solid $grey; - border-radius: 33px; - background-color: $white; - padding: 2px 6px 2px 13px; - align-items: center; - display: flex; - cursor: pointer; - .btnText { - justify-content: center; - font-family: Trebuchet MS; - font-style: normal; - font-weight: normal; - font-size: 13px; - line-height: 19px; - display: flex; - align-items: center; - } - } - .selected { - border: 1px solid $orange-light; - color: $orange-light; - .arrow { - background-color: transparent; - border-bottom: 1px solid $orange-light; - border-right: 1px solid $orange-light; - transform: translateY(25%) rotate(-135deg); - margin: 0 5px 0 10px; - height: 7px; - width: 7px; - } - } - .arrow { - background-color: transparent; - border-bottom: 1px solid $grey; - border-right: 1px solid $grey; - transform: translateY(-25%) rotate(45deg); - margin: 0 5px 0 10px; - height: 7px; - width: 7px; - } - } -} -.footer { - margin: 0px 0 16px 0; - a { - font-family: Trebuchet MS; - font-style: normal; - font-weight: bold; - font-size: 13px; - line-height: 18px; - /* or 120% */ - - display: flex; - align-items: center; - text-decoration-line: underline; - } -} -.modalaccueil { - margin-left: 100px; -} -.modalplusFiltres { - margin-left: 196px; -} -.modal { - max-height: 654px; - max-width: 1100px; - background: $white; - border: 1px solid $purple; - box-sizing: border-box; - border-radius: 8px; - z-index: 1; - position: absolute; - margin-top: 80px; - padding: 20px 16px 10px 16px; - .contentModal { - writing-mode: vertical-lr; - overflow-y: hidden; - max-width: 1100px; - border-bottom: 1px solid grey; - margin-bottom: 10px; - .blockFiltre { - writing-mode: horizontal-tb; - max-width: 320px; - padding: 0 30px 10px 10px; - } - .ligneFiltre { - margin: 5px 0 5px 0; - } - h4 { - font-family: Trebuchet MS; - font-style: normal; - font-weight: bold; - font-size: 13px; - line-height: 17px; - display: flex; - align-items: center; - margin-top: 0; - } - .nbResult { - font-family: Trebuchet MS; - font-style: normal; - font-weight: normal; - font-size: 13px; - line-height: 15px; - } - label { - font-family: Trebuchet MS; - font-style: normal; - font-weight: normal; - font-size: 14px; - line-height: 16px; - } - } - .footer { - height: 32px; - button { - height: 100%; - border: none; - cursor: pointer; - background-color: $purple; - font-family: Trebuchet MS; - font-style: normal; - font-weight: bold; - font-size: 13px; - line-height: 100%; - align-items: center; - text-align: center; - color: $white; - padding: 3px 16px 3px 16px; - outline: none; - } - } -} -.checkbox { - position: relative; - display: grid; - align-items: center; - grid-template-columns: min-content auto; - min-height: 25px; - input { - opacity: 0; - display: none; - &:checked ~ .customCheck { - background-color: $orange-light; - border-color: transparent; - } - &:checked ~ .customCheck:after { - display: block; - } - } - label { - display: inline-grid; - } - .label { - padding-left: 8px; - font-family: Trebuchet MS; - font-style: normal; - font-weight: normal; - font-size: 14px; - line-height: 17px; - padding: 0 16px 0 16px; - } - .customCheck { - display: inline-grid; - width: 18px; - height: 18px; - background-color: $white; - border: 1px solid $grey; - cursor: pointer; - position: relative; - - top: 0; - left: 0; - &:hover { - background-color: $grey-4; - } - &:after { - content: ''; - position: absolute; - display: none; - } - &:after { - left: 7px; - top: 3px; - width: 4px; - height: 8px; - border: solid white; - border-width: 0 2px 2px 0; - transform: rotate(45deg); - -webkit-transform: rotate(45deg); - -ms-transform: rotate(45deg); - } - } -} diff --git a/src/app/structure/components/recherche/recherche.component.spec.ts b/src/app/structure/components/recherche/recherche.component.spec.ts deleted file mode 100644 index e38e4d4e8..000000000 --- a/src/app/structure/components/recherche/recherche.component.spec.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { ComponentFixture, TestBed } from '@angular/core/testing'; - -import { RechercheComponent } from './recherche.component'; - -describe('RechercheComponent', () => { - let component: RechercheComponent; - let fixture: ComponentFixture<RechercheComponent>; - - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ RechercheComponent ] - }) - .compileComponents(); - }); - - beforeEach(() => { - fixture = TestBed.createComponent(RechercheComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }); -}); diff --git a/src/app/structure/components/recherche/recherche.component.ts b/src/app/structure/components/recherche/recherche.component.ts deleted file mode 100644 index 34881d906..000000000 --- a/src/app/structure/components/recherche/recherche.component.ts +++ /dev/null @@ -1,140 +0,0 @@ -import { Component, OnInit } from '@angular/core'; -import { Module } from '../../models/recherche.model'; - -@Component({ - selector: 'app-recherche', - templateUrl: './recherche.component.html', - styleUrls: ['./recherche.component.scss'], -}) -export class RechercheComponent implements OnInit { - constructor() {} - //Variables btn filtres - modalType: string[] = ['services', 'accueil', 'plusFiltres']; - - //Variable gestion liste modal - servicesCategories: Module[]; - modaliteCategories: Module[]; - modules: Module[]; - filtresCategories: Module[]; - modalOpened: string; - - //Variable gestion Checkbox - checkedTab: string[]; - filterCheck: string[]; - - ngOnInit(): void { - //Sert à afficher la modal et indiquer le type de filtre choisit - this.modalOpened = null; - - //Sert à stocker les différentes catégories - this.servicesCategories = []; - this.modaliteCategories = []; - this.modules = []; - this.filtresCategories = []; - - //Sert à gérer la checkbox multiple - this.checkedTab = new Array(); - this.filterCheck = new Array(); - } - - //Ouvrir la modal et afficher la liste en fonction du btn de filtre appuyé - openModal(option: string) { - this.modules = []; - switch (option) { - case this.modalType[0]: - //Vérifie si le btn n'est pas actif - if (this.modalOpened != this.modalType[0]) { - this.modalOpened = this.modalType[0]; - this.fakeDataServices(); - } else { - this.modalOpened = null; - } - break; - case this.modalType[1]: - //Vérifie si le btn n'est pas actif - if (this.modalOpened != this.modalType[1]) { - this.modalOpened = this.modalType[1]; - this.fakeDataModalite(); - } else { - this.modalOpened = null; - } - break; - case this.modalType[2]: - //Vérifie si le btn n'est pas actif - if (this.modalOpened != this.modalType[2]) { - this.modalOpened = this.modalType[2]; - this.fakeDataFiltres(); - } else { - this.modalOpened = null; - } - break; - } - //Initialisation de la liste temporaire - this.checkedTab = this.filterCheck.slice(); - } - - //Envoie d'un tableau contenant tous les filtres - applyFilter() { - this.filterCheck = this.checkedTab.slice(); - this.openModal(this.modalOpened); - console.log(this.filterCheck); - } - - //Gestion de l'evenement checkbox(Cocher/Décocher) - onCheckboxChange(e, reset: boolean) { - //Condition btn effacer filtre d'une liste - if (!reset) { - if (e.target.checked) { - this.checkedTab.push(e.target.value); - } else { - //Vérifie si la case décochée est présente dans la liste temporaire et la supprime - if (this.checkedTab.indexOf(e.target.value) > -1) { - this.checkedTab.splice(this.checkedTab.indexOf(e.target.value), 1); - } - } - } else { - //Efface uniquement les éléments de la liste en cours - this.modules.forEach((m) => { - m.categories.forEach((categ) => { - if (this.checkedTab.indexOf(categ) > -1) this.checkedTab.splice(this.checkedTab.indexOf(categ), 1); - }); - }); - } - } - - /** - * En attendant les apis - */ - mockService(module: Module[], titre: string, categ: string, nbCateg: number) { - var m = new Module(); - m.titre = titre; - m.categories = []; - for (var i = 0; i < nbCateg; i++) { - m.categories.push(categ + i); - } - module.push(m); - } - fakeDataServices() { - this.mockService(this.modules, 'Accompagnement aux démarches en ligne', 'CAF', 7); - this.mockService(this.modules, 'Insertion sociale et professionnelle', ' Diffuser son CV en ligne', 5); - this.mockService( - this.modules, - 'Accès aux droits', - 'Déclarer ses revenus en ligne et découvertes des services proposés', - 8 - ); - this.mockService(this.modules, 'Aide à la parentalité/éducation', 'Découvrir l’univers des jeux vidéos', 4); - this.mockService(this.modules, 'Compétences de base', 'Faire un diagnostic des compétences', 8); - this.mockService(this.modules, 'Culture et sécurité numérique', 'Traitement de texte : découverte', 4); - } - fakeDataModalite() { - this.mockService(this.modules, "Modalité d'accueil", 'Matériel mis à dispostion', 6); - } - fakeDataFiltres() { - this.mockService(this.modules, 'Équipements', 'Accès à des revues ou livres infoirmatiques numériques', 8); - this.mockService(this.modules, "Type d'acteurs", 'Lieux de médiation (Pimms, assos...)', 5); - this.mockService(this.modules, 'Publics', 'Langues étrangères autres qu’anglais', 12); - this.mockService(this.modules, 'Labelisation', 'Prescripteur du Pass Numérique', 6); - this.mockService(this.modules, 'Type de structure', 'Espace de co-working', 6); - } -} diff --git a/src/app/structure/models/recherche.model.ts b/src/app/structure/models/recherche.model.ts deleted file mode 100644 index a498b7318..000000000 --- a/src/app/structure/models/recherche.model.ts +++ /dev/null @@ -1,5 +0,0 @@ -export class Module { - titre: string; - categories: string[]; - size: number; -} diff --git a/src/app/structure/models/structure.model.ts b/src/app/structure/models/structure.model.ts deleted file mode 100644 index 5617a7948..000000000 --- a/src/app/structure/models/structure.model.ts +++ /dev/null @@ -1,44 +0,0 @@ -export class Structure { - numero: string; - date_de_creation: string; - derniere_modification: string; - nom_de_lusager: string; - votre_structure_est_elle: string; - nom_de_votre_structure: string; - type_de_structure: string; - description: string; - n: string; - voie: string; - telephone: string; - courriel: string; - site_web: string; - facebook: string; - twitter: string; - instagram: string; - civilite: string; - nom: string; - prenom: string; - email_contact: string; - fonction: string; - accessibilite_personnes_a_mobilite_reduite_pmr: boolean; - jaccompagne_les_usagers_dans_leurs_demarches_en_ligne: boolean; - accompagnement_des_demarches: string[]; - wifi: boolean; - horaires: horaireStructure; - estOuvert: boolean; - ouvreLe: { jour: string; horaire: string }; -} - -export class horaireStructure { - lundi: Jour; - mardi: Jour; - mercredi: Jour; - jeudi: Jour; - vendredi: Jour; - samedi: Jour; - dimanche: Jour; -} -export class Jour { - open: boolean; - time: { openning: number; closing: number }[]; -} diff --git a/src/app/structure/services/structure.service.spec.ts b/src/app/structure/services/structure.service.spec.ts deleted file mode 100644 index 7c885d669..000000000 --- a/src/app/structure/services/structure.service.spec.ts +++ /dev/null @@ -1,221 +0,0 @@ -import { HttpClient, HttpClientModule } from '@angular/common/http'; -import { inject, TestBed } from '@angular/core/testing'; -import { horaireStructure, Jour, Structure } from '../models/structure.model'; -import { StructureService } from './structure.service'; -const { DateTime } = require('luxon'); - -describe('StructureService', () => { - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [HttpClientModule], - }); - }); - let _structureService: StructureService; - beforeEach(inject([StructureService], (_s: StructureService) => { - _structureService = _s; - })); - it('should return an hour string', () => { - const result = _structureService.numberToHour(928); - expect(result).toBe('9h28'); - }); - - it('should return a day string', () => { - const result = _structureService.numberToDay(1); - expect(result).toBe('lundi'); - }); - it('should return null', () => { - const result = _structureService.numberToDay(8); - expect(result).toBeNull(); - }); - - it('Comparer Horaire : should return true', () => { - const result = _structureService.comparerHoraire(830, 1200, 900); - expect(result).toBeTrue(); - }); - - it('Comparer Horaire : should return false', () => { - const result = _structureService.comparerHoraire(830, 1200, 800); - expect(result).toBeFalse(); - }); - - it('Recuperer Horaire : should return an object (Jour)', () => { - const s: Structure = new Structure(); - var horaire = [ - { openning: 800, closing: 1200 }, - { openning: 1400, closing: 1600 }, - ]; - s.horaires = new horaireStructure(); - s.horaires.mardi = new Jour(); - s.horaires.mardi.open = true; - s.horaires.mardi.time = horaire; - const jour: Jour = new Jour(); - jour.open = true; - jour.time = horaire; - const result = _structureService.recupererHoraire(s, 2); - expect(result).toEqual(jour); - }); - - it('Recuperer Horaire : should return undefined', () => { - const s: Structure = new Structure(); - var horaire = [ - { openning: 800, closing: 1200 }, - { openning: 1400, closing: 1600 }, - ]; - s.horaires = new horaireStructure(); - s.horaires.lundi = new Jour(); - s.horaires.lundi.open = true; - s.horaires.lundi.time = horaire; - const jour: Jour = new Jour(); - jour.open = true; - jour.time = horaire; - const result = _structureService.recupererHoraire(s, 2); - expect(result).toBeUndefined(); - }); - - it('Recuperer Horaire : should return null', () => { - const s: Structure = new Structure(); - var horaire = [ - { openning: 800, closing: 1200 }, - { openning: 1400, closing: 1600 }, - ]; - s.horaires = new horaireStructure(); - s.horaires.mardi = new Jour(); - s.horaires.mardi.open = true; - s.horaires.mardi.time = horaire; - const result = _structureService.recupererHoraire(s, 8); - expect(result).toBeNull(); - }); - - it('Recuperer Prochaine Ouverture : should return an object ({Jour/Horaire})', () => { - //Init structure - const s: Structure = new Structure(); - var horaire = [ - { openning: 805, closing: 1200 }, - { openning: 1400, closing: 1600 }, - ]; - s.horaires = new horaireStructure(); - s.horaires.lundi = new Jour(); - s.horaires.mardi = new Jour(); - s.horaires.mercredi = new Jour(); - s.horaires.jeudi = new Jour(); - s.horaires.vendredi = new Jour(); - s.horaires.samedi = new Jour(); - s.horaires.dimanche = new Jour(); - s.horaires.mardi.open = true; - s.horaires.mardi.time = horaire; - - //Init sur vendredi à 14h00 - const result = _structureService.recupererProchaineOuverture(s, 5, 5, 1400); - expect(result).toEqual({ jour: 'mardi', horaire: '8h05' }); - }); - - it('Recuperer Prochaine Ouverture dans la journée : should return an object ({Jour/Horaire})', () => { - //Init structure - const s: Structure = new Structure(); - var horaire = [ - { openning: 805, closing: 1200 }, - { openning: 1400, closing: 1600 }, - ]; - s.horaires = new horaireStructure(); - s.horaires.lundi = new Jour(); - s.horaires.mardi = new Jour(); - s.horaires.mercredi = new Jour(); - s.horaires.jeudi = new Jour(); - s.horaires.vendredi = new Jour(); - s.horaires.samedi = new Jour(); - s.horaires.dimanche = new Jour(); - s.horaires.mardi.open = true; - s.horaires.mardi.time = horaire; - - //Init sur mardi à 12h06 - const result = _structureService.recupererProchaineOuverture(s, 2, 2, 1206); - expect(result).toEqual({ jour: ' ', horaire: '14h00' }); - }); - - it('Recuperer Prochaine Ouverture pour la semaine prochaine sur le même jour : should return an object ({Jour/Horaire})', () => { - //Init structure avec deux horaires le mardi - const s: Structure = new Structure(); - var horaire = [ - { openning: 805, closing: 1200 }, - { openning: 1400, closing: 1600 }, - ]; - s.horaires = new horaireStructure(); - s.horaires.lundi = new Jour(); - s.horaires.mardi = new Jour(); - s.horaires.mercredi = new Jour(); - s.horaires.jeudi = new Jour(); - s.horaires.vendredi = new Jour(); - s.horaires.samedi = new Jour(); - s.horaires.dimanche = new Jour(); - s.horaires.mardi.open = true; - s.horaires.mardi.time = horaire; - - //Init sur mardi à 15h15 - const result = _structureService.recupererProchaineOuverture(s, 2, 2, 1515); - expect(result).toEqual({ jour: 'mardi', horaire: '8h05' }); - }); - - it('Recuperer Prochaine Ouverture : should return an error string', () => { - //Init structure avec aucun horaire - const s: Structure = new Structure(); - s.horaires = new horaireStructure(); - s.horaires.lundi = new Jour(); - s.horaires.mardi = new Jour(); - s.horaires.mercredi = new Jour(); - s.horaires.jeudi = new Jour(); - s.horaires.vendredi = new Jour(); - s.horaires.samedi = new Jour(); - s.horaires.dimanche = new Jour(); - - //Init sur jeudi à 12h06 - const result = _structureService.recupererProchaineOuverture(s, 4, 2, 1206); - expect(result).toEqual('Aucun horaire disponible'); - }); - - it('Mise à jour ouverture de la structure : should return true', () => { - var horaire = [ - { openning: 805, closing: 1200 }, - { openning: 1400, closing: 1600 }, - ]; - //Init structure avec aucun horaire - const s: Structure = new Structure(); - s.horaires = new horaireStructure(); - s.horaires.lundi = new Jour(); - s.horaires.mardi = new Jour(); - s.horaires.mercredi = new Jour(); - s.horaires.jeudi = new Jour(); - s.horaires.vendredi = new Jour(); - s.horaires.samedi = new Jour(); - s.horaires.dimanche = new Jour(); - - s.horaires.jeudi.open = true; - s.horaires.jeudi.time = horaire; - - //Init date sur un jeudi à 9h05 - var dt = new DateTime.local(2020, 10, 8, 9, 5); - const result = _structureService.majOuvertureStructure(s, dt); - expect(result.estOuvert).toEqual(true); - }); - - it('Mise à jour ouverture de la structure : should return false', () => { - var horaire = [{ openning: 1400, closing: 1600 }]; - //Init structure avec aucun horaire - const s: Structure = new Structure(); - s.horaires = new horaireStructure(); - s.horaires.lundi = new Jour(); - s.horaires.mardi = new Jour(); - s.horaires.mercredi = new Jour(); - s.horaires.jeudi = new Jour(); - s.horaires.vendredi = new Jour(); - s.horaires.samedi = new Jour(); - s.horaires.dimanche = new Jour(); - - s.horaires.jeudi.open = true; - s.horaires.jeudi.time = horaire; - - //Init date sur un jeudi à 9h05 - var dt = new DateTime.local(2020, 10, 8, 9, 5); - const result = _structureService.majOuvertureStructure(s, dt); - expect(result.estOuvert).toEqual(false); - }); -}); diff --git a/src/app/structure/services/structure.service.ts b/src/app/structure/services/structure.service.ts deleted file mode 100644 index f18978024..000000000 --- a/src/app/structure/services/structure.service.ts +++ /dev/null @@ -1,163 +0,0 @@ -import { HttpClient } from '@angular/common/http'; -import { Injectable } from '@angular/core'; -import { Jour, Structure } from '../models/structure.model'; - -@Injectable({ - providedIn: 'root', -}) -export class StructureService { - constructor(private http: HttpClient) {} - - recupererStructures() { - return this.http.get('/api/Structures'); - } - - majOuvertureStructure(structure: Structure, dateActuelle: any) { - //Récupère le jour de la semaine. - var jourSemaine: number = dateActuelle.weekday; - - //Vérifie si les minutes commencent par zéro pour éviter la suppression. - var now: number; - if (dateActuelle.minute.toString().length != 1) { - now = parseInt('' + dateActuelle.hour + dateActuelle.minute, 10); - } else { - now = parseInt('' + dateActuelle.hour + 0 + dateActuelle.minute, 10); - } - - //Récupérer les horaires d'une structure en fonction de son jour pour indiquer si elle est ouverte. - var horaireStructure: Jour = this.recupererHoraire(structure, jourSemaine); - structure.estOuvert = false; - if (horaireStructure.open) { - horaireStructure.time.forEach((periode) => { - if (this.comparerHoraire(periode.openning, periode.closing, now)) { - structure.estOuvert = true; - } - }); - } - structure.ouvreLe = this.recupererProchaineOuverture(structure, jourSemaine, jourSemaine, now); - return structure; - } - - //Récupère les horaires d'une structure en fonction du jour de la semaine - recupererHoraire(structure: Structure, jourActuel: number) { - switch (jourActuel) { - case 1: - return structure.horaires.lundi; - case 2: - return structure.horaires.mardi; - case 3: - return structure.horaires.mercredi; - case 4: - return structure.horaires.jeudi; - case 5: - return structure.horaires.vendredi; - case 6: - return structure.horaires.samedi; - case 7: - return structure.horaires.dimanche; - default: - return null; - } - } - //Vérifie si l'heure actuelle est dans l'interval des horaires de la structure - comparerHoraire(heureDeb: number, heureFin: number, heureActuelle: number) { - return heureActuelle >= heureDeb && heureActuelle <= heureFin; - } - - recupererProchaineOuverture(s: Structure, j: number, baseJour: number, baseHeure: number) { - //Récupérer horaire du jour en cours - var horaires = this.recupererHoraire(s, j); - //Condition pour stopper la récursion (Si le jour du compteur est égal au jour en cours) - if (j + 1 != baseJour) { - if (horaires.open) { - //Vérifie si le compteur correspond au jour en cours pour éviter de proposer - //les horaires déjà passés. - if (j != baseJour) { - var jourOuverture = null; - horaires.time.every((periode) => { - if (periode.openning) { - jourOuverture = { jour: this.numberToDay(j), horaire: this.numberToHour(periode.openning) }; - return false; - } - return true; - }); - //Si pas de période trouvée, on réitère. - if (!jourOuverture) { - return this.recupererProchaineOuverture(s, j + 1, baseJour, baseHeure); - } - return jourOuverture; - } else { - var jourOuverture = null; - horaires.time.every((periode) => { - if (periode.openning >= baseHeure) { - jourOuverture = { jour: ' ', horaire: this.numberToHour(periode.openning) }; - return false; - } - return true; - }); - //Si pas de période trouvée, on réitère. - if (!jourOuverture) { - return this.recupererProchaineOuverture(s, j + 1, baseJour, baseHeure); - } - return jourOuverture; - } - } else { - //Si le jour n'est pas égal à Dimanche, on l'incrémente de 1. - if (j != 7) { - return this.recupererProchaineOuverture(s, j + 1, baseJour, baseHeure); - } - //Si le jour est égal à Lundi, on le positionne sur 0 pour activer la condition d'arrêt. - if (baseJour == 1) { - return this.recupererProchaineOuverture(s, 0, baseJour, baseHeure); - } - //Si le jour est égal à Dimanche, on le positionne sur Lundi. - return this.recupererProchaineOuverture(s, 1, baseJour, baseHeure); - } - } - var lastChancehoraire = this.recupererHoraire(s, j + 1); - var lastJour: any; - if (lastChancehoraire.open) { - lastChancehoraire.time.every((periode) => { - if (periode.openning && periode.openning < baseHeure) { - lastJour = { jour: this.numberToDay(j + 1), horaire: this.numberToHour(periode.openning) }; - return false; - } - lastJour = 'Aucun horaire disponible'; - }); - } else { - lastJour = 'Aucun horaire disponible'; - } - return lastJour; - } - - numberToDay(n: number) { - switch (n) { - case 1: - return 'lundi'; - case 2: - return 'mardi'; - case 3: - return 'mercredi'; - case 4: - return 'jeudi'; - case 5: - return 'vendredi'; - case 6: - return 'samedi'; - case 7: - return 'dimanche'; - default: - return null; - } - } - - numberToHour(n: number) { - if (n.toString().length == 3) { - var tabNum = n.toString().match(/.{1,1}/g); - return tabNum[0] + 'h' + tabNum[1] + tabNum[2]; - } else if (n.toString().length == 4) { - var tabNum = n.toString().match(/.{1,2}/g); - return tabNum[0] + 'h' + tabNum[1]; - } - } -} diff --git a/src/app/structure/structure.component.html b/src/app/structure/structure.component.html deleted file mode 100644 index 86c8f6308..000000000 --- a/src/app/structure/structure.component.html +++ /dev/null @@ -1,5 +0,0 @@ -<div class="container"> - <app-recherche></app-recherche> - <div class="divider"></div> - <app-card></app-card> -</div> diff --git a/src/app/structure/structure.component.scss b/src/app/structure/structure.component.scss deleted file mode 100644 index 2d506b58d..000000000 --- a/src/app/structure/structure.component.scss +++ /dev/null @@ -1,11 +0,0 @@ -@import '../../assets/scss/color'; - -.divider { - width: 100%; - height: 1px; - background-color: $grey-4; -} -//En attendant de l'intégrer avec la map -.container { - width: 320px; -} diff --git a/src/app/structure/structure.component.spec.ts b/src/app/structure/structure.component.spec.ts deleted file mode 100644 index 47da9d53d..000000000 --- a/src/app/structure/structure.component.spec.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { ComponentFixture, TestBed } from '@angular/core/testing'; - -import { StructureComponent } from './structure.component'; - -describe('StructureComponent', () => { - let component: StructureComponent; - let fixture: ComponentFixture<StructureComponent>; - - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ StructureComponent ] - }) - .compileComponents(); - }); - - beforeEach(() => { - fixture = TestBed.createComponent(StructureComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }); -}); diff --git a/src/app/structure/structure.component.ts b/src/app/structure/structure.component.ts deleted file mode 100644 index c74423ddc..000000000 --- a/src/app/structure/structure.component.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { Component, OnInit } from '@angular/core'; - -@Component({ - selector: 'app-structure', - templateUrl: './structure.component.html', - styleUrls: ['./structure.component.scss'] -}) -export class StructureComponent implements OnInit { - - constructor() { } - - ngOnInit(): void { - } - -} diff --git a/src/app/structure/structure.module.ts b/src/app/structure/structure.module.ts deleted file mode 100644 index fdc77203d..000000000 --- a/src/app/structure/structure.module.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { NgModule } from '@angular/core'; -import { CommonModule } from '@angular/common'; -import { StructureComponent } from './structure.component'; -import { CardComponent } from './components/card/card.component'; -import { RechercheComponent } from './components/recherche/recherche.component'; -import { HttpClientModule } from '@angular/common/http'; -import { FlexLayoutModule } from '@angular/flex-layout'; -import { FormsModule, ReactiveFormsModule } from '@angular/forms'; - -@NgModule({ - declarations: [StructureComponent, CardComponent, RechercheComponent], - imports: [CommonModule, HttpClientModule, FlexLayoutModule, ReactiveFormsModule], - exports: [StructureComponent], -}) -export class StructureModule {} -- GitLab From bbe32831003a66a4fa9b58c344c9baa94616676d Mon Sep 17 00:00:00 2001 From: Jeremie BRISON <ext.sopra.jbrison@grandlyon.com> Date: Mon, 19 Oct 2020 17:10:31 +0200 Subject: [PATCH 21/50] fix(search) : fix selector html --- src/app/structure-list/components/card/card.component.ts | 2 +- .../components/search/search.component.scss | 9 --------- .../structure-list/components/search/search.component.ts | 2 +- src/app/structure-list/structure-list.component.html | 4 ++-- 4 files changed, 4 insertions(+), 13 deletions(-) diff --git a/src/app/structure-list/components/card/card.component.ts b/src/app/structure-list/components/card/card.component.ts index a54d92069..dc782ec45 100644 --- a/src/app/structure-list/components/card/card.component.ts +++ b/src/app/structure-list/components/card/card.component.ts @@ -5,7 +5,7 @@ import { StructureService } from '../../services/structure-list.service'; const { DateTime } = require('luxon'); @Component({ - selector: 'app-card', + selector: 'app-structure-list-card', templateUrl: './card.component.html', styleUrls: ['./card.component.scss'], }) diff --git a/src/app/structure-list/components/search/search.component.scss b/src/app/structure-list/components/search/search.component.scss index cbe065b6c..4a8926c2f 100644 --- a/src/app/structure-list/components/search/search.component.scss +++ b/src/app/structure-list/components/search/search.component.scss @@ -1,7 +1,6 @@ @import '../../../../assets/scss/icons'; @import '../../../../assets/scss/color'; @import '../../../../assets/scss/typography'; -@import '../../../../assets/scss/breakpoint'; .header { .title { @@ -238,11 +237,3 @@ } } } -/*@media #{$phone} { - .allSection { - display: none !important; - } - .phoneSection { - display: flex; - } -}*/ diff --git a/src/app/structure-list/components/search/search.component.ts b/src/app/structure-list/components/search/search.component.ts index 86550580e..30c27b5f7 100644 --- a/src/app/structure-list/components/search/search.component.ts +++ b/src/app/structure-list/components/search/search.component.ts @@ -5,7 +5,7 @@ import { Module } from '../../models/module.model'; import { SearchService } from '../../services/search.service'; @Component({ - selector: 'app-search', + selector: 'app-structure-list-search', templateUrl: './search.component.html', styleUrls: ['./search.component.scss'], }) diff --git a/src/app/structure-list/structure-list.component.html b/src/app/structure-list/structure-list.component.html index 38562830e..d9375a386 100644 --- a/src/app/structure-list/structure-list.component.html +++ b/src/app/structure-list/structure-list.component.html @@ -1,5 +1,5 @@ <div class="container"> - <app-search (searchEvent)="fetchResults($event)"></app-search> + <app-structure-list-search (searchEvent)="fetchResults($event)"></app-structure-list-search> <div class="divider"></div> - <app-card [filter]="currentFilter"></app-card> + <app-structure-list-card [filter]="currentFilter"></app-structure-list-card> </div> -- GitLab From 908281b7ff6ad231b15ece95b361806faa45c67d Mon Sep 17 00:00:00 2001 From: Jeremie BRISON <ext.sopra.jbrison@grandlyon.com> Date: Tue, 20 Oct 2020 09:28:42 +0200 Subject: [PATCH 22/50] fix(search) : fix multiple filter checkbox --- api/server.js | 30 +++++++++++++++++++ .../components/search/search.component.html | 2 +- .../components/search/search.component.ts | 15 +++++++--- .../structure-list/models/category.model.ts | 4 +++ src/app/structure-list/models/module.model.ts | 1 + .../structure-list/services/search.service.ts | 20 +++++++++++-- .../services/structure-list.service.ts | 12 ++++++-- 7 files changed, 75 insertions(+), 9 deletions(-) create mode 100644 api/server.js diff --git a/api/server.js b/api/server.js new file mode 100644 index 000000000..0bcb25ead --- /dev/null +++ b/api/server.js @@ -0,0 +1,30 @@ +const jsonServer = require('json-server'); +const server = jsonServer.create(); +const router = jsonServer.router('db.json'); +const middlewares = jsonServer.defaults(); + +// Set default middlewares (logger, static, cors and no-cache) +server.use(middlewares); + +// Add custom routes before JSON Server router +server.get('/structures/count', (req, res) => { + let structureCountTab = []; + structureCountTab.push({ id: 260, count: 3 }); + structureCountTab.push({ id: 260, count: 3 }); + structureCountTab.push({ id: 259, count: 3 }); + structureCountTab.push({ id: 261, count: 3 }); + structureCountTab.push({ id: 249, count: 3 }); + structureCountTab.push({ id: 222, count: 2 }); + structureCountTab.push({ id: 212, count: 3 }); + structureCountTab.push({ id: 186, count: 2 }); + structureCountTab.push({ id: 183, count: 2 }); + return res.status(200).jsonp({ + structureCountTab, + }); +}); + +// Use default router +server.use(router); +server.listen(3000, () => { + console.log('JSON Server is running'); +}); diff --git a/src/app/structure-list/components/search/search.component.html b/src/app/structure-list/components/search/search.component.html index 8236e0fcd..df0c51915 100644 --- a/src/app/structure-list/components/search/search.component.html +++ b/src/app/structure-list/components/search/search.component.html @@ -65,7 +65,7 @@ <div class="label">{{ module.text }}</div> </div> </li> - <span class="nbResult">34</span> + <span class="nbResult">{{ module.count ? module.count : '0' }}</span> </div> </ul> </div> diff --git a/src/app/structure-list/components/search/search.component.ts b/src/app/structure-list/components/search/search.component.ts index 30c27b5f7..259d6e208 100644 --- a/src/app/structure-list/components/search/search.component.ts +++ b/src/app/structure-list/components/search/search.component.ts @@ -77,6 +77,8 @@ export class SearchComponent implements OnInit { // Management of the checkbox event (Check / Uncheck) public onCheckboxChange(event, categ: string): void { const checkValue: number = parseInt(event.target.value); + console.log(checkValue); + if (event.target.checked) { this.checkedModules.push(new Module(checkValue, categ)); } else { @@ -131,10 +133,15 @@ export class SearchComponent implements OnInit { if (option === this.modalType[0]) { this.mockService(this.categories, 'Accompagnement des démarches', { name: 'CAF', id: '' }, 7); } else if (option === this.modalType[1]) { - this.searchService.getCategories().subscribe((d) => { - d.forEach((element) => { - this.categories.push(element); - }); + this.searchService.getCategories().subscribe((categories: Category[]) => { + this.searchService + .getFakeCounterModule() + .subscribe((res: { structureCountTab: { id: number; count: number }[] }) => { + categories.forEach((category) => { + category = this.searchService.setCountModules(category, res.structureCountTab); + this.categories.push(category); + }); + }); }); } else if (option === this.modalType[2]) { this.mockService(this.categories, 'Équipements', 'Accès à des revues ou livres infoirmatiques numériques', 8); diff --git a/src/app/structure-list/models/category.model.ts b/src/app/structure-list/models/category.model.ts index f6c60e54e..cb5a96eee 100644 --- a/src/app/structure-list/models/category.model.ts +++ b/src/app/structure-list/models/category.model.ts @@ -3,4 +3,8 @@ import { Module } from './module.model'; export class Category { name: string; modules: Module[]; + + constructor(obj?: any) { + Object.assign(this, obj); + } } diff --git a/src/app/structure-list/models/module.model.ts b/src/app/structure-list/models/module.model.ts index 83d025356..340c04092 100644 --- a/src/app/structure-list/models/module.model.ts +++ b/src/app/structure-list/models/module.model.ts @@ -1,6 +1,7 @@ export class Module { id: number; text: string; + count: number; constructor(id: number, text: string) { this.id = id; diff --git a/src/app/structure-list/services/search.service.ts b/src/app/structure-list/services/search.service.ts index d48c602e1..4ae64b197 100644 --- a/src/app/structure-list/services/search.service.ts +++ b/src/app/structure-list/services/search.service.ts @@ -1,6 +1,9 @@ import { HttpClient } from '@angular/common/http'; import { Injectable } from '@angular/core'; import { Observable } from 'rxjs'; +import { map } from 'rxjs/operators'; +import { Category } from '../models/category.model'; +import { Module } from '../models/module.model'; @Injectable({ providedIn: 'root', @@ -8,7 +11,20 @@ import { Observable } from 'rxjs'; export class SearchService { constructor(private http: HttpClient) {} - public getCategories(): Observable<any> { - return this.http.get('/api/Categories'); + public getCategories(): Observable<Category[]> { + return this.http.get('/api/Categories').pipe(map((data: any[]) => data.map((item) => new Category(item)))); + } + public getFakeCounterModule(): Observable<any> { + return this.http.get('http://localhost:3000/structures/count'); + } + public setCountModules(category: Category, structureCountTab: { id: number; count: number }[]): Category { + category.modules.forEach((m: Module) => { + for (let i = 0; i < structureCountTab.length; i++) { + if (structureCountTab[i].id === m.id) { + m.count = structureCountTab[i].count; + } + } + }); + return category; } } diff --git a/src/app/structure-list/services/structure-list.service.ts b/src/app/structure-list/services/structure-list.service.ts index 0a1d1e34a..2b9f77512 100644 --- a/src/app/structure-list/services/structure-list.service.ts +++ b/src/app/structure-list/services/structure-list.service.ts @@ -32,9 +32,17 @@ export class StructureService { api = api + '&'; } if (filter.isStrict) { - api = api + filter.name + '=' + filter.value; + if (api.includes(filter.name)) { + api = api + '=' + filter.value; + } else { + api = api + filter.name + '=' + filter.value; + } } else { - api = api + filter.name + '_like=' + filter.value; + if (api.includes(filter.name)) { + api = api + filter.value; + } else { + api = api + filter.name + '_like=' + filter.value; + } } }); } -- GitLab From fae81e5cdf6d1f803106223e8dd3ddd939fb5b72 Mon Sep 17 00:00:00 2001 From: Jeremie BRISON <ext.sopra.jbrison@grandlyon.com> Date: Tue, 20 Oct 2020 09:40:45 +0200 Subject: [PATCH 23/50] fix(search) : add data counter --- api/server.js | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/api/server.js b/api/server.js index 0bcb25ead..08ca86cb0 100644 --- a/api/server.js +++ b/api/server.js @@ -9,6 +9,7 @@ server.use(middlewares); // Add custom routes before JSON Server router server.get('/structures/count', (req, res) => { let structureCountTab = []; + // Compétences de base structureCountTab.push({ id: 260, count: 3 }); structureCountTab.push({ id: 260, count: 3 }); structureCountTab.push({ id: 259, count: 3 }); @@ -18,6 +19,45 @@ server.get('/structures/count', (req, res) => { structureCountTab.push({ id: 212, count: 3 }); structureCountTab.push({ id: 186, count: 2 }); structureCountTab.push({ id: 183, count: 2 }); + // Accès aux droits + structureCountTab.push({ id: 176, count: 2 }); + structureCountTab.push({ id: 175, count: 1 }); + structureCountTab.push({ id: 174, count: 1 }); + structureCountTab.push({ id: 173, count: 1 }); + structureCountTab.push({ id: 172, count: 1 }); + structureCountTab.push({ id: 171, count: 1 }); + structureCountTab.push({ id: 167, count: 1 }); + structureCountTab.push({ id: 165, count: 1 }); + // Insertion sociale et professionnelle + structureCountTab.push({ id: 254, count: 2 }); + structureCountTab.push({ id: 240, count: 2 }); + structureCountTab.push({ id: 194, count: 3 }); + structureCountTab.push({ id: 193, count: 3 }); + structureCountTab.push({ id: 192, count: 3 }); + structureCountTab.push({ id: 191, count: 3 }); + structureCountTab.push({ id: 262, count: 3 }); + structureCountTab.push({ id: 263, count: 2 }); + structureCountTab.push({ id: 3, count: 2 }); + // Aide à la parentalité + structureCountTab.push({ id: 257, count: 2 }); + structureCountTab.push({ id: 238, count: 2 }); + structureCountTab.push({ id: 178, count: 1 }); + structureCountTab.push({ id: 166, count: 1 }); + // Culture et sécurité numérique + structureCountTab.push({ id: 264, count: 2 }); + structureCountTab.push({ id: 255, count: 2 }); + structureCountTab.push({ id: 265, count: 2 }); + structureCountTab.push({ id: 232, count: 2 }); + structureCountTab.push({ id: 225, count: 2 }); + structureCountTab.push({ id: 221, count: 2 }); + structureCountTab.push({ id: 218, count: 1 }); + structureCountTab.push({ id: 209, count: 1 }); + structureCountTab.push({ id: 208, count: 1 }); + structureCountTab.push({ id: 206, count: 2 }); + structureCountTab.push({ id: 195, count: 1 }); + structureCountTab.push({ id: 164, count: 1 }); + structureCountTab.push({ id: 163, count: 1 }); + structureCountTab.push({ id: 162, count: 2 }); return res.status(200).jsonp({ structureCountTab, }); -- GitLab From 465f7da090442cd554a29110fb568cc571376c69 Mon Sep 17 00:00:00 2001 From: Jeremie BRISON <ext.sopra.jbrison@grandlyon.com> Date: Tue, 20 Oct 2020 11:41:04 +0200 Subject: [PATCH 24/50] fix(search) : fix design --- src/app/home/home.component.html | 4 +- .../components/card/card.component.html | 42 +++++++------- .../components/search/search.component.html | 58 ++++++++++--------- .../components/search/search.component.scss | 40 ++++++++----- .../components/search/search.component.ts | 5 +- .../structure-list.component.html | 8 ++- .../structure-list.component.scss | 5 +- src/assets/scss/_color.scss | 1 + src/assets/scss/_typography.scss | 2 +- 9 files changed, 91 insertions(+), 74 deletions(-) diff --git a/src/app/home/home.component.html b/src/app/home/home.component.html index 22f5aeb0f..9b962fa14 100644 --- a/src/app/home/home.component.html +++ b/src/app/home/home.component.html @@ -1,5 +1,3 @@ <div class="content-container"> - <div class="section-container"> - <app-structure-list></app-structure-list> - </div> + <app-structure-list></app-structure-list> </div> diff --git a/src/app/structure-list/components/card/card.component.html b/src/app/structure-list/components/card/card.component.html index 490d59af8..7afed396a 100644 --- a/src/app/structure-list/components/card/card.component.html +++ b/src/app/structure-list/components/card/card.component.html @@ -1,25 +1,27 @@ <span class="nbStructuresLabel">{{ structures.length }} structures</span> -<div class="structure" fxLayout="column" *ngFor="let structure of structures"> - <span class="nomStructure">{{ structure.nom }}</span> +<div class="listStructure"> + <div class="structure" fxLayout="column" *ngFor="let structure of structures"> + <span class="nomStructure">{{ structure.nom }}</span> - <div class="headerStructure" fxLayout="row" fxLayoutAlign="space-between center"> - <span class="typeStructure">{{ structure.typeDeStructure }}</span> - <span class="distanceStructure">├─┤ 63 m</span> - </div> - <br /> - <div class="statusStructure" fxLayout="row" fxLayoutAlign="start center"> - <div *ngIf="structure.isOpen; else closed"> - <span class="ico-dot-available"></span> - <span>Ouvert actuellement</span> + <div class="headerStructure" fxLayout="row" fxLayoutAlign="space-between center"> + <span class="typeStructure">{{ structure.typeDeStructure }}</span> + <span class="distanceStructure">├─┤ 63 m</span> + </div> + <br /> + <div class="statusStructure" fxLayout="row" fxLayoutAlign="start center"> + <div *ngIf="structure.isOpen; else closed"> + <span class="ico-dot-available"></span> + <span>Ouvert actuellement</span> + </div> + <ng-template #closed> + <span class="ico-dot-unavailable"></span> + <span *ngIf="structure.openedOn.day; else noTime"> + Fermé - Ouvre {{ structure.openedOn.day }} à {{ structure.openedOn.schedule }}</span + > + </ng-template> + <ng-template #noTime> + <span> Fermé - Aucun horaire disponible</span> + </ng-template> </div> - <ng-template #closed> - <span class="ico-dot-unavailable"></span> - <span *ngIf="structure.openedOn.day; else noTime"> - Fermé - Ouvre {{ structure.openedOn.day }} à {{ structure.openedOn.schedule }}</span - > - </ng-template> - <ng-template #noTime> - <span> Fermé - Aucun horaire disponible</span> - </ng-template> </div> </div> diff --git a/src/app/structure-list/components/search/search.component.html b/src/app/structure-list/components/search/search.component.html index df0c51915..730c6b49d 100644 --- a/src/app/structure-list/components/search/search.component.html +++ b/src/app/structure-list/components/search/search.component.html @@ -10,32 +10,36 @@ <button type="button" (click)="applyFilter()">Rechercher</button> </div> - <div class="btnSection"> - <div class="phoneSection" fxLayout="row" fxLayoutAlign="center center"> - <button - type="button" - [className]="modalTypeOpened === modalType[0] ? 'selected' : ''" - (click)="openModal(this.modalType[0])" - > - <span class="btnText">Accompagnement</span> - <div class="arrow"></div> - </button> - <button - type="button" - [className]="modalTypeOpened === modalType[1] ? 'selected' : ''" - (click)="openModal(this.modalType[1])" - > - <span class="btnText">Formations</span> - <div class="arrow"></div> - </button> - <button - type="button" - [className]="modalTypeOpened === modalType[2] ? 'selected' : ''" - (click)="openModal(this.modalType[2])" - > - <span class="btnText">Plus de filtres</span> - <div class="arrow"></div> - </button> + <div class="btnSection" fxLayout="row" fxLayoutAlign="space-between center"> + <div + class="button" + [ngClass]="{ selected: modalTypeOpened === modalType[0] }" + (click)="openModal(this.modalType[0])" + fxLayout="row" + fxLayoutAlign="space-between center" + > + <span class="btnText">Accompagnement</span> + <div class="arrow"></div> + </div> + <div + class="button" + [ngClass]="{ selected: modalTypeOpened === modalType[1] }" + (click)="openModal(this.modalType[1])" + fxLayout="row" + fxLayoutAlign="space-between center" + > + <span class="btnText">Formations</span> + <div class="arrow"></div> + </div> + <div + class="button" + [ngClass]="{ selected: modalTypeOpened === modalType[2] }" + (click)="openModal(this.modalType[2])" + fxLayout="row" + fxLayoutAlign="space-between center" + > + <span class="btnText">Plus de filtres</span> + <div class="arrow"></div> </div> </div> <div @@ -76,7 +80,7 @@ </div> </div> </div> -<div class="footer" fxLayout="row" fxLayoutAlign="space-between center"> +<div class="footerSearchSection" fxLayout="row" fxLayoutAlign="space-between center"> <div class="checkbox"> <div class="checkboxItem"> <label> diff --git a/src/app/structure-list/components/search/search.component.scss b/src/app/structure-list/components/search/search.component.scss index 4a8926c2f..b6196462f 100644 --- a/src/app/structure-list/components/search/search.component.scss +++ b/src/app/structure-list/components/search/search.component.scss @@ -21,7 +21,7 @@ } input { width: 100%; - background-color: $grey-4; + background-color: $grey-5; border: none; @include cn-regular-14; display: flex; @@ -45,11 +45,10 @@ } } .btnSection { - padding: 16px 0 16px 0; - .phoneSection { - display: none; - } - button { + padding: 16px 0 8px 0; + .button { + height: 40px; + width: 190px; outline: none; border: 1px solid $grey; border-radius: 33px; @@ -89,27 +88,29 @@ } } } -.modalaccueil { - margin-left: 100px; +.modalformations { + margin-left: 206px; } .modalplusFiltres { - margin-left: 196px; + margin-left: 412px; } .modal { - max-height: 654px; - max-width: 754px; + -moz-box-shadow: -5px 5px 10px 0px $grey; + box-shadow: -5px 5px 10px 0px $grey; + max-height: 648px; + width: 754px; background: $white; border: 1px solid $grey; box-sizing: border-box; z-index: 1; position: absolute; - margin-top: 80px; + margin-top: 96px; ::-webkit-scrollbar { width: 10px; } ::-webkit-scrollbar-track { - background: $grey-4; + background: $grey-5; } ::-webkit-scrollbar-thumb { background: $grey; @@ -159,7 +160,6 @@ @include cn-bold-14; display: flex; align-items: center; - text-decoration-line: underline; } height: 32px; button { @@ -203,7 +203,6 @@ .label { padding-left: 8px; @include cn-regular-14; - padding: 0 16px 0 16px; } .customCheck { display: inline-grid; @@ -217,7 +216,7 @@ top: 0; left: 0; &:hover { - background-color: $grey-4; + background-color: $grey-5; } &:after { content: ''; @@ -237,3 +236,12 @@ } } } +.footerSearchSection { + margin-bottom: 30px; + margin-right: 20px; + + a { + @include cn-bold-14; + font-weight: bold; + } +} diff --git a/src/app/structure-list/components/search/search.component.ts b/src/app/structure-list/components/search/search.component.ts index 259d6e208..8ce476264 100644 --- a/src/app/structure-list/components/search/search.component.ts +++ b/src/app/structure-list/components/search/search.component.ts @@ -18,7 +18,7 @@ export class SearchComponent implements OnInit { searchTerm: string = ''; // Button variable - modalType: string[] = ['services', 'modalite', 'plusFiltres']; + modalType: string[] = ['accompagnement', 'formations', 'plusFiltres']; // Modal variable categories: Category[]; @@ -77,8 +77,6 @@ export class SearchComponent implements OnInit { // Management of the checkbox event (Check / Uncheck) public onCheckboxChange(event, categ: string): void { const checkValue: number = parseInt(event.target.value); - console.log(checkValue); - if (event.target.checked) { this.checkedModules.push(new Module(checkValue, categ)); } else { @@ -117,6 +115,7 @@ export class SearchComponent implements OnInit { .replace(/[\s-]/g, ' ') .replace('?', ''); } + // Fake service api private mockService(module: Category[], titre: string, categ: any, nbCateg: number): void { let m = new Category(); diff --git a/src/app/structure-list/structure-list.component.html b/src/app/structure-list/structure-list.component.html index d9375a386..84d1d39ee 100644 --- a/src/app/structure-list/structure-list.component.html +++ b/src/app/structure-list/structure-list.component.html @@ -1,5 +1,7 @@ <div class="container"> - <app-structure-list-search (searchEvent)="fetchResults($event)"></app-structure-list-search> - <div class="divider"></div> - <app-structure-list-card [filter]="currentFilter"></app-structure-list-card> + <div class="content"> + <app-structure-list-search (searchEvent)="fetchResults($event)"></app-structure-list-search> + <div class="divider"></div> + <app-structure-list-card [filter]="currentFilter"></app-structure-list-card> + </div> </div> diff --git a/src/app/structure-list/structure-list.component.scss b/src/app/structure-list/structure-list.component.scss index 2d506b58d..fa639184d 100644 --- a/src/app/structure-list/structure-list.component.scss +++ b/src/app/structure-list/structure-list.component.scss @@ -7,5 +7,8 @@ } //En attendant de l'intégrer avec la map .container { - width: 320px; + width: 640px; + .content { + padding: 0 20px 0 20px; + } } diff --git a/src/assets/scss/_color.scss b/src/assets/scss/_color.scss index 2a650bee2..319c1008e 100644 --- a/src/assets/scss/_color.scss +++ b/src/assets/scss/_color.scss @@ -7,6 +7,7 @@ $grey-1: #333333; $grey-2: #eeeeee; $grey-3: #c3c3c3; $grey-4: #f2ecf2; +$grey-5: #f2f2f2; /* YELLOW */ $yellow: #f2cb04; $yellow-light: #fff8d6; diff --git a/src/assets/scss/_typography.scss b/src/assets/scss/_typography.scss index d21536e48..0fd92b3fc 100644 --- a/src/assets/scss/_typography.scss +++ b/src/assets/scss/_typography.scss @@ -1,4 +1,4 @@ -$text-font: 'Courier New', 'Helvetica', sans-serif; +$text-font: 'Trebuchet MS'; $footer-text-font: 'Arial', 'Helvetica', sans-serif; $title-font: 'Courier New', 'Helvetica', sans-serif; -- GitLab From bb2610f1965490ae2a0500431c384dcc7ed2bcf2 Mon Sep 17 00:00:00 2001 From: Jeremie BRISON <ext.sopra.jbrison@grandlyon.com> Date: Tue, 20 Oct 2020 13:48:47 +0200 Subject: [PATCH 25/50] fix(search) : fix modal responsive --- .../components/search/search.component.scss | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/app/structure-list/components/search/search.component.scss b/src/app/structure-list/components/search/search.component.scss index b6196462f..a8e53de50 100644 --- a/src/app/structure-list/components/search/search.component.scss +++ b/src/app/structure-list/components/search/search.component.scss @@ -1,6 +1,7 @@ @import '../../../../assets/scss/icons'; @import '../../../../assets/scss/color'; @import '../../../../assets/scss/typography'; +@import '../../../../assets/scss/breakpoint'; .header { .title { @@ -89,16 +90,24 @@ } } .modalformations { + @media #{$desktop} { + margin-left: 0; + } + margin-left: 206px; } .modalplusFiltres { + @media #{$desktop} { + margin-left: 0; + } margin-left: 412px; } .modal { -moz-box-shadow: -5px 5px 10px 0px $grey; box-shadow: -5px 5px 10px 0px $grey; max-height: 648px; - width: 754px; + max-width: 754px; + width: 94%; background: $white; border: 1px solid $grey; box-sizing: border-box; @@ -137,6 +146,11 @@ column-count: 2; column-gap: 46px; column-rule: dashed 1px $grey; + @media #{$large-phone} { + -moz-column-count: 1; + -webkit-column-count: 1; + column-count: 1; + } } .ligneFiltre { padding: 5px 0 5px 0; -- GitLab From 1ea159c97c5d118b0d7ac69e035d0f87437ef265 Mon Sep 17 00:00:00 2001 From: Jeremie BRISON <ext.sopra.jbrison@grandlyon.com> Date: Tue, 20 Oct 2020 13:52:37 +0200 Subject: [PATCH 26/50] fix(search) : change div to btn --- .../components/search/search.component.html | 18 +++++++++--------- .../components/search/search.component.scss | 2 +- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/app/structure-list/components/search/search.component.html b/src/app/structure-list/components/search/search.component.html index 730c6b49d..7df7b8806 100644 --- a/src/app/structure-list/components/search/search.component.html +++ b/src/app/structure-list/components/search/search.component.html @@ -11,8 +11,8 @@ </div> <div class="btnSection" fxLayout="row" fxLayoutAlign="space-between center"> - <div - class="button" + <button + type="button" [ngClass]="{ selected: modalTypeOpened === modalType[0] }" (click)="openModal(this.modalType[0])" fxLayout="row" @@ -20,9 +20,9 @@ > <span class="btnText">Accompagnement</span> <div class="arrow"></div> - </div> - <div - class="button" + </button> + <button + type="button" [ngClass]="{ selected: modalTypeOpened === modalType[1] }" (click)="openModal(this.modalType[1])" fxLayout="row" @@ -30,9 +30,9 @@ > <span class="btnText">Formations</span> <div class="arrow"></div> - </div> - <div - class="button" + </button> + <button + type="button" [ngClass]="{ selected: modalTypeOpened === modalType[2] }" (click)="openModal(this.modalType[2])" fxLayout="row" @@ -40,7 +40,7 @@ > <span class="btnText">Plus de filtres</span> <div class="arrow"></div> - </div> + </button> </div> <div *ngIf="modalTypeOpened" diff --git a/src/app/structure-list/components/search/search.component.scss b/src/app/structure-list/components/search/search.component.scss index a8e53de50..76dc8311b 100644 --- a/src/app/structure-list/components/search/search.component.scss +++ b/src/app/structure-list/components/search/search.component.scss @@ -47,7 +47,7 @@ } .btnSection { padding: 16px 0 8px 0; - .button { + button { height: 40px; width: 190px; outline: none; -- GitLab From 8aaf7497318ff2b0065c448da3989d053e145940 Mon Sep 17 00:00:00 2001 From: Jeremie BRISON <ext.sopra.jbrison@grandlyon.com> Date: Tue, 20 Oct 2020 16:44:18 +0200 Subject: [PATCH 27/50] fix(search) : fix label checkbox + fake data --- .../components/search/search.component.html | 4 +-- .../components/search/search.component.scss | 10 +++++-- .../components/search/search.component.ts | 26 ++++++++++++------- 3 files changed, 27 insertions(+), 13 deletions(-) diff --git a/src/app/structure-list/components/search/search.component.html b/src/app/structure-list/components/search/search.component.html index 7df7b8806..709182b53 100644 --- a/src/app/structure-list/components/search/search.component.html +++ b/src/app/structure-list/components/search/search.component.html @@ -65,8 +65,8 @@ (change)="onCheckboxChange($event, c.name)" /> <span class="customCheck"></span> + <div class="label">{{ module.text }}</div> </label> - <div class="label">{{ module.text }}</div> </div> </li> <span class="nbResult">{{ module.count ? module.count : '0' }}</span> @@ -86,8 +86,8 @@ <label> <input type="checkbox" /> <span class="customCheck"></span> + <div class="label">Pass numérique</div> </label> - <div class="label">Pass numérique</div> </div> </div> <a href="">Ajouter une structure</a> diff --git a/src/app/structure-list/components/search/search.component.scss b/src/app/structure-list/components/search/search.component.scss index 76dc8311b..160f8dffe 100644 --- a/src/app/structure-list/components/search/search.component.scss +++ b/src/app/structure-list/components/search/search.component.scss @@ -174,6 +174,7 @@ @include cn-bold-14; display: flex; align-items: center; + text-decoration: underline; } height: 32px; button { @@ -193,11 +194,11 @@ } .checkbox { .checkboxItem { - position: relative; + /*position: relative; display: inline-grid; align-items: center; grid-template-columns: min-content auto; - min-height: 25px; + min-height: 25px;*/ } list-style-type: none; input { @@ -212,7 +213,11 @@ } } label { + //display: inline-grid; + align-items: center; + grid-template-columns: min-content auto; display: inline-grid; + cursor: pointer; } .label { padding-left: 8px; @@ -257,5 +262,6 @@ a { @include cn-bold-14; font-weight: bold; + text-decoration: underline; } } diff --git a/src/app/structure-list/components/search/search.component.ts b/src/app/structure-list/components/search/search.component.ts index 8ce476264..2bc7ad008 100644 --- a/src/app/structure-list/components/search/search.component.ts +++ b/src/app/structure-list/components/search/search.component.ts @@ -89,6 +89,9 @@ export class SearchComponent implements OnInit { // Return index of a specific module in array modules public getIndex(id: number, categ: string): number { + console.log(this.checkedModules); + console.log(id); + console.log(categ); return this.checkedModules.findIndex((m: Module) => m.id === id && m.text === categ); } @@ -122,7 +125,7 @@ export class SearchComponent implements OnInit { m.name = titre; m.modules = []; for (let i = 0; i < nbCateg; i++) { - m.modules.push(new Module(categ.id, categ.name + i)); + m.modules.push(new Module(categ.id + i, categ.name + i)); } module.push(m); } @@ -130,7 +133,7 @@ export class SearchComponent implements OnInit { // Fake data private fakeData(option: string): void { if (option === this.modalType[0]) { - this.mockService(this.categories, 'Accompagnement des démarches', { name: 'CAF', id: '' }, 7); + this.mockService(this.categories, 'Accompagnement des démarches', { name: 'CAF', id: 5 }, 7); } else if (option === this.modalType[1]) { this.searchService.getCategories().subscribe((categories: Category[]) => { this.searchService @@ -143,13 +146,18 @@ export class SearchComponent implements OnInit { }); }); } else if (option === this.modalType[2]) { - this.mockService(this.categories, 'Équipements', 'Accès à des revues ou livres infoirmatiques numériques', 8); - this.mockService(this.categories, "Modalité d'accueil", 'Matériel mis à dispostion', 6); - - this.mockService(this.categories, "Type d'acteurs", 'Lieux de médiation (Pimms, assos...)', 5); - this.mockService(this.categories, 'Publics', 'Langues étrangères autres qu’anglais', 12); - this.mockService(this.categories, 'Labelisation', 'Prescripteur du Pass Numérique', 6); - this.mockService(this.categories, 'Type de structure', 'Espace de co-working', 6); + this.mockService( + this.categories, + 'Équipements', + { name: 'Accès à des revues ou livres infoirmatiques numériques', id: 1 }, + 8 + ); + this.mockService(this.categories, "Modalité d'accueil", { name: 'Matériel mis à dispostion', id: 2 }, 6); + + this.mockService(this.categories, "Type d'acteurs", { name: 'Lieux de médiation (Pimms, assos...)', id: 3 }, 5); + this.mockService(this.categories, 'Publics', { name: 'Langues étrangères autres qu’anglais', id: 4 }, 12); + this.mockService(this.categories, 'Labelisation', { name: 'Prescripteur du Pass Numérique', id: 5 }, 6); + this.mockService(this.categories, 'Type de structure', { name: 'Espace de co-working', id: 6 }, 6); } } } -- GitLab From 5f1db7c6b99d0343e5f726eda3e5518b4d6a6033 Mon Sep 17 00:00:00 2001 From: Jeremie BRISON <ext.sopra.jbrison@grandlyon.com> Date: Tue, 20 Oct 2020 17:38:22 +0200 Subject: [PATCH 28/50] fix(search) : fix submit search when press enter key --- .../components/search/search.component.html | 21 ++++++++++++------ .../components/search/search.component.ts | 22 ++++++++++--------- .../structure-list/structure-list.module.ts | 4 ++-- 3 files changed, 28 insertions(+), 19 deletions(-) diff --git a/src/app/structure-list/components/search/search.component.html b/src/app/structure-list/components/search/search.component.html index 709182b53..8f8826d2e 100644 --- a/src/app/structure-list/components/search/search.component.html +++ b/src/app/structure-list/components/search/search.component.html @@ -2,12 +2,19 @@ <span class="title">Acteurs de la médiation</span> </div> <div class="content" fxLayout="column"> - <div class="searchSection" fxLayout="row" fxLayoutGap="1.5vw"> - <div class="icon"> - <div class="ico-pin-search grey"></div> - </div> - <input type="text" [(ngModel)]="searchTerm" placeholder="Rechercher une adresse, une association..." /> - <button type="button" (click)="applyFilter()">Rechercher</button> + <div class="searchSection"> + <form + [formGroup]="searchForm" + fxLayout="row" + fxLayoutGap="1.5vw" + (ngSubmit)="applyFilter(searchForm.value.searchTerm)" + > + <div class="icon"> + <div class="ico-pin-search grey"></div> + </div> + <input type="text" formControlName="searchTerm" placeholder="Rechercher une adresse, une association..." /> + <button type="submit">Rechercher</button> + </form> </div> <div class="btnSection" fxLayout="row" fxLayoutAlign="space-between center"> @@ -76,7 +83,7 @@ </div> <div class="footer" fxLayout="row" fxLayoutAlign="end center" fxLayoutGap="3vw"> <a (click)="clearFilters()">Effacer</a> - <button type="button" (click)="applyFilter(modalTypeOpened)">Appliquer</button> + <button type="button" (click)="applyFilter(searchForm.value.searchTerm)">Appliquer</button> </div> </div> </div> diff --git a/src/app/structure-list/components/search/search.component.ts b/src/app/structure-list/components/search/search.component.ts index 2bc7ad008..a2c205d20 100644 --- a/src/app/structure-list/components/search/search.component.ts +++ b/src/app/structure-list/components/search/search.component.ts @@ -1,4 +1,6 @@ import { Component, EventEmitter, OnInit, Output } from '@angular/core'; +import { stringToKeyValue } from '@angular/flex-layout/extended/typings/style/style-transforms'; +import { FormBuilder, FormGroup } from '@angular/forms'; import { Category } from '../../models/category.model'; import { Filter } from '../../models/filter.model'; import { Module } from '../../models/module.model'; @@ -10,12 +12,16 @@ import { SearchService } from '../../services/search.service'; styleUrls: ['./search.component.scss'], }) export class SearchComponent implements OnInit { - constructor(private searchService: SearchService) {} + constructor(private searchService: SearchService, private fb: FormBuilder) { + this.searchForm = this.fb.group({ + searchTerm: '', + }); + } @Output() searchEvent = new EventEmitter(); - // Search input variable - searchTerm: string = ''; + // Form search input + searchForm: FormGroup; // Button variable modalType: string[] = ['accompagnement', 'formations', 'plusFiltres']; @@ -57,14 +63,13 @@ export class SearchComponent implements OnInit { } // Sends an array containing all filters - public applyFilter(): void { + public applyFilter(term: string): void { this.checkedModulesFilter = this.checkedModules.slice(); this.openModal(this.modalTypeOpened); - // Send search input filter let filters: Filter[] = []; - if (this.searchTerm) { - filters.push(new Filter('nom', this.searchTerm, false)); + if (term) { + filters.push(new Filter('nom', term, false)); } // Send checked box filter @@ -89,9 +94,6 @@ export class SearchComponent implements OnInit { // Return index of a specific module in array modules public getIndex(id: number, categ: string): number { - console.log(this.checkedModules); - console.log(id); - console.log(categ); return this.checkedModules.findIndex((m: Module) => m.id === id && m.text === categ); } diff --git a/src/app/structure-list/structure-list.module.ts b/src/app/structure-list/structure-list.module.ts index 9947bca5b..eac1b0ac0 100644 --- a/src/app/structure-list/structure-list.module.ts +++ b/src/app/structure-list/structure-list.module.ts @@ -5,11 +5,11 @@ import { CardComponent } from './components/card/card.component'; import { SearchComponent } from './components/search/search.component'; import { HttpClientModule } from '@angular/common/http'; import { FlexLayoutModule } from '@angular/flex-layout'; -import { FormsModule } from '@angular/forms'; +import { FormsModule, ReactiveFormsModule } from '@angular/forms'; @NgModule({ declarations: [StructureListComponent, CardComponent, SearchComponent], - imports: [CommonModule, HttpClientModule, FlexLayoutModule, FormsModule], + imports: [CommonModule, HttpClientModule, FlexLayoutModule, FormsModule, ReactiveFormsModule], exports: [StructureListComponent], }) export class StructureListModule {} -- GitLab From 49defde1d759b866cd5ddff5507e43cef6f200c7 Mon Sep 17 00:00:00 2001 From: Jeremie BRISON <ext.sopra.jbrison@grandlyon.com> Date: Wed, 21 Oct 2020 10:59:40 +0200 Subject: [PATCH 29/50] fix(search) : add some test + fix design modal --- debug.log | 1 + .../components/search/search.component.html | 61 +++++++++++-------- .../components/search/search.component.scss | 16 +++-- .../search/search.component.spec.ts | 28 ++++++++- .../services/search.service.spec.ts | 6 +- .../services/structure-list.service.spec.ts | 12 ++-- 6 files changed, 83 insertions(+), 41 deletions(-) create mode 100644 debug.log diff --git a/debug.log b/debug.log new file mode 100644 index 000000000..e4874e229 --- /dev/null +++ b/debug.log @@ -0,0 +1 @@ +[1021/094448.838:ERROR:directory_reader_win.cc(43)] FindFirstFile: Le chemin d’accès spécifié est introuvable. (0x3) diff --git a/src/app/structure-list/components/search/search.component.html b/src/app/structure-list/components/search/search.component.html index 8f8826d2e..f59c9ba93 100644 --- a/src/app/structure-list/components/search/search.component.html +++ b/src/app/structure-list/components/search/search.component.html @@ -55,35 +55,42 @@ fxLayoutAlign="space-between" [ngClass]="['modal', 'modal' + modalTypeOpened]" > - <div class="contentModal" fxLayout="row wrap" fxLayoutAlign="flex-start" *ngIf="categories.length > 0"> - <!--<div class="blockFiltre" *ngFor="let s of services">--> - <div class="blockFiltre" *ngFor="let c of categories"> - <h4>{{ c.name }}</h4> + <div class="borderTricks"> + <div class="contentModal" fxLayout="row wrap" fxLayoutAlign="flex-start" *ngIf="categories.length > 0"> + <!--<div class="blockFiltre" *ngFor="let s of services">--> + <div class="blockFiltre" *ngFor="let c of categories"> + <h4>{{ c.name }}</h4> - <ul class="blockLigne"> - <div fxLayout="row" class="ligneFiltre" fxLayoutAlign="space-between center" *ngFor="let module of c.modules"> - <li class="checkbox"> - <div class="checkboxItem"> - <label> - <input - type="checkbox" - [checked]="getIndex(module.id, c.name) > -1" - [value]="module.id" - (change)="onCheckboxChange($event, c.name)" - /> - <span class="customCheck"></span> - <div class="label">{{ module.text }}</div> - </label> - </div> - </li> - <span class="nbResult">{{ module.count ? module.count : '0' }}</span> - </div> - </ul> + <ul class="blockLigne"> + <div + fxLayout="row" + class="ligneFiltre" + fxLayoutAlign="space-between center" + *ngFor="let module of c.modules" + > + <li class="checkbox"> + <div class="checkboxItem"> + <label> + <input + type="checkbox" + [checked]="getIndex(module.id, c.name) > -1" + [value]="module.id" + (change)="onCheckboxChange($event, c.name)" + /> + <span class="customCheck"></span> + <div class="label">{{ module.text }}</div> + </label> + </div> + </li> + <span class="nbResult">{{ module.count ? module.count : '0' }}</span> + </div> + </ul> + </div> + </div> + <div class="footer" fxLayout="row" fxLayoutAlign="end center" fxLayoutGap="3vw"> + <a (click)="clearFilters()">Effacer</a> + <button type="button" (click)="applyFilter(searchForm.value.searchTerm)">Appliquer</button> </div> - </div> - <div class="footer" fxLayout="row" fxLayoutAlign="end center" fxLayoutGap="3vw"> - <a (click)="clearFilters()">Effacer</a> - <button type="button" (click)="applyFilter(searchForm.value.searchTerm)">Appliquer</button> </div> </div> </div> diff --git a/src/app/structure-list/components/search/search.component.scss b/src/app/structure-list/components/search/search.component.scss index 160f8dffe..e15560478 100644 --- a/src/app/structure-list/components/search/search.component.scss +++ b/src/app/structure-list/components/search/search.component.scss @@ -103,13 +103,18 @@ margin-left: 412px; } .modal { - -moz-box-shadow: -5px 5px 10px 0px $grey; - box-shadow: -5px 5px 10px 0px $grey; max-height: 648px; max-width: 754px; width: 94%; background: $white; - border: 1px solid $grey; + border-left: 6.5px solid transparent; + border-bottom: 6.5px solid transparent; + border-radius: 11px; + //repeating-linear-gradient(37deg, transparent 0, transparent 1px, $grey 2px, $grey 2px) 12; + //border-image: repeating-linear-gradient(-45deg, transparent 0, transparent 4px, $grey 4px, $grey 5px) 8; + + background: linear-gradient($white, $white) padding-box, + repeating-linear-gradient(-45deg, transparent 0, transparent 4px, $grey 4px, $grey 5px) border-box; box-sizing: border-box; z-index: 1; position: absolute; @@ -125,12 +130,15 @@ background: $grey; border-radius: 6px; } - + .borderTricks { + border: 1px solid #e0e0e0; + } .contentModal { overflow-y: auto; max-width: 1100px; border-bottom: 1px solid $grey; margin-bottom: 10px; + max-height: 500px; .blockFiltre { width: 100%; 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 56e05f1d6..62c81724c 100644 --- a/src/app/structure-list/components/search/search.component.spec.ts +++ b/src/app/structure-list/components/search/search.component.spec.ts @@ -1,14 +1,20 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; - +import { ReactiveFormsModule } from '@angular/forms'; +import { Category } from '../../models/category.model'; +import { Filter } from '../../models/filter.model'; +import { Module } from '../../models/module.model'; +import { HttpClientTestingModule } from '@angular/common/http/testing'; import { SearchComponent } from './search.component'; +import { SearchService } from '../../services/search.service'; -describe('RechercheComponent', () => { +describe('SearchComponent', () => { let component: SearchComponent; let fixture: ComponentFixture<SearchComponent>; beforeEach(async () => { await TestBed.configureTestingModule({ declarations: [SearchComponent], + imports: [HttpClientTestingModule, ReactiveFormsModule], }).compileComponents(); }); @@ -21,4 +27,22 @@ describe('RechercheComponent', () => { it('should create', () => { expect(component).toBeTruthy(); }); + + it('should emit filters', () => { + const filter: Filter[] = [new Filter('nom', 'valInput', false)]; + spyOn(component.searchEvent, 'emit'); + component.applyFilter('valInput'); + expect(component.searchEvent.emit).toHaveBeenCalled(); + expect(component.searchEvent.emit).toHaveBeenCalledWith(filter); + }); + + it('should update categories', () => { + let categories: Category[] = [new Category({ name: 'Accompagnement des démarches' })]; + categories[0].modules = []; + for (let i = 0; i < 7; i++) { + categories[0].modules.push(new Module(5 + i, 'CAF' + i)); + } + component.openModal('accompagnement'); + expect(component.categories).toEqual(categories); + }); }); diff --git a/src/app/structure-list/services/search.service.spec.ts b/src/app/structure-list/services/search.service.spec.ts index 23c42c7bb..d8b757560 100644 --- a/src/app/structure-list/services/search.service.spec.ts +++ b/src/app/structure-list/services/search.service.spec.ts @@ -1,12 +1,14 @@ import { TestBed } from '@angular/core/testing'; - +import { HttpClientTestingModule } from '@angular/common/http/testing'; import { SearchService } from './search.service'; describe('SearchService', () => { let service: SearchService; beforeEach(() => { - TestBed.configureTestingModule({}); + TestBed.configureTestingModule({ + imports: [HttpClientTestingModule], + }); service = TestBed.inject(SearchService); }); diff --git a/src/app/structure-list/services/structure-list.service.spec.ts b/src/app/structure-list/services/structure-list.service.spec.ts index 243602d45..230f2e331 100644 --- a/src/app/structure-list/services/structure-list.service.spec.ts +++ b/src/app/structure-list/services/structure-list.service.spec.ts @@ -1,4 +1,4 @@ -import { HttpClientModule } from '@angular/common/http'; +import { HttpClientTestingModule } from '@angular/common/http/testing'; import { inject, TestBed } from '@angular/core/testing'; import { Day } from '../models/day.model'; import { Structure } from '../models/structure.model'; @@ -7,15 +7,15 @@ import { StructureService } from './structure-list.service'; const { DateTime } = require('luxon'); describe('StructureService', () => { + let structureService: StructureService; + beforeEach(() => { TestBed.configureTestingModule({ - imports: [HttpClientModule], + imports: [HttpClientTestingModule], + providers: [StructureService], }); + structureService = TestBed.inject(StructureService); }); - let structureService: StructureService; - beforeEach(inject([StructureService], (s: StructureService) => { - structureService = s; - })); it('Mise à jour ouverture de la structure : should return true', () => { // Init structure avec aucun horaire -- GitLab From 6510c5e4049ffdc729488a97bddb5b0c3ac807b5 Mon Sep 17 00:00:00 2001 From: Jeremie BRISON <ext.sopra.jbrison@grandlyon.com> Date: Wed, 21 Oct 2020 15:34:16 +0200 Subject: [PATCH 30/50] fix merge --- src/app/app.module.ts | 16 +++++++++++++--- src/app/home/home.component.ts | 11 ++++++++++- .../components/search/search.component.scss | 4 +++- .../components/search/search.component.ts | 2 +- .../structure-list/structure-list.component.scss | 13 +++++++------ src/app/structure-list/structure-list.scss | 10 ---------- 6 files changed, 34 insertions(+), 22 deletions(-) delete mode 100644 src/app/structure-list/structure-list.scss diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 7cb7bc0d7..4934e7b00 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -12,9 +12,10 @@ import { FooterComponent } from './footer/footer.component'; import { HeaderComponent } from './header/header.component'; import { SharedModule } from './shared/shared.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'; +import { FormsModule, ReactiveFormsModule } from '@angular/forms'; +import { SearchComponent } from './structure-list/components/search/search.component'; @NgModule({ declarations: [ @@ -24,9 +25,18 @@ import { CardComponent } from './structure-list/components/card/card.component'; HomeComponent, StructureListComponent, CardComponent, - RechercheComponent, + SearchComponent, + ], + imports: [ + BrowserModule, + HttpClientModule, + AppRoutingModule, + FlexLayoutModule, + SharedModule, + MapModule, + FormsModule, + ReactiveFormsModule, ], - imports: [BrowserModule, HttpClientModule, AppRoutingModule, FlexLayoutModule, SharedModule, MapModule], providers: [{ provide: LOCALE_ID, useValue: 'fr' }, CustomBreakPointsProvider], bootstrap: [AppComponent], }) diff --git a/src/app/home/home.component.ts b/src/app/home/home.component.ts index 2264953e0..1c41605d4 100644 --- a/src/app/home/home.component.ts +++ b/src/app/home/home.component.ts @@ -2,6 +2,7 @@ import { Component, OnInit } from '@angular/core'; import { mergeMap } from 'rxjs/operators'; import { Structure } from '../models/structure.model'; import { StructureService } from '../services/structure-list.service'; +import { Filter } from '../structure-list/models/filter.model'; const { DateTime } = require('luxon'); @Component({ @@ -14,7 +15,15 @@ export class HomeComponent implements OnInit { constructor(private structureService: StructureService) {} ngOnInit(): void { - this.structureService.getStructures().subscribe((structures) => { + this.structureService.getStructures(null).subscribe((structures) => { + this.structures = structures.map((structure) => + this.structureService.updateOpeningStructure(structure, DateTime.local()) + ); + }); + } + + fetchResults(filters: Filter[]) { + this.structureService.getStructures(filters).subscribe((structures) => { this.structures = structures.map((structure) => this.structureService.updateOpeningStructure(structure, DateTime.local()) ); diff --git a/src/app/structure-list/components/search/search.component.scss b/src/app/structure-list/components/search/search.component.scss index e15560478..b904c1283 100644 --- a/src/app/structure-list/components/search/search.component.scss +++ b/src/app/structure-list/components/search/search.component.scss @@ -110,11 +110,14 @@ border-left: 6.5px solid transparent; border-bottom: 6.5px solid transparent; border-radius: 11px; + z-index: 401 !important; + //repeating-linear-gradient(37deg, transparent 0, transparent 1px, $grey 2px, $grey 2px) 12; //border-image: repeating-linear-gradient(-45deg, transparent 0, transparent 4px, $grey 4px, $grey 5px) 8; background: linear-gradient($white, $white) padding-box, repeating-linear-gradient(-45deg, transparent 0, transparent 4px, $grey 4px, $grey 5px) border-box; + //repeating-linear-gradient(-51deg, transparent 0, transparent 1px, $grey 1px, $grey 2px) border-box; box-sizing: border-box; z-index: 1; position: absolute; @@ -139,7 +142,6 @@ border-bottom: 1px solid $grey; margin-bottom: 10px; max-height: 500px; - .blockFiltre { width: 100%; padding: 32px 40px 10px 40px; diff --git a/src/app/structure-list/components/search/search.component.ts b/src/app/structure-list/components/search/search.component.ts index a2c205d20..778430893 100644 --- a/src/app/structure-list/components/search/search.component.ts +++ b/src/app/structure-list/components/search/search.component.ts @@ -69,7 +69,7 @@ export class SearchComponent implements OnInit { // Send search input filter let filters: Filter[] = []; if (term) { - filters.push(new Filter('nom', term, false)); + filters.push(new Filter('nomDeVotreStructure', term, false)); } // Send checked box filter diff --git a/src/app/structure-list/structure-list.component.scss b/src/app/structure-list/structure-list.component.scss index fa639184d..3be0db3da 100644 --- a/src/app/structure-list/structure-list.component.scss +++ b/src/app/structure-list/structure-list.component.scss @@ -1,14 +1,15 @@ @import '../../assets/scss/color'; +@import '../../assets/scss/icons'; +@import '../../assets/scss/typography'; .divider { width: 100%; height: 1px; background-color: $grey-4; } -//En attendant de l'intégrer avec la map -.container { - width: 640px; - .content { - padding: 0 20px 0 20px; - } +.nbStructuresLabel { + color: $grey; + @include cn-regular-16; + display: flex; + align-items: center; } diff --git a/src/app/structure-list/structure-list.scss b/src/app/structure-list/structure-list.scss deleted file mode 100644 index 68c10dffe..000000000 --- a/src/app/structure-list/structure-list.scss +++ /dev/null @@ -1,10 +0,0 @@ -@import '../../assets/scss/icons'; -@import '../../assets/scss/color'; -@import '../../assets/scss/typography'; - -.nbStructuresLabel { - color: $grey; - @include cn-regular-16; - display: flex; - align-items: center; -} -- GitLab From 91e9f74a88010c7db5ad1a6f6e823f289aff1615 Mon Sep 17 00:00:00 2001 From: Jeremie BRISON <ext.sopra.jbrison@grandlyon.com> Date: Wed, 21 Oct 2020 17:42:38 +0200 Subject: [PATCH 31/50] fix(search) : set scroll bar to list structures + fix test --- src/app/app.component.scss | 4 ++-- src/app/footer/footer.component.scss | 1 + src/app/header/header.component.scss | 1 + src/app/home/home.component.html | 3 ++- src/app/home/home.component.scss | 5 ++--- .../components/search/search.component.spec.ts | 2 +- .../structure-list/structure-list.component.html | 13 +++++++++---- .../structure-list/structure-list.component.scss | 7 +++++++ 8 files changed, 25 insertions(+), 11 deletions(-) diff --git a/src/app/app.component.scss b/src/app/app.component.scss index 4f5c46104..803b77c89 100644 --- a/src/app/app.component.scss +++ b/src/app/app.component.scss @@ -10,8 +10,8 @@ } .app-body { - flex: 1 0 auto; - overflow-y: auto; + flex: 1 1 auto; + overflow-y: hidden; overflow-x: hidden; position: relative; } diff --git a/src/app/footer/footer.component.scss b/src/app/footer/footer.component.scss index 038add29a..008df688f 100644 --- a/src/app/footer/footer.component.scss +++ b/src/app/footer/footer.component.scss @@ -10,6 +10,7 @@ align-items: center !important; justify-content: space-between !important; padding: 0px 4vw; + flex: 0 0 auto; a { color: $white; margin: 0 10px 0 12px; diff --git a/src/app/header/header.component.scss b/src/app/header/header.component.scss index f22e53e19..6dfdc3889 100644 --- a/src/app/header/header.component.scss +++ b/src/app/header/header.component.scss @@ -11,6 +11,7 @@ justify-content: space-between; padding: 0px 0 0 4vw; text-align: center; + flex: 0 0 auto; a { &.active { @include highlight; diff --git a/src/app/home/home.component.html b/src/app/home/home.component.html index 39a5681a1..930a43cf2 100644 --- a/src/app/home/home.component.html +++ b/src/app/home/home.component.html @@ -1,8 +1,9 @@ -<div fxLayout="row"> +<div fxLayout="row" style="height: 100%"> <app-structure-list (searchEvent)="fetchResults($event)" [structureList]="structures" class="left-pane" + fxLayout="column" ></app-structure-list> <app-map [structures]="structures" fxFlex="100"></app-map> </div> diff --git a/src/app/home/home.component.scss b/src/app/home/home.component.scss index 1a2d33f8e..f2884d25f 100644 --- a/src/app/home/home.component.scss +++ b/src/app/home/home.component.scss @@ -1,5 +1,4 @@ .left-pane { - padding: 0 25px; - width: 590px; - min-width: 590px; + width: 640px; + min-width: 640px; } 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 62c81724c..790ae3595 100644 --- a/src/app/structure-list/components/search/search.component.spec.ts +++ b/src/app/structure-list/components/search/search.component.spec.ts @@ -29,7 +29,7 @@ describe('SearchComponent', () => { }); it('should emit filters', () => { - const filter: Filter[] = [new Filter('nom', 'valInput', false)]; + const filter: Filter[] = [new Filter('nomDeVotreStructure', 'valInput', false)]; spyOn(component.searchEvent, 'emit'); component.applyFilter('valInput'); expect(component.searchEvent.emit).toHaveBeenCalled(); diff --git a/src/app/structure-list/structure-list.component.html b/src/app/structure-list/structure-list.component.html index 030bcf353..e0de815ee 100644 --- a/src/app/structure-list/structure-list.component.html +++ b/src/app/structure-list/structure-list.component.html @@ -1,4 +1,9 @@ -<app-structure-list-search (searchEvent)="fetchResults($event)"></app-structure-list-search> -<div class="divider"></div> -<span class="nbStructuresLabel">{{ structureList.length }} structures</span> -<app-card *ngFor="let structure of structureList" [structure]="structure"></app-card> +<div class="topBlock"> + <app-structure-list-search (searchEvent)="fetchResults($event)"></app-structure-list-search> + <div class="divider"></div> + <span class="nbStructuresLabel">{{ structureList.length }} structures</span> +</div> + +<div class="listCard"> + <app-card *ngFor="let structure of structureList" [structure]="structure"></app-card> +</div> diff --git a/src/app/structure-list/structure-list.component.scss b/src/app/structure-list/structure-list.component.scss index 3be0db3da..5b09b7ee8 100644 --- a/src/app/structure-list/structure-list.component.scss +++ b/src/app/structure-list/structure-list.component.scss @@ -13,3 +13,10 @@ display: flex; align-items: center; } +.listCard { + overflow-y: auto; + padding: 0 25px; +} +.topBlock { + padding: 0 25px; +} -- GitLab From ec70e6e11f866e22a5d7fe508b10ae66833a5f22 Mon Sep 17 00:00:00 2001 From: Hugo SUBTIL <ext.sopra.husubtil@grandlyon.com> Date: Mon, 26 Oct 2020 12:11:25 +0100 Subject: [PATCH 32/50] fix: small fix --- debug.log | 1 - src/app/home/home.component.ts | 2 +- src/app/services/structure-list.service.ts | 25 +++++++++---------- .../structure-list/models/category.model.ts | 4 ++- 4 files changed, 16 insertions(+), 16 deletions(-) delete mode 100644 debug.log diff --git a/debug.log b/debug.log deleted file mode 100644 index e4874e229..000000000 --- a/debug.log +++ /dev/null @@ -1 +0,0 @@ -[1021/094448.838:ERROR:directory_reader_win.cc(43)] FindFirstFile: Le chemin d’accès spécifié est introuvable. (0x3) diff --git a/src/app/home/home.component.ts b/src/app/home/home.component.ts index 1c41605d4..090ae1018 100644 --- a/src/app/home/home.component.ts +++ b/src/app/home/home.component.ts @@ -22,7 +22,7 @@ export class HomeComponent implements OnInit { }); } - fetchResults(filters: Filter[]) { + public fetchResults(filters: Filter[]): void { this.structureService.getStructures(filters).subscribe((structures) => { this.structures = structures.map((structure) => this.structureService.updateOpeningStructure(structure, DateTime.local()) diff --git a/src/app/services/structure-list.service.ts b/src/app/services/structure-list.service.ts index 745a69a54..9f2425166 100644 --- a/src/app/services/structure-list.service.ts +++ b/src/app/services/structure-list.service.ts @@ -18,35 +18,34 @@ export class StructureService { constructor(private http: HttpClient) {} public getStructures(filters: Filter[]): Observable<Structure[]> { - console.log(this.constructApi(filters)); return this.http - .get('/api/Structures?' + this.constructApi(filters)) + .get('/api/Structures?' + this.constructSearchRequest(filters)) .pipe(map((data: any[]) => data.map((item) => new Structure(item)))); } - private constructApi(filters: Filter[]): string { - let api: string = ''; + private constructSearchRequest(filters: Filter[]): string { + let requestParam = ''; if (filters) { filters.forEach((filter) => { - if (api) { - api = api + '&'; + if (requestParam) { + requestParam = requestParam + '&'; } if (filter.isStrict) { - if (api.includes(filter.name)) { - api = api + '=' + filter.value; + if (requestParam.includes(filter.name)) { + requestParam = requestParam + '=' + filter.value; } else { - api = api + filter.name + '=' + filter.value; + requestParam = requestParam + filter.name + '=' + filter.value; } } else { - if (api.includes(filter.name)) { - api = api + filter.value; + if (requestParam.includes(filter.name)) { + requestParam = requestParam + filter.value; } else { - api = api + filter.name + '_like=' + filter.value; + requestParam = requestParam + filter.name + '_like=' + filter.value; } } }); } - return api; + return requestParam; } /** diff --git a/src/app/structure-list/models/category.model.ts b/src/app/structure-list/models/category.model.ts index cb5a96eee..0ffaec8dc 100644 --- a/src/app/structure-list/models/category.model.ts +++ b/src/app/structure-list/models/category.model.ts @@ -5,6 +5,8 @@ export class Category { modules: Module[]; constructor(obj?: any) { - Object.assign(this, obj); + Object.assign(this, obj, { + modules: obj && obj.modules ? obj.modules.map((module) => new Module(module.id, module.text)) : null, + }); } } -- GitLab From c32212be2a853cdd5649242341cc8fec9446daf7 Mon Sep 17 00:00:00 2001 From: Hugo SUBTIL <ext.sopra.husubtil@grandlyon.com> Date: Mon, 26 Oct 2020 12:11:56 +0100 Subject: [PATCH 33/50] fix: search component code --- .../structure-list/components/search/search.component.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/app/structure-list/components/search/search.component.ts b/src/app/structure-list/components/search/search.component.ts index 778430893..aa70de956 100644 --- a/src/app/structure-list/components/search/search.component.ts +++ b/src/app/structure-list/components/search/search.component.ts @@ -67,7 +67,7 @@ export class SearchComponent implements OnInit { this.checkedModulesFilter = this.checkedModules.slice(); this.openModal(this.modalTypeOpened); // Send search input filter - let filters: Filter[] = []; + const filters: Filter[] = []; if (term) { filters.push(new Filter('nomDeVotreStructure', term, false)); } @@ -81,7 +81,7 @@ export class SearchComponent implements OnInit { // Management of the checkbox event (Check / Uncheck) public onCheckboxChange(event, categ: string): void { - const checkValue: number = parseInt(event.target.value); + const checkValue: number = parseInt(event.target.value, 10); if (event.target.checked) { this.checkedModules.push(new Module(checkValue, categ)); } else { @@ -101,8 +101,9 @@ export class SearchComponent implements OnInit { public clearFilters(): void { this.categories.forEach((categ: Category) => { categ.modules.forEach((module: Module) => { - if (this.getIndex(module.id, categ.name) > -1) + if (this.getIndex(module.id, categ.name) > -1) { this.checkedModules.splice(this.getIndex(module.id, categ.name), 1); + } }); }); } @@ -155,7 +156,6 @@ export class SearchComponent implements OnInit { 8 ); this.mockService(this.categories, "Modalité d'accueil", { name: 'Matériel mis à dispostion', id: 2 }, 6); - this.mockService(this.categories, "Type d'acteurs", { name: 'Lieux de médiation (Pimms, assos...)', id: 3 }, 5); this.mockService(this.categories, 'Publics', { name: 'Langues étrangères autres qu’anglais', id: 4 }, 12); this.mockService(this.categories, 'Labelisation', { name: 'Prescripteur du Pass Numérique', id: 5 }, 6); -- GitLab From 3d45ba5323372d4b5241ec5313ff1c36f5e6af1a Mon Sep 17 00:00:00 2001 From: Hugo SUBTIL <ext.sopra.husubtil@grandlyon.com> Date: Tue, 27 Oct 2020 10:48:27 +0100 Subject: [PATCH 34/50] fix: improve border style --- .../components/search/search.component.html | 3 +-- .../components/search/search.component.scss | 19 +++++------------- src/assets/scss/_shapes.scss | 20 +++++++++++++++++++ 3 files changed, 26 insertions(+), 16 deletions(-) diff --git a/src/app/structure-list/components/search/search.component.html b/src/app/structure-list/components/search/search.component.html index f59c9ba93..68ef0abfa 100644 --- a/src/app/structure-list/components/search/search.component.html +++ b/src/app/structure-list/components/search/search.component.html @@ -55,9 +55,8 @@ fxLayoutAlign="space-between" [ngClass]="['modal', 'modal' + modalTypeOpened]" > - <div class="borderTricks"> + <div class="body-wrap"> <div class="contentModal" fxLayout="row wrap" fxLayoutAlign="flex-start" *ngIf="categories.length > 0"> - <!--<div class="blockFiltre" *ngFor="let s of services">--> <div class="blockFiltre" *ngFor="let c of categories"> <h4>{{ c.name }}</h4> diff --git a/src/app/structure-list/components/search/search.component.scss b/src/app/structure-list/components/search/search.component.scss index b904c1283..5b8230750 100644 --- a/src/app/structure-list/components/search/search.component.scss +++ b/src/app/structure-list/components/search/search.component.scss @@ -2,6 +2,7 @@ @import '../../../../assets/scss/color'; @import '../../../../assets/scss/typography'; @import '../../../../assets/scss/breakpoint'; +@import '../../../../assets/scss/shapes'; .header { .title { @@ -106,23 +107,16 @@ max-height: 648px; max-width: 754px; width: 94%; - background: $white; border-left: 6.5px solid transparent; border-bottom: 6.5px solid transparent; border-radius: 11px; z-index: 401 !important; - - //repeating-linear-gradient(37deg, transparent 0, transparent 1px, $grey 2px, $grey 2px) 12; - //border-image: repeating-linear-gradient(-45deg, transparent 0, transparent 4px, $grey 4px, $grey 5px) 8; - - background: linear-gradient($white, $white) padding-box, - repeating-linear-gradient(-45deg, transparent 0, transparent 4px, $grey 4px, $grey 5px) border-box; - //repeating-linear-gradient(-51deg, transparent 0, transparent 1px, $grey 1px, $grey 2px) border-box; - box-sizing: border-box; - z-index: 1; + margin: 8px 8px 0 0; position: absolute; margin-top: 96px; - + border: 1px solid $grey-5; + border-radius: 6px; + @include background-hash; ::-webkit-scrollbar { width: 10px; } @@ -133,9 +127,6 @@ background: $grey; border-radius: 6px; } - .borderTricks { - border: 1px solid #e0e0e0; - } .contentModal { overflow-y: auto; max-width: 1100px; diff --git a/src/assets/scss/_shapes.scss b/src/assets/scss/_shapes.scss index 21c498f05..22281d819 100644 --- a/src/assets/scss/_shapes.scss +++ b/src/assets/scss/_shapes.scss @@ -33,3 +33,23 @@ $mat-tab-shadow: 0px 2px 7px rgba(0, 0, 0, 0.25); background-repeat: no-repeat; background-position-y: 12px; } + +@mixin background-hash { + background: linear-gradient( + -45deg, + $grey 2.5%, + $white 2.5%, + $white 47.5%, + $grey 47.5%, + $grey 52.5%, + $white 52.5%, + $white 97.5%, + $grey 97.5% + ); + background-size: 5px 5px; + background-position: 25px 25px; + padding: 0 0 8px 8px; + .body-wrap { + background-color: $white; + } +} -- GitLab From d27fbaccd36deffb1c87e99aa1f1299d4b27e147 Mon Sep 17 00:00:00 2001 From: Hugo SUBTIL <ext.sopra.husubtil@grandlyon.com> Date: Wed, 28 Oct 2020 15:40:27 +0100 Subject: [PATCH 35/50] fix: dockerfile --- Dockerfile | 1 + 1 file changed, 1 insertion(+) diff --git a/Dockerfile b/Dockerfile index de073df46..6cc3c3cac 100644 --- a/Dockerfile +++ b/Dockerfile @@ -28,6 +28,7 @@ FROM nginx:1.16.0-alpine # copy artifact build from the 'build environment' COPY --from=build /app/dist/fr /usr/share/nginx/html +COPY --from=build /app/dist/fr /usr/share/nginx/html/fr RUN touch /var/run/nginx.pid -- GitLab From 59522f66145b3667f4c145f9e8145de915894982 Mon Sep 17 00:00:00 2001 From: Hugo SUBTIL <ext.sopra.husubtil@grandlyon.com> Date: Wed, 28 Oct 2020 15:49:44 +0100 Subject: [PATCH 36/50] fix: fix background shape style --- src/app/map/components/map.component.scss | 1 - src/assets/scss/_shapes.scss | 8 ++++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/app/map/components/map.component.scss b/src/app/map/components/map.component.scss index d12f41e83..c91352723 100644 --- a/src/app/map/components/map.component.scss +++ b/src/app/map/components/map.component.scss @@ -11,7 +11,6 @@ #map { height: calc(100vh - #{$header-height} - #{$footer-height} - 50px); - width: 100%; border: 10px solid white; border-radius: 6px; } diff --git a/src/assets/scss/_shapes.scss b/src/assets/scss/_shapes.scss index 164a637b1..fec384566 100644 --- a/src/assets/scss/_shapes.scss +++ b/src/assets/scss/_shapes.scss @@ -37,14 +37,14 @@ $mat-tab-shadow: 0px 2px 7px rgba(0, 0, 0, 0.25); @mixin background-hash { background: linear-gradient( -45deg, - $grey 2.5%, + $grey-2 2.5%, $white 2.5%, $white 47.5%, - $grey 47.5%, - $grey 52.5%, + $grey-2 47.5%, + $grey-2 52.5%, $white 52.5%, $white 97.5%, - $grey 97.5% + $grey-2 97.5% ); background-size: 5px 5px; background-position: 25px 25px; -- GitLab From 8b3bd921778fd2c18dd4a1ec6e28894a757a094b Mon Sep 17 00:00:00 2001 From: Hugo SUBTIL <ext.sopra.husubtil@grandlyon.com> Date: Fri, 30 Oct 2020 19:59:31 +0100 Subject: [PATCH 37/50] fix: tooltip status issue --- src/app/map/components/map.component.ts | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/app/map/components/map.component.ts b/src/app/map/components/map.component.ts index 08bacc687..81b35c455 100644 --- a/src/app/map/components/map.component.ts +++ b/src/app/map/components/map.component.ts @@ -74,7 +74,15 @@ export class MapComponent implements OnChanges { * @param structure Structure */ private buildToolTip(structure: Structure): string { - const cssAvailabilityClass = structure.isOpen ? 'available' : 'unavailable'; + let cssAvailabilityClass = structure.isOpen ? 'available' : null; + if (cssAvailabilityClass === null) { + if (structure.openedOn.day) { + cssAvailabilityClass = 'unavailable'; + } else { + cssAvailabilityClass = 'unknown'; + } + } + return ( '<h1>' + structure.nomDeVotreStructure + -- GitLab From 7d6177ad2402f84c148922663ed21ad96b125296 Mon Sep 17 00:00:00 2001 From: Hugo SUBTIL <ext.sopra.husubtil@grandlyon.com> Date: Fri, 30 Oct 2020 22:28:00 +0100 Subject: [PATCH 38/50] feat: add address on strucutre details --- src/app/home/home.component.ts | 1 + src/app/map/models/geoJsonProperties.model.ts | 7 +++++++ src/app/map/models/geojson.model.ts | 3 ++- src/app/models/structure.model.ts | 1 + .../structure-details/structure-details.component.html | 2 +- 5 files changed, 12 insertions(+), 2 deletions(-) create mode 100644 src/app/map/models/geoJsonProperties.model.ts diff --git a/src/app/home/home.component.ts b/src/app/home/home.component.ts index 6630be72c..e198b3374 100644 --- a/src/app/home/home.component.ts +++ b/src/app/home/home.component.ts @@ -52,6 +52,7 @@ export class HomeComponent implements OnInit { private getStructurePosition(structure: Structure): Promise<Structure> { return new Promise((resolve, reject) => { this.getCoord(structure.voie).subscribe((coord: GeoJson) => { + structure.address = coord.properties.name + ' - ' + coord.properties.postcode + ' ' + coord.properties.city; structure.distance = this.geoJsonService.getDistance( coord.geometry.getLon(), coord.geometry.getLat(), diff --git a/src/app/map/models/geoJsonProperties.model.ts b/src/app/map/models/geoJsonProperties.model.ts new file mode 100644 index 000000000..fc9abed8d --- /dev/null +++ b/src/app/map/models/geoJsonProperties.model.ts @@ -0,0 +1,7 @@ +export class GeoJsonProperties { + public city: string; + public country: string; + public name: string; + public postcode: string; + public state: string; +} diff --git a/src/app/map/models/geojson.model.ts b/src/app/map/models/geojson.model.ts index 3407c70da..8ca263895 100644 --- a/src/app/map/models/geojson.model.ts +++ b/src/app/map/models/geojson.model.ts @@ -1,9 +1,10 @@ import { AddressGeometry } from './addressGeometry.model'; +import { GeoJsonProperties } from './geoJsonProperties.model'; export class GeoJson { public geometry: AddressGeometry; public type: string; - public properties: object; + public properties: GeoJsonProperties; constructor(obj?: any) { Object.assign(this, obj, { diff --git a/src/app/models/structure.model.ts b/src/app/models/structure.model.ts index 16f2781e6..6cc2c585f 100644 --- a/src/app/models/structure.model.ts +++ b/src/app/models/structure.model.ts @@ -36,6 +36,7 @@ export class Structure { public isOpen: boolean; public openedOn: OpeningDay; public distance?: string; + public address?: string; constructor(obj?: any) { Object.assign(this, obj, { diff --git a/src/app/structure-list/components/structure-details/structure-details.component.html b/src/app/structure-list/components/structure-details/structure-details.component.html index 03cbfe870..ba303e734 100644 --- a/src/app/structure-list/components/structure-details/structure-details.component.html +++ b/src/app/structure-list/components/structure-details/structure-details.component.html @@ -12,7 +12,7 @@ <div fxLayout="column" fxFlex="60%"> <div *ngIf="structure.voie" fxLayout="row" fxLayoutAlign="none center"> <em class="ico-marker-pin-sm absolute"></em> - <p>{{ structure.voie }}</p> + <p>{{ structure.n }} {{ structure.address }}</p> </div> <div *ngIf="structure.siteWeb" fxLayout="row" fxLayoutAlign="none center"> <em class="ic-globe-alt"></em> -- GitLab From 945f93f2ecf15041551c1582c6c79f88c7537630 Mon Sep 17 00:00:00 2001 From: Jeremie BRISON <ext.sopra.jbrison@grandlyon.com> Date: Mon, 2 Nov 2020 12:19:47 +0100 Subject: [PATCH 39/50] fix(search) : create modal component --- src/app/app.module.ts | 2 + .../modal-filter/modal-filter.component.html | 33 ++++ .../modal-filter/modal-filter.component.scss | 170 ++++++++++++++++++ .../modal-filter.component.spec.ts | 25 +++ .../modal-filter/modal-filter.component.ts | 64 +++++++ .../recherche/recherche.component.ts | 12 -- .../components/search/search.component.html | 49 +---- .../components/search/search.component.ts | 80 +++------ .../structure-list/services/search.service.ts | 6 +- .../structure-list.component.ts | 1 + 10 files changed, 332 insertions(+), 110 deletions(-) create mode 100644 src/app/structure-list/components/modal-filter/modal-filter.component.html create mode 100644 src/app/structure-list/components/modal-filter/modal-filter.component.scss create mode 100644 src/app/structure-list/components/modal-filter/modal-filter.component.spec.ts create mode 100644 src/app/structure-list/components/modal-filter/modal-filter.component.ts delete mode 100644 src/app/structure-list/components/recherche/recherche.component.ts diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 4934e7b00..2b3e218eb 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -16,6 +16,7 @@ import { StructureListComponent } from './structure-list/structure-list.componen import { CardComponent } from './structure-list/components/card/card.component'; import { FormsModule, ReactiveFormsModule } from '@angular/forms'; import { SearchComponent } from './structure-list/components/search/search.component'; +import { ModalFilterComponent } from './structure-list/components/modal-filter/modal-filter.component'; @NgModule({ declarations: [ @@ -26,6 +27,7 @@ import { SearchComponent } from './structure-list/components/search/search.compo StructureListComponent, CardComponent, SearchComponent, + ModalFilterComponent, ], imports: [ BrowserModule, diff --git a/src/app/structure-list/components/modal-filter/modal-filter.component.html b/src/app/structure-list/components/modal-filter/modal-filter.component.html new file mode 100644 index 000000000..d006c7cac --- /dev/null +++ b/src/app/structure-list/components/modal-filter/modal-filter.component.html @@ -0,0 +1,33 @@ +<div *ngIf="modalType" fxLayout="column" fxLayoutAlign="space-between" [ngClass]="['modal', 'modal' + modalType]"> + <div class="body-wrap"> + <div class="contentModal" fxLayout="row wrap" fxLayoutAlign="flex-start" *ngIf="categories.length > 0"> + <div class="blockFiltre" *ngFor="let c of categories"> + <h4>{{ c.name }}</h4> + + <ul class="blockLigne"> + <div fxLayout="row" class="ligneFiltre" fxLayoutAlign="space-between center" *ngFor="let module of c.modules"> + <li class="checkbox"> + <div class="checkboxItem"> + <label> + <input + type="checkbox" + [checked]="getIndex(module.id, c.name) > -1" + [value]="module.id" + (change)="onCheckboxChange($event, c.name)" + /> + <span class="customCheck"></span> + <div class="label">{{ module.text }}</div> + </label> + </div> + </li> + <span class="nbResult">{{ module.count ? module.count : '0' }}</span> + </div> + </ul> + </div> + </div> + <div class="footer" fxLayout="row" fxLayoutAlign="end center" fxLayoutGap="3vw"> + <a (click)="clearFilters()">Effacer</a> + <button type="button" (click)="emitFilter(searchForm.value.searchTerm)">Appliquer</button> + </div> + </div> +</div> diff --git a/src/app/structure-list/components/modal-filter/modal-filter.component.scss b/src/app/structure-list/components/modal-filter/modal-filter.component.scss new file mode 100644 index 000000000..08adc9c1c --- /dev/null +++ b/src/app/structure-list/components/modal-filter/modal-filter.component.scss @@ -0,0 +1,170 @@ +@import '../../../../assets/scss/icons'; +@import '../../../../assets/scss/color'; +@import '../../../../assets/scss/typography'; +@import '../../../../assets/scss/breakpoint'; +@import '../../../../assets/scss/shapes'; + +.modalformations { + @media #{$desktop} { + margin-left: 0; + } + + margin-left: 206px; +} +.modalplusFiltres { + @media #{$desktop} { + margin-left: 0; + } + margin-left: 412px; +} +.modal { + max-height: 648px; + max-width: 754px; + width: 94%; + border-left: 6.5px solid transparent; + border-bottom: 6.5px solid transparent; + border-radius: 11px; + z-index: 401 !important; + position: absolute; + border: 1px solid $grey-5; + border-radius: 6px; + @include background-hash; + ::-webkit-scrollbar { + width: 10px; + } + ::-webkit-scrollbar-track { + background: $grey-5; + } + ::-webkit-scrollbar-thumb { + background: $grey; + border-radius: 6px; + } + .contentModal { + overflow-y: auto; + max-width: 1100px; + border-bottom: 1px solid $grey; + margin-bottom: 10px; + max-height: 500px; + .blockFiltre { + width: 100%; + padding: 32px 40px 10px 40px; + min-width: 450px; + } + .blockLigne { + padding-left: 0; + -moz-column-count: 2; + -moz-column-gap: 46px; + -webkit-column-count: 2; + -webkit-column-gap: 46px; + column-count: 2; + column-gap: 46px; + column-rule: dashed 1px $grey; + @media #{$large-phone} { + -moz-column-count: 1; + -webkit-column-count: 1; + column-count: 1; + } + } + .ligneFiltre { + padding: 5px 0 5px 0; + } + h4 { + @include cn-bold-14; + display: flex; + align-items: center; + margin-top: 0; + } + .nbResult { + @include cn-regular-14; + } + label { + @include cn-regular-14; + } + } + .footer { + margin: 0px 20px 16px 0; + a { + @include cn-bold-14; + display: flex; + align-items: center; + text-decoration: underline; + } + height: 32px; + button { + height: 100%; + border: none; + cursor: pointer; + background-color: $purple; + @include cn-bold-14; + line-height: 100%; + align-items: center; + text-align: center; + color: $white; + padding: 3px 16px 3px 16px; + outline: none; + } + } +} +.checkbox { + .checkboxItem { + /*position: relative; + display: inline-grid; + align-items: center; + grid-template-columns: min-content auto; + min-height: 25px;*/ + } + list-style-type: none; + input { + opacity: 0; + display: none; + &:checked ~ .customCheck { + background-color: $orange-light; + border-color: transparent; + } + &:checked ~ .customCheck:after { + display: block; + } + } + label { + //display: inline-grid; + align-items: center; + grid-template-columns: min-content auto; + display: inline-grid; + cursor: pointer; + } + .label { + padding-left: 8px; + @include cn-regular-14; + } + .customCheck { + display: inline-grid; + width: 18px; + height: 18px; + background-color: $white; + border: 1px solid $grey; + cursor: pointer; + position: relative; + + top: 0; + left: 0; + &:hover { + background-color: $grey-5; + } + &:after { + content: ''; + position: absolute; + display: none; + } + &:after { + left: 7px; + top: 3px; + width: 4px; + height: 8px; + border: solid $white; + border-width: 0 2px 2px 0; + transform: rotate(45deg); + -webkit-transform: rotate(45deg); + -ms-transform: rotate(45deg); + } + } +} diff --git a/src/app/structure-list/components/modal-filter/modal-filter.component.spec.ts b/src/app/structure-list/components/modal-filter/modal-filter.component.spec.ts new file mode 100644 index 000000000..5228b636c --- /dev/null +++ b/src/app/structure-list/components/modal-filter/modal-filter.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ModalFilterComponent } from './modal-filter.component'; + +describe('ModalFilterComponent', () => { + let component: ModalFilterComponent; + let fixture: ComponentFixture<ModalFilterComponent>; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ModalFilterComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ModalFilterComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/structure-list/components/modal-filter/modal-filter.component.ts b/src/app/structure-list/components/modal-filter/modal-filter.component.ts new file mode 100644 index 000000000..3be4344db --- /dev/null +++ b/src/app/structure-list/components/modal-filter/modal-filter.component.ts @@ -0,0 +1,64 @@ +import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; +import { FormBuilder, FormGroup } from '@angular/forms'; +import { Category } from '../../models/category.model'; +import { Filter } from '../../models/filter.model'; +import { Module } from '../../models/module.model'; + +@Component({ + selector: 'app-modal-filter', + templateUrl: './modal-filter.component.html', + styleUrls: ['./modal-filter.component.scss'], +}) +export class ModalFilterComponent implements OnInit { + constructor(private fb: FormBuilder) { + this.searchForm = this.fb.group({ + searchTerm: '', + }); + } + @Input() public modalType: string; + @Input() public categories: Category[]; + @Input() public modules: Module[]; + @Output() searchEvent = new EventEmitter(); + // Checkbox variable + checkedModules: Module[]; + // Form search input + searchForm: FormGroup; + ngOnInit(): void { + // Manage checkbox + this.checkedModules = this.modules.slice(); + } + + // Return index of a specific module in array modules + public getIndex(id: number, categ: string): number { + return this.checkedModules.findIndex((m: Module) => m.id === id && m.text === categ); + } + + // Management of the checkbox event (Check / Uncheck) + public onCheckboxChange(event, categ: string): void { + const checkValue: number = parseInt(event.target.value, 10); + if (event.target.checked) { + this.checkedModules.push(new Module(checkValue, categ)); + } else { + // Check if the unchecked module is present in the list and remove it + if (this.getIndex(checkValue, categ) > -1) { + this.checkedModules.splice(this.getIndex(checkValue, categ), 1); + } + } + } + + // Clear only filters in the current modal + public clearFilters(): void { + this.categories.forEach((categ: Category) => { + categ.modules.forEach((module: Module) => { + if (this.getIndex(module.id, categ.name) > -1) { + this.checkedModules.splice(this.getIndex(module.id, categ.name), 1); + } + }); + }); + } + + // Sends an array containing all filters + public emitFilter(): void { + this.searchEvent.emit(this.checkedModules); + } +} diff --git a/src/app/structure-list/components/recherche/recherche.component.ts b/src/app/structure-list/components/recherche/recherche.component.ts deleted file mode 100644 index 6ccca06c4..000000000 --- a/src/app/structure-list/components/recherche/recherche.component.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { Component, OnInit, Input } from '@angular/core'; - -@Component({ - selector: 'app-recherche', - templateUrl: './recherche.component.html', - styleUrls: ['./recherche.component.scss'], -}) -export class RechercheComponent implements OnInit { - constructor() {} - - ngOnInit(): void {} -} diff --git a/src/app/structure-list/components/search/search.component.html b/src/app/structure-list/components/search/search.component.html index 68ef0abfa..8f962c47d 100644 --- a/src/app/structure-list/components/search/search.component.html +++ b/src/app/structure-list/components/search/search.component.html @@ -49,48 +49,13 @@ <div class="arrow"></div> </button> </div> - <div - *ngIf="modalTypeOpened" - fxLayout="column" - fxLayoutAlign="space-between" - [ngClass]="['modal', 'modal' + modalTypeOpened]" - > - <div class="body-wrap"> - <div class="contentModal" fxLayout="row wrap" fxLayoutAlign="flex-start" *ngIf="categories.length > 0"> - <div class="blockFiltre" *ngFor="let c of categories"> - <h4>{{ c.name }}</h4> - - <ul class="blockLigne"> - <div - fxLayout="row" - class="ligneFiltre" - fxLayoutAlign="space-between center" - *ngFor="let module of c.modules" - > - <li class="checkbox"> - <div class="checkboxItem"> - <label> - <input - type="checkbox" - [checked]="getIndex(module.id, c.name) > -1" - [value]="module.id" - (change)="onCheckboxChange($event, c.name)" - /> - <span class="customCheck"></span> - <div class="label">{{ module.text }}</div> - </label> - </div> - </li> - <span class="nbResult">{{ module.count ? module.count : '0' }}</span> - </div> - </ul> - </div> - </div> - <div class="footer" fxLayout="row" fxLayoutAlign="end center" fxLayoutGap="3vw"> - <a (click)="clearFilters()">Effacer</a> - <button type="button" (click)="applyFilter(searchForm.value.searchTerm)">Appliquer</button> - </div> - </div> + <div *ngIf="modalTypeOpened"> + <app-modal-filter + [modalType]="modalTypeOpened" + [categories]="categories" + [modules]="checkedModulesFilter" + (searchEvent)="fetchResults($event)" + ></app-modal-filter> </div> </div> <div class="footerSearchSection" fxLayout="row" fxLayoutAlign="space-between center"> diff --git a/src/app/structure-list/components/search/search.component.ts b/src/app/structure-list/components/search/search.component.ts index aa70de956..c7440073c 100644 --- a/src/app/structure-list/components/search/search.component.ts +++ b/src/app/structure-list/components/search/search.component.ts @@ -1,5 +1,4 @@ import { Component, EventEmitter, OnInit, Output } from '@angular/core'; -import { stringToKeyValue } from '@angular/flex-layout/extended/typings/style/style-transforms'; import { FormBuilder, FormGroup } from '@angular/forms'; import { Category } from '../../models/category.model'; import { Filter } from '../../models/filter.model'; @@ -31,84 +30,57 @@ export class SearchComponent implements OnInit { modalTypeOpened: string; // Checkbox variable - checkedModules: Module[]; checkedModulesFilter: Module[]; ngOnInit(): void { // Will store the different categories this.categories = []; - // Manage checkbox - this.checkedModules = new Array(); this.checkedModulesFilter = new Array(); } - // Delete when getting back-end - private mockApiNumber(nb: number): string { - return ('00' + nb).slice(-3); - } - - // Open the modal and display the list according to the right filter button - public openModal(option: string): void { - this.categories = []; - if (this.modalTypeOpened !== option) { - this.modalTypeOpened = option; - this.fakeData(option); - } else { - this.modalTypeOpened = null; - } - - // Init checked list modules - this.checkedModules = this.checkedModulesFilter.slice(); - } - // Sends an array containing all filters public applyFilter(term: string): void { - this.checkedModulesFilter = this.checkedModules.slice(); - this.openModal(this.modalTypeOpened); - // Send search input filter - const filters: Filter[] = []; + // Add search input filter + let filters: Filter[] = []; if (term) { filters.push(new Filter('nomDeVotreStructure', term, false)); } - - // Send checked box filter + // Add checked box filter this.checkedModulesFilter.forEach((cm) => { filters.push(new Filter(this.fromStringToIdExcel(cm.text), this.mockApiNumber(cm.id), false)); }); + // Send filters this.searchEvent.emit(filters); } - // Management of the checkbox event (Check / Uncheck) - public onCheckboxChange(event, categ: string): void { - const checkValue: number = parseInt(event.target.value, 10); - if (event.target.checked) { - this.checkedModules.push(new Module(checkValue, categ)); - } else { - // Check if the unchecked module is present in the list and remove it - if (this.getIndex(checkValue, categ) > -1) { - this.checkedModules.splice(this.getIndex(checkValue, categ), 1); - } - } + // Delete when getting back-end + private mockApiNumber(nb: number): string { + return ('00' + nb).slice(-3); } - // Return index of a specific module in array modules - public getIndex(id: number, categ: string): number { - return this.checkedModules.findIndex((m: Module) => m.id === id && m.text === categ); + public fetchResults(checkedModules: Module[]): void { + let inputTerm = this.searchForm.get('searchTerm').value; + + // Store checked modules + this.checkedModulesFilter = checkedModules; + + // Close modal after receive filters from her. + this.openModal(this.modalTypeOpened); + inputTerm ? this.applyFilter(inputTerm) : this.applyFilter(null); } - // Clear only filters in the current modal - public clearFilters(): void { - this.categories.forEach((categ: Category) => { - categ.modules.forEach((module: Module) => { - if (this.getIndex(module.id, categ.name) > -1) { - this.checkedModules.splice(this.getIndex(module.id, categ.name), 1); - } - }); - }); + // Open the modal and display the list according to the right filter button + public openModal(option: string): void { + this.categories = []; + if (this.modalTypeOpened !== option) { + this.modalTypeOpened = option; + this.fakeData(option); + } else { + this.modalTypeOpened = null; + } } - // Format title of category to id of excel category private fromStringToIdExcel(categ: string): string { let splitStr = categ.toLowerCase().split(' '); for (let i = 1; i < splitStr.length; i++) { @@ -138,7 +110,7 @@ export class SearchComponent implements OnInit { if (option === this.modalType[0]) { this.mockService(this.categories, 'Accompagnement des démarches', { name: 'CAF', id: 5 }, 7); } else if (option === this.modalType[1]) { - this.searchService.getCategories().subscribe((categories: Category[]) => { + this.searchService.getCategoriesFormations().subscribe((categories: Category[]) => { this.searchService .getFakeCounterModule() .subscribe((res: { structureCountTab: { id: number; count: number }[] }) => { diff --git a/src/app/structure-list/services/search.service.ts b/src/app/structure-list/services/search.service.ts index 4ae64b197..fc3e73583 100644 --- a/src/app/structure-list/services/search.service.ts +++ b/src/app/structure-list/services/search.service.ts @@ -11,8 +11,10 @@ import { Module } from '../models/module.model'; export class SearchService { constructor(private http: HttpClient) {} - public getCategories(): Observable<Category[]> { - return this.http.get('/api/Categories').pipe(map((data: any[]) => data.map((item) => new Category(item)))); + public getCategoriesFormations(): Observable<Category[]> { + return this.http + .get('/api/CategoriesFormations') + .pipe(map((data: any[]) => data.map((item) => new Category(item)))); } public getFakeCounterModule(): Observable<any> { return this.http.get('http://localhost:3000/structures/count'); diff --git a/src/app/structure-list/structure-list.component.ts b/src/app/structure-list/structure-list.component.ts index 5152fa5fb..62fe27456 100644 --- a/src/app/structure-list/structure-list.component.ts +++ b/src/app/structure-list/structure-list.component.ts @@ -16,6 +16,7 @@ export class StructureListComponent implements OnInit { ngOnInit(): void {} public fetchResults(filters: Filter[]): void { + console.log(filters); this.searchEvent.emit(filters); } } -- GitLab From 51df52c9078cd00b0d536f09536de99a56df5265 Mon Sep 17 00:00:00 2001 From: Jeremie BRISON <ext.sopra.jbrison@grandlyon.com> Date: Mon, 2 Nov 2020 12:15:18 +0100 Subject: [PATCH 40/50] fix(search) : fix button + color --- .../modal-filter/modal-filter.component.scss | 20 +-- .../components/search/search.component.html | 4 +- .../components/search/search.component.scss | 157 ++---------------- .../components/search/search.component.ts | 10 +- src/assets/scss/_buttons.scss | 31 ++++ src/assets/scss/_color.scss | 12 +- src/assets/scss/_inputs.scss | 0 7 files changed, 67 insertions(+), 167 deletions(-) create mode 100644 src/assets/scss/_buttons.scss create mode 100644 src/assets/scss/_inputs.scss diff --git a/src/app/structure-list/components/modal-filter/modal-filter.component.scss b/src/app/structure-list/components/modal-filter/modal-filter.component.scss index 08adc9c1c..b4b705285 100644 --- a/src/app/structure-list/components/modal-filter/modal-filter.component.scss +++ b/src/app/structure-list/components/modal-filter/modal-filter.component.scss @@ -3,6 +3,7 @@ @import '../../../../assets/scss/typography'; @import '../../../../assets/scss/breakpoint'; @import '../../../../assets/scss/shapes'; +@import '../../../../assets/scss/buttons'; .modalformations { @media #{$desktop} { @@ -88,31 +89,16 @@ display: flex; align-items: center; text-decoration: underline; + color: $secondary-color; } height: 32px; button { - height: 100%; - border: none; - cursor: pointer; - background-color: $purple; + @include btn-search-filter; @include cn-bold-14; - line-height: 100%; - align-items: center; - text-align: center; - color: $white; - padding: 3px 16px 3px 16px; - outline: none; } } } .checkbox { - .checkboxItem { - /*position: relative; - display: inline-grid; - align-items: center; - grid-template-columns: min-content auto; - min-height: 25px;*/ - } list-style-type: none; input { opacity: 0; diff --git a/src/app/structure-list/components/search/search.component.html b/src/app/structure-list/components/search/search.component.html index 8f962c47d..b4b59c342 100644 --- a/src/app/structure-list/components/search/search.component.html +++ b/src/app/structure-list/components/search/search.component.html @@ -13,7 +13,9 @@ <div class="ico-pin-search grey"></div> </div> <input type="text" formControlName="searchTerm" placeholder="Rechercher une adresse, une association..." /> - <button type="submit">Rechercher</button> + <div class="searchButton"> + <button type="submit">Rechercher</button> + </div> </form> </div> diff --git a/src/app/structure-list/components/search/search.component.scss b/src/app/structure-list/components/search/search.component.scss index 5b8230750..559e50345 100644 --- a/src/app/structure-list/components/search/search.component.scss +++ b/src/app/structure-list/components/search/search.component.scss @@ -3,6 +3,7 @@ @import '../../../../assets/scss/typography'; @import '../../../../assets/scss/breakpoint'; @import '../../../../assets/scss/shapes'; +@import '../../../../assets/scss/buttons'; .header { .title { @@ -34,45 +35,32 @@ outline: none; } .searchSection { - button { - border: none; - cursor: pointer; - background-color: $purple; - @include cn-bold-14; - align-items: center; - text-align: center; - color: $white; - padding: 3px 16px 3px 16px; - outline: none; + .searchButton { + border: 1px solid $grey-6; + border-radius: 6px; + @include background-hash; + padding: 0 0 4px 5px; + button { + @include btn-search; + @include cn-bold-14; + } } } .btnSection { padding: 16px 0 8px 0; button { - height: 40px; - width: 190px; - outline: none; - border: 1px solid $grey; - border-radius: 33px; - background-color: $white; - padding: 2px 6px 2px 13px; - align-items: center; - display: flex; - cursor: pointer; + @include btn-filter; .btnText { - justify-content: center; @include cn-regular-14; - display: flex; - align-items: center; } } .selected { - border: 1px solid $orange-light; - color: $orange-light; + border: 1px solid $primary-color; + color: $primary-color; .arrow { background-color: transparent; - border-bottom: 1px solid $orange-light; - border-right: 1px solid $orange-light; + border-bottom: 1px solid $primary-color; + border-right: 1px solid $primary-color; transform: translateY(25%) rotate(-135deg); margin: 0 5px 0 10px; height: 7px; @@ -81,8 +69,8 @@ } .arrow { background-color: transparent; - border-bottom: 1px solid $grey; - border-right: 1px solid $grey; + border-bottom: 1px solid $grey-2; + border-right: 1px solid $grey-2; transform: translateY(-25%) rotate(45deg); margin: 0 5px 0 10px; height: 7px; @@ -90,117 +78,8 @@ } } } -.modalformations { - @media #{$desktop} { - margin-left: 0; - } - margin-left: 206px; -} -.modalplusFiltres { - @media #{$desktop} { - margin-left: 0; - } - margin-left: 412px; -} -.modal { - max-height: 648px; - max-width: 754px; - width: 94%; - border-left: 6.5px solid transparent; - border-bottom: 6.5px solid transparent; - border-radius: 11px; - z-index: 401 !important; - margin: 8px 8px 0 0; - position: absolute; - margin-top: 96px; - border: 1px solid $grey-5; - border-radius: 6px; - @include background-hash; - ::-webkit-scrollbar { - width: 10px; - } - ::-webkit-scrollbar-track { - background: $grey-5; - } - ::-webkit-scrollbar-thumb { - background: $grey; - border-radius: 6px; - } - .contentModal { - overflow-y: auto; - max-width: 1100px; - border-bottom: 1px solid $grey; - margin-bottom: 10px; - max-height: 500px; - .blockFiltre { - width: 100%; - padding: 32px 40px 10px 40px; - min-width: 450px; - } - .blockLigne { - padding-left: 0; - -moz-column-count: 2; - -moz-column-gap: 46px; - -webkit-column-count: 2; - -webkit-column-gap: 46px; - column-count: 2; - column-gap: 46px; - column-rule: dashed 1px $grey; - @media #{$large-phone} { - -moz-column-count: 1; - -webkit-column-count: 1; - column-count: 1; - } - } - .ligneFiltre { - padding: 5px 0 5px 0; - } - h4 { - @include cn-bold-14; - display: flex; - align-items: center; - margin-top: 0; - } - .nbResult { - @include cn-regular-14; - } - label { - @include cn-regular-14; - } - } - .footer { - margin: 0px 20px 16px 0; - a { - @include cn-bold-14; - display: flex; - align-items: center; - text-decoration: underline; - } - height: 32px; - button { - height: 100%; - border: none; - cursor: pointer; - background-color: $purple; - @include cn-bold-14; - line-height: 100%; - align-items: center; - text-align: center; - color: $white; - padding: 3px 16px 3px 16px; - outline: none; - } - } -} .checkbox { - .checkboxItem { - /*position: relative; - display: inline-grid; - align-items: center; - grid-template-columns: min-content auto; - min-height: 25px;*/ - } list-style-type: none; input { opacity: 0; @@ -242,8 +121,6 @@ content: ''; position: absolute; display: none; - } - &:after { left: 7px; top: 3px; width: 4px; diff --git a/src/app/structure-list/components/search/search.component.ts b/src/app/structure-list/components/search/search.component.ts index c7440073c..c8baac522 100644 --- a/src/app/structure-list/components/search/search.component.ts +++ b/src/app/structure-list/components/search/search.component.ts @@ -96,13 +96,13 @@ export class SearchComponent implements OnInit { // Fake service api private mockService(module: Category[], titre: string, categ: any, nbCateg: number): void { - let m = new Category(); - m.name = titre; - m.modules = []; + const category = new Category(); + category.name = titre; + category.modules = []; for (let i = 0; i < nbCateg; i++) { - m.modules.push(new Module(categ.id + i, categ.name + i)); + category.modules.push(new Module(categ.id + i, categ.name + i)); } - module.push(m); + module.push(category); } // Fake data diff --git a/src/assets/scss/_buttons.scss b/src/assets/scss/_buttons.scss new file mode 100644 index 000000000..4d203db52 --- /dev/null +++ b/src/assets/scss/_buttons.scss @@ -0,0 +1,31 @@ +@import './color'; +@import './shapes'; + +@mixin btn-filter { + background: $white; + height: 40px; + width: 190px; + border: 1px solid $grey-6; + padding: 3px 16px 3px 16px; + outline: none; + border-radius: 4px; + cursor: pointer; +} +@mixin btn-search { + background: $white; + height: 34px; + border: none; + color: $primary-color; + padding: 3px 16px 3px 16px; + outline: none; + cursor: pointer; +} +@mixin btn-search-filter { + background: $secondary-color; + height: 40px; + border: none; + color: $white; + padding: 3px 16px 3px 16px; + outline: none; + cursor: pointer; +} diff --git a/src/assets/scss/_color.scss b/src/assets/scss/_color.scss index 40d9d77e3..bf291a307 100644 --- a/src/assets/scss/_color.scss +++ b/src/assets/scss/_color.scss @@ -8,6 +8,7 @@ $grey-2: #4f4f4f; $grey-3: #c3c3c3; $grey-4: #f2ecf2; $grey-5: #f2f2f2; +$grey-6: #bdbdbd; /* YELLOW */ $yellow: #f2cb04; $yellow-light: #fff8d6; @@ -17,13 +18,16 @@ $orange-light: #f29f05; $orange-3: #fff4ea; /* GREEN */ $green: #41c29c; -/* OTHERS */ -$blue: #b3f8f8; +/* BLUE */ +$blue: #348899; + +$blue-light: #b3f8f8; $blue-dark: #2f5480; +/* OTHERS */ $purple: #594d59; $red-metro: #d50000; /* APP COLORS */ -$primary-color: $yellow; -$secondary-color: $orange; +$primary-color: $red-metro; +$secondary-color: $blue; $default-link-color: $grey-2; $button-secondary: $blue-dark; diff --git a/src/assets/scss/_inputs.scss b/src/assets/scss/_inputs.scss new file mode 100644 index 000000000..e69de29bb -- GitLab From 8cde8224f36925adf0306d867ecee3a62f7a60d3 Mon Sep 17 00:00:00 2001 From: Jeremie BRISON <ext.sopra.jbrison@grandlyon.com> Date: Mon, 2 Nov 2020 12:45:42 +0100 Subject: [PATCH 41/50] fix(search) : fix input + design --- .../modal-filter/modal-filter.component.scss | 5 +-- .../components/search/search.component.html | 12 +++++-- .../components/search/search.component.scss | 35 +++++++++++-------- .../components/search/search.component.ts | 5 +++ src/assets/scss/_icons.scss | 24 +++++++++++-- src/assets/scss/_inputs.scss | 9 +++++ 6 files changed, 69 insertions(+), 21 deletions(-) diff --git a/src/app/structure-list/components/modal-filter/modal-filter.component.scss b/src/app/structure-list/components/modal-filter/modal-filter.component.scss index b4b705285..5275c2945 100644 --- a/src/app/structure-list/components/modal-filter/modal-filter.component.scss +++ b/src/app/structure-list/components/modal-filter/modal-filter.component.scss @@ -10,13 +10,13 @@ margin-left: 0; } - margin-left: 206px; + margin-left: 196px; } .modalplusFiltres { @media #{$desktop} { margin-left: 0; } - margin-left: 412px; + margin-left: 396px; } .modal { max-height: 648px; @@ -29,6 +29,7 @@ position: absolute; border: 1px solid $grey-5; border-radius: 6px; + margin-top: 3.5px; @include background-hash; ::-webkit-scrollbar { width: 10px; diff --git a/src/app/structure-list/components/search/search.component.html b/src/app/structure-list/components/search/search.component.html index b4b59c342..44fa60bd2 100644 --- a/src/app/structure-list/components/search/search.component.html +++ b/src/app/structure-list/components/search/search.component.html @@ -9,10 +9,16 @@ fxLayoutGap="1.5vw" (ngSubmit)="applyFilter(searchForm.value.searchTerm)" > - <div class="icon"> - <div class="ico-pin-search grey"></div> + <div class="inputSection" fxLayout="row" fxLayoutAlign="space-between center"> + <input type="text" formControlName="searchTerm" placeholder="Rechercher une adresse, une association..." /> + <div class="icon close" (click)="clearInput()"> + <div class="ico-close grey"></div> + </div> + <div class="separator"></div> + <div class="icon pin"> + <div class="ico-pin-search blue"></div> + </div> </div> - <input type="text" formControlName="searchTerm" placeholder="Rechercher une adresse, une association..." /> <div class="searchButton"> <button type="submit">Rechercher</button> </div> diff --git a/src/app/structure-list/components/search/search.component.scss b/src/app/structure-list/components/search/search.component.scss index 559e50345..5b8368862 100644 --- a/src/app/structure-list/components/search/search.component.scss +++ b/src/app/structure-list/components/search/search.component.scss @@ -4,6 +4,7 @@ @import '../../../../assets/scss/breakpoint'; @import '../../../../assets/scss/shapes'; @import '../../../../assets/scss/buttons'; +@import '../../../../assets/scss/inputs'; .header { .title { @@ -17,24 +18,31 @@ .content { margin: 10px 0 0px 0; .icon { - border: 1px solid $grey; - padding: 4px 6px 8px 6px; + padding: 0 6px 0 6px; border-radius: 4px; cursor: pointer; + &.pin { + margin-bottom: 4px; + } } input { - width: 100%; - background-color: $grey-5; - border: none; @include cn-regular-14; - display: flex; - align-items: center; - padding-left: 10px; - text-overflow: ellipsis; - color: $grey-1; - outline: none; + @include input-search; } .searchSection { + .separator { + height: 100%; + width: 2px; + background-color: $grey-6; + margin: 0 5px 0 5px; + } + .inputSection { + padding: 6px 3px 6px 6px; + min-width: 463px; + border: 1px solid $grey-6; + background-color: $white; + height: 40px; + } .searchButton { border: 1px solid $grey-6; border-radius: 6px; @@ -47,7 +55,7 @@ } } .btnSection { - padding: 16px 0 8px 0; + padding: 16px 0 0px 0; button { @include btn-filter; .btnText { @@ -134,8 +142,7 @@ } } .footerSearchSection { - margin-bottom: 30px; - margin-right: 20px; + margin: 17px 0px 17px 0px; a { @include cn-bold-14; diff --git a/src/app/structure-list/components/search/search.component.ts b/src/app/structure-list/components/search/search.component.ts index c8baac522..d95cf649b 100644 --- a/src/app/structure-list/components/search/search.component.ts +++ b/src/app/structure-list/components/search/search.component.ts @@ -38,6 +38,11 @@ export class SearchComponent implements OnInit { this.checkedModulesFilter = new Array(); } + // Clear input search + public clearInput(): void { + this.searchForm.reset(); + this.applyFilter(null); + } // Sends an array containing all filters public applyFilter(term: string): void { diff --git a/src/assets/scss/_icons.scss b/src/assets/scss/_icons.scss index 77ed9a879..52da3fd2e 100644 --- a/src/assets/scss/_icons.scss +++ b/src/assets/scss/_icons.scss @@ -66,8 +66,8 @@ border-radius: 4px; background-color: white; } - &.grey { - background-color: #828282; + &.blue { + background-color: $secondary-color; } } .ico-dot-available { @@ -123,3 +123,23 @@ border-left: 2px solid $purple; } } + +.ico-close { + width: 15px; + height: 13px; + text-align: center; + &:before { + transform: rotate(45deg); + } + &:after { + transform: rotate(-45deg); + } +} +.ico-close:before, +.ico-close:after { + position: absolute; + content: ''; + height: 14px; + width: 2px; + background-color: $grey-6; +} diff --git a/src/assets/scss/_inputs.scss b/src/assets/scss/_inputs.scss index e69de29bb..dac479e10 100644 --- a/src/assets/scss/_inputs.scss +++ b/src/assets/scss/_inputs.scss @@ -0,0 +1,9 @@ +@mixin input-search { + width: 100%; + border: none; + padding-left: 10px; + text-overflow: ellipsis; + color: $grey-1; + outline: none; + font-style: italic; +} -- GitLab From da50466067477ccbe8337f2b8ab51d5192cd1bdb Mon Sep 17 00:00:00 2001 From: Jeremie BRISON <ext.sopra.jbrison@grandlyon.com> Date: Mon, 2 Nov 2020 14:21:30 +0100 Subject: [PATCH 42/50] fix(search) : use proxy --- api/routes.json | 3 --- api/server.js | 6 +++++- src/app/structure-list/services/search.service.ts | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) delete mode 100644 api/routes.json diff --git a/api/routes.json b/api/routes.json deleted file mode 100644 index 6a7af55fa..000000000 --- a/api/routes.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "/api/*": "/$1" -} diff --git a/api/server.js b/api/server.js index 08ca86cb0..43c5b108c 100644 --- a/api/server.js +++ b/api/server.js @@ -1,13 +1,17 @@ const jsonServer = require('json-server'); const server = jsonServer.create(); const router = jsonServer.router('db.json'); -const middlewares = jsonServer.defaults(); +const routes = { + '/api/*': '/$1', +}; +const middlewares = [jsonServer.defaults(), jsonServer.rewriter(routes)]; // Set default middlewares (logger, static, cors and no-cache) server.use(middlewares); // Add custom routes before JSON Server router server.get('/structures/count', (req, res) => { + console.log('ok'); let structureCountTab = []; // Compétences de base structureCountTab.push({ id: 260, count: 3 }); diff --git a/src/app/structure-list/services/search.service.ts b/src/app/structure-list/services/search.service.ts index fc3e73583..906fc3aee 100644 --- a/src/app/structure-list/services/search.service.ts +++ b/src/app/structure-list/services/search.service.ts @@ -17,7 +17,7 @@ export class SearchService { .pipe(map((data: any[]) => data.map((item) => new Category(item)))); } public getFakeCounterModule(): Observable<any> { - return this.http.get('http://localhost:3000/structures/count'); + return this.http.get('/api/structures/count'); } public setCountModules(category: Category, structureCountTab: { id: number; count: number }[]): Category { category.modules.forEach((m: Module) => { -- GitLab From 5a94bf4e393741c1cf465f3834e08b6c12ad23a3 Mon Sep 17 00:00:00 2001 From: Jeremie BRISON <ext.sopra.jbrison@grandlyon.com> Date: Mon, 2 Nov 2020 15:51:09 +0100 Subject: [PATCH 43/50] fix(search) : fix review merge --- api/server.js | 5 +- .../modal-filter/modal-filter.component.scss | 4 +- .../components/search/search.component.html | 14 +++--- .../components/search/search.component.ts | 49 ++++++++++--------- src/app/structure-list/enum/typeModal.enum.ts | 5 ++ .../models/structureCounter.model.ts | 8 +++ .../structure-list/services/search.service.ts | 10 ++-- .../structure-list.component.html | 1 - .../structure-list.component.scss | 5 -- 9 files changed, 57 insertions(+), 44 deletions(-) create mode 100644 src/app/structure-list/enum/typeModal.enum.ts create mode 100644 src/app/structure-list/models/structureCounter.model.ts diff --git a/api/server.js b/api/server.js index 43c5b108c..e85ef232a 100644 --- a/api/server.js +++ b/api/server.js @@ -11,7 +11,6 @@ server.use(middlewares); // Add custom routes before JSON Server router server.get('/structures/count', (req, res) => { - console.log('ok'); let structureCountTab = []; // Compétences de base structureCountTab.push({ id: 260, count: 3 }); @@ -62,9 +61,7 @@ server.get('/structures/count', (req, res) => { structureCountTab.push({ id: 164, count: 1 }); structureCountTab.push({ id: 163, count: 1 }); structureCountTab.push({ id: 162, count: 2 }); - return res.status(200).jsonp({ - structureCountTab, - }); + return res.status(200).jsonp(structureCountTab); }); // Use default router diff --git a/src/app/structure-list/components/modal-filter/modal-filter.component.scss b/src/app/structure-list/components/modal-filter/modal-filter.component.scss index 5275c2945..ccb052e16 100644 --- a/src/app/structure-list/components/modal-filter/modal-filter.component.scss +++ b/src/app/structure-list/components/modal-filter/modal-filter.component.scss @@ -5,14 +5,14 @@ @import '../../../../assets/scss/shapes'; @import '../../../../assets/scss/buttons'; -.modalformations { +.modaltraining { @media #{$desktop} { margin-left: 0; } margin-left: 196px; } -.modalplusFiltres { +.modalmoreFilters { @media #{$desktop} { margin-left: 0; } diff --git a/src/app/structure-list/components/search/search.component.html b/src/app/structure-list/components/search/search.component.html index 44fa60bd2..9de95de24 100644 --- a/src/app/structure-list/components/search/search.component.html +++ b/src/app/structure-list/components/search/search.component.html @@ -14,7 +14,7 @@ <div class="icon close" (click)="clearInput()"> <div class="ico-close grey"></div> </div> - <div class="separator"></div> + <span class="separator"></span> <div class="icon pin"> <div class="ico-pin-search blue"></div> </div> @@ -28,8 +28,8 @@ <div class="btnSection" fxLayout="row" fxLayoutAlign="space-between center"> <button type="button" - [ngClass]="{ selected: modalTypeOpened === modalType[0] }" - (click)="openModal(this.modalType[0])" + [ngClass]="{ selected: modalTypeOpened === TypeModal[0] }" + (click)="openModal(TypeModal[0])" fxLayout="row" fxLayoutAlign="space-between center" > @@ -38,8 +38,8 @@ </button> <button type="button" - [ngClass]="{ selected: modalTypeOpened === modalType[1] }" - (click)="openModal(this.modalType[1])" + [ngClass]="{ selected: modalTypeOpened === TypeModal[1] }" + (click)="openModal(TypeModal[1])" fxLayout="row" fxLayoutAlign="space-between center" > @@ -48,8 +48,8 @@ </button> <button type="button" - [ngClass]="{ selected: modalTypeOpened === modalType[2] }" - (click)="openModal(this.modalType[2])" + [ngClass]="{ selected: modalTypeOpened === TypeModal[2] }" + (click)="openModal(TypeModal[2])" fxLayout="row" fxLayoutAlign="space-between center" > diff --git a/src/app/structure-list/components/search/search.component.ts b/src/app/structure-list/components/search/search.component.ts index d95cf649b..1fb011826 100644 --- a/src/app/structure-list/components/search/search.component.ts +++ b/src/app/structure-list/components/search/search.component.ts @@ -1,8 +1,11 @@ import { Component, EventEmitter, OnInit, Output } from '@angular/core'; import { FormBuilder, FormGroup } from '@angular/forms'; +import { forkJoin } from 'rxjs'; +import { TypeModal } from '../../enum/typeModal.enum'; import { Category } from '../../models/category.model'; import { Filter } from '../../models/filter.model'; import { Module } from '../../models/module.model'; +import { StructureCounter } from '../../models/structureCounter.model'; import { SearchService } from '../../services/search.service'; @Component({ @@ -20,24 +23,26 @@ export class SearchComponent implements OnInit { @Output() searchEvent = new EventEmitter(); // Form search input - searchForm: FormGroup; - - // Button variable - modalType: string[] = ['accompagnement', 'formations', 'plusFiltres']; - + private searchForm: FormGroup; // Modal variable - categories: Category[]; - modalTypeOpened: string; - + private categories: Category[]; + private modalTypeOpened: string; // Checkbox variable - checkedModulesFilter: Module[]; + private checkedModulesFilter: Module[]; ngOnInit(): void { // Will store the different categories this.categories = []; this.checkedModulesFilter = new Array(); + console.log(TypeModal[0]); } + + // Accessor to template angular. + public get TypeModal(): typeof TypeModal { + return TypeModal; + } + // Clear input search public clearInput(): void { this.searchForm.reset(); @@ -110,22 +115,22 @@ export class SearchComponent implements OnInit { module.push(category); } - // Fake data + // Get the correct list of checkbox/modules depending on the type of modal. private fakeData(option: string): void { - if (option === this.modalType[0]) { + if (option === TypeModal[0]) { this.mockService(this.categories, 'Accompagnement des démarches', { name: 'CAF', id: 5 }, 7); - } else if (option === this.modalType[1]) { - this.searchService.getCategoriesFormations().subscribe((categories: Category[]) => { - this.searchService - .getFakeCounterModule() - .subscribe((res: { structureCountTab: { id: number; count: number }[] }) => { - categories.forEach((category) => { - category = this.searchService.setCountModules(category, res.structureCountTab); - this.categories.push(category); - }); + } else if (option === TypeModal[1]) { + forkJoin([this.searchService.getCategoriesFormations(), this.searchService.getFakeCounterModule()]).subscribe( + (res) => { + const categories: Category[] = res[0]; + const structureCounter: StructureCounter[] = res[1]; + categories.forEach((category) => { + category = this.searchService.setCountModules(category, structureCounter); + this.categories.push(category); }); - }); - } else if (option === this.modalType[2]) { + } + ); + } else if (option === TypeModal[2]) { this.mockService( this.categories, 'Équipements', diff --git a/src/app/structure-list/enum/typeModal.enum.ts b/src/app/structure-list/enum/typeModal.enum.ts new file mode 100644 index 000000000..ab391e2f6 --- /dev/null +++ b/src/app/structure-list/enum/typeModal.enum.ts @@ -0,0 +1,5 @@ +export enum TypeModal { + accompaniment, + training, + moreFilters, +} diff --git a/src/app/structure-list/models/structureCounter.model.ts b/src/app/structure-list/models/structureCounter.model.ts new file mode 100644 index 000000000..d208192f0 --- /dev/null +++ b/src/app/structure-list/models/structureCounter.model.ts @@ -0,0 +1,8 @@ +export class StructureCounter { + id: number; + count: number; + + constructor(obj?: any) { + Object.assign(this, obj); + } +} diff --git a/src/app/structure-list/services/search.service.ts b/src/app/structure-list/services/search.service.ts index 906fc3aee..1b6a33b59 100644 --- a/src/app/structure-list/services/search.service.ts +++ b/src/app/structure-list/services/search.service.ts @@ -4,6 +4,7 @@ import { Observable } from 'rxjs'; import { map } from 'rxjs/operators'; import { Category } from '../models/category.model'; import { Module } from '../models/module.model'; +import { StructureCounter } from '../models/structureCounter.model'; @Injectable({ providedIn: 'root', @@ -16,10 +17,13 @@ export class SearchService { .get('/api/CategoriesFormations') .pipe(map((data: any[]) => data.map((item) => new Category(item)))); } - public getFakeCounterModule(): Observable<any> { - return this.http.get('/api/structures/count'); + + public getFakeCounterModule(): Observable<StructureCounter[]> { + return this.http + .get('/api/structures/count') + .pipe(map((data: any[]) => data.map((item) => new StructureCounter(item)))); } - public setCountModules(category: Category, structureCountTab: { id: number; count: number }[]): Category { + public setCountModules(category: Category, structureCountTab: StructureCounter[]): Category { category.modules.forEach((m: Module) => { for (let i = 0; i < structureCountTab.length; i++) { if (structureCountTab[i].id === m.id) { diff --git a/src/app/structure-list/structure-list.component.html b/src/app/structure-list/structure-list.component.html index e0de815ee..95735d1d1 100644 --- a/src/app/structure-list/structure-list.component.html +++ b/src/app/structure-list/structure-list.component.html @@ -1,6 +1,5 @@ <div class="topBlock"> <app-structure-list-search (searchEvent)="fetchResults($event)"></app-structure-list-search> - <div class="divider"></div> <span class="nbStructuresLabel">{{ structureList.length }} structures</span> </div> diff --git a/src/app/structure-list/structure-list.component.scss b/src/app/structure-list/structure-list.component.scss index 5b09b7ee8..ee31dcc05 100644 --- a/src/app/structure-list/structure-list.component.scss +++ b/src/app/structure-list/structure-list.component.scss @@ -2,11 +2,6 @@ @import '../../assets/scss/icons'; @import '../../assets/scss/typography'; -.divider { - width: 100%; - height: 1px; - background-color: $grey-4; -} .nbStructuresLabel { color: $grey; @include cn-regular-16; -- GitLab From aa058269ad28874fc4b4e99472eb3ed0bf8b75e8 Mon Sep 17 00:00:00 2001 From: Jeremie BRISON <ext.sopra.jbrison@grandlyon.com> Date: Mon, 2 Nov 2020 16:16:43 +0100 Subject: [PATCH 44/50] fix(search) : fix review request merge --- debug.log | 1 + .../modal-filter/modal-filter.component.html | 2 +- .../modal-filter/modal-filter.component.scss | 1 - .../modal-filter.component.spec.ts | 14 +++++++++++--- .../modal-filter/modal-filter.component.ts | 8 ++++---- .../components/search/search.component.scss | 1 - .../search/search.component.spec.ts | 4 ++-- .../components/search/search.component.ts | 3 +-- .../services/search.service.spec.ts | 19 +++++++++++++++++++ 9 files changed, 39 insertions(+), 14 deletions(-) create mode 100644 debug.log diff --git a/debug.log b/debug.log new file mode 100644 index 000000000..a9f90adc5 --- /dev/null +++ b/debug.log @@ -0,0 +1 @@ +[1102/160447.168:ERROR:directory_reader_win.cc(43)] FindFirstFile: Le chemin d’accès spécifié est introuvable. (0x3) diff --git a/src/app/structure-list/components/modal-filter/modal-filter.component.html b/src/app/structure-list/components/modal-filter/modal-filter.component.html index d006c7cac..12b002559 100644 --- a/src/app/structure-list/components/modal-filter/modal-filter.component.html +++ b/src/app/structure-list/components/modal-filter/modal-filter.component.html @@ -27,7 +27,7 @@ </div> <div class="footer" fxLayout="row" fxLayoutAlign="end center" fxLayoutGap="3vw"> <a (click)="clearFilters()">Effacer</a> - <button type="button" (click)="emitFilter(searchForm.value.searchTerm)">Appliquer</button> + <button type="button" (click)="emitFilter()">Appliquer</button> </div> </div> </div> diff --git a/src/app/structure-list/components/modal-filter/modal-filter.component.scss b/src/app/structure-list/components/modal-filter/modal-filter.component.scss index ccb052e16..420969748 100644 --- a/src/app/structure-list/components/modal-filter/modal-filter.component.scss +++ b/src/app/structure-list/components/modal-filter/modal-filter.component.scss @@ -113,7 +113,6 @@ } } label { - //display: inline-grid; align-items: center; grid-template-columns: min-content auto; display: inline-grid; diff --git a/src/app/structure-list/components/modal-filter/modal-filter.component.spec.ts b/src/app/structure-list/components/modal-filter/modal-filter.component.spec.ts index 5228b636c..bf696da42 100644 --- a/src/app/structure-list/components/modal-filter/modal-filter.component.spec.ts +++ b/src/app/structure-list/components/modal-filter/modal-filter.component.spec.ts @@ -1,4 +1,6 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { ReactiveFormsModule } from '@angular/forms'; +import { Filter } from '../../models/filter.model'; import { ModalFilterComponent } from './modal-filter.component'; @@ -8,9 +10,9 @@ describe('ModalFilterComponent', () => { beforeEach(async () => { await TestBed.configureTestingModule({ - declarations: [ ModalFilterComponent ] - }) - .compileComponents(); + declarations: [ModalFilterComponent], + imports: [ReactiveFormsModule], + }).compileComponents(); }); beforeEach(() => { @@ -22,4 +24,10 @@ describe('ModalFilterComponent', () => { it('should create', () => { expect(component).toBeTruthy(); }); + + it('should emit filters', () => { + spyOn(component.searchEvent, 'emit'); + component.emitFilter(); + expect(component.searchEvent.emit).toHaveBeenCalled(); + }); }); diff --git a/src/app/structure-list/components/modal-filter/modal-filter.component.ts b/src/app/structure-list/components/modal-filter/modal-filter.component.ts index 3be4344db..ff6050e60 100644 --- a/src/app/structure-list/components/modal-filter/modal-filter.component.ts +++ b/src/app/structure-list/components/modal-filter/modal-filter.component.ts @@ -17,7 +17,7 @@ export class ModalFilterComponent implements OnInit { } @Input() public modalType: string; @Input() public categories: Category[]; - @Input() public modules: Module[]; + @Input() public modules: Module[] = []; @Output() searchEvent = new EventEmitter(); // Checkbox variable checkedModules: Module[]; @@ -29,12 +29,12 @@ export class ModalFilterComponent implements OnInit { } // Return index of a specific module in array modules - public getIndex(id: number, categ: string): number { + private getIndex(id: number, categ: string): number { return this.checkedModules.findIndex((m: Module) => m.id === id && m.text === categ); } // Management of the checkbox event (Check / Uncheck) - public onCheckboxChange(event, categ: string): void { + private onCheckboxChange(event, categ: string): void { const checkValue: number = parseInt(event.target.value, 10); if (event.target.checked) { this.checkedModules.push(new Module(checkValue, categ)); @@ -47,7 +47,7 @@ export class ModalFilterComponent implements OnInit { } // Clear only filters in the current modal - public clearFilters(): void { + private clearFilters(): void { this.categories.forEach((categ: Category) => { categ.modules.forEach((module: Module) => { if (this.getIndex(module.id, categ.name) > -1) { diff --git a/src/app/structure-list/components/search/search.component.scss b/src/app/structure-list/components/search/search.component.scss index 5b8368862..279b2772b 100644 --- a/src/app/structure-list/components/search/search.component.scss +++ b/src/app/structure-list/components/search/search.component.scss @@ -101,7 +101,6 @@ } } label { - //display: inline-grid; align-items: center; grid-template-columns: min-content auto; display: inline-grid; 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 790ae3595..a5507ed76 100644 --- a/src/app/structure-list/components/search/search.component.spec.ts +++ b/src/app/structure-list/components/search/search.component.spec.ts @@ -5,7 +5,7 @@ import { Filter } from '../../models/filter.model'; import { Module } from '../../models/module.model'; import { HttpClientTestingModule } from '@angular/common/http/testing'; import { SearchComponent } from './search.component'; -import { SearchService } from '../../services/search.service'; +import { TypeModal } from '../../enum/typeModal.enum'; describe('SearchComponent', () => { let component: SearchComponent; @@ -42,7 +42,7 @@ describe('SearchComponent', () => { for (let i = 0; i < 7; i++) { categories[0].modules.push(new Module(5 + i, 'CAF' + i)); } - component.openModal('accompagnement'); + component.openModal(TypeModal[0]); expect(component.categories).toEqual(categories); }); }); diff --git a/src/app/structure-list/components/search/search.component.ts b/src/app/structure-list/components/search/search.component.ts index 1fb011826..6db165c6c 100644 --- a/src/app/structure-list/components/search/search.component.ts +++ b/src/app/structure-list/components/search/search.component.ts @@ -25,7 +25,7 @@ export class SearchComponent implements OnInit { // Form search input private searchForm: FormGroup; // Modal variable - private categories: Category[]; + public categories: Category[]; private modalTypeOpened: string; // Checkbox variable private checkedModulesFilter: Module[]; @@ -35,7 +35,6 @@ export class SearchComponent implements OnInit { this.categories = []; this.checkedModulesFilter = new Array(); - console.log(TypeModal[0]); } // Accessor to template angular. diff --git a/src/app/structure-list/services/search.service.spec.ts b/src/app/structure-list/services/search.service.spec.ts index d8b757560..4da5c5954 100644 --- a/src/app/structure-list/services/search.service.spec.ts +++ b/src/app/structure-list/services/search.service.spec.ts @@ -1,6 +1,9 @@ import { TestBed } from '@angular/core/testing'; import { HttpClientTestingModule } from '@angular/common/http/testing'; import { SearchService } from './search.service'; +import { StructureCounter } from '../models/structureCounter.model'; +import { Category } from '../models/category.model'; +import { Module } from '../models/module.model'; describe('SearchService', () => { let service: SearchService; @@ -15,4 +18,20 @@ describe('SearchService', () => { it('should be created', () => { expect(service).toBeTruthy(); }); + + it('should return category with number of modules inside', () => { + const structureCount: StructureCounter[] = [ + { id: 176, count: 2 }, + { id: 172, count: 1 }, + { id: 173, count: 1 }, + ]; + const m1: Module = { id: 176, text: 'strm1', count: 0 }; + const m2: Module = { id: 173, text: 'strm2', count: 0 }; + const m3: Module = { id: 172, text: 'strm3', count: 0 }; + const category: Category = { name: 'strCateg', modules: [m1, m2, m3] }; + const result = service.setCountModules(category, structureCount); + expect(result.modules[0].count).toBe(2); + expect(result.modules[1].count).toBe(1); + expect(result.modules[2].count).toBe(1); + }); }); -- GitLab From 1ea5c8f619afca077ca7265f1281576f71f03f9c Mon Sep 17 00:00:00 2001 From: Jeremie BRISON <ext.sopra.jbrison@grandlyon.com> Date: Mon, 2 Nov 2020 17:35:31 +0100 Subject: [PATCH 45/50] fix(search) : Add unit test --- debug.log | 1 + .../modal-filter/modal-filter.component.html | 2 +- .../modal-filter.component.spec.ts | 62 ++++++++++++++++++- .../modal-filter/modal-filter.component.ts | 10 +-- .../components/search/search.component.ts | 6 +- 5 files changed, 70 insertions(+), 11 deletions(-) diff --git a/debug.log b/debug.log index a9f90adc5..301edff39 100644 --- a/debug.log +++ b/debug.log @@ -1 +1,2 @@ [1102/160447.168:ERROR:directory_reader_win.cc(43)] FindFirstFile: Le chemin d’accès spécifié est introuvable. (0x3) +[1102/165734.564:ERROR:directory_reader_win.cc(43)] FindFirstFile: Le chemin d’accès spécifié est introuvable. (0x3) diff --git a/src/app/structure-list/components/modal-filter/modal-filter.component.html b/src/app/structure-list/components/modal-filter/modal-filter.component.html index 12b002559..ec2d69fb0 100644 --- a/src/app/structure-list/components/modal-filter/modal-filter.component.html +++ b/src/app/structure-list/components/modal-filter/modal-filter.component.html @@ -27,7 +27,7 @@ </div> <div class="footer" fxLayout="row" fxLayoutAlign="end center" fxLayoutGap="3vw"> <a (click)="clearFilters()">Effacer</a> - <button type="button" (click)="emitFilter()">Appliquer</button> + <button type="button" (click)="emitModules()">Appliquer</button> </div> </div> </div> diff --git a/src/app/structure-list/components/modal-filter/modal-filter.component.spec.ts b/src/app/structure-list/components/modal-filter/modal-filter.component.spec.ts index bf696da42..9c1ad3d14 100644 --- a/src/app/structure-list/components/modal-filter/modal-filter.component.spec.ts +++ b/src/app/structure-list/components/modal-filter/modal-filter.component.spec.ts @@ -1,6 +1,8 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { ReactiveFormsModule } from '@angular/forms'; +import { Category } from '../../models/category.model'; import { Filter } from '../../models/filter.model'; +import { Module } from '../../models/module.model'; import { ModalFilterComponent } from './modal-filter.component'; @@ -25,9 +27,65 @@ describe('ModalFilterComponent', () => { expect(component).toBeTruthy(); }); - it('should emit filters', () => { + it('should emit modules', () => { + const modules: Module[] = [ + { id: 176, text: 'training', count: 3 }, + { id: 173, text: 'training', count: 2 }, + { id: 172, text: 'training', count: 2 }, + ]; + component.checkedModules = modules; spyOn(component.searchEvent, 'emit'); - component.emitFilter(); + component.emitModules(); expect(component.searchEvent.emit).toHaveBeenCalled(); + expect(component.searchEvent.emit).toHaveBeenCalledWith(modules); + }); + it('should return an index or -1', () => { + const modules: Module[] = [ + { id: 176, text: 'training', count: 0 }, + { id: 173, text: 'training', count: 0 }, + { id: 172, text: 'training', count: 0 }, + ]; + component.checkedModules = modules; + const foundItem = component.getIndex(173, 'training'); + const notFoundItem = component.getIndex(189, 'training'); + expect(foundItem).toEqual(1); + expect(notFoundItem).toEqual(-1); + }); + it('should add a module to checkedModule array', () => { + const modules: Module[] = [ + { id: 176, text: 'training', count: 0 }, + { id: 173, text: 'training', count: 0 }, + { id: 172, text: 'training', count: 0 }, + ]; + component.checkedModules = modules; + const evt = { target: { checked: true, value: 175 } }; + component.onCheckboxChange(evt, 'training'); + expect(component.checkedModules.length).toEqual(4); + }); + it('should remove a module to checkedModule array', () => { + const modules: Module[] = [ + { id: 176, text: 'training', count: 0 }, + { id: 173, text: 'training', count: 0 }, + { id: 172, text: 'training', count: 0 }, + ]; + component.checkedModules = modules; + const evt = { target: { checked: false, value: 173 } }; + component.onCheckboxChange(evt, 'training'); + expect(component.checkedModules.length).toEqual(2); + }); + it('should remove all modules checked from same modal, here morefilters', () => { + const modules: Module[] = [ + { id: 176, text: 'morefilters', count: 0 }, + { id: 173, text: 'morefilters', count: 0 }, + { id: 172, text: 'morefilters', count: 0 }, + { id: 179, text: 'training', count: 0 }, + { id: 190, text: 'training', count: 0 }, + { id: 167, text: 'training', count: 0 }, + ]; + component.checkedModules = modules; + const category: Category = { name: 'morefilters', modules: [modules[0], modules[1], modules[2]] }; + component.categories = [category]; + component.clearFilters(); + expect(component.checkedModules.length).toEqual(3); }); }); diff --git a/src/app/structure-list/components/modal-filter/modal-filter.component.ts b/src/app/structure-list/components/modal-filter/modal-filter.component.ts index ff6050e60..2f46075fa 100644 --- a/src/app/structure-list/components/modal-filter/modal-filter.component.ts +++ b/src/app/structure-list/components/modal-filter/modal-filter.component.ts @@ -29,12 +29,12 @@ export class ModalFilterComponent implements OnInit { } // Return index of a specific module in array modules - private getIndex(id: number, categ: string): number { + public getIndex(id: number, categ: string): number { return this.checkedModules.findIndex((m: Module) => m.id === id && m.text === categ); } // Management of the checkbox event (Check / Uncheck) - private onCheckboxChange(event, categ: string): void { + public onCheckboxChange(event, categ: string): void { const checkValue: number = parseInt(event.target.value, 10); if (event.target.checked) { this.checkedModules.push(new Module(checkValue, categ)); @@ -47,7 +47,7 @@ export class ModalFilterComponent implements OnInit { } // Clear only filters in the current modal - private clearFilters(): void { + public clearFilters(): void { this.categories.forEach((categ: Category) => { categ.modules.forEach((module: Module) => { if (this.getIndex(module.id, categ.name) > -1) { @@ -57,8 +57,8 @@ export class ModalFilterComponent implements OnInit { }); } - // Sends an array containing all filters - public emitFilter(): void { + // Sends an array containing all modules + public emitModules(): void { this.searchEvent.emit(this.checkedModules); } } diff --git a/src/app/structure-list/components/search/search.component.ts b/src/app/structure-list/components/search/search.component.ts index 6db165c6c..5ad6e6a1f 100644 --- a/src/app/structure-list/components/search/search.component.ts +++ b/src/app/structure-list/components/search/search.component.ts @@ -23,12 +23,12 @@ export class SearchComponent implements OnInit { @Output() searchEvent = new EventEmitter(); // Form search input - private searchForm: FormGroup; + public searchForm: FormGroup; // Modal variable public categories: Category[]; - private modalTypeOpened: string; + public modalTypeOpened: string; // Checkbox variable - private checkedModulesFilter: Module[]; + public checkedModulesFilter: Module[]; ngOnInit(): void { // Will store the different categories -- GitLab From 82f2a129a935fc350b1bdeded742fb1116b90258 Mon Sep 17 00:00:00 2001 From: Jeremie BRISON <ext.sopra.jbrison@grandlyon.com> Date: Mon, 2 Nov 2020 17:36:08 +0100 Subject: [PATCH 46/50] Update debug.log --- debug.log | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/debug.log b/debug.log index 301edff39..168913fe1 100644 --- a/debug.log +++ b/debug.log @@ -1,2 +1 @@ -[1102/160447.168:ERROR:directory_reader_win.cc(43)] FindFirstFile: Le chemin d’accès spécifié est introuvable. (0x3) -[1102/165734.564:ERROR:directory_reader_win.cc(43)] FindFirstFile: Le chemin d’accès spécifié est introuvable. (0x3) +[1102/160447.168:ERROR:directory_reader_win.cc(43)] FindFirstFile: Le chemin d�acc�s sp�cifi� est introuvable. (0x3) -- GitLab From 4be3f698d993e30918ee555b7c8eb5522aea58e9 Mon Sep 17 00:00:00 2001 From: Hugo SUBTIL <ext.sopra.husubtil@grandlyon.com> Date: Mon, 2 Nov 2020 17:39:24 +0100 Subject: [PATCH 47/50] fix: put checkbox style in global style + small fixes --- .../modal-filter/modal-filter.component.scss | 55 ------------------ .../components/search/search.component.scss | 54 +----------------- .../components/search/search.component.ts | 10 ++-- src/styles.scss | 56 +++++++++++++++++++ 4 files changed, 61 insertions(+), 114 deletions(-) diff --git a/src/app/structure-list/components/modal-filter/modal-filter.component.scss b/src/app/structure-list/components/modal-filter/modal-filter.component.scss index 420969748..8317c3f19 100644 --- a/src/app/structure-list/components/modal-filter/modal-filter.component.scss +++ b/src/app/structure-list/components/modal-filter/modal-filter.component.scss @@ -99,58 +99,3 @@ } } } -.checkbox { - list-style-type: none; - input { - opacity: 0; - display: none; - &:checked ~ .customCheck { - background-color: $orange-light; - border-color: transparent; - } - &:checked ~ .customCheck:after { - display: block; - } - } - label { - align-items: center; - grid-template-columns: min-content auto; - display: inline-grid; - cursor: pointer; - } - .label { - padding-left: 8px; - @include cn-regular-14; - } - .customCheck { - display: inline-grid; - width: 18px; - height: 18px; - background-color: $white; - border: 1px solid $grey; - cursor: pointer; - position: relative; - - top: 0; - left: 0; - &:hover { - background-color: $grey-5; - } - &:after { - content: ''; - position: absolute; - display: none; - } - &:after { - left: 7px; - top: 3px; - width: 4px; - height: 8px; - border: solid $white; - border-width: 0 2px 2px 0; - transform: rotate(45deg); - -webkit-transform: rotate(45deg); - -ms-transform: rotate(45deg); - } - } -} diff --git a/src/app/structure-list/components/search/search.component.scss b/src/app/structure-list/components/search/search.component.scss index 279b2772b..6ee105f2f 100644 --- a/src/app/structure-list/components/search/search.component.scss +++ b/src/app/structure-list/components/search/search.component.scss @@ -49,6 +49,7 @@ @include background-hash; padding: 0 0 4px 5px; button { + border-radius: 6px; @include btn-search; @include cn-bold-14; } @@ -87,59 +88,6 @@ } } -.checkbox { - list-style-type: none; - input { - opacity: 0; - display: none; - &:checked ~ .customCheck { - background-color: $orange-light; - border-color: transparent; - } - &:checked ~ .customCheck:after { - display: block; - } - } - label { - align-items: center; - grid-template-columns: min-content auto; - display: inline-grid; - cursor: pointer; - } - .label { - padding-left: 8px; - @include cn-regular-14; - } - .customCheck { - display: inline-grid; - width: 18px; - height: 18px; - background-color: $white; - border: 1px solid $grey; - cursor: pointer; - position: relative; - - top: 0; - left: 0; - &:hover { - background-color: $grey-5; - } - &:after { - content: ''; - position: absolute; - display: none; - left: 7px; - top: 3px; - width: 4px; - height: 8px; - border: solid $white; - border-width: 0 2px 2px 0; - transform: rotate(45deg); - -webkit-transform: rotate(45deg); - -ms-transform: rotate(45deg); - } - } -} .footerSearchSection { margin: 17px 0px 17px 0px; diff --git a/src/app/structure-list/components/search/search.component.ts b/src/app/structure-list/components/search/search.component.ts index 5ad6e6a1f..10f0393f2 100644 --- a/src/app/structure-list/components/search/search.component.ts +++ b/src/app/structure-list/components/search/search.component.ts @@ -51,7 +51,7 @@ export class SearchComponent implements OnInit { // Sends an array containing all filters public applyFilter(term: string): void { // Add search input filter - let filters: Filter[] = []; + const filters: Filter[] = []; if (term) { filters.push(new Filter('nomDeVotreStructure', term, false)); } @@ -69,7 +69,7 @@ export class SearchComponent implements OnInit { } public fetchResults(checkedModules: Module[]): void { - let inputTerm = this.searchForm.get('searchTerm').value; + const inputTerm = this.searchForm.get('searchTerm').value; // Store checked modules this.checkedModulesFilter = checkedModules; @@ -91,7 +91,7 @@ export class SearchComponent implements OnInit { } private fromStringToIdExcel(categ: string): string { - let splitStr = categ.toLowerCase().split(' '); + const splitStr = categ.toLowerCase().split(' '); for (let i = 1; i < splitStr.length; i++) { splitStr[i] = splitStr[i].charAt(0).toUpperCase() + splitStr[i].substring(1); } @@ -105,9 +105,7 @@ export class SearchComponent implements OnInit { // Fake service api private mockService(module: Category[], titre: string, categ: any, nbCateg: number): void { - const category = new Category(); - category.name = titre; - category.modules = []; + const category = new Category({ name: titre, modules: [] }); for (let i = 0; i < nbCateg; i++) { category.modules.push(new Module(categ.id + i, categ.name + i)); } diff --git a/src/styles.scss b/src/styles.scss index b0d48863f..8f149c3a9 100644 --- a/src/styles.scss +++ b/src/styles.scss @@ -68,3 +68,59 @@ a { width: unset; } } + +/** Checkboxes **/ + +.checkbox { + list-style-type: none; + input { + opacity: 0; + display: none; + &:checked ~ .customCheck { + background-color: $primary-color; + border-color: transparent; + } + &:checked ~ .customCheck:after { + display: block; + } + } + label { + align-items: center; + grid-template-columns: min-content auto; + display: inline-grid; + cursor: pointer; + } + .label { + padding-left: 8px; + @include cn-regular-14; + } + .customCheck { + display: inline-grid; + width: 18px; + height: 18px; + background-color: $white; + border: 1px solid $grey; + cursor: pointer; + position: relative; + + top: 0; + left: 0; + &:hover { + background-color: $grey-5; + } + &:after { + content: ''; + position: absolute; + display: none; + left: 7px; + top: 3px; + width: 4px; + height: 8px; + border: solid $white; + border-width: 0 2px 2px 0; + transform: rotate(45deg); + -webkit-transform: rotate(45deg); + -ms-transform: rotate(45deg); + } + } +} -- GitLab From 4b9254baf0f2153040e779983ce1b8693425adc1 Mon Sep 17 00:00:00 2001 From: Hugo SUBTIL <ext.sopra.husubtil@grandlyon.com> Date: Mon, 2 Nov 2020 17:40:35 +0100 Subject: [PATCH 48/50] fix: remove debug.log --- debug.log | 1 - 1 file changed, 1 deletion(-) delete mode 100644 debug.log diff --git a/debug.log b/debug.log deleted file mode 100644 index 168913fe1..000000000 --- a/debug.log +++ /dev/null @@ -1 +0,0 @@ -[1102/160447.168:ERROR:directory_reader_win.cc(43)] FindFirstFile: Le chemin d�acc�s sp�cifi� est introuvable. (0x3) -- GitLab From e0ebab2600dff44cbf241a5f5068209c2bfbf397 Mon Sep 17 00:00:00 2001 From: Hugo SUBTIL <ext.sopra.husubtil@grandlyon.com> Date: Tue, 3 Nov 2020 09:18:45 +0100 Subject: [PATCH 49/50] fix: build budget --- angular.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/angular.json b/angular.json index 20abea0c5..6e95360f6 100644 --- a/angular.json +++ b/angular.json @@ -70,8 +70,8 @@ }, { "type": "anyComponentStyle", - "maximumWarning": "6kb", - "maximumError": "10kb" + "maximumWarning": "10kb", + "maximumError": "15kb" } ] }, -- GitLab From c0f25b1a18df364e6dba539caaf4a2374bd589cf Mon Sep 17 00:00:00 2001 From: Hugo SUBTIL <ext.sopra.husubtil@grandlyon.com> Date: Tue, 3 Nov 2020 09:55:45 +0100 Subject: [PATCH 50/50] feat: update back deploy --- api/Dockerfile | 11 ++++------- api/package.json | 4 ++-- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/api/Dockerfile b/api/Dockerfile index 4a8add9b9..8866e160e 100644 --- a/api/Dockerfile +++ b/api/Dockerfile @@ -1,18 +1,15 @@ -# Stage 0, based on Node.js -FROM node:12.16-slim +# Based on Node.js +FROM node:12.16 WORKDIR /app # Copy the package.json file first in order to cache the modules COPY . . -RUN mkdir api -RUN cp routes.json ./api - # Install npm dependencies RUN npm install # expose port 3000 -EXPOSE 80 3000 +EXPOSE 3000 -CMD ["npm", "run", "api"] +CMD ["npm", "start"] diff --git a/api/package.json b/api/package.json index a74b88aa6..997401923 100644 --- a/api/package.json +++ b/api/package.json @@ -1,8 +1,8 @@ { "name": "pamn-mock-api", - "version": "0.0.1", + "version": "0.1.0", "scripts": { - "api": "json-server api/db.json --routes api/routes.json --no-cors=true" + "start": "node server.js" }, "private": true, "dependencies": { -- GitLab