From 466ecd8bf2ac4b66859edbacead7345dfa9de2b9 Mon Sep 17 00:00:00 2001
From: Augustin LECONTE <["ext.sopra.aleconte@grandlyon.com"]>
Date: Mon, 28 Feb 2022 08:16:04 +0000
Subject: [PATCH 1/7] fix/issues-fix (#3 #4 #6 #7)

---
 .../manage-users/manage-users.component.ts    |  1 +
 src/app/carto/carto.component.scss            |  6 +++
 .../structure-detail-print.component.ts       | 37 +------------------
 .../post-details/post-details.component.scss  | 16 ++++++++
 4 files changed, 25 insertions(+), 35 deletions(-)

diff --git a/src/app/admin/components/manage-users/manage-users.component.ts b/src/app/admin/components/manage-users/manage-users.component.ts
index 5e89e6f04..d4713e661 100644
--- a/src/app/admin/components/manage-users/manage-users.component.ts
+++ b/src/app/admin/components/manage-users/manage-users.component.ts
@@ -63,6 +63,7 @@ export class ManageUsersComponent {
       },
       {
         headerName: 'Actions',
+        editable: false,
         minWidth: 150,
         cellRenderer: 'deleteUserComponent',
         cellRendererParams: {
diff --git a/src/app/carto/carto.component.scss b/src/app/carto/carto.component.scss
index 3fcf8948f..b30874632 100644
--- a/src/app/carto/carto.component.scss
+++ b/src/app/carto/carto.component.scss
@@ -2,6 +2,12 @@
 @import '../../assets/scss/layout';
 @import '../../assets/scss/z-index';
 
+::ng-deep .footer {
+  @media #{$tablet} {
+    display: none !important;
+  }
+}
+
 .left-pane {
   width: 640px;
   min-width: 640px;
diff --git a/src/app/form/orientation-form/component/structure-detail-print/structure-detail-print.component.ts b/src/app/form/orientation-form/component/structure-detail-print/structure-detail-print.component.ts
index d1e0fb6ed..eb6dc63bb 100644
--- a/src/app/form/orientation-form/component/structure-detail-print/structure-detail-print.component.ts
+++ b/src/app/form/orientation-form/component/structure-detail-print/structure-detail-print.component.ts
@@ -5,7 +5,6 @@ import { TclService } from '../../../../services/tcl.service';
 import { TclStopPoint } from '../../../../models/tclStopPoint.model';
 import { AuthService } from '../../../../services/auth.service';
 import { AccessModality } from '../../../../structure-list/enum/access-modality.enum';
-import { PublicCategorie } from '../../../../structure-list/enum/public.enum';
 @Component({
   selector: 'app-structure-detail-print',
   templateUrl: './structure-detail-print.component.html',
@@ -29,44 +28,12 @@ export class StructureDetailPrintComponent implements OnInit {
     }
   }
 
+  public keepOriginalOrder = (a, b) => a.key;
+
   public userIsLoggedIn(): boolean {
     return this.authService.isLoggedIn();
   }
 
-  public getAccessLabel(accessModality: AccessModality): string {
-    switch (accessModality) {
-      case AccessModality.free:
-        return 'Accès libre';
-      case AccessModality.meeting:
-        return 'Sur rendez-vous';
-      case AccessModality.meetingOnly:
-        return 'Uniquement sur RDV';
-      case AccessModality.numeric:
-        return 'Téléphone / Visio';
-      default:
-        return null;
-    }
-  }
-
-  public getPublicLabel(tagetPublic: PublicCategorie): string {
-    switch (tagetPublic) {
-      case PublicCategorie.young:
-        return 'Jeunes (16 - 25 ans)';
-      case PublicCategorie.adult:
-        return 'Adultes';
-      case PublicCategorie.elderly:
-        return 'Séniors (+ de 65 ans)';
-      case PublicCategorie.all:
-        return 'Tout public';
-      case PublicCategorie.under16Years:
-        return 'Moins de 16 ans';
-      case PublicCategorie.women:
-        return 'Uniquement femmes';
-      default:
-        return null;
-    }
-  }
-
   public getTclStopPoints(): void {
     this.tclService.getTclStopPointBycoord(this.structure.getLon(), this.structure.getLat()).subscribe((res) => {
       this.tclStopPoints = res;
diff --git a/src/app/post/components/post-details/post-details.component.scss b/src/app/post/components/post-details/post-details.component.scss
index 56d471bb1..38f180a38 100644
--- a/src/app/post/components/post-details/post-details.component.scss
+++ b/src/app/post/components/post-details/post-details.component.scss
@@ -22,9 +22,25 @@
 }
 
 .description {
+  div {
+    height: fit-content;
+  }
   ::ng-deep img {
     height: 100%;
   }
+  ::ng-deep iframe {
+    width: 100% !important;
+    max-height: 400px;
+    height: 100vw;
+  }
+  ::ng-deep .kg-embed-card {
+    max-height: 400px;
+    iframe {
+      width: 100% !important;
+      max-height: 100%;
+      min-height: 100px;
+    }
+  }
   ::ng-deep figure {
     figcaption {
       margin-top: 1%;
-- 
GitLab


From e52fbf5657b0a41d638f153bd6af708ec9f5cd60 Mon Sep 17 00:00:00 2001
From: Etienne LOUPIAS <eloupias@grandlyon.com>
Date: Wed, 2 Mar 2022 12:51:31 +0000
Subject: [PATCH 2/7] fix(orientation-form): set progression to 100 when
 clicking print

-- 
GitLab


From 42147665ecc287079acc03c169708b87daedcd2d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marl=C3=A8ne=20SIMONDANT?= <msimondant@grandlyon.com>
Date: Wed, 2 Mar 2022 13:31:20 +0000
Subject: [PATCH 3/7] feat(data-consent): add data sharing consent when
 creating and editing a structure and at log-in if no consent was ever
 registered for at least one of the user's structures

---
 src/app/app-routing.module.ts                 |   1 -
 src/app/app.module.ts                         |   2 +
 .../form/structure-form/form.component.html   | 123 ++++++++++++------
 .../form/structure-form/form.component.scss   |  11 +-
 src/app/form/structure-form/form.component.ts |  18 ++-
 src/app/header/header.component.html          |   4 +
 src/app/header/header.component.ts            |  22 ++++
 src/app/models/structure.model.ts             |   1 +
 src/app/profile/services/profile.service.ts   |   6 +
 src/app/services/structure.service.ts         |   5 +
 .../data-share-consent.component.html         |  62 +++++++++
 .../data-share-consent.component.scss         |  80 ++++++++++++
 .../data-share-consent.component.spec.ts      |  25 ++++
 .../data-share-consent.component.ts           |  86 ++++++++++++
 .../radio-form/radio-form.component.html      |   9 +-
 .../radio-form/radio-form.component.scss      |  11 ++
 .../radio-form/radio-form.component.ts        |  15 ++-
 17 files changed, 432 insertions(+), 49 deletions(-)
 create mode 100644 src/app/shared/components/data-share-consent/data-share-consent.component.html
 create mode 100644 src/app/shared/components/data-share-consent/data-share-consent.component.scss
 create mode 100644 src/app/shared/components/data-share-consent/data-share-consent.component.spec.ts
 create mode 100644 src/app/shared/components/data-share-consent/data-share-consent.component.ts

diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts
index 8718c9630..ea7f55407 100644
--- a/src/app/app-routing.module.ts
+++ b/src/app/app-routing.module.ts
@@ -102,7 +102,6 @@ const routes: Routes = [
     path: 'newsletter',
     component: NewsletterSubscriptionComponent,
   },
-
   {
     path: 'newsletter-unsubscribe',
     component: NewsletterSubscriptionComponent,
diff --git a/src/app/app.module.ts b/src/app/app.module.ts
index eb67d95d7..4496fc8d9 100644
--- a/src/app/app.module.ts
+++ b/src/app/app.module.ts
@@ -45,6 +45,7 @@ import { environment } from '../environments/environment';
 import { StructureResolver } from './resolvers/structure.resolver';
 import { RoleGuard } from './guards/role.guard';
 import { UpdateService } from './services/update.service';
+import { DataShareConsentComponent } from './shared/components/data-share-consent/data-share-consent.component';
 
 @NgModule({
   declarations: [
@@ -72,6 +73,7 @@ import { UpdateService } from './services/update.service';
     StructureDetailPrintComponent,
     StructureListPrintComponent,
     StructurePrintHeaderComponent,
+    DataShareConsentComponent,
     OrientationComponent,
   ],
   imports: [
diff --git a/src/app/form/structure-form/form.component.html b/src/app/form/structure-form/form.component.html
index 8c2aee131..036171d93 100644
--- a/src/app/form/structure-form/form.component.html
+++ b/src/app/form/structure-form/form.component.html
@@ -85,7 +85,7 @@
       <div class="summary" *ngFor="let page of pagesValidation; let index = index">
         <div
           class="itemSummary"
-          [ngClass]="{ last: index == 22 }"
+          [ngClass]="{ last: index == lastPage }"
           fxLayout="row"
           fxLayoutAlign="space-between center"
           *ngIf="page.name && shouldDisplayPage(index)"
@@ -1285,49 +1285,88 @@
         </div>
       </div>
     </form>
-    <div *ngIf="currentPage == pageTypeEnum.cgu" class="page">
-      <div class="section">
-        <div class="title">
-          <h3>
-            Acceptez-vous que les informations saisies soient enregistrées par la Métropole de Lyon<span
-              class="asterisk"
-              >*</span
+    <form>
+      <div *ngIf="currentPage == pageTypeEnum.cgu" class="page">
+        <div class="section" *ngIf="!isEditMode">
+          <div class="title">
+            <h3>
+              Acceptez-vous que les informations saisies soient enregistrées par la Métropole de Lyon<span
+                class="asterisk"
+                >*</span
+              >
+              ?
+            </h3>
+          </div>
+          <app-checkbox-form
+            [isChecked]="userAcceptSavedDate"
+            [text]="'J\'accepte'"
+            (checkEvent)="acceptDataBeSaved($event)"
+          >
+          </app-checkbox-form>
+        </div>
+        <div class="section">
+          <div class="title">
+            <h3>
+              Acceptez-vous que les informations de votre structure soient mises à disposition sur la plateforme
+              data.grandlyon.com<span class="asterisk" *ngIf="!isEditMode">**</span
+              ><span class="asterisk" *ngIf="isEditMode">*</span> ?
+            </h3>
+            <p class="notRequired" *ngIf="!isEditMode">facultatif</p>
+          </div>
+          <app-checkbox-form
+            *ngIf="!isEditMode"
+            [text]="'J\'accepte'"
+            (checkEvent)="acceptOpenData($event)"
+          ></app-checkbox-form>
+          <div class="dataShareConsent">
+            <app-radio-form
+              *ngIf="isEditMode"
+              name="{{ getStructureControl('structureName').value }}"
+              horizontal="true"
+              [selectedOption]="getStructureControl('dataShareConsentDate').value === null ? false : true"
+              (selectedEvent)="onRadioBtnChange('dataShareConsentDate', $event)"
             >
-            ?
-          </h3>
+            </app-radio-form>
+          </div>
         </div>
-        <app-checkbox-form
-          [isChecked]="userAcceptSavedDate"
-          [text]="'J\'accepte'"
-          (checkEvent)="acceptDataBeSaved($event)"
-        >
-        </app-checkbox-form>
-      </div>
-      <div *ngIf="!profile">
-        <div class="title">
-          <h3>Acceptez-vous de recevoir des mails d'informations de la part de Res'in ?</h3>
+        <div *ngIf="!profile">
+          <div class="title">
+            <h3>Souhaitez-vous vous abonner à la lettre d’information de Res'in ?</h3>
+            <p class="notRequired" *ngIf="!isEditMode">facultatif</p>
+          </div>
+          <app-checkbox-form
+            [isChecked]="userAcceptNewsletter"
+            [text]="'J\'accepte'"
+            (checkEvent)="acceptReceiveNewsletter($event)"
+          >
+          </app-checkbox-form>
+        </div>
+        <p *ngIf="!isEditMode" class="informationEndForm">
+          <span class="asterisk">*</span> Les informations recueillies sont enregistrées dans un fichier par la
+          Métropole de Lyon en vue de l'animation du réseau des acteurs de la médiation numérique. Elles sont conservées
+          pendant 24 mois et sont destinées aux seuls intervenants habilités de la Métropole de Lyon. Vos données
+          personnelles sont traitées dans ce cadre aux fins de recensement des actions de médiation numérique sur le
+          territoire de la métropole. Conformément à la loi 78-17 du 6 janvier 1978 modifiée relative à l'information,
+          aux fichiers et aux libertés, et au Règlement Général européen à la Protection des Données, vous avez la
+          possibilité d’exercer vos droits d’accès, de rectification, d’effacement, d’opposition, de limitation du
+          traitement et de révocation de votre consentement. Afin d'exercer vos droits, vous pouvez vous adresser : par
+          courrier postal à : Métropole de Lyon - Direction des Affaires Juridiques et de la Commande Publique - 20, rue
+          du Lac - BP 33569 - 69505 Lyon Cedex par courrier électronique en remplissant le formulaire dédié sur Toodego,
+          le site des services et démarches en ligne dans la Métropole de Lyon
+        </p>
+        <div class="page" *ngIf="currentPage == pageTypeEnum.cgu">
+          <p class="informationEndForm">
+            <span class="asterisk" *ngIf="!isEditMode">**</span><span class="asterisk" *ngIf="isEditMode">*</span> La
+            Métropole de Lyon, engagée pour la transparence de l’action publique et la valorisation de ses partenaires,
+            encourage l’ouverture des données. Les données de votre structure seront publiées sur la plateforme
+            <a href="https://data.grandlyon.com/" target="_blank">https://data.grandlyon.com/</a> sous la licence
+            ouverte (open data) et seront donc librement accessibles et réutilisables. Vous pourrez modifier votre choix
+            à tout moment, exercer vos droits d’accès et de modification, en le signifiant, par tout moyen à votre
+            convenance, auprès de vos interlocuteurs de la Métropole de Lyon.
+          </p>
         </div>
-        <app-checkbox-form
-          [isChecked]="userAcceptNewsletter"
-          [text]="'J\'accepte'"
-          (checkEvent)="acceptReceiveNewsletter($event)"
-        >
-        </app-checkbox-form>
       </div>
-      <p class="informationEndForm">
-        <span class="asterisk">*</span> Les informations recueillies sont enregistrées dans un fichier par la Métropole
-        de Lyon en vue de l'animation du réseau des acteurs de la médiation numérique. Elles sont conservées pendant 24
-        mois et sont destinées aux seuls intervenants habilités de la Métropole de Lyon. Vos données personnelles sont
-        traitées dans ce cadre aux fins de recensement des actions de médiation numérique sur le territoire de la
-        métropole. Conformément à la loi 78-17 du 6 janvier 1978 modifiée relative à l'information, aux fichiers et aux
-        libertés, et au Règlement Général européen à la Protection des Données, vous avez la possibilité d’exercer vos
-        droits d’accès, de rectification, d’effacement, d’opposition, de limitation du traitement et de révocation de
-        votre consentement. Afin d'exercer vos droits, vous pouvez vous adresser : par courrier postal à : Métropole de
-        Lyon - Direction des Affaires Juridiques et de la Commande Publique - 20, rue du Lac - BP 33569 - 69505 Lyon
-        Cedex par courrier électronique en remplissant le formulaire dédié sur Toodego, le site des services et
-        démarches en ligne dans la Métropole de Lyon
-      </p>
-    </div>
+    </form>
     <div
       *ngIf="currentPage == nbPagesForm && !profile"
       class="page"
@@ -1340,7 +1379,7 @@
       </svg>
       <h3>Un courriel vous a été envoyé afin de valider votre inscription</h3>
     </div>
-    <div *ngIf="currentPage == nbPagesForm && profile" class="lastPage">
+    <div *ngIf="currentPage == nbPagesForm && profile && !isEditMode" class="lastPage">
       <div class="lastPage">
         <div class="title">
           <h3>
@@ -1390,7 +1429,7 @@
         Ok
       </button>
       <button
-        *ngIf="currentPage == nbPagesForm && profile"
+        *ngIf="currentPage == nbPagesForm && profile && !isEditMode"
         class="btn-primary unique"
         routerLink="/acteurs"
         [queryParams]="{ id: createdStructure._id }"
diff --git a/src/app/form/structure-form/form.component.scss b/src/app/form/structure-form/form.component.scss
index 1fabc2e2c..9e499337c 100644
--- a/src/app/form/structure-form/form.component.scss
+++ b/src/app/form/structure-form/form.component.scss
@@ -189,6 +189,11 @@ h4 {
       margin-top: 18px;
       color: $grey-2;
       @include cn-regular-14;
+      a {
+        color: $default-link-color;
+        text-decoration: underline;
+        font-weight: bold;
+      }
     }
   }
   .textareaBlock {
@@ -560,7 +565,11 @@ img {
 .section {
   padding-bottom: 2rem;
 }
-
+.dataShareConsent {
+  ::ng-deep button p {
+    font-weight: normal !important;
+  }
+}
 .missing-information {
   display: flex;
   color: $orange-warning;
diff --git a/src/app/form/structure-form/form.component.ts b/src/app/form/structure-form/form.component.ts
index d0b4d04ad..5de928c31 100644
--- a/src/app/form/structure-form/form.component.ts
+++ b/src/app/form/structure-form/form.component.ts
@@ -83,6 +83,8 @@ export class FormComponent implements OnInit {
 
   // Structure id for edit mode
   public structureId: string;
+  // last page for edit form
+  public lastPage = this.pageTypeEnum.cgu;
 
   constructor(
     private structureService: StructureService,
@@ -320,6 +322,7 @@ export class FormComponent implements OnInit {
         Validators.min(0),
       ]),
       freeWorkShop: new FormControl(structure.freeWorkShop, [Validators.required]),
+      dataShareConsentDate: new FormControl(structure.dataShareConsentDate),
     });
   }
 
@@ -590,7 +593,14 @@ export class FormComponent implements OnInit {
         valid: this.getStructureControl('lockdownActivity').valid,
         name: 'Informations spécifiques à la période COVID',
       };
-      this.pagesValidation[PageTypeEnum.cgu] = { valid: this.userAcceptSavedDate };
+      if (this.isEditMode) {
+        this.pagesValidation[PageTypeEnum.cgu] = {
+          valid: this.getStructureControl('dataShareConsentDate').valid,
+          name: 'Partage de données sur data.grandlyon.com',
+        };
+      } else {
+        this.pagesValidation[PageTypeEnum.cgu] = { valid: this.userAcceptSavedDate };
+      }
       this.updatePageValid();
     }
   }
@@ -898,6 +908,12 @@ export class FormComponent implements OnInit {
     this.setValidationsForm();
   }
 
+  public acceptOpenData(isAccepted: boolean): void {
+    let now = new Date().toString();
+    this.getStructureControl('dataShareConsentDate').setValue(now);
+    this.setValidationsForm();
+  }
+
   public acceptReceiveNewsletter(isAccepted: boolean): void {
     this.userAcceptNewsletter = isAccepted;
   }
diff --git a/src/app/header/header.component.html b/src/app/header/header.component.html
index 87949d944..a44bb541e 100644
--- a/src/app/header/header.component.html
+++ b/src/app/header/header.component.html
@@ -57,6 +57,10 @@
 </div>
 
 <app-signup-modal *ngIf="displaySignUp" [openned]="isPopUpOpen" (closed)="closeSignUpModal($event)"></app-signup-modal>
+<app-data-share-consent
+  *ngIf="isDisplayDataShare"
+  [dataConsentPendingStructures]="dataConsentPendingStructures"
+></app-data-share-consent>
 
 <ng-template #customTitle>
   <img class="desktop-show logo-grand-lyon" width="108" height="37" src="/assets/logos/resin.svg" alt />
diff --git a/src/app/header/header.component.ts b/src/app/header/header.component.ts
index ee446b18f..e1cee9024 100644
--- a/src/app/header/header.component.ts
+++ b/src/app/header/header.component.ts
@@ -1,5 +1,6 @@
 import { Component, OnInit } from '@angular/core';
 import { ActivatedRoute, NavigationEnd, Router } from '@angular/router';
+import { Structure } from '../models/structure.model';
 import { ProfileService } from '../profile/services/profile.service';
 import { AuthService } from '../services/auth.service';
 
@@ -15,6 +16,9 @@ export class HeaderComponent implements OnInit {
   public currentRoute = '';
   public formRoute = '/create-structure';
   public returnUrl = null;
+  public dataConsentPendingStructures: Structure[];
+  private displayDataShare = false;
+  private loadingDataShare = false;
 
   constructor(
     private authService: AuthService,
@@ -53,6 +57,24 @@ export class HeaderComponent implements OnInit {
     return this.authService.isLoggedIn();
   }
 
+  public get isDisplayDataShare(): boolean {
+    if (this.displayDataShare) {
+      return this.displayDataShare;
+    } else {
+      if (this.isLoggedIn && !this.loadingDataShare) {
+        this.loadingDataShare = true;
+        this.profileService.getAllDataConsentPendingStructures().subscribe((dataConsentPendingStructures) => {
+          if (dataConsentPendingStructures.length) {
+            this.displayDataShare = true;
+            this.dataConsentPendingStructures = dataConsentPendingStructures;
+            return this.displayDataShare;
+          }
+        });
+      }
+    }
+    return false;
+  }
+
   public closeSignInModal(): void {
     this.isPopUpOpen = false;
     this.displaySignUp = true;
diff --git a/src/app/models/structure.model.ts b/src/app/models/structure.model.ts
index b66121725..f8dc38fd7 100644
--- a/src/app/models/structure.model.ts
+++ b/src/app/models/structure.model.ts
@@ -50,6 +50,7 @@ export class Structure {
 
   public distance?: number;
   public coord?: number[] = [];
+  public dataShareConsentDate?: string;
 
   public accountVerified: boolean = false;
 
diff --git a/src/app/profile/services/profile.service.ts b/src/app/profile/services/profile.service.ts
index 2f044a5f5..74158fb4b 100644
--- a/src/app/profile/services/profile.service.ts
+++ b/src/app/profile/services/profile.service.ts
@@ -5,6 +5,8 @@ import { User } from '../../models/user.model';
 import decode from 'jwt-decode';
 import { UserRole } from '../../shared/enum/userRole.enum';
 import { AuthService } from '../../services/auth.service';
+import { Structure } from '../../models/structure.model';
+import { map } from 'rxjs/operators';
 
 @Injectable({
   providedIn: 'root',
@@ -81,4 +83,8 @@ export class ProfileService {
   public isEmailAlreadyUsed(newMail: string): Observable<boolean> {
     return this.http.post<boolean>(`${this.baseUrl}/verify-exist-user`, { newMail });
   }
+
+  public getAllDataConsentPendingStructures(): Observable<Structure[]> {
+    return this.http.get<Structure[]>(`${this.baseUrl}/dataConsentValidation`);
+  }
 }
diff --git a/src/app/services/structure.service.ts b/src/app/services/structure.service.ts
index 71f6417cc..6135dd776 100644
--- a/src/app/services/structure.service.ts
+++ b/src/app/services/structure.service.ts
@@ -36,6 +36,11 @@ export class StructureService {
 
   public editStructure(structure: Structure): Observable<Structure> {
     structure.updatedAt = new Date().toString();
+    if (structure.dataShareConsentDate) {
+      structure.dataShareConsentDate = new Date().toString();
+    } else {
+      structure.dataShareConsentDate = null;
+    }
     const id = structure._id;
     delete structure._id; // id should not be provided for update
     return this.http.put(`${this.baseUrl}/${id}`, structure).pipe(map((item: Structure) => new Structure(item)));
diff --git a/src/app/shared/components/data-share-consent/data-share-consent.component.html b/src/app/shared/components/data-share-consent/data-share-consent.component.html
new file mode 100644
index 000000000..a978e92ff
--- /dev/null
+++ b/src/app/shared/components/data-share-consent/data-share-consent.component.html
@@ -0,0 +1,62 @@
+<div *ngIf="openned" class="modalBackground">
+  <div class="modal">
+    <div class="contentModal" fxLayout="column" fxLayoutAlign="space-around start">
+      <div class="form">
+        <div class="modalTitle">
+          <h3>
+            Acceptez-vous que les informations de vos structures soient mises à disposition sur la plateforme
+            data.grandlyon.com* ?
+          </h3>
+        </div>
+        <form [formGroup]="consentForm" class="dataShareConsent">
+          <app-radio-form
+            *ngIf="dataConsentPendingStructures && dataConsentPendingStructures.length > 1"
+            name="Toutes les structures"
+            horizontal="true"
+            (selectedEvent)="onRadioBtnChangeAll($event)"
+            [events]="eventsSubject.asObservable()"
+            layoutGap="8px"
+            class="firstLine"
+          ></app-radio-form>
+
+          <div *ngFor="let structure of dataConsentPendingStructures">
+            <app-radio-form
+              name="{{ structure.structureName }}"
+              horizontal="true"
+              [selectedOption]="
+                structure.dataShareConsentDate === undefined
+                  ? null
+                  : structure.dataShareConsentDate === null
+                  ? false
+                  : true
+              "
+              (selectedEvent)="onRadioBtnChangeStructure(structure._id, $event)"
+              layoutGap="8px"
+            ></app-radio-form>
+          </div>
+
+          <div class="footerModal" fxLayout="row" fxLayoutAlign="space-around center">
+            <button
+              (click)="onSubmit()"
+              class="btn-primary"
+              [disabled]="!isPageValid"
+              [ngClass]="{ invalid: !isPageValid }"
+            >
+              Valider
+            </button>
+          </div>
+        </form>
+
+        <p class="informationEndForm">
+          <span class="asterisk">*</span> La Métropole de Lyon, engagée pour la transparence de l’action publique et la
+          valorisation de ses partenaires, encourage l’ouverture des données. Les données de votre structure seront
+          publiées sur la plateforme
+          <a href="https://data.grandlyon.com/" target="_blank">https://data.grandlyon.com/</a> sous la licence ouverte
+          (open data) et seront donc librement accessibles et réutilisables. Vous pourrez modifier votre choix à tout
+          moment, exercer vos droits d’accès et de modification, en le signifiant, par tout moyen à votre convenance,
+          auprès de vos interlocuteurs de la Métropole de Lyon.
+        </p>
+      </div>
+    </div>
+  </div>
+</div>
diff --git a/src/app/shared/components/data-share-consent/data-share-consent.component.scss b/src/app/shared/components/data-share-consent/data-share-consent.component.scss
new file mode 100644
index 000000000..f7bbdfa94
--- /dev/null
+++ b/src/app/shared/components/data-share-consent/data-share-consent.component.scss
@@ -0,0 +1,80 @@
+@import '../../../../assets/scss/typography';
+@import '../../../../assets/scss/breakpoint';
+@import '../../../../assets/scss/color';
+@import '../../../../assets/scss/buttons';
+@import '../../../../assets/scss/z-index';
+@import '../../../../assets/scss/hyperlink';
+@import '../radio-form/radio-form.component.scss';
+
+.modalBackground .modal {
+  max-width: 700px;
+  @media #{$large-phone} {
+    max-width: 95%;
+  }
+}
+.modalTitle {
+  display: flex;
+  h3 {
+    margin-top: 6%;
+    width: 90%;
+  }
+}
+h3 {
+  @include cn-bold-26;
+  color: $black;
+  margin-top: 0;
+}
+.form {
+  max-width: 90%;
+  margin: 0 32px;
+  margin-bottom: 8%;
+}
+.footerModal {
+  button {
+    &.invalid {
+      opacity: 0.4;
+    }
+  }
+}
+.dataShareConsent {
+  ::ng-deep button,
+  ::ng-deep .name {
+    font-size: $font-size-small;
+    font-weight: normal;
+    margin: 4px 0;
+    height: 40px;
+    ::ng-deep p {
+      font-weight: normal !important;
+    }
+    @media #{$phone} {
+      height: auto;
+    }
+  }
+  ::ng-deep .name {
+    padding: 0 10px;
+  }
+  ::ng-deep button {
+    width: 162px;
+    height: 40px;
+  }
+  ::ng-deep .firstLine {
+    .name,
+    button {
+      background-color: $grey-4;
+      &.selected {
+        p {
+          color: $black;
+        }
+      }
+    }
+  }
+}
+.informationEndForm {
+  color: $grey-1;
+  font-size: $font-size-xsmall;
+  a {
+    color: $blue;
+    text-decoration: underline;
+    font-weight: bold;
+  }
+}
diff --git a/src/app/shared/components/data-share-consent/data-share-consent.component.spec.ts b/src/app/shared/components/data-share-consent/data-share-consent.component.spec.ts
new file mode 100644
index 000000000..a617845c6
--- /dev/null
+++ b/src/app/shared/components/data-share-consent/data-share-consent.component.spec.ts
@@ -0,0 +1,25 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { DataShareConsentComponent } from './data-share-consent.component';
+
+describe('DataShareConsentComponent', () => {
+  let component: DataShareConsentComponent;
+  let fixture: ComponentFixture<DataShareConsentComponent>;
+
+  beforeEach(async () => {
+    await TestBed.configureTestingModule({
+      declarations: [ DataShareConsentComponent ]
+    })
+    .compileComponents();
+  });
+
+  beforeEach(() => {
+    fixture = TestBed.createComponent(DataShareConsentComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});
diff --git a/src/app/shared/components/data-share-consent/data-share-consent.component.ts b/src/app/shared/components/data-share-consent/data-share-consent.component.ts
new file mode 100644
index 000000000..26785ea77
--- /dev/null
+++ b/src/app/shared/components/data-share-consent/data-share-consent.component.ts
@@ -0,0 +1,86 @@
+import { Component, Input, OnInit } from '@angular/core';
+import { AbstractControl, FormControl, FormGroup, Validators } from '@angular/forms';
+import { Subject } from 'rxjs';
+import { Structure } from '../../../models/structure.model';
+import { StructureService } from '../../../services/structure.service';
+
+@Component({
+  selector: 'app-data-share-consent',
+  templateUrl: './data-share-consent.component.html',
+  styleUrls: ['./data-share-consent.component.scss'],
+})
+export class DataShareConsentComponent implements OnInit {
+  public consentForm: FormGroup;
+  public isPageValid: boolean;
+  public loading = false;
+  public submitted = false;
+  public eventsSubject: Subject<Object> = new Subject<Object>();
+
+  constructor(private structureService: StructureService) {}
+
+  @Input() public openned: boolean = true;
+  @Input() public dataConsentPendingStructures: Structure[];
+
+  ngOnInit() {
+    this.consentForm = new FormGroup({});
+    for (let structure of this.dataConsentPendingStructures) {
+      this.consentForm.addControl(
+        structure._id,
+        new FormControl(structure.dataShareConsentDate, [Validators.required])
+      );
+    }
+  }
+
+  public getFormControl(nameControl: string): AbstractControl {
+    return this.consentForm.get(nameControl);
+  }
+
+  public getPendingStructure(id: string): Structure {
+    var result = this.dataConsentPendingStructures.filter(function (o) {
+      return o._id == id;
+    });
+    return result ? result[0] : null;
+  }
+
+  public onRadioBtnChangeAll(bool: boolean): void {
+    for (let structure of this.dataConsentPendingStructures) {
+      structure.dataShareConsentDate = bool ? new Date().toString() : null;
+      this.getFormControl(structure._id).setValue(bool);
+    }
+    this.setValidationsForm();
+  }
+
+  public onRadioBtnChangeStructure(controlName: string, bool: boolean): void {
+    this.getPendingStructure(controlName).dataShareConsentDate = bool ? new Date().toString() : null;
+    this.getFormControl(controlName).setValue(bool);
+
+    // select or unselect "all structures" radio button
+    let isAllYes: boolean = true;
+    let isAllNo: boolean = true;
+    for (let structure of this.dataConsentPendingStructures) {
+      isAllYes = isAllYes && this.getFormControl(structure._id).value === true;
+      isAllNo = isAllNo && this.getFormControl(structure._id).value === false;
+    }
+    this.eventsSubject.next(isAllYes ? true : isAllNo ? false : null);
+
+    this.setValidationsForm();
+  }
+
+  public setValidationsForm(): void {
+    let isPageValid: boolean = true;
+    for (let structure of this.dataConsentPendingStructures) {
+      isPageValid = isPageValid && this.getFormControl(structure._id).valid;
+    }
+    this.isPageValid = isPageValid;
+  }
+
+  public onSubmit(): void {
+    this.submitted = true;
+    this.loading = true;
+    for (let structure of this.dataConsentPendingStructures) {
+      this.structureService.editStructure(structure).subscribe((s: Structure) => {});
+    }
+    this.loading = false;
+    this.openned = false;
+  }
+}
diff --git a/src/app/shared/components/radio-form/radio-form.component.html b/src/app/shared/components/radio-form/radio-form.component.html
index b120dde99..a80aa999f 100644
--- a/src/app/shared/components/radio-form/radio-form.component.html
+++ b/src/app/shared/components/radio-form/radio-form.component.html
@@ -1,10 +1,13 @@
-<div [fxLayout]="horizontal ? 'row' : 'column'" [fxLayoutGap]="horizontal ? '17px' : ''">
+<div [fxLayout]="horizontal ? 'row' : 'column'" [fxLayoutGap]="horizontal ? (layoutGap ? layoutGap : '17px') : ''">
+  <div *ngIf="name" fxLayout="row" fxLayoutAlign=" center" [fxLayoutGap]="layoutGap ? layoutGap : '17px'" class="name">
+    {{ name }}
+  </div>
   <button
     (click)="clicked(true)"
     [ngClass]="{ selected: selectedOption && selectedOption != null }"
     fxLayout="row"
     fxLayoutAlign=" center"
-    fxLayoutGap="17px"
+    [fxLayoutGap]="layoutGap ? layoutGap : '17px'"
   >
     <div class="checkmark">
       <svg class="validate" aria-hidden="true">
@@ -18,7 +21,7 @@
     [ngClass]="{ selected: !selectedOption && selectedOption != null }"
     fxLayout="row"
     fxLayoutAlign=" center"
-    fxLayoutGap="17px"
+    [fxLayoutGap]="layoutGap ? layoutGap : '17px'"
   >
     <div class="checkmark">
       <svg class="validate" aria-hidden="true">
diff --git a/src/app/shared/components/radio-form/radio-form.component.scss b/src/app/shared/components/radio-form/radio-form.component.scss
index 81d1c661e..75ae988dc 100644
--- a/src/app/shared/components/radio-form/radio-form.component.scss
+++ b/src/app/shared/components/radio-form/radio-form.component.scss
@@ -49,3 +49,14 @@ button {
     border-radius: 10px;
   }
 }
+
+.name {
+  width: 310px;
+  background: $grey-6;
+  border-radius: 4px;
+  padding: 0 16px;
+  font-size: $font-size-small;
+  outline: none;
+  border: none;
+  margin: 8px 0;
+}
diff --git a/src/app/shared/components/radio-form/radio-form.component.ts b/src/app/shared/components/radio-form/radio-form.component.ts
index 84075f64f..e0fbd385b 100644
--- a/src/app/shared/components/radio-form/radio-form.component.ts
+++ b/src/app/shared/components/radio-form/radio-form.component.ts
@@ -1,4 +1,5 @@
 import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
+import { Observable, Subscription } from 'rxjs';
 
 @Component({
   selector: 'app-radio-form',
@@ -10,8 +11,20 @@ export class RadioFormComponent implements OnInit {
 
   @Input() public selectedOption: boolean;
   @Input() public horizontal: boolean;
+  @Input() public layoutGap: string;
+  @Input() public name: string;
+  @Input() events: Observable<Object>;
   @Output() selectedEvent: EventEmitter<boolean> = new EventEmitter<boolean>();
-  ngOnInit(): void {}
+
+  private eventsSubscription: Subscription;
+
+  ngOnInit(): void {
+    if (this.events) this.eventsSubscription = this.events.subscribe((data: boolean) => (this.selectedOption = data));
+  }
+
+  ngOnDestroy() {
+    if (this.eventsSubscription) this.eventsSubscription.unsubscribe();
+  }
 
   public clicked(bool: boolean): void {
     this.selectedOption = bool;
-- 
GitLab


From 2083c2a3576d2425896543ca6234cc6d8aed58a3 Mon Sep 17 00:00:00 2001
From: Marlene Simondant <msimondant@grandlyon.com>
Date: Wed, 2 Mar 2022 15:50:52 +0100
Subject: [PATCH 4/7] fix(data-consent) : the information text should be before
 the validation button

---
 .../data-share-consent.component.html         | 20 +++++++++----------
 1 file changed, 10 insertions(+), 10 deletions(-)

diff --git a/src/app/shared/components/data-share-consent/data-share-consent.component.html b/src/app/shared/components/data-share-consent/data-share-consent.component.html
index a978e92ff..1fc7aafb6 100644
--- a/src/app/shared/components/data-share-consent/data-share-consent.component.html
+++ b/src/app/shared/components/data-share-consent/data-share-consent.component.html
@@ -35,6 +35,16 @@
             ></app-radio-form>
           </div>
 
+          <p class="informationEndForm">
+            <span class="asterisk">*</span> La Métropole de Lyon, engagée pour la transparence de l’action publique et
+            la valorisation de ses partenaires, encourage l’ouverture des données. Les données de votre structure seront
+            publiées sur la plateforme
+            <a href="https://data.grandlyon.com/" target="_blank">https://data.grandlyon.com/</a> sous la licence
+            ouverte (open data) et seront donc librement accessibles et réutilisables. Vous pourrez modifier votre choix
+            à tout moment, exercer vos droits d’accès et de modification, en le signifiant, par tout moyen à votre
+            convenance, auprès de vos interlocuteurs de la Métropole de Lyon.
+          </p>
+
           <div class="footerModal" fxLayout="row" fxLayoutAlign="space-around center">
             <button
               (click)="onSubmit()"
@@ -46,16 +56,6 @@
             </button>
           </div>
         </form>
-
-        <p class="informationEndForm">
-          <span class="asterisk">*</span> La Métropole de Lyon, engagée pour la transparence de l’action publique et la
-          valorisation de ses partenaires, encourage l’ouverture des données. Les données de votre structure seront
-          publiées sur la plateforme
-          <a href="https://data.grandlyon.com/" target="_blank">https://data.grandlyon.com/</a> sous la licence ouverte
-          (open data) et seront donc librement accessibles et réutilisables. Vous pourrez modifier votre choix à tout
-          moment, exercer vos droits d’accès et de modification, en le signifiant, par tout moyen à votre convenance,
-          auprès de vos interlocuteurs de la Métropole de Lyon.
-        </p>
       </div>
     </div>
   </div>
-- 
GitLab


From 916739f91d9fb14334278a44a953a7bcdf1f575b Mon Sep 17 00:00:00 2001
From: Etienne LOUPIAS <eloupias@grandlyon.com>
Date: Fri, 4 Mar 2022 11:17:45 +0100
Subject: [PATCH 5/7] fix: typo and labels

---
 .../structure-detail-print.component.html                     | 4 ++--
 src/app/form/orientation-form/orientation-form.component.html | 2 +-
 src/app/form/structure-form/form.component.html               | 2 +-
 src/app/form/structure-form/form.component.scss               | 3 +++
 4 files changed, 7 insertions(+), 4 deletions(-)

diff --git a/src/app/form/orientation-form/component/structure-detail-print/structure-detail-print.component.html b/src/app/form/orientation-form/component/structure-detail-print/structure-detail-print.component.html
index eb6736c0e..1a4934a37 100644
--- a/src/app/form/orientation-form/component/structure-detail-print/structure-detail-print.component.html
+++ b/src/app/form/orientation-form/component/structure-detail-print/structure-detail-print.component.html
@@ -39,7 +39,7 @@
     <!-- Opening Hours -->
     <div fxLayout="row" class="w-100 mobile-column">
       <div *ngIf="structure.hours.hasData()" fxFlex="50%">
-        <h3 class="subtitle">Horaires d’ouverture au public</h3>
+        <h3 class="subtitle">Horaires</h3>
         <div fxLayout="column">
           <div *ngFor="let day of structure.hours | keyvalue: keepOriginalOrder">
             <div *ngIf="day.value.open">
@@ -60,7 +60,7 @@
       </div>
       <!-- accessModality -->
       <div *ngIf="structure.accessModality.length > 0" fxFlex="40%">
-        <h3 class="subtitle">Accès transports en commun</h3>
+        <h3 class="subtitle">Accès</h3>
         <div fxLayout="column">
           <div *ngFor="let tclStop of tclStopPoints">
             <div fxLayout="row wrap" fxLayoutGap="5px">
diff --git a/src/app/form/orientation-form/orientation-form.component.html b/src/app/form/orientation-form/orientation-form.component.html
index 3174a45f0..c8c0679cf 100644
--- a/src/app/form/orientation-form/orientation-form.component.html
+++ b/src/app/form/orientation-form/orientation-form.component.html
@@ -293,7 +293,7 @@
     <!-- ADDRESS SEARCH -->
     <div *ngIf="currentPage == pageTypeEnum.beneficiaryAddress" class="page">
       <div class="title">
-        <h3>Autour de quelle adresse chercher une structure ?</h3>
+        <h3>Autour de quelle adresse cherchez-vous une structure ?</h3>
         <p class="notRequired lg">facultatif</p>
       </div>
       <div class="form-group" fxLayout="column">
diff --git a/src/app/form/structure-form/form.component.html b/src/app/form/structure-form/form.component.html
index 036171d93..f943a8432 100644
--- a/src/app/form/structure-form/form.component.html
+++ b/src/app/form/structure-form/form.component.html
@@ -408,7 +408,7 @@
     >
       <div *ngIf="currentPage == pageTypeEnum.structureNameAndAddress" class="page">
         <div class="title">
-          <h3>Quelle structure voulez-vous réferencer ?</h3>
+          <h3>Quelle structure voulez-vous référencer ?</h3>
         </div>
         <p
           class="missing-information"
diff --git a/src/app/form/structure-form/form.component.scss b/src/app/form/structure-form/form.component.scss
index 9e499337c..7ab8c6a5c 100644
--- a/src/app/form/structure-form/form.component.scss
+++ b/src/app/form/structure-form/form.component.scss
@@ -195,6 +195,9 @@ h4 {
         font-weight: bold;
       }
     }
+    &.notRequired {
+      font-style: italic;
+    }
   }
   .textareaBlock {
     @media #{$tablet} {
-- 
GitLab


From a003d055cf594db61cdf4ca773194bd913aa4159 Mon Sep 17 00:00:00 2001
From: Etienne LOUPIAS <eloupias@grandlyon.com>
Date: Fri, 4 Mar 2022 14:30:28 +0100
Subject: [PATCH 6/7] fix(posts): load more posts with tag

---
 .../post-list/post-list.component.ts          | 22 ++++++++------
 src/app/post/services/post.service.ts         | 29 +++++++++----------
 2 files changed, 27 insertions(+), 24 deletions(-)

diff --git a/src/app/post/components/post-list/post-list.component.ts b/src/app/post/components/post-list/post-list.component.ts
index 38cad37da..b5347b836 100644
--- a/src/app/post/components/post-list/post-list.component.ts
+++ b/src/app/post/components/post-list/post-list.component.ts
@@ -56,11 +56,14 @@ export class PostListComponent implements OnInit {
           ...this.selectedLocationTagSlug,
           ...this.selectedPublicTagsSlug,
         ];
+        // Reset posts
+        this.resetPosts();
         // Apply search
-        this.getPosts(this.filters);
+        this.getPosts(1, this.filters);
       } else {
         // Init default news list
         this.allPosts = [];
+        this.filters = [];
         this.postService.getPosts(1).subscribe((news) => {
           this.fillArticles(news);
         });
@@ -84,7 +87,7 @@ export class PostListComponent implements OnInit {
     this.allPosts = [...headLineTag, ..._.difference(this.allPosts, headLineTag)];
   }
 
-  public getPosts(filters?: Tag[]): void {
+  public getPosts(page: number, filters?: Tag[]): void {
     // Parse filter
     let parsedFilters = null;
     if (filters) {
@@ -97,11 +100,8 @@ export class PostListComponent implements OnInit {
       }
     }
 
-    // Reset posts
-    this.resetPosts();
-
     this.isLoading = true;
-    this.postService.getPosts(1, parsedFilters).subscribe((news) => {
+    this.postService.getPosts(page, parsedFilters).subscribe((news) => {
       this.fillArticles(news);
     });
   }
@@ -135,9 +135,13 @@ export class PostListComponent implements OnInit {
   private loadMore(): void {
     if (this.pagination && this.pagination.page < this.pagination.pages) {
       this.isLoading = true;
-      this.postService.getPosts(this.pagination.next).subscribe((news) => {
-        this.fillArticles(news);
-      });
+      if (this.filters) {
+        this.getPosts(this.pagination.next, this.filters);
+      } else {
+        this.postService.getPosts(this.pagination.next).subscribe((news) => {
+          this.fillArticles(news);
+        });
+      }
     }
   }
 
diff --git a/src/app/post/services/post.service.ts b/src/app/post/services/post.service.ts
index 89020397d..e7f51cfd9 100644
--- a/src/app/post/services/post.service.ts
+++ b/src/app/post/services/post.service.ts
@@ -23,22 +23,21 @@ export class PostService {
   }
 
   public getPosts(page: number, tags?: string[]): Observable<PostWithMeta> {
-    if (!tags) {
-      return this.http
-        .get<PostWithMeta>(`${this.baseUrl}?page=${page}&include=tags,authors`)
-        .pipe(map((item: PostWithMeta) => new PostWithMeta(item)));
+    let tagsFilter = '';
+
+    if (tags) {
+      let tagsString = '';
+      // Transform tab filters to string filters
+      tags.forEach((tag, index) => {
+        tagsString += tag;
+        if (index != tags.length - 1) {
+          tagsString += '+tags:';
+        }
+      });
+      tagsFilter = `&filter=tags:${encodeURIComponent(tagsString)}`;
     }
-    let tagsString = '';
-    // Transform tab filters to string filters
-    tags.forEach((tag, index) => {
-      tagsString += tag;
-      if (index != tags.length - 1) {
-        tagsString += '+tags:';
-      }
-    });
-    return this.http
-      .get<PostWithMeta>(`${this.baseUrl}?include=tags,authors&filter=tags:${encodeURIComponent(tagsString)}`)
-      .pipe(map((item: PostWithMeta) => new PostWithMeta(item)));
+
+    return this.http.get<PostWithMeta>(`${this.baseUrl}?page=${page}&include=tags,authors${tagsFilter}`);
   }
 
   public getTags(): Observable<TagWithMeta> {
-- 
GitLab


From 490e659b55c0fc16fb69207b1e2a99e789239362 Mon Sep 17 00:00:00 2001
From: Hugo SUBTIL <ext.sopra.husubtil@grandlyon.com>
Date: Tue, 8 Mar 2022 11:30:08 +0100
Subject: [PATCH 7/7] chore(release): 1.15.0

---
 CHANGELOG.md      | 14 ++++++++++++++
 package-lock.json |  2 +-
 package.json      |  2 +-
 3 files changed, 16 insertions(+), 2 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 72bd55265..c4aed4b02 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,20 @@
 
 All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
 
+## [1.15.0](https://forge.grandlyon.com/web-et-numerique/pamn_plateforme-des-acteurs-de-la-mediation-numerique/pamn_client/compare/v1.14.0...v1.15.0) (2022-03-08)
+
+
+### Features
+
+* **data-consent:** add data sharing consent when creating and editing a structure and at log-in if no consent was ever registered for at least one of the user's structures ([4214766](https://forge.grandlyon.com/web-et-numerique/pamn_plateforme-des-acteurs-de-la-mediation-numerique/pamn_client/commit/42147665ecc287079acc03c169708b87daedcd2d))
+
+
+### Bug Fixes
+
+* **orientation-form:** set progression to 100 when clicking print ([e52fbf5](https://forge.grandlyon.com/web-et-numerique/pamn_plateforme-des-acteurs-de-la-mediation-numerique/pamn_client/commit/e52fbf5657b0a41d638f153bd6af708ec9f5cd60))
+* **posts:** load more posts with tag ([a003d05](https://forge.grandlyon.com/web-et-numerique/pamn_plateforme-des-acteurs-de-la-mediation-numerique/pamn_client/commit/a003d055cf594db61cdf4ca773194bd913aa4159))
+* typo and labels ([916739f](https://forge.grandlyon.com/web-et-numerique/pamn_plateforme-des-acteurs-de-la-mediation-numerique/pamn_client/commit/916739f91d9fb14334278a44a953a7bcdf1f575b))
+
 ## [1.14.0](https://forge.grandlyon.com/web-et-numerique/pamn_plateforme-des-acteurs-de-la-mediation-numerique/pamn_client/compare/v1.13.0...v1.14.0) (2022-02-21)
 
 
diff --git a/package-lock.json b/package-lock.json
index 17360dfd8..fd2d00ca8 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,6 +1,6 @@
 {
   "name": "pamn",
-  "version": "1.14.0",
+  "version": "1.15.0",
   "lockfileVersion": 1,
   "requires": true,
   "dependencies": {
diff --git a/package.json b/package.json
index e978d75bb..541783c6e 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "pamn",
-  "version": "1.14.0",
+  "version": "1.15.0",
   "scripts": {
     "ng": "ng",
     "start": "ng serve --configuration=fr --proxy-config proxy.conf.json",
-- 
GitLab