From 86116113b3d7edb4d02d18503245a15c81c76e1c Mon Sep 17 00:00:00 2001
From: FORESTIER Fabien <fabien.forestier@soprasteria.com>
Date: Fri, 26 Oct 2018 14:05:28 +0200
Subject: [PATCH] Block copy paste for emailVerification input, add loading and
 disable form while processing, fix some trnaslation

---
 .../components/contact/contact.component.html | 12 +++++------
 .../components/contact/contact.component.ts   | 15 ++++++++++----
 .../directives/block-copypaste.directive.ts   | 20 +++++++++++++++++++
 src/app/shared/directives/index.ts            |  4 +++-
 src/i18n/contact/contact.ts                   |  2 +-
 src/i18n/messages.fr.xlf                      |  2 +-
 6 files changed, 42 insertions(+), 13 deletions(-)
 create mode 100644 src/app/shared/directives/block-copypaste.directive.ts

diff --git a/src/app/core/components/contact/contact.component.html b/src/app/core/components/contact/contact.component.html
index 856cb617..7f2be042 100644
--- a/src/app/core/components/contact/contact.component.html
+++ b/src/app/core/components/contact/contact.component.html
@@ -77,7 +77,7 @@
             <label class="label" for="emailConfirmation" i18n="@@contact.emailConfirmation">Confirm your email
               address</label>
             <p class="control has-icons-right">
-              <input id="emailConfirmation" class="input" type="email" formControlName="emailConfirmation" [ngClass]="{'is-danger': emailConfirmationError || fieldIsInvalid('emailConfirmation'), 'is-success': !emailConfirmationError && fieldIsValid('emailConfirmation')}">
+              <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>
@@ -111,19 +111,19 @@
 
       <div class="column is-12-mobile is-10-tablet is-9-desktop">
         <div class="field">
-          <label class="label" [for]="subjectLabelFor" i18n="@@contact.subject">Sujet</label>
+          <label class="label" [for]="subjectLabelFor" i18n="@@contact.subject">Subject</label>
           <div class="dropdown" [ngClass]="{'is-active': subjectDropdownState}" (clickOutside)="closeSubjectDropdown()">
             <div class="dropdown-trigger" (click)="toggleSubject()">
-              <button id="subjectDropdown" type="button" class="button" aria-haspopup="true" aria-controls="dropdown-menu">
+              <button id="subjectDropdown" type="button" class="button" aria-haspopup="true" aria-controls="dropdown-menu" [disabled]="formDisabled">
                 <span>{{ selectedSubject !== null && selectedSubject.value !== null ? selectedSubject.value : '---'}}</span>
                 <span class="icon is-small">
                   <i class="fas fa-angle-down" aria-hidden="true"></i>
                 </span>
               </button>
             </div>
-            <div class="dropdown-menu" id="dropdown-menu" role="menu">
+            <div class="dropdown-menu" id="dropdown-menu" role="menu">  
               <ul class="dropdown-content">
-                <li class="dropdown-item" *ngFor="let sub of subjects" (click)="setSubject(sub)">
+                <li class="dropdown-item" *ngFor="let sub of subjects" (keydown.enter)="setSubject(sub)" (click)="setSubject(sub)" tabindex=0>
                   {{ sub.value }}
                 </li>
               </ul>
@@ -167,7 +167,7 @@
         </div>
 
         <div class="has-text-right button-wrapper">
-          <button type="submit" class="button is-primary" [disabled]="formIsInvalid()" i18n="@@contact.send">Envoyer</button>
+          <button type="submit" class="button is-primary" [ngClass]="{'is-loading': formDisabled}" [disabled]="formIsInvalid() || formDisabled" i18n="@@contact.send">Send</button>
         </div>
       </div>
     </div>
diff --git a/src/app/core/components/contact/contact.component.ts b/src/app/core/components/contact/contact.component.ts
index 9861a053..a5c695c4 100644
--- a/src/app/core/components/contact/contact.component.ts
+++ b/src/app/core/components/contact/contact.component.ts
@@ -24,7 +24,7 @@ export class ContactComponent implements OnInit {
   ) {
     this.form = this._fb.group(
       {
-        firstname: ['', Validators.required],
+        firstname: ['', [Validators.required]],
         lastname: ['', Validators.required],
         email: ['', [Validators.required, Validators.email]],
         emailConfirmation: ['', [Validators.required, Validators.email]],
@@ -33,13 +33,14 @@ export class ContactComponent implements OnInit {
       });
   }
 
-  ngOnInit() {
-  }
+  ngOnInit() {}
 
   send() {
     const email = new Email(this.form.value);
+    this.form.disable();
     this._emailService.send(email).subscribe(
       (res) => {
+        this.form.enable();
         this._notificationService.notify(
           {
             type: 'success',
@@ -49,6 +50,7 @@ export class ContactComponent implements OnInit {
         this.form.reset();
       },
       (err) => {
+        this.form.enable();
         this._notificationService.notify(
           {
             type: 'error',
@@ -90,7 +92,9 @@ export class ContactComponent implements OnInit {
   }
 
   toggleSubject() {
-    this.subjectDropdownState = !this.subjectDropdownState;
+    if (!this.formDisabled) {
+      this.subjectDropdownState = !this.subjectDropdownState;
+    }
   }
 
   closeSubjectDropdown() {
@@ -114,6 +118,9 @@ export class ContactComponent implements OnInit {
     return this.displaySubjectInput ? 'subjectInput' : 'subjectDropdown';
   }
 
+  get formDisabled(): boolean {
+    return this.form.disabled;
+  }
 }
 
 interface Subject {
diff --git a/src/app/shared/directives/block-copypaste.directive.ts b/src/app/shared/directives/block-copypaste.directive.ts
new file mode 100644
index 00000000..7cb989da
--- /dev/null
+++ b/src/app/shared/directives/block-copypaste.directive.ts
@@ -0,0 +1,20 @@
+import { Directive, HostListener } from '@angular/core';
+
+@Directive({
+  selector: '[blockCopyPaste]',
+})
+export class BlockCopyPasteDirective {
+  constructor() { }
+
+  @HostListener('paste', ['$event']) blockPaste(e: KeyboardEvent) {
+    e.preventDefault();
+  }
+
+  @HostListener('copy', ['$event']) blockCopy(e: KeyboardEvent) {
+    e.preventDefault();
+  }
+
+  @HostListener('cut', ['$event']) blockCut(e: KeyboardEvent) {
+    e.preventDefault();
+  }
+}
diff --git a/src/app/shared/directives/index.ts b/src/app/shared/directives/index.ts
index b0c41d94..79989eb7 100644
--- a/src/app/shared/directives/index.ts
+++ b/src/app/shared/directives/index.ts
@@ -1,12 +1,14 @@
 import { PreventDefaultDirective } from './prevent-default.directive';
 import { DynamicLinks } from './dynamic-links';
 import { ClickOutsideDirective } from './click-outside.directive';
+import { BlockCopyPasteDirective } from './block-copypaste.directive';
 
-export { PreventDefaultDirective, DynamicLinks, ClickOutsideDirective };
+export { PreventDefaultDirective, DynamicLinks, ClickOutsideDirective, BlockCopyPasteDirective };
 
 // tslint:disable-next-line:variable-name
 export const SharedDirectives = [
   PreventDefaultDirective,
   DynamicLinks,
   ClickOutsideDirective,
+  BlockCopyPasteDirective,
 ];
diff --git a/src/i18n/contact/contact.ts b/src/i18n/contact/contact.ts
index 76cdd9ff..c340e7d7 100644
--- a/src/i18n/contact/contact.ts
+++ b/src/i18n/contact/contact.ts
@@ -31,5 +31,5 @@ export const subjects = [
 
 export const feedbackMessages = {
   error: 'Sorry, we couldn\'t send your message, please try again later',
-  success: 'You message has been sent successfully.',
+  success: 'Your message has been sent successfully.',
 };
diff --git a/src/i18n/messages.fr.xlf b/src/i18n/messages.fr.xlf
index f5cd22d5..87340a07 100644
--- a/src/i18n/messages.fr.xlf
+++ b/src/i18n/messages.fr.xlf
@@ -337,7 +337,7 @@
       </trans-unit>
       <trans-unit id="contact.emailConfirmation" datatype="html">
          <source>Confirm your email address</source>
-         <target>Confirmez votre adresse email</target>
+         <target>Confirmez votre adresse email.</target>
       </trans-unit>
       <trans-unit id="contact.errors.missingConfirmationEmail" datatype="html">
          <source>You must confirm your email address.</source>
-- 
GitLab