diff --git a/src/app/core/components/contact/contact.component.html b/src/app/core/components/contact/contact.component.html index c0077ff24fe75fe9e5554692dcce92cfc0662435..dd9a5bb5f4f2a874299810a5c58d223f32d5cb21 100644 --- a/src/app/core/components/contact/contact.component.html +++ b/src/app/core/components/contact/contact.component.html @@ -1,119 +1,123 @@ <h1 class="has-text-centered" i18n="@@contact.contactUs">Contact us</h1> <div class="contact-form-container"> - <h2 i18n="@@contact.contactForm">Form contact</h2> - <form [formGroup]="form" (ngSubmit)="send()"> - <div class="columns is-multiline"> + <div class="columns"> <div class="column is-12-mobile is-2-tablet is-3-desktop"> <h3 i18n="@@contact.identity">Identity</h3> </div> <div class="column is-12-mobile is-10-tablet is-9-desktop"> - <div class="fields-container"> - - <div class="field"> - <label class="label" for="lastname" i18n="@@contact.lastname">Lastname</label> - <p class="control has-icons-right"> - <input id="lastname" class="input" type="text" formControlName="lastname" (keyup)="toUppercase('lastname')" - [ngClass]="{'is-danger': fieldIsInvalid('lastname'), 'is-success': fieldIsValid('lastname')}"> - <span class="icon is-small is-right has-text-success" *ngIf="fieldIsValid('lastname')"> - <i class="fas fa-check-circle"></i> - </span> - <span class="icon is-small is-right has-text-danger" *ngIf="fieldIsInvalid('lastname')"> - <i class="fas fa-exclamation-circle"></i> - </span> - </p> - - <div class="incorrect-field-message" *ngIf="fieldIsInvalid('lastname')"> - <div *ngIf="form.controls['lastname'].errors.required" i18n="@@contact.errors.missingLastname"> - You must indicate a lastname. - </div> - <div *ngIf="form.controls['lastname'].errors.pattern" i18n="@@contact.errors.forbiddenCharacters"> - Special characters are forbidden. + <div class="fields-container" *ngIf="user !== null; else unauthenticatedUserTemplate"> + <p class="fullname">{{ user.firstname }} {{ user.lastname }}</p> + <p>{{ user.email }}</p> + </div> + <ng-template #unauthenticatedUserTemplate> + <div class="fields-container"> + + <div class="field"> + <label class="label" for="lastname" i18n="@@contact.lastname">Lastname</label> + <p class="control has-icons-right"> + <input id="lastname" class="input" type="text" formControlName="lastname" (keyup)="toUppercase('lastname')" + [ngClass]="{'is-danger': fieldIsInvalid('lastname'), 'is-success': fieldIsValid('lastname')}"> + <span class="icon is-small is-right has-text-success" *ngIf="fieldIsValid('lastname')"> + <i class="fas fa-check-circle"></i> + </span> + <span class="icon is-small is-right has-text-danger" *ngIf="fieldIsInvalid('lastname')"> + <i class="fas fa-exclamation-circle"></i> + </span> + </p> + + <div class="incorrect-field-message" *ngIf="fieldIsInvalid('lastname')"> + <div *ngIf="form.controls['lastname'].errors.required" i18n="@@contact.errors.missingLastname"> + You must indicate a lastname. + </div> + <div *ngIf="form.controls['lastname'].errors.pattern" i18n="@@contact.errors.forbiddenCharacters"> + Special characters are forbidden. + </div> </div> </div> - </div> - <div class="field"> - <label class="label" for="firstname" i18n="@@contact.firstname">Firstname</label> - <p class="control has-icons-right"> - <input id="firstname" class="input" type="text" (keyup)="toUppercase('firstname')" formControlName="firstname" - [ngClass]="{'is-danger': fieldIsInvalid('firstname'), 'is-success': fieldIsValid('firstname')}"> - <span class="icon is-small is-right has-text-success" *ngIf="fieldIsValid('firstname')"> - <i class="fas fa-check-circle"></i> - </span> - <span class="icon is-small is-right has-text-danger" *ngIf="fieldIsInvalid('firstname')"> - <i class="fas fa-exclamation-circle"></i> - </span> - </p> - - <div class="incorrect-field-message" *ngIf="fieldIsInvalid('firstname')"> - <div *ngIf="form.controls['firstname'].errors.required" i18n="@@contact.errors.missingFirstname"> - You must indicate a firstname. - </div> - <div *ngIf="form.controls['lastname'].errors.pattern" i18n="@@contact.errors.forbiddenCharacters"> - Special characters are forbidden. + <div class="field"> + <label class="label" for="firstname" i18n="@@contact.firstname">Firstname</label> + <p class="control has-icons-right"> + <input id="firstname" class="input" type="text" (keyup)="toUppercase('firstname')" formControlName="firstname" + [ngClass]="{'is-danger': fieldIsInvalid('firstname'), 'is-success': fieldIsValid('firstname')}"> + <span class="icon is-small is-right has-text-success" *ngIf="fieldIsValid('firstname')"> + <i class="fas fa-check-circle"></i> + </span> + <span class="icon is-small is-right has-text-danger" *ngIf="fieldIsInvalid('firstname')"> + <i class="fas fa-exclamation-circle"></i> + </span> + </p> + + <div class="incorrect-field-message" *ngIf="fieldIsInvalid('firstname')"> + <div *ngIf="form.controls['firstname'].errors.required" i18n="@@contact.errors.missingFirstname"> + You must indicate a firstname. + </div> + <div *ngIf="form.controls['lastname'].errors.pattern" i18n="@@contact.errors.forbiddenCharacters"> + Special characters are forbidden. + </div> </div> </div> - </div> - <div class="field"> - <label class="label" for="email" i18n="@@contact.email">Email</label> - <p class="control has-icons-right"> - <input id="email" class="input" type="email" formControlName="email" [ngClass]="{'is-danger': fieldIsInvalid('email'), 'is-success': fieldIsValid('email')}"> - <span class="icon is-small is-right has-text-success" *ngIf="fieldIsValid('email')"> - <i class="fas fa-check-circle"></i> - </span> - <span class="icon is-small is-right has-text-danger" *ngIf="fieldIsInvalid('email')"> - <i class="fas fa-exclamation-circle"></i> - </span> - </p> - - <div class="incorrect-field-message" *ngIf="fieldIsInvalid('email')"> - <div *ngIf="form.controls['email'].errors.required" i18n="@@contact.errors.missingEmail"> - You must enter an email address. - </div> + <div class="field"> + <label class="label" for="email" i18n="@@contact.email">Email</label> + <p class="control has-icons-right"> + <input id="email" class="input" type="email" formControlName="email" [ngClass]="{'is-danger': fieldIsInvalid('email'), 'is-success': fieldIsValid('email')}"> + <span class="icon is-small is-right has-text-success" *ngIf="fieldIsValid('email')"> + <i class="fas fa-check-circle"></i> + </span> + <span class="icon is-small is-right has-text-danger" *ngIf="fieldIsInvalid('email')"> + <i class="fas fa-exclamation-circle"></i> + </span> + </p> + + <div class="incorrect-field-message" *ngIf="fieldIsInvalid('email')"> + <div *ngIf="form.controls['email'].errors.required" i18n="@@contact.errors.missingEmail"> + You must enter an email address. + </div> - <div *ngIf="form.controls['email'].errors.email" i18n="@@contact.errors.invalidEmail"> - You must enter a valid email address. + <div *ngIf="form.controls['email'].errors.email" i18n="@@contact.errors.invalidEmail"> + You must enter a valid email address. + </div> </div> </div> - </div> - <div class="field"> - <label class="label" for="emailConfirmation" i18n="@@contact.emailConfirmation">Confirm your email - address</label> - <p class="control has-icons-right"> - <input blockCopyPaste id="emailConfirmation" class="input" type="email" formControlName="emailConfirmation" - [ngClass]="{'is-danger': emailConfirmationError || fieldIsInvalid('emailConfirmation'), 'is-success': !emailConfirmationError && fieldIsValid('emailConfirmation')}"> - <span class="icon is-small is-right has-text-success" *ngIf="!emailConfirmationError && fieldIsValid('emailConfirmation')"> - <i class="fas fa-check-circle"></i> - </span> - <span class="icon is-small is-right has-text-danger" *ngIf="emailConfirmationError || fieldIsInvalid('emailConfirmation')"> - <i class="fas fa-exclamation-circle"></i> - </span> - </p> - - <div class="incorrect-field-message" *ngIf="fieldIsInvalid('emailConfirmation')"> - <div *ngIf="form.controls['emailConfirmation'].errors.required" i18n="@@contact.errors.missingConfirmationEmail"> - You must confirm your email address. - </div> + <div class="field"> + <label class="label" for="emailConfirmation" i18n="@@contact.emailConfirmation">Confirm your email + address</label> + <p class="control has-icons-right"> + <input blockCopyPaste id="emailConfirmation" class="input" type="email" formControlName="emailConfirmation" + [ngClass]="{'is-danger': emailConfirmationError || fieldIsInvalid('emailConfirmation'), 'is-success': !emailConfirmationError && fieldIsValid('emailConfirmation')}"> + <span class="icon is-small is-right has-text-success" *ngIf="!emailConfirmationError && fieldIsValid('emailConfirmation')"> + <i class="fas fa-check-circle"></i> + </span> + <span class="icon is-small is-right has-text-danger" *ngIf="emailConfirmationError || fieldIsInvalid('emailConfirmation')"> + <i class="fas fa-exclamation-circle"></i> + </span> + </p> + + <div class="incorrect-field-message" *ngIf="fieldIsInvalid('emailConfirmation')"> + <div *ngIf="form.controls['emailConfirmation'].errors.required" i18n="@@contact.errors.missingConfirmationEmail"> + You must confirm your email address. + </div> - <div *ngIf="form.controls['emailConfirmation'].errors.email" i18n="@@contact.errors.invalidEmail"> - You must enter a valid email address. + <div *ngIf="form.controls['emailConfirmation'].errors.email" i18n="@@contact.errors.invalidEmail"> + You must enter a valid email address. + </div> </div> - </div> - <div class="incorrect-field-message" *ngIf="emailConfirmationError"> - <div *ngIf="emailConfirmationError" i18n="@@contact.errors.confirmationEmailNotCorresponding"> - You must enter the same email address. + <div class="incorrect-field-message" *ngIf="emailConfirmationError"> + <div *ngIf="emailConfirmationError" i18n="@@contact.errors.confirmationEmailNotCorresponding"> + You must enter the same email address. + </div> </div> </div> </div> - - </div> + </ng-template> </div> - + </div> + <div class="columns"> <div class="column is-12-mobile is-2-tablet is-3-desktop"> <h3 i18n="@@contact.message">Message</h3> </div> @@ -176,11 +180,17 @@ </div> </div> </div> - - <div class="has-text-right button-wrapper"> - <button class="button button-gl is-outlined" type="button" [disabled]="formDisabled" (click)="cancel()" i18n="@@contact.cancel">Cancel</button> - <button type="submit" class="button button-gl" [ngClass]="{'is-loading': formDisabled}" [disabled]="formIsInvalid || formDisabled" - i18n="@@contact.send">Send</button> + </div> + </div> + <div class="columns"> + <div class="column is-12"> + <div class="field"> + <div class="has-text-right button-wrapper"> + <button class="button button-gl is-outlined" type="button" [disabled]="formDisabled" (click)="cancel()" + i18n="@@contact.cancel">Cancel</button> + <button type="submit" class="button button-gl" [ngClass]="{'is-loading': formDisabled}" [disabled]="formIsInvalid || formDisabled" + i18n="@@contact.send">Send</button> + </div> </div> </div> </div> diff --git a/src/app/core/components/contact/contact.component.scss b/src/app/core/components/contact/contact.component.scss index 5b76c9a460dd64dedc83164f35c6b107013d95be..7e29d02c9af67951b5ae719248b7d89f533adec3 100644 --- a/src/app/core/components/contact/contact.component.scss +++ b/src/app/core/components/contact/contact.component.scss @@ -8,11 +8,6 @@ h1 { background-color: white; } -h2 { - font-size: 1.6rem; - margin-bottom: 2rem; -} - h3 { margin-top: 0; margin-bottom: 0; @@ -22,15 +17,28 @@ h3 { .contact-form-container { background-color: white; padding: 0 1rem 0 1rem; - margin-left: 1.5rem; - margin-right: 1.5rem; - margin-bottom: 1.25rem; + margin: 1.5rem; + .columns:first-of-type { + margin-top: 0; + } + + @media(max-width: $tablet) { + .columns { + .column:last-of-type { + border-top: solid 2px #f2f2f2; + } + } + } @media(min-width: $tablet) { .fields-container { width: 66%; } + + .columns { + border-bottom: solid 2px #f2f2f2; + } } label { @@ -42,6 +50,10 @@ h3 { } } + .fullname { + font-weight: bold; + } + .incorrect-field-message { color: #333745; font-style: italic; diff --git a/src/app/core/components/contact/contact.component.spec.ts b/src/app/core/components/contact/contact.component.spec.ts index c96cc896011afa63744b689c3eba64c88c058b0f..0e25bf27d52b359a65b27f98a573fb656de3d213 100644 --- a/src/app/core/components/contact/contact.component.spec.ts +++ b/src/app/core/components/contact/contact.component.spec.ts @@ -2,7 +2,7 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing'; import { ContactComponent } from './contact.component'; import { ReactiveFormsModule, FormControl, AbstractControl } from '@angular/forms'; -import { EmailService, NotificationService, NavigationHistoryService } from '../../services'; +import { EmailService, NotificationService, NavigationHistoryService, AuthService } from '../../services'; import { BehaviorSubject, of } from 'rxjs'; import { Email } from '../../models'; import { RouterTestingModule } from '@angular/router/testing'; @@ -33,6 +33,16 @@ export class EmailServiceMock { } +export class AuthServiceMock { + + constructor() { } + + get userIsSignedIn() { + return false; + } + +} + describe('ContactComponent', () => { let component: ContactComponent; let fixture: ComponentFixture<ContactComponent>; @@ -55,6 +65,10 @@ describe('ContactComponent', () => { provide: EmailService, useClass: EmailServiceMock, }, + { + provide: AuthService, + useClass: AuthServiceMock, + }, { provide: NotificationService, useClass: NotificationServiceMock, diff --git a/src/app/core/components/contact/contact.component.ts b/src/app/core/components/contact/contact.component.ts index e06099f82cabc4b6c1b0e82bd188d7004f70664e..92cd69478f20e62bee20c073e0a04dcd2681f906 100644 --- a/src/app/core/components/contact/contact.component.ts +++ b/src/app/core/components/contact/contact.component.ts @@ -1,7 +1,7 @@ import { Component, OnInit } from '@angular/core'; import { FormGroup, FormBuilder, Validators, FormControl } from '@angular/forms'; -import { EmailService, NotificationService, NavigationHistoryService } from '../../services'; -import { Email } from '../../models'; +import { EmailService, NotificationService, NavigationHistoryService, AuthService } from '../../services'; +import { Email, User } from '../../models'; import { subjects as Subjects, feedbackMessages } from '../../../../i18n/contact/contact'; import { Router, ActivatedRoute } from '@angular/router'; import { AppRoutes } from '../../../routes'; @@ -17,6 +17,7 @@ export class ContactComponent implements OnInit { subjectDropdownState = false; subjects: Subject[] = Subjects; // Keep this line in order to access the subjects in the html template selectedSubject: Subject = null; + user: User = null; constructor( private _fb: FormBuilder, @@ -25,6 +26,7 @@ export class ContactComponent implements OnInit { private _navigationHistoryService: NavigationHistoryService, private _router: Router, private _route: ActivatedRoute, + private _authService: AuthService, ) { this.form = this._fb.group( { @@ -43,6 +45,16 @@ export class ContactComponent implements OnInit { } ngOnInit() { + // if user authenticated then initialize the form with its name and email + if (this._authService.userIsSignedIn) { + this.user = this._authService.user; + this.form.controls.firstname.patchValue(this.user.firstname); + this.form.controls.lastname.patchValue(this.user.lastname); + this.form.controls.email.patchValue(this.user.email); + this.form.controls.emailConfirmation.patchValue(this.user.email); + } else { + this.user = null; + } this._route.queryParams.subscribe((params) => { if (params.subject) { this.selectedSubject = this.subjects.find(sub => sub.key === 'other'); @@ -153,6 +165,10 @@ export class ContactComponent implements OnInit { return (this.selectedSubject && this.selectedSubject.key) === 'other' ? true : false; } + get userIsSignedIn() { + return this._authService.userIsSignedIn; + } + toUppercase(controlName: string) { const input = this.form.controls[controlName].value; const uppercased = input.substring(0, 1).toUpperCase() + input.substring(1); diff --git a/src/app/core/components/header/header.component.spec.ts b/src/app/core/components/header/header.component.spec.ts index c39130af302155729b2f1232cfe9658ff2bb879b..bb988afa4439b5edcf383ac732c45fc69a37b6ec 100644 --- a/src/app/core/components/header/header.component.spec.ts +++ b/src/app/core/components/header/header.component.spec.ts @@ -13,7 +13,7 @@ export class AuthServiceMock { constructor() { } - userIsSignedIn() { + get userIsSignedIn() { return false; } @@ -65,7 +65,7 @@ describe('HeaderComponent', () => { } as Router; const authServiceMock = { - userIsSignedIn: () => { + get userIsSignedIn() { return false; }, } as AuthService; diff --git a/src/app/core/components/header/header.component.ts b/src/app/core/components/header/header.component.ts index ab8f8a535fb41b8da36e828c6d0e941845df706c..e17ac2464325c05c17a1afe30a0cc2bcfecfa1af 100644 --- a/src/app/core/components/header/header.component.ts +++ b/src/app/core/components/header/header.component.ts @@ -33,7 +33,7 @@ export class HeaderComponent implements OnInit { } get userIsSignedIn() { - return this._authService.userIsSignedIn(); + return this._authService.userIsSignedIn; } get username() { diff --git a/src/app/core/components/login/login.component.spec.ts b/src/app/core/components/login/login.component.spec.ts index 94ec03e78030be80e51d1e43fd819af65fb6a2ae..5a44fe2c6fce87959a919a7dcb97908f64630999 100644 --- a/src/app/core/components/login/login.component.spec.ts +++ b/src/app/core/components/login/login.component.spec.ts @@ -9,7 +9,7 @@ export class AuthServiceMock { constructor() { } - userIsSignedIn() { + get userIsSignedIn() { return false; } diff --git a/src/app/core/models/auth.model.ts b/src/app/core/models/auth.model.ts index 6de44da6faa4fc16e828b328272204e6b26a167a..c279c0d8691571f52f4503b0391e73eb6c9e6ff7 100644 --- a/src/app/core/models/auth.model.ts +++ b/src/app/core/models/auth.model.ts @@ -2,6 +2,7 @@ export class User { id: number; firstname: string; lastname: string; + email: string; // payload is the decrypted payload of the JWT token constructor(payload) { @@ -9,6 +10,7 @@ export class User { this.id = payload.id; this.firstname = payload.firstname; this.lastname = payload.lastname; + this.email = payload.email; } } } diff --git a/src/app/core/services/auth.service.ts b/src/app/core/services/auth.service.ts index 30ed859eec183a890ca7cc60e6c9921cc6c4e007..4bf38b2d5a87dd677d190400599ff40a7baa5c26 100644 --- a/src/app/core/services/auth.service.ts +++ b/src/app/core/services/auth.service.ts @@ -95,7 +95,7 @@ export class AuthService { return this._user; } - userIsSignedIn() { + get userIsSignedIn() { return this._user != null; } } diff --git a/src/i18n/messages.en.xlf b/src/i18n/messages.en.xlf index de3129be728f55667e3fc8c3ce67f1507333af24..cfcee6c0dd4031ee8ac28fc36d89d09a0b76baf9 100644 --- a/src/i18n/messages.en.xlf +++ b/src/i18n/messages.en.xlf @@ -307,10 +307,6 @@ <source>Contact us</source> <target>Contact us</target> </trans-unit> - <trans-unit id="contact.contactForm" datatype="html"> - <source>Form contact</source> - <target>Form contact</target> - </trans-unit> <trans-unit id="contact.identity" datatype="html"> <source>Identity</source> <target>Identity</target> diff --git a/src/i18n/messages.fr.xlf b/src/i18n/messages.fr.xlf index 2e716c421ba9a90eea8eea6636c8735c680e30a8..199e92a9ac7b2148a213c6e2b08a82211713679c 100644 --- a/src/i18n/messages.fr.xlf +++ b/src/i18n/messages.fr.xlf @@ -315,10 +315,6 @@ <source>Contact us</source> <target>Contactez nous</target> </trans-unit> - <trans-unit id="contact.contactForm" datatype="html"> - <source>Form contact</source> - <target>Formulaire de contact</target> - </trans-unit> <trans-unit id="contact.identity" datatype="html"> <source>Identity</source> <target>Identité</target>