Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • web-et-numerique/factory/pamn_plateforme-des-acteurs-de-la-mediation-numerique/pamn_client
1 result
Show changes
Showing
with 1082 additions and 201 deletions
import { Component } from '@angular/core';
import { ICellRendererAngularComp } from 'ag-grid-angular';
import { ICellRendererParams } from 'ag-grid-community';
@Component({
selector: 'app-job-renderer',
template: ` <span>{{ jobName }}</span> `,
})
export class JobRenderer implements ICellRendererAngularComp {
public params!: ICellRendererParams;
public jobName: string;
agInit(params: ICellRendererParams): void {
this.params = params;
if (params.value) {
if (params.value.name) {
this.jobName = params.value.name;
} else if (params.data.name && !params.data.job) {
this.jobName = params.data.name;
} else {
this.jobName = params.value;
}
} else {
this.jobName = null;
}
}
refresh() {
return false;
}
}
......@@ -11,6 +11,7 @@
<div>
<h3 class="title" *ngIf="unVerifiedUsers">Utilisateurs non vérifiés ({{ unVerifiedUsers.length }})</h3>
<ag-grid-angular
*ngIf="validatedJobs && validatedEmployers"
class="ag-theme-alpine user-table"
[rowData]="unVerifiedUsers"
[columnDefs]="columnDefs"
......@@ -25,6 +26,7 @@
<div>
<h3 class="title" *ngIf="unAttachedUsers">Utilisateurs non rattachés ({{ unAttachedUsers.length }})</h3>
<ag-grid-angular
*ngIf="validatedJobs && validatedEmployers"
class="ag-theme-alpine user-table"
[rowData]="unAttachedUsers"
[columnDefs]="columnDefs"
......@@ -39,6 +41,7 @@
<div>
<h3 class="title" *ngIf="attachedUsers">Utilisateurs rattachés ({{ attachedUsers.length }})</h3>
<ag-grid-angular
*ngIf="validatedJobs && validatedEmployers"
class="ag-theme-alpine user-table"
[rowData]="attachedUsers"
[columnDefs]="columnDefs"
......@@ -57,3 +60,27 @@
[content]="'Voulez-vous vraiment supprimer cet utilisateur&nbsp;? (' + userToDelete.email + ')'"
(closed)="deleteUser(userToDelete, $event)"
></app-modal-confirmation>
<app-modal-confirmation
*ngIf="changingJobs"
[openned]="editJobModalOpenned"
[content]="
'Voulez-vous vraiment changer la fonction de cet utilisateur&nbsp;? (' +
changingJobs[1].name +
' par ' +
changingJobs[0].name +
')'
"
(closed)="editJob(changingJobs[0], changingJobs[1], $event, contextRow)"
></app-modal-confirmation>
<app-modal-confirmation
*ngIf="changingEmployers"
[openned]="editEmployerModalOpenned"
[content]="
'Voulez-vous vraiment changer l\'employeur de cet utilisateur&nbsp;? (' +
changingEmployers[1].name +
' par ' +
changingEmployers[0].name +
')'
"
(closed)="editEmployer(changingEmployers[0], changingEmployers[1], $event, contextRow)"
></app-modal-confirmation>
......@@ -2,6 +2,11 @@ import { Component } from '@angular/core';
import { User } from '../../../models/user.model';
import { AdminService } from '../../services/admin.service';
import { AdministredStructuresComponent } from './administred-structures/administred-structures.component';
import { JobRenderer } from './job-renderer/job-renderer.component';
import { Job } from '../../../models/job.model';
import { Employer } from '../../../models/employer.model';
import { EmployerRenderer } from './employer-renderer/employer-renderer.component';
import { NotificationService } from '../../../services/notification.service';
import { DeleteUserComponent } from './delete-user/delete-user.component';
@Component({
......@@ -13,8 +18,23 @@ export class ManageUsersComponent {
public attachedUsers: User[] = [];
public unAttachedUsers: User[] = [];
public unVerifiedUsers: User[] = [];
public validatedJobsName: String[] = [];
public validatedJobs: Job[] = [];
public validatedEmployersName: String[] = [];
public validatedEmployers: Employer[] = [];
public deleteModalOpenned = false;
public editJobModalOpenned = false;
public editEmployerModalOpenned = false;
public userToDelete: User = null;
public changingJobs: Job[] = [
{ name: null, hasPersonalOffer: true, validated: false },
{ name: null, hasPersonalOffer: true, validated: false },
];
public changingEmployers: Employer[] = [
{ name: null, validated: false },
{ name: null, validated: false },
];
public contextRow: any;
public columnDefs;
public frameworkComponents;
......@@ -33,7 +53,9 @@ export class ManageUsersComponent {
},
};
constructor(private adminService: AdminService) {
constructor(private adminService: AdminService, private notificationService: NotificationService) {
this.findValidatedJobs();
this.findValidatedEmployers();
this.columnDefs = [
{
headerName: 'Nom',
......@@ -49,7 +71,7 @@ export class ManageUsersComponent {
field: 'email',
},
{
minWidth: 150,
minWidth: 100,
headerName: 'Téléphone',
field: 'phone',
},
......@@ -61,6 +83,28 @@ export class ManageUsersComponent {
},
minWidth: 350,
},
{
headerName: 'Fonction',
field: 'job',
cellRenderer: 'jobRenderer',
cellEditor: 'agSelectCellEditor',
// Ag select cell editor doesn't accept an object a parameter.
// Only giving name to display in the select, then recompose the full object when filter on change.
cellEditorParams: {
values: this.validatedJobsName,
},
onCellValueChanged: this.onJobChange.bind(this),
},
{
headerName: 'Employeur',
field: 'employer',
cellRenderer: 'employerRenderer',
cellEditor: 'agSelectCellEditor',
cellEditorParams: {
values: this.validatedEmployersName,
},
onCellValueChanged: this.onEmployerChange.bind(this),
},
{
headerName: 'Actions',
editable: false,
......@@ -75,6 +119,8 @@ export class ManageUsersComponent {
];
this.frameworkComponents = {
deleteUserComponent: DeleteUserComponent,
jobRenderer: JobRenderer,
employerRenderer: EmployerRenderer,
administredStructuresComponent: AdministredStructuresComponent,
};
this.findAttachedUsers();
......@@ -86,6 +132,45 @@ export class ManageUsersComponent {
this.deleteUser(arg.data, false);
}
public onJobChange(arg): void {
const selectedJob = this.validatedJobs.find((job) => job.name === arg.newValue);
if (selectedJob && arg.oldValue === undefined) {
// user had no job assigned, and admin selected a job -> call setUserJob without modal
this.adminService.setUserJob(selectedJob._id, arg.data.id).subscribe(() => {
arg.node.data[arg.colDef.field] = selectedJob;
arg.api.refreshCells({ rowNodes: [arg.node], columns: [arg.column.colId] });
this.notificationService.showSuccess('La fonction a bien été attribuée.', '');
});
return;
}
if (selectedJob === arg.oldValue || selectedJob.name === arg.oldValue.name) {
arg.node.data[arg.colDef.field] = selectedJob;
arg.api.refreshCells({ rowNodes: [arg.node], columns: [arg.column.colId] });
return;
}
this.toggleEditJobModal(selectedJob, arg.oldValue, arg);
}
public onEmployerChange(arg): void {
const selectedEmployer = this.validatedEmployers.find((employ) => employ.name === arg.newValue);
if (selectedEmployer && arg.oldValue === undefined) {
// user had no employer assigned, and admin selected a employer -> call setUserEmployer
this.adminService.setUserEmployer(selectedEmployer._id, arg.data.id).subscribe(() => {
arg.node.data[arg.colDef.field] = selectedEmployer;
arg.api.refreshCells({ rowNodes: [arg.node], columns: [arg.column.colId] });
this.notificationService.showSuccess("L'employeur a bien été attribué.", '');
});
return;
}
if (selectedEmployer === arg.oldValue || selectedEmployer.name === arg.oldValue.name) {
arg.node.data[arg.colDef.field] = selectedEmployer;
arg.api.refreshCells({ rowNodes: [arg.node], columns: [arg.column.colId] });
return;
}
this.toggleEditEmployerModal(selectedEmployer, arg.oldValue, arg);
}
public deleteUser(user: User, shouldDelete: boolean): void {
this.toggleDeleteModal(user);
if (shouldDelete) {
......@@ -97,11 +182,74 @@ export class ManageUsersComponent {
}
}
public editJob(newJob: Job, oldJob: Job, shouldEdit: boolean, context?): void {
this.toggleEditJobModal(newJob, oldJob, context);
if (shouldEdit) {
// store newJob otherwise cell will only keep name value
this.adminService.setUserJob(newJob._id, context.node.data._id).subscribe((data) => {
context.node.data[context.colDef.field] = data.job;
context.api.refreshCells({ rowNodes: [context.node], columns: [context.column.colId] });
this.notificationService.showSuccess("L'opération a réussie.", '');
});
} else {
if (context.oldValue && context.oldValue.name) {
context.node.data[context.colDef.field] = context.oldValue;
context.api.refreshCells({ rowNodes: [context.node], columns: [context.column.colId] });
}
}
}
public editEmployer(newEmployer: Employer, oldEmployer: Employer, shouldEdit: boolean, context?): void {
this.toggleEditEmployerModal(newEmployer, oldEmployer, context);
if (shouldEdit) {
this.adminService.setUserEmployer(newEmployer._id, context.node.data._id).subscribe((data) => {
context.node.data[context.colDef.field] = data.employer;
context.api.refreshCells({ rowNodes: [context.node], columns: [context.column.colId] });
this.notificationService.showSuccess("L'opération a réussie.", '');
});
} else {
if (context.oldValue && context.oldValue.name) {
context.node.data[context.colDef.field] = context.oldValue;
context.api.refreshCells({ rowNodes: [context.node], columns: [context.column.colId] });
}
}
}
public toggleDeleteModal(userToDelete: User): void {
this.userToDelete = userToDelete;
this.deleteModalOpenned = !this.deleteModalOpenned;
}
public toggleEditJobModal(newValue: Job, oldValue: Job, dataGrid): void {
this.changingJobs = [newValue, oldValue];
this.contextRow = dataGrid;
this.editJobModalOpenned = !this.editJobModalOpenned;
}
public toggleEditEmployerModal(newValue: Employer, oldValue: Employer, dataGrid): void {
this.changingEmployers = [newValue, oldValue];
this.contextRow = dataGrid;
this.editEmployerModalOpenned = !this.editEmployerModalOpenned;
}
public findValidatedJobs(): void {
this.adminService.getJobs().subscribe((jobs) => {
this.validatedJobs = jobs;
jobs.map((job) => {
this.validatedJobsName.push(job.name);
});
});
}
public findValidatedEmployers(): void {
this.adminService.getEmployers().subscribe((employers) => {
this.validatedEmployers = employers;
employers.map((employer) => {
this.validatedEmployersName.push(employer.name);
});
});
}
public findAttachedUsers(): void {
this.adminService.getAttachedUsers().subscribe((users) => {
this.attachedUsers = users;
......@@ -114,6 +262,9 @@ export class ManageUsersComponent {
public findUnAttachedUsers(): void {
this.adminService.getUnAttachedUsers().subscribe((users) => {
this.unAttachedUsers = users;
this.unAttachedUsers.forEach((user) => {
user._id = user['id'];
});
});
}
......
......@@ -3,15 +3,17 @@
<div fxLayout="row" fxLayoutGap="20px" fxLayoutAlign="center center">
<button (click)="changeActiveFeature(features.pendingStructures)">Revendication structure</button>
<button (click)="changeActiveFeature(features.structuresList)">Liste structures</button>
<button (click)="changeActiveFeature(features.deleteUsers)">Gestion des utilisateurs</button>
<button (click)="changeActiveFeature(features.manageUsers)">Gestion des utilisateurs</button>
<button (click)="changeActiveFeature(features.lockdownInfo)">Gestion des infos covid</button>
<button (click)="changeActiveFeature(features.newsletterUsers)">Newsletter</button>
<button (click)="changeActiveFeature(features.jobsList)">Fonctions</button>
<button (click)="changeActiveFeature(features.employersList)">Employeurs</button>
<a target="_blank" class="custom-link" rel="noopener noreferrer" [href]="ghostLink">Ghost</a>
</div>
<div *ngIf="selectedFeature === features.structuresList">
<app-admin-structures-list></app-admin-structures-list>
</div>
<div *ngIf="selectedFeature === features.deleteUsers">
<div *ngIf="selectedFeature === features.manageUsers">
<app-admin-manage-users></app-admin-manage-users>
</div>
<div *ngIf="selectedFeature === features.pendingStructures">
......@@ -23,4 +25,10 @@
<div *ngIf="selectedFeature === features.newsletterUsers">
<app-admin-newsletter-users></app-admin-newsletter-users>
</div>
<div *ngIf="selectedFeature === features.jobsList">
<app-admin-manage-jobs></app-admin-manage-jobs>
</div>
<div *ngIf="selectedFeature === features.employersList">
<app-admin-manage-employers></app-admin-manage-employers>
</div>
</div>
import { Component, OnInit } from '@angular/core';
import { environment } from '../../../../environments/environment';
import { AdminPannelEnum } from '../../../shared/enum/adminPanel.enum';
import { PanelRouteService } from '../../services/panel-route.service';
@Component({
selector: 'app-admin-panel',
templateUrl: './panel.component.html',
providers: [PanelRouteService],
})
export class PanelComponent implements OnInit {
public features = AdminPannelEnum;
public ghostLink = environment.ghostAdmin;
public selectedFeature;
constructor() {}
constructor(private panelRouteService: PanelRouteService) {
this.panelRouteService.destinationChanged$.subscribe((selected: AdminPannelEnum) => {
this.selectedFeature = selected;
});
}
ngOnInit(): void {
this.selectedFeature = this.features.pendingStructures;
......
import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import { Employer } from '../../models/employer.model';
import { Job } from '../../models/job.model';
import { NewsletterSubscription } from '../../models/subscription-model';
import { User } from '../../models/user.model';
import { StructureAdminInfo } from '../models/demandAttachment.model';
......@@ -10,6 +12,8 @@ import { StructureAdminInfo } from '../models/demandAttachment.model';
})
export class AdminService {
private readonly baseUrl = 'api/admin';
private readonly jobBaseUrl = 'api/jobs';
private readonly employerBaseUrl = 'api/employer';
constructor(private http: HttpClient) {}
// Return pendingAttachments of all profiles.
......@@ -26,19 +30,61 @@ export class AdminService {
}
public getUsers(): Observable<User[]> {
return this.http.get<User[]>(`api/admin/searchUsers`);
return this.http.get<User[]>(`${this.baseUrl}/searchUsers`);
}
public getAttachedUsers(): Observable<User[]> {
return this.http.get<User[]>(`api/admin/getAttachedUsers`);
return this.http.get<User[]>(`${this.baseUrl}/attachedUsers`);
}
public getUnAttachedUsers(): Observable<User[]> {
return this.http.get<User[]>(`api/admin/getUnAttachedUsers`);
return this.http.get<User[]>(`${this.baseUrl}/unAttachedUsers`);
}
public getUnVerifiedUsers(): Observable<User[]> {
return this.http.get<User[]>(`api/admin/getUnVerifiedUsers`);
return this.http.get<User[]>(`${this.baseUrl}/unVerifiedUsers`);
}
public setUserJob(jobId: string, userId: string): Observable<User> {
return this.http.put<User>(`${this.baseUrl}/setUserJob`, {
userId,
jobId,
});
}
public setUserEmployer(employerId: string, userId: string): Observable<User> {
return this.http.put<User>(`${this.baseUrl}/setUserEmployer`, {
userId,
employerId,
});
}
// By default return only validated jobs
public getJobs(): Observable<Job[]> {
return this.http.get<Job[]>(`api/jobs`);
}
// By default return only validated employers
public getEmployers(): Observable<Employer[]> {
return this.http.get<Employer[]>(`api/employer`);
}
// populated with users for admin purposes
public getUnvalidatedJobs(): Observable<Job[]> {
return this.http.get<Job[]>(`${this.jobBaseUrl}/unvalidated`);
}
// populated with users for admin purposes
public getValidatedJobs(): Observable<Job[]> {
return this.http.get<Job[]>(`${this.jobBaseUrl}/validated`);
}
public getUnvalidatedEmployers(): Observable<Employer[]> {
return this.http.get<Employer[]>(`${this.employerBaseUrl}/unvalidated`);
}
public getValidatedEmployers(): Observable<Employer[]> {
return this.http.get<Employer[]>(`${this.employerBaseUrl}/validated`);
}
public searchUsers(searchString: string): Observable<User[]> {
......@@ -49,6 +95,57 @@ export class AdminService {
return this.http.delete<User>(`${this.baseUrl}/user/` + id);
}
public deleteJob(id: string): Observable<Job> {
return this.http.delete<Job>(`${this.jobBaseUrl}/${id}`);
}
public deleteEmployer(id: string): Observable<Employer> {
return this.http.delete<Employer>(`${this.employerBaseUrl}/${id}`);
}
public createJob(name: string): Observable<Job> {
return this.http.post<Job>(`${this.jobBaseUrl}`, { name, hasPersonalOffer: true });
}
public createEmployer(name: string): Observable<Employer> {
return this.http.post<Employer>(`${this.employerBaseUrl}`, { name });
}
public validateJob(id: string): Observable<Job> {
return this.http.post<Job>(`${this.jobBaseUrl}/validate/${id}`, {});
}
public validateEmployer(id: string): Observable<Employer> {
return this.http.post<Employer>(`${this.employerBaseUrl}/validate/${id}`, {});
}
public editJob(id: string, name: string, hasPersonalOffer: boolean): Observable<Job> {
return this.http.put<Job>(`${this.jobBaseUrl}/${id}`, {
name,
hasPersonalOffer,
});
}
public editEmployer(id: string, name: string): Observable<Employer> {
return this.http.put<Employer>(`${this.employerBaseUrl}/${id}`, {
name,
});
}
public mergeEmployer(sourceEmployerId: string, targetEmployerId: string): Observable<Employer> {
return this.http.put<Employer>(`${this.employerBaseUrl}/merge`, {
sourceEmployerId,
targetEmployerId,
});
}
public mergeJob(sourceJobId: string, targetJobId: string): Observable<Job> {
return this.http.put<Job>(`${this.jobBaseUrl}/merge`, {
sourceJobId,
targetJobId,
});
}
public searchNewsletterSubscriptions(searchString: string): Observable<NewsletterSubscription[]> {
return this.http.post<NewsletterSubscription[]>(`${this.baseUrl}/searchNewsletterSubscriptions`, { searchString });
}
......
import { Injectable } from '@angular/core';
import { Subject } from 'rxjs';
import { AdminPannelEnum } from '../../shared/enum/adminPanel.enum';
@Injectable()
export class PanelRouteService {
private destination = new Subject<AdminPannelEnum>();
destinationChanged$ = this.destination.asObservable();
redirectTo(dest: AdminPannelEnum) {
this.destination.next(dest);
}
}
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { PageComponent } from './page/page.component';
import { Route, RouterModule, Routes } from '@angular/router';
import { CartoComponent } from './carto/carto.component';
import { ContactComponent } from './contact/contact.component';
import { FormComponent } from './form/structure-form/form.component';
import { FooterComponent } from './footer/footer.component';
import { StructureListPrintComponent } from './form/orientation-form/component/structure-list-print/structure-list-print.component';
import { OrientationFormComponent } from './form/orientation-form/orientation-form.component';
import { AdminGuard } from './guards/admin.guard';
import { AuthGuard } from './guards/auth.guard';
import { LoginGuard } from './guards/login.guard';
import { DeactivateGuard } from './guards/deactivate.guard';
import { CartoComponent } from './carto/carto.component';
import { LegalNoticeComponent } from './legal-notice/legal-notice.component';
import { LoginComponent } from './login/login.component';
import { NewsletterSubscriptionComponent } from './newsletter-subscription/newsletter-subscription.component';
import { PageComponent } from './page/page.component';
import { EditComponent } from './profile/edit/edit.component';
import { ResetEmailComponent } from './reset-email/reset-email.component';
import { ResetPasswordComponent } from './reset-password/reset-password.component';
import { TempUserResolver } from './resolvers/temp-user.resolver';
import { StructureJoinComponent } from './structure-join/structure-join.component';
import { StructureResolver } from './resolvers/structure.resolver';
import { PasswordFormComponent } from './shared/components';
import { StructureJoinComponent } from './structure/structure-join/structure-join.component';
import { StructureDetailsComponent } from './structure-list/components/structure-details/structure-details.component';
import { StructureListComponent } from './structure-list/structure-list.component';
import { UserVerificationComponent } from './user-verification/user-verification.component';
import { NewsletterSubscriptionComponent } from './newsletter-subscription/newsletter-subscription.component';
import { OrientationFormComponent } from './form/orientation-form/orientation-form.component';
import { StructureListPrintComponent } from './form/orientation-form/component/structure-list-print/structure-list-print.component';
import { StructureResolver } from './resolvers/structure.resolver';
import { RoleGuard } from './guards/role.guard';
import { RouteRole } from './shared/enum/routeRole.enum';
import { StructureExcludeComponent } from './structure/structure-exclude/structure-exclude.component';
const footerOutletRoute: Route = {
path: '',
outlet: 'footer',
component: FooterComponent,
};
const routes: Routes = [
{ path: 'print', outlet: 'print', children: [{ path: 'structure', component: StructureDetailsComponent }] },
{ path: 'print', outlet: 'print', children: [{ path: 'structures', component: StructureListPrintComponent }] },
{
path: 'print',
outlet: 'print',
children: [{ path: 'structure', component: StructureDetailsComponent }, footerOutletRoute],
},
{
path: 'print',
outlet: 'print',
children: [{ path: 'structures', component: StructureListPrintComponent }, footerOutletRoute],
},
{
path: 'orientation',
component: OrientationFormComponent,
children: [
{
path: '',
component: OrientationFormComponent,
},
footerOutletRoute,
],
},
{
path: 'acteurs',
component: CartoComponent,
children: [
{
path: '',
component: CartoComponent,
},
{
path: '',
outlet: 'left-pane',
component: StructureDetailsComponent,
},
],
},
{
path: 'login',
component: CartoComponent,
children: [
{
path: '',
component: LoginComponent,
},
footerOutletRoute,
],
},
{
path: 'structures',
component: StructureListComponent,
children: [
{
path: '',
component: StructureListComponent,
},
footerOutletRoute,
],
},
{
path: 'legal-notice',
component: LegalNoticeComponent,
children: [
{
path: '',
component: LegalNoticeComponent,
},
footerOutletRoute,
],
},
{
path: 'page/:slugPage',
component: PageComponent,
children: [
{
path: '',
component: PageComponent,
},
footerOutletRoute,
],
},
{
path: 'contact',
component: ContactComponent,
children: [
{
path: '',
component: ContactComponent,
},
footerOutletRoute,
],
},
{
path: 'users/verify/:id',
component: UserVerificationComponent,
},
{
path: 'register',
component: FormComponent,
canDeactivate: [DeactivateGuard],
resolve: {
user: TempUserResolver,
},
children: [
{
path: '',
component: LoginComponent,
},
footerOutletRoute,
],
},
{
path: 'change-email/:id',
component: ResetEmailComponent,
children: [
{
path: '',
component: ResetEmailComponent,
},
footerOutletRoute,
],
},
{
path: 'profile',
canActivate: [AuthGuard],
loadChildren: () => import('./profile/profile.module').then((m) => m.ProfileModule),
children: [
{
path: '',
canActivate: [AuthGuard],
loadChildren: () => import('./profile/profile.module').then((m) => m.ProfileModule),
},
{
path: 'edit',
canActivate: [AuthGuard],
component: EditComponent,
},
footerOutletRoute,
{
path: '',
outlet: 'left-pane',
data: { fullScreen: true },
component: StructureDetailsComponent,
},
],
},
{
path: 'join',
canActivate: [AuthGuard],
component: StructureJoinComponent,
path: 'join/:id',
children: [
{
path: '',
canActivate: [AuthGuard],
component: StructureJoinComponent,
resolve: {
structure: StructureResolver,
},
},
footerOutletRoute,
],
},
{
path: 'reset-password',
component: ResetPasswordComponent,
path: 'exclude',
children: [
{
path: '',
canActivate: [LoginGuard],
component: StructureExcludeComponent,
},
footerOutletRoute,
],
},
{
path: 'create-structure',
component: FormComponent,
canDeactivate: [DeactivateGuard],
path: 'reset-password',
children: [
{
path: '',
component: ResetPasswordComponent,
},
footerOutletRoute,
],
},
{
path: 'create-structure/:id',
component: FormComponent,
canDeactivate: [DeactivateGuard],
canActivate: [RoleGuard],
data: { allowedRoles: [RouteRole.structureAdmin] },
resolve: {
structure: StructureResolver,
},
path: 'new-password',
component: PasswordFormComponent,
},
{
path: 'newsletter',
component: NewsletterSubscriptionComponent,
children: [
{
path: '',
component: NewsletterSubscriptionComponent,
},
footerOutletRoute,
],
},
{
path: 'newsletter-unsubscribe',
component: NewsletterSubscriptionComponent,
children: [
{
path: '',
component: NewsletterSubscriptionComponent,
},
footerOutletRoute,
],
},
{
path: 'news',
loadChildren: () => import('./post/post.module').then((m) => m.PostModule),
children: [
{
path: '',
loadChildren: () => import('./post/post.module').then((m) => m.PostModule),
},
footerOutletRoute,
],
},
{
path: 'admin',
canActivate: [AdminGuard],
loadChildren: () => import('./admin/admin.module').then((m) => m.AdminModule),
children: [
{
path: '',
canActivate: [AdminGuard],
loadChildren: () => import('./admin/admin.module').then((m) => m.AdminModule),
},
footerOutletRoute,
],
},
{
path: 'form',
loadChildren: () => import('./form/form-view/form-view.module').then((m) => m.FormViewModule),
},
{
path: 'home',
......
<div class="app-container">
<app-header></app-header>
<div class="app-body">
<router-outlet name="left-pane"></router-outlet>
<router-outlet></router-outlet>
<router-outlet name="print"></router-outlet>
<app-footer></app-footer>
<router-outlet name="footer"></router-outlet>
</div>
</div>
......@@ -12,7 +12,7 @@ import { PrintService } from './shared/service/print.service';
styleUrls: ['./app.component.scss'],
})
export class AppComponent implements OnInit {
title = 'pamn';
title = 'resin';
constructor(
public printService: PrintService,
......
......@@ -17,22 +17,19 @@ import { StructureListComponent } from './structure-list/structure-list.componen
import { CardComponent } from './structure-list/components/card/card.component';
import { StructureListSearchComponent } from './structure-list/components/structure-list-search/structure-list-search.component';
import { StructureDetailsComponent } from './structure-list/components/structure-details/structure-details.component';
import { StructureOpeningStatusComponent } from './structure-list/components/structure-opening-status/structure-opening-status.component';
import { ModalFilterComponent } from './structure-list/components/modal-filter/modal-filter.component';
import { LegalNoticeComponent } from './legal-notice/legal-notice.component';
import { PageComponent } from './page/page.component';
import { ContactComponent } from './contact/contact.component';
import { FormComponent } from './form/structure-form/form.component';
import { UserVerificationComponent } from './user-verification/user-verification.component';
import { AuthGuard } from './guards/auth.guard';
import { LoginGuard } from './guards/login.guard';
import { CustomHttpInterceptor } from './config/http-interceptor';
import { ResetEmailComponent } from './reset-email/reset-email.component';
import { ResetPasswordComponent } from './reset-password/reset-password.component';
import { AdminGuard } from './guards/admin.guard';
import { DeactivateGuard } from './guards/deactivate.guard';
import { FooterFormComponent } from './form/footer-form/footer-form.component';
import { TempUserResolver } from './resolvers/temp-user.resolver';
import { StructureJoinComponent } from './structure-join/structure-join.component';
import { StructureJoinComponent } from './structure/structure-join/structure-join.component';
import { RouterListenerService } from './services/routerListener.service';
import { NewsletterSubscriptionComponent } from './newsletter-subscription/newsletter-subscription.component';
import { OrientationFormComponent } from './form/orientation-form/orientation-form.component';
......@@ -46,6 +43,9 @@ 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';
import { FormViewModule } from './form/form-view/form-view.module';
import { LoginComponent } from './login/login.component';
import { StructureExcludeComponent } from './structure/structure-exclude/structure-exclude.component';
@NgModule({
declarations: [
......@@ -58,15 +58,11 @@ import { DataShareConsentComponent } from './shared/components/data-share-consen
StructureListSearchComponent,
ModalFilterComponent,
StructureDetailsComponent,
StructureOpeningStatusComponent,
LegalNoticeComponent,
PageComponent,
ContactComponent,
UserVerificationComponent,
ResetEmailComponent,
ResetPasswordComponent,
FormComponent,
FooterFormComponent,
StructureJoinComponent,
NewsletterSubscriptionComponent,
OrientationFormComponent,
......@@ -75,6 +71,8 @@ import { DataShareConsentComponent } from './shared/components/data-share-consen
StructurePrintHeaderComponent,
DataShareConsentComponent,
OrientationComponent,
LoginComponent,
StructureExcludeComponent,
],
imports: [
BrowserModule,
......@@ -84,6 +82,7 @@ import { DataShareConsentComponent } from './shared/components/data-share-consen
MapModule,
BrowserAnimationsModule,
ToastrModule.forRoot(),
FormViewModule,
ServiceWorkerModule.register('ngsw-worker.js', {
enabled: environment.production,
}),
......@@ -95,6 +94,7 @@ import { DataShareConsentComponent } from './shared/components/data-share-consen
AuthGuard,
AdminGuard,
RoleGuard,
LoginGuard,
DeactivateGuard,
TempUserResolver,
StructureResolver,
......
<div fxLayout="row" class="content-container">
<app-structure-list
(searchEvent)="getStructures($event)"
[structureList]="structures"
[location]="currentLocation"
[locate]="locate"
(displayMapMarkerId)="setMapMarkerId($event)"
(selectedMarkerId)="setSelectedMarkerId($event)"
[selectedStructure]="currentStructure"
(updatedStructure)="updateStructures($event)"
(locatationReset)="locatationReset()"
(locatationTrigger)="locatationTrigger(null)"
class="left-pane"
[ngClass]="{ mapPhone: isMapPhone == true }"
fxLayout="column"
></app-structure-list>
<div class="btnSwitch">
<app-button
[style]="'roundedButton'"
[text]="isMapPhone ? 'Liste' : 'Carte'"
[iconBtn]="isMapPhone ? 'liste' : 'map-marker'"
(action)="switchMapList()"
></app-button>
<div class="content-container">
<div class="hide-on-print">
<app-structure-list-search (searchEvent)="getStructures($event)"></app-structure-list-search>
</div>
<div class="panes-container" fxLayout="row">
<app-structure-list
(searchEvent)="getStructures($event)"
[structureList]="structures"
[location]="currentLocation"
(displayMapMarkerId)="setMapMarkerId($event)"
(selectedMarkerId)="setSelectedMarkerId($event)"
[selectedStructure]="currentStructure"
(updatedStructure)="updateStructures($event)"
class="left-pane"
[ngClass]="{ mapPhone: isMapPhone == true }"
fxLayout="column"
></app-structure-list>
<div class="btnSwitch">
<app-button
[style]="buttonTypeEnum.ButtonPhone"
[text]="isMapPhone ? 'Liste' : 'Carte'"
[iconBtn]="isMapPhone ? 'liste' : 'map-markerButtonPhone'"
(action)="switchMapList()"
></app-button>
</div>
<app-map
[structures]="structures"
[toogleToolTipId]="displayMarkerId"
[selectedMarkerId]="selectedMarkerId"
(selectedStructure)="showDetailStructure($event)"
[isMapPhone]="isMapPhone"
[searchedValue]="searchedValue"
class="right-pane"
[ngClass]="{ mapPhone: isMapPhone == true }"
></app-map>
</div>
<app-map
[structures]="structures"
[toogleToolTipId]="displayMarkerId"
[selectedMarkerId]="selectedMarkerId"
[locate]="locate"
(selectedStructure)="showDetailStructure($event)"
(locatationTrigger)="locatationTrigger($event)"
[isMapPhone]="isMapPhone"
[searchedValue]="searchedValue"
class="right-pane"
[ngClass]="{ mapPhone: isMapPhone == true }"
></app-map>
</div>
@import '../../assets/scss/breakpoint';
@import '../../assets/scss/layout';
@import '../../assets/scss/z-index';
@import '../../assets/scss/color';
::ng-deep .footer {
@media #{$tablet} {
......@@ -8,36 +9,48 @@
}
}
.left-pane {
width: 640px;
min-width: 640px;
@media #{$tablet} {
width: 100%;
min-width: unset;
&.mapPhone {
display: none !important;
}
}
.content-container {
height: calc(100vh - #{$header-height});
background: $white;
padding-top: 0.6rem;
display: flex;
flex-direction: column;
}
.right-pane {
width: 80%;
padding: 0 16px;
@media #{$tablet} {
display: none;
&.mapPhone {
display: block;
.panes-container {
width: 100%;
position: relative;
flex: 1;
overflow-y: hidden;
overflow-x: hidden;
.left-pane {
height: 100%;
width: 600px;
min-width: 600px;
overflow-y: auto;
border-right: 1px solid $grey-4;
@media #{$tablet} {
width: 100%;
min-width: unset;
border-right: none;
&.mapPhone {
display: none !important;
}
}
width: 100%;
padding: 0;
}
}
.content-container {
height: calc(100vh - #{$header-height} - #{$footer-height});
@media #{$tablet} {
padding: 0;
height: calc(100vh - #{$header-height});
.right-pane {
height: 100%;
width: 100%;
@media #{$tablet} {
display: none;
&.mapPhone {
display: block;
}
padding: 0;
}
}
}
.btnSwitch {
position: fixed;
left: 50%;
......
import { Component, OnInit } from '@angular/core';
import { Meta } from '@angular/platform-browser';
const { DateTime } = require('luxon');
import { ActivatedRoute } from '@angular/router';
import * as _ from 'lodash';
import { GeoJson } from '../map/models/geojson.model';
import { Structure } from '../models/structure.model';
import { GeojsonService } from '../services/geojson.service';
import { StructureService } from '../services/structure.service';
import { ButtonType } from '../shared/components/button/buttonType.enum';
import { Filter } from '../structure-list/models/filter.model';
import { GeoJson } from '../map/models/geojson.model';
import { GeojsonService } from '../services/geojson.service';
import { CustomRegExp } from '../utils/CustomRegExp';
import { ActivatedRoute } from '@angular/router';
@Component({
selector: 'app-carto',
......@@ -17,6 +16,7 @@ import { ActivatedRoute } from '@angular/router';
styleUrls: ['./carto.component.scss'],
})
export class CartoComponent implements OnInit {
public filters: Filter[] = [];
public structures: Structure[] = [];
public displayMarkerId: string;
public selectedMarkerId: string;
......@@ -27,7 +27,7 @@ export class CartoComponent implements OnInit {
public userLongitude: number;
public isMapPhone = false;
public searchedValue = null;
public locate = false; // Use to sync location between search and map
public buttonTypeEnum = ButtonType;
constructor(
private structureService: StructureService,
private geoJsonService: GeojsonService,
......@@ -112,7 +112,7 @@ export class CartoComponent implements OnInit {
if (this.geolocation) {
structure = this.getStructurePosition(structure, lon, lat);
}
return this.structureService.updateOpeningStructure(structure);
return structure;
})
).then((structureList) => {
if (sortByDistance) {
......@@ -207,17 +207,4 @@ export class CartoComponent implements OnInit {
public switchMapList(): void {
this.isMapPhone = !this.isMapPhone;
}
public locatationTrigger(event: any): void {
if (event && event !== this.locate) {
this.locate = !this.locate;
}
if (!event) {
this.locate = true;
}
}
public locatationReset(): void {
this.locate = false;
}
}
......@@ -14,7 +14,7 @@
color: $white;
margin: 0px 0px 0px 10px;
text-decoration: none;
@include cn-regular-12;
@include lato-regular-12;
&:hover {
text-decoration: underline;
}
......
<div fxLayout="row" [ngClass]="{ column: hasFinishButton() }" fxLayoutGap="10px" fxLayoutAlign="center center">
<button *ngIf="displayPreviousButton" class="btn-primary small previous" (click)="goToPreviousPage()">
<div class="rowBtn" fxLayout="row" fxLayoutAlign="center center">
<svg class="chevronLeft" aria-hidden="true">
<use [attr.xlink:href]="'assets/form/sprite.svg#chevronLeft'"></use>
</svg>
{{ btnName[0] }}
</div>
</button>
<div
class="footerForm"
fxLayout="row"
[ngClass]="{ column: hasFinishButton() }"
fxLayoutGap="10px"
fxLayoutAlign="center center"
>
<app-button
*ngIf="!isLastFormStep && !isNextFormTransition && !isStructureLastPage() && !isPersonalOfferFirstPage()"
(action)="prevPage()"
[text]="!isEditMode ? btnName[0] : 'Annuler'"
[iconType]="'form'"
[iconBtn]="!isEditMode && 'chevronLeft'"
></app-button>
<button *ngIf="hasFinishButton()" class="btn-primary small previous" (click)="finishedModal()">
<div class="rowBtn" fxLayout="row" fxLayoutAlign="center center">
<svg class="flag" aria-hidden="true">
<use [attr.xlink:href]="'/assets/ico/flag.svg'"></use>
</svg>
{{ btnName[2] }}
</div>
</button>
<app-button
*ngIf="!isLastFormStep && !isNextFormTransition && !isEditMode"
(action)="nextPage()"
[disabled]="!isValid"
[text]="btnName[1]"
[iconBtn]="btnName[1] == 'Imprimer' ? 'print' : 'chevronRight'"
[iconType]="'form'"
[iconPos]="'right'"
[style]="buttonTypeEnum.Primary"
>
</app-button>
<button
class="btn-primary small next"
(click)="goToNextPage()"
<app-button
*ngIf="isEditMode"
(action)="saveEdit()"
[disabled]="!isValid"
type="submit"
[ngClass]="{ invalid: !isValid }"
[text]="'Valider'"
[style]="buttonTypeEnum.Primary"
>
<div *ngIf="btnName[1] == 'Imprimer'" fxLayout="row" fxLayoutAlign="center center">
<svg class="print" aria-hidden="true">
<use [attr.xlink:href]="'/assets/ico/print.svg'"></use>
</svg>
{{ btnName[1] }}
</div>
<div *ngIf="btnName[1] != 'Imprimer'" class="rowBtn" fxLayout="row" fxLayoutAlign="center center">
{{ btnName[1] }}
<svg class="chevronRight" aria-hidden="true">
<use [attr.xlink:href]="'assets/form/sprite.svg#chevronRight'"></use>
</svg>
</div>
</button>
</app-button>
</div>
......@@ -2,18 +2,22 @@
@import '../../../assets/scss/typography';
@import '../../../assets/scss/breakpoint';
.footerForm {
padding: 20px 0;
}
.btn-primary {
&.previous {
background-color: $white;
color: $grey-2;
border: solid $grey-4 1px;
color: $grey-1;
border: 1px solid $grey-1;
}
&.invalid {
opacity: 0.4;
}
&:focus .print {
background-color: $secondary-color;
background-color: $primary-color;
}
&.next {
......
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
import { Component, EventEmitter, Input, OnChanges, Output, SimpleChanges } from '@angular/core';
import { FormGroup } from '@angular/forms';
import { Router } from '@angular/router';
import { User } from '../../models/user.model';
import { ProfileService } from '../../profile/services/profile.service';
import { AuthService } from '../../services/auth.service';
import { NewsletterService } from '../../services/newsletter.service';
import { ButtonType } from '../../shared/components/button/buttonType.enum';
import { Utils } from '../../utils/utils';
import { accountFormStep } from '../form-view/account-form/accountFormStep.enum';
import { formType } from '../form-view/formType.enum';
import { personalOfferFormStep } from '../form-view/personal-offer-form/personalOfferFormStep.enum';
import { profileFormStep } from '../form-view/profile-form/profileFormStep.enum';
import { structureFormStep } from '../form-view/structure-form/structureFormStep.enum';
@Component({
selector: 'app-footer-form',
templateUrl: './footer-form.component.html',
styleUrls: ['./footer-form.component.scss'],
})
export class FooterFormComponent {
export class FooterFormComponent implements OnChanges {
@Input() currentForm: formType;
@Input() isValid: boolean;
@Input() isClaimMode: boolean;
@Input() isAccountMode: boolean;
@Input() btnName: string[];
@Input() displayPreviousButton: boolean = true;
@Output() nextPage = new EventEmitter<any>();
@Output() previousPage = new EventEmitter<any>();
@Input() nbPagesForm: number;
@Input() form: FormGroup;
@Input() linkedStructureId: Array<string> = null;
@Input() acceptNewsletter: boolean;
@Input() currentStep: accountFormStep | profileFormStep | structureFormStep | personalOfferFormStep;
@Input() hasOtherPersonalOffer: boolean;
@Input() isEditMode: boolean;
@Output() goNext = new EventEmitter<any>();
@Output() goPrev = new EventEmitter<any>();
@Output() endPage = new EventEmitter<any>();
@Output() endForm = new EventEmitter<any>();
@Output() changeCurrentStep = new EventEmitter<any>();
@Output() saveEditedStructure = new EventEmitter<any>();
public isLastFormStep: boolean = false;
public isNextFormTransition: boolean = false;
public buttonTypeEnum = ButtonType;
constructor(
private authService: AuthService,
public utils: Utils,
private router: Router,
private profileService: ProfileService,
private newsletterService: NewsletterService
) {}
public goToNextPage(): void {
this.nextPage.emit();
this.goNext.emit();
}
async ngOnChanges(changes: SimpleChanges): Promise<void> {
if (changes.currentStep) {
if (this.currentStep === accountFormStep.confirmEmailSentInfo && this.currentForm === formType.account) {
this.isLastFormStep = true;
}
if (
this.currentForm === formType.personaloffer &&
this.currentStep === personalOfferFormStep.personalOfferFinishedInfo &&
!this.hasOtherPersonalOffer
) {
this.isNextFormTransition = true;
}
if (this.currentForm === formType.structure && this.currentStep === structureFormStep.mailSentInfo) {
const user: User = await this.profileService.getProfile();
if (!user.job || !user.job.hasPersonalOffer) {
this.isLastFormStep = true;
}
}
if (
this.currentForm === formType.structure &&
(this.currentStep === structureFormStep.noStructure ||
this.currentStep === structureFormStep.StructureInfoUnknown)
) {
this.isLastFormStep = true;
}
}
}
public goToPreviousPage(): void {
this.previousPage.emit();
this.goPrev.emit();
}
public hasFinishButton(): boolean {
......@@ -27,4 +91,106 @@ export class FooterFormComponent {
public finishedModal(): void {
this.endPage.emit();
}
public goToHome(): void {
this.router.navigateByUrl('news');
}
public prevPage(): void {
if (!this.isEditMode) {
if (this.currentForm === formType.structure && this.currentStep === structureFormStep.structureType) {
this.changeCurrentStep.emit(structureFormStep.structureFormTime);
return;
}
this.goToPreviousPage();
} else {
history.back();
}
}
public async nextPage(): Promise<void> {
if (this.currentForm === formType.account && this.currentStep === accountFormStep.accountNewsletter) {
const user = new User(this.form.value);
// Create user with structure
user.structuresLink = this.linkedStructureId;
this.authService.register(user).subscribe(() => {});
this.newsletterService.newsletterSubscribe(user.email).subscribe(() => {});
document.getElementsByClassName('page')[0].scrollTo(0, 0);
}
if (this.isProfileLastPage()) {
this.endForm.emit({ formType: this.currentForm });
return;
}
if (this.currentForm === formType.structure) {
if (this.currentStep === structureFormStep.structureChoiceCompletion) {
const chooseCompleteStructInfo = this.form.get('choiceCompletion').value;
if (!chooseCompleteStructInfo) {
this.changeCurrentStep.emit(structureFormStep.StructureInfoUnknown);
return;
}
}
if (this.currentStep === structureFormStep.structureAccompanimentChoice) {
const hasPlaceOfReception = this.form.get('placeOfReception').value;
if (!hasPlaceOfReception) {
this.changeCurrentStep.emit(structureFormStep.noStructure);
return;
}
}
if (this.currentStep === structureFormStep.structureFormTime) {
this.changeCurrentStep.emit(structureFormStep.structureType);
return;
}
if (this.currentStep === structureFormStep.structureContactCompletion) {
//TODO Go to send mail page and send the mail
return;
}
}
if (this.isPersonalOfferpage()) {
this.endForm.emit({ formType: this.currentForm });
return;
}
if (this.isStructureChoiceValid()) {
this.endForm.emit({ formType: this.currentForm, formStep: this.currentStep });
return;
}
if (this.isStructureLastPage()) {
this.endForm.emit({ formType: this.currentForm, formStep: this.currentStep });
return;
}
this.goToNextPage();
}
public saveEdit(): void {
this.saveEditedStructure.emit();
}
private isStructureChoiceValid(): boolean {
return (
this.currentForm === formType.structure &&
this.currentStep === structureFormStep.structureChoice &&
this.form.value._id
);
}
public isStructureLastPage(): boolean {
return (
this.currentForm === formType.structure &&
(this.currentStep === structureFormStep.mailSentInfo ||
this.currentStep === structureFormStep.structureCreationFinishedInfo ||
this.currentStep === structureFormStep.noStructure ||
this.currentStep === structureFormStep.StructureInfoUnknown)
);
}
private isProfileLastPage(): boolean {
return this.currentForm === formType.profile && this.currentStep === profileFormStep.profileJobSelection;
}
private isPersonalOfferpage(): boolean {
return (
this.currentForm === formType.personaloffer &&
this.currentStep === personalOfferFormStep.personalOfferStructureChoice
);
}
public isPersonalOfferFirstPage(): boolean {
return this.currentStep === personalOfferFormStep.personalOfferAccompaniment;
}
}
<form
[formGroup]="accountForm"
*ngIf="accountForm && !profile"
(keyup.enter)="isPageValid && !isEditMode ? nextPage() : null"
>
<div class="title">
<h3>Quels identifiants utiliserez-vous pour vous connecter&nbsp;?</h3>
</div>
<div class="form-group" fxLayout="column">
<label for="email">Email du compte</label>
<p class="special invalid" *ngIf="this.accountForm.get('email').hasError('alreadyExist')">
L'email est déja utilisé.
</p>
<div fxLayout="row" fxLayoutGap="13px">
<input
type="text"
(input)="setValidationsForm()"
(keyup)="verifyUserExist($event.target.value)"
formControlName="email"
placeholder="exemple: prenom.nom@grandlyon.com"
class="form-input email-placeholder"
[readonly]="isAccountMode"
[ngClass]="{ disabled: isAccountMode }"
/>
<app-svg-icon
*ngIf="accountForm.get('email').valid"
[iconClass]="'icon-26'"
[type]="'form'"
[icon]="'validate'"
></app-svg-icon>
<app-svg-icon
*ngIf="accountForm.get('email').invalid && accountForm.get('email').value"
[iconClass]="'icon-26'"
[type]="'form'"
[icon]="'notValidate'"
></app-svg-icon>
</div>
</div>
<div class="form-group" fxLayout="column">
<p
class="special"
[ngClass]="{ invalid: accountForm.get('password').invalid && accountForm.get('password').value }"
>
Le mot de passe doit contenir au minimum
</p>
<ul>
<li
fxLayout="row"
fxLayoutAlign="start center"
fxLayoutGap="10px"
[ngClass]="{
invalid: accountForm.get('password').value.length < 8,
valid: accountForm.get('password').value.length >= 8
}"
class=""
>
<app-svg-icon
*ngIf="accountForm.get('password').value.length >= 8"
[iconClass]="'icon-16'"
[type]="'form'"
[icon]="'validate'"
></app-svg-icon>
<app-svg-icon
*ngIf="accountForm.get('password').value.length < 8"
[iconClass]="'icon-16'"
[type]="'form'"
[icon]="'notValidate'"
></app-svg-icon>
<p>8 caractères</p>
</li>
<li
fxLayout="row"
fxLayoutAlign="start center"
fxLayoutGap="10px"
[ngClass]="{
invalid: !checkIfPasswordHasSpecialChar(accountForm.get('password').value),
valid: checkIfPasswordHasSpecialChar(accountForm.get('password').value)
}"
>
<app-svg-icon
*ngIf="checkIfPasswordHasSpecialChar(accountForm.get('password').value)"
[iconClass]="'icon-16'"
[type]="'form'"
[icon]="'validate'"
></app-svg-icon>
<app-svg-icon
*ngIf="!checkIfPasswordHasSpecialChar(accountForm.get('password').value)"
[iconClass]="'icon-16'"
[type]="'form'"
[icon]="'notValidate'"
></app-svg-icon>
<p>un caractère spécial</p>
</li>
<li
fxLayout="row"
fxLayoutAlign="start center"
fxLayoutGap="10px"
[ngClass]="{
invalid: !checkIfPasswordHasLowerCase(accountForm.get('password').value),
valid: checkIfPasswordHasLowerCase(accountForm.get('password').value)
}"
>
<app-svg-icon
*ngIf="checkIfPasswordHasLowerCase(accountForm.get('password').value)"
[iconClass]="'icon-16'"
[type]="'form'"
[icon]="'validate'"
></app-svg-icon>
<app-svg-icon
*ngIf="!checkIfPasswordHasLowerCase(accountForm.get('password').value); s"
[iconClass]="'icon-16'"
[type]="'form'"
[icon]="'notValidate'"
></app-svg-icon>
<p>un caractère en minuscule</p>
</li>
<li
fxLayout="row"
fxLayoutAlign="start center"
fxLayoutGap="10px"
[ngClass]="{
invalid: !checkIfPasswordHasUpperCase(accountForm.get('password').value),
valid: checkIfPasswordHasUpperCase(accountForm.get('password').value)
}"
>
<app-svg-icon
*ngIf="checkIfPasswordHasUpperCase(accountForm.get('password').value)"
[iconClass]="'icon-16'"
[type]="'form'"
[icon]="'validate'"
></app-svg-icon>
<app-svg-icon
*ngIf="!checkIfPasswordHasUpperCase(accountForm.get('password').value); s"
[iconClass]="'icon-16'"
[type]="'form'"
[icon]="'notValidate'"
></app-svg-icon>
<p>un caractère en majuscule</p>
</li>
<li
fxLayout="row"
fxLayoutAlign="start center"
fxLayoutGap="10px"
[ngClass]="{
invalid: !checkIfPasswordHasDigit(accountForm.get('password').value),
valid: checkIfPasswordHasDigit(accountForm.get('password').value)
}"
>
<app-svg-icon
*ngIf="checkIfPasswordHasDigit(accountForm.get('password').value)"
[iconClass]="'icon-16'"
[type]="'form'"
[icon]="'validate'"
></app-svg-icon>
<app-svg-icon
*ngIf="!checkIfPasswordHasDigit(accountForm.get('password').value)"
[iconClass]="'icon-16'"
[type]="'form'"
[icon]="'notValidate'"
></app-svg-icon>
<p>un chiffre</p>
</li>
</ul>
<div fxLayout="row" fxLayoutAlign="none center" fxLayoutGap="13px">
<input
[type]="isShowPassword ? 'text' : 'password'"
formControlName="password"
class="form-input password"
(input)="setValidationsForm()"
autocomplete="on"
/>
<app-svg-icon
[iconClass]="'icon-26 grey hover'"
[type]="'form'"
[icon]="'eyePassword'"
(click)="showPassword()"
></app-svg-icon>
<app-svg-icon
*ngIf="accountForm.get('password').valid"
[iconClass]="'icon-26'"
[type]="'form'"
[icon]="'validate'"
></app-svg-icon>
<app-svg-icon
*ngIf="accountForm.get('password').invalid && accountForm.get('password').value"
[iconClass]="'icon-26'"
[type]="'form'"
[icon]="'notValidate'"
></app-svg-icon>
</div>
</div>
<div class="form-group" fxLayout="column">
<label for="confirmPassword">Vérification du mot de passe</label>
<div fxLayout="row" fxLayoutAlign="none center" fxLayoutGap="13px">
<input
[type]="isShowConfirmPassword ? 'text' : 'password'"
formControlName="confirmPassword"
class="form-input password"
(input)="setValidationsForm()"
autocomplete="on"
/>
<app-svg-icon
[iconClass]="'icon-26 grey hover'"
[type]="'form'"
[icon]="'eyePassword'"
(click)="showConfirmPassword()"
></app-svg-icon>
<app-svg-icon
*ngIf="accountForm.get('confirmPassword').valid && accountForm.get('confirmPassword').value"
[iconClass]="'icon-26'"
[type]="'form'"
[icon]="'validate'"
></app-svg-icon>
<app-svg-icon
*ngIf="accountForm.get('confirmPassword').invalid && accountForm.get('confirmPassword').value"
[iconClass]="'icon-26'"
[type]="'form'"
[icon]="'notValidate'"
></app-svg-icon>
</div>
</div>
</form>
@import '../../../../../assets/scss/color';
@import '../../../../../assets/scss/typography';
p.special {
@include lato-regular-14;
color: $grey-3;
margin: 4px 0;
width: 280px;
&.invalid {
color: $orange-warning;
}
}
ul {
padding-left: 0;
margin: 0 0 8px 8px;
li {
display: flex;
margin: 4px 0 0 0;
font-size: $font-size-xsmall;
align-items: center;
p {
margin-top: unset;
margin-bottom: 0;
}
&.valid {
color: $green;
}
&.invalid {
color: $orange-warning;
}
}
}