From ee7246d7fef118b4000b53034c948149e544b620 Mon Sep 17 00:00:00 2001 From: Alex ORLUC <alex.orluc@maarch.org> Date: Thu, 25 Jun 2020 17:14:50 +0200 Subject: [PATCH] FEAT #13671 TIME 3:30 front installer mail server --- .../customization.component.html | 2 +- .../app/installer/installer.component.html | 21 +- .../app/installer/installer.module.ts | 2 + .../mailserver/mailserver.component.html | 85 ++++++++ .../mailserver/mailserver.component.scss | 55 +++++ .../mailserver/mailserver.component.ts | 194 ++++++++++++++++++ src/frontend/lang/lang-fr.ts | 3 + src/frontend/service/functions.service.ts | 29 ++- 8 files changed, 373 insertions(+), 18 deletions(-) create mode 100644 src/frontend/app/installer/mailserver/mailserver.component.html create mode 100644 src/frontend/app/installer/mailserver/mailserver.component.scss create mode 100644 src/frontend/app/installer/mailserver/mailserver.component.ts diff --git a/src/frontend/app/installer/customization/customization.component.html b/src/frontend/app/installer/customization/customization.component.html index a7f199212a2..0ad45beb5b9 100644 --- a/src/frontend/app/installer/customization/customization.component.html +++ b/src/frontend/app/installer/customization/customization.component.html @@ -3,7 +3,7 @@ <div class="alert-message alert-message-info" role="alert" style="margin-top: 30px;min-width: 100%;"> {{lang.stepCustomization_desc}} </div> - <form [formGroup]="stepFormGroup" style="display: content;"> + <form [formGroup]="stepFormGroup" style="display: contents;"> <div class="col-md-6"> <mat-form-field appearance="outline"> <mat-label>{{lang.instanceId}}</mat-label> diff --git a/src/frontend/app/installer/installer.component.html b/src/frontend/app/installer/installer.component.html index 699069827c0..cd3aa4022e0 100644 --- a/src/frontend/app/installer/installer.component.html +++ b/src/frontend/app/installer/installer.component.html @@ -7,6 +7,20 @@ <div class="container" [class.fullContainer]="appService.getViewMode()"> <div class="container-content" style="overflow: hidden;"> <mat-horizontal-stepper [@.disabled]="true" linear #stepper style="height: 100vh;overflow: auto;" (selectionChange)="initStep($event)"> + <mat-step [stepControl]="appMailserver.getFormGroup()"> + <ng-template matStepLabel>{{lang.stepMailServer}}</ng-template> + <div class="stepContainer"> + <div class="stepContent"> + <app-mailserver #appMailserver #stepContent (tiggerInstall)="endInstall()"></app-mailserver> + </div> + <button mat-fab matStepperPrevious class="previousStepButton" color="primary"> + <mat-icon class="fa fa-arrow-left"></mat-icon> + </button> + <button mat-fab matStepperNext class="nextStepButton" color="primary" [disabled]="!appMailserver.isValidStep()"> + <mat-icon class="fa fa-arrow-right"></mat-icon> + </button> + </div> + </mat-step> <mat-step label="install"> <ng-template matStepLabel>Installation</ng-template> <div class="stepContainer"> @@ -88,13 +102,6 @@ </button> </div> </mat-step> - <mat-step optional> - <ng-template matStepLabel>Serveur mail</ng-template> - Bonjour - <div> - <button mat-button matStepperPrevious>Back</button> - </div> - </mat-step> <ng-template matStepperIcon="edit"> <mat-icon class="fa fa-check stepIcon"></mat-icon> </ng-template> diff --git a/src/frontend/app/installer/installer.module.ts b/src/frontend/app/installer/installer.module.ts index 8cbe8921142..c27c72afb70 100644 --- a/src/frontend/app/installer/installer.module.ts +++ b/src/frontend/app/installer/installer.module.ts @@ -8,6 +8,7 @@ import { DatabaseComponent } from './database/database.component'; import { DocserversComponent } from './docservers/docservers.component'; import { CustomizationComponent } from './customization/customization.component'; import { UseradminComponent } from './useradmin/useradmin.component'; +import { MailserverComponent } from './mailserver/mailserver.component'; import { InstallerRoutingModule } from './installer-routing.module'; @NgModule({ @@ -24,6 +25,7 @@ import { InstallerRoutingModule } from './installer-routing.module'; DocserversComponent, CustomizationComponent, UseradminComponent, + MailserverComponent ], entryComponents: [InstallActionComponent] }) diff --git a/src/frontend/app/installer/mailserver/mailserver.component.html b/src/frontend/app/installer/mailserver/mailserver.component.html new file mode 100644 index 00000000000..7d7a167a615 --- /dev/null +++ b/src/frontend/app/installer/mailserver/mailserver.component.html @@ -0,0 +1,85 @@ +<div class="stepContent"> + <h2 class="stepContentTitle"><i class="fa fa-mail-bulk"></i> {{lang.stepMailServer}}</h2> + <div class="alert-message alert-message-info" role="alert" style="margin-top: 30px;min-width: 100%;" + [innerHTML]="lang.stepMailServer_desc"> + </div> + <div class="alert-message alert-message-danger" role="alert" style="margin-top: 30px;min-width: 100%;" + [innerHTML]="lang.stepMailServer_warning"> +</div> + <mat-drawer-container autosize> + <mat-drawer-content> + <div style="width: 99%;"> + <form [formGroup]="stepFormGroup" style="display: contents;"> + <mat-form-field> + <mat-select #smtpType name="smtpType" [placeholder]="lang.configurationType" + formControlName="type" required> + <mat-option *ngFor="let type of smtpTypeList" [value]="type.id"> + {{type.label}} + </mat-option> + </mat-select> + </mat-form-field> + <div class="row" style="margin:0px;"> + <div class="col-md-2"> + <mat-form-field> + <mat-select name="SMTPSecure" [placeholder]="lang.smtpAuth" formControlName="secure"> + <mat-option *ngFor="let security of smtpSecList" [value]="security.id"> + {{security.label}} + </mat-option> + </mat-select> + </mat-form-field> + </div> + <div class="col-md-9"> + <mat-form-field> + <input matInput name="host" formControlName="host" [placeholder]="lang.host" required> + </mat-form-field> + </div> + <div class="col-md-1"> + <mat-form-field> + <input name="port" type="number" matInput formControlName="port" + [placeholder]="lang.port" required> + </mat-form-field> + </div> + </div> + <mat-slide-toggle color="primary" name="SMTPAuth" formControlName="auth"> + {{lang.enableAuth}} + </mat-slide-toggle> + <mat-form-field> + <input name="user" formControlName="user" matInput placeholder="{{lang.id}}" required> + </mat-form-field> + <mat-form-field> + <input name="password" [type]="hidePassword ? 'password' : 'text'" formControlName="password" + matInput [placeholder]="this.lang.password" required> + <mat-icon color="primary" style="cursor: pointer;" matSuffix + (click)="hidePassword = !hidePassword" class="fa fa-2x" + [ngClass]="[hidePassword ? 'fa-eye-slash' : 'fa-eye']"></mat-icon> + </mat-form-field> + <mat-form-field> + <input name="mailFrom" formControlName="from" required matInput [placeholder]="lang.mailFrom"> + </mat-form-field> + </form> + </div> + </mat-drawer-content> + <mat-drawer #checkMailserverContent mode="side" position="end" style="padding:10px;width: 350px;"> + <mat-nav-list disableRipple="true" style="display: flex;flex-direction: column;"> + <h3 mat-subheader>{{lang.emailSendTest}}</h3> + <mat-form-field> + <input name="recipientTest" matInput placeholder="{{lang.mailTo}}" [(ngModel)]="recipientTest" + [disabled]="emailSendLoading"> + <mat-icon *ngIf="!emailSendLoading" title="{{lang.beginSendTest}}" (click)="testEmailSend()" + color="primary" style="cursor: pointer;" matSuffix class="fa fa-paper-plane fa-2x"></mat-icon> + </mat-form-field> + <mat-list-item *ngIf="emailSendResult.msg != ''"> + <mat-icon mat-list-icon class="fas {{emailSendResult.icon}} fa-2x"></mat-icon> + <p mat-line> {{emailSendResult.msg}} </p> + </mat-list-item> + </mat-nav-list> + <div class="bash" *ngIf="this.emailSendResult.msg === lang.emailSendFailed"> + {{this.emailSendResult.debug}} + </div> + </mat-drawer> + </mat-drawer-container> + <div class="text-center"> + <button mat-raised-button type="button" color="primary" (click)="checkMailserverContent.open()" + [disabled]="!stepFormGroup.valid">{{lang.checkSendmail}}</button> + </div> +</div> \ No newline at end of file diff --git a/src/frontend/app/installer/mailserver/mailserver.component.scss b/src/frontend/app/installer/mailserver/mailserver.component.scss new file mode 100644 index 00000000000..af9d1274baf --- /dev/null +++ b/src/frontend/app/installer/mailserver/mailserver.component.scss @@ -0,0 +1,55 @@ +@import '../../../css/vars.scss'; + + +.stepContent { + // max-width: 850px; + margin: auto; + + .stepContentTitle { + color: $primary; + margin-bottom: 30px; + border-bottom: solid 1px; + padding: 0; + } +} + +.backgroundList { + display: grid; + grid-template-columns: repeat(5, 1fr); + grid-gap: 10px; +} + +.selected { + transition: all 0.3s; + opacity: 1 !important; + border: solid 10px $secondary !important; +} + +.backgroundItem { + border: solid 0px $secondary; + opacity: 0.5; + transition: all 0.3s; + cursor: pointer; + height: 120px; + background-size: cover !important; +} + +.backgroundItem:hover { + transition: all 0.3s; + opacity: 1 !important; +} + +.bash { + background: #34495e; + height: 310px; + border-radius: 5px; + top: 40px; + display: absolute; + color: #fff; + padding: 10px; + margin: 10px; +} + +mat-drawer-container { + background: none !important; +} \ No newline at end of file diff --git a/src/frontend/app/installer/mailserver/mailserver.component.ts b/src/frontend/app/installer/mailserver/mailserver.component.ts new file mode 100644 index 00000000000..760071c86b8 --- /dev/null +++ b/src/frontend/app/installer/mailserver/mailserver.component.ts @@ -0,0 +1,194 @@ +import { Component, OnInit, ViewChild } from '@angular/core'; +import { FormBuilder, FormGroup, Validators, ValidatorFn } from '@angular/forms'; +import { LANG } from '../../translate.component'; +import { StepAction } from '../types'; +import { DomSanitizer } from '@angular/platform-browser'; +import { NotificationService } from '../../../service/notification/notification.service'; +import { environment } from '../../../environments/environment'; +import { ScanPipe } from 'ngx-pipes'; +import { debounceTime, filter, tap, catchError } from 'rxjs/operators'; +import { HttpClient } from '@angular/common/http'; +import { of } from 'rxjs/internal/observable/of'; +import { MatDrawer } from '@angular/material/sidenav'; + +declare var tinymce: any; + +@Component({ + selector: 'app-mailserver', + templateUrl: './mailserver.component.html', + styleUrls: ['./mailserver.component.scss'], +}) +export class MailserverComponent implements OnInit { + lang: any = LANG; + + hidePassword: boolean = true; + stepFormGroup: FormGroup; + + testRecipient: string = ''; + emailSendLoading: boolean = false; + emailSendResult: any = { + msg: '', + debug: '' + }; + + smtpTypeList = [ + { + id: 'smtp', + label: this.lang.smtpclient + }, + { + id: 'sendmail', + label: this.lang.smtprelay + }, + { + id: 'qmail', + label: this.lang.qmail + }, + { + id: 'mail', + label: this.lang.phpmail + } + ]; + smtpSecList = [ + { + id: '', + label: this.lang.none + }, + { + id: 'ssl', + label: 'ssl' + }, + { + id: 'tls', + label: 'tls' + } + ]; + + @ViewChild('checkMailserverContent', { static: true }) checkMailserverContent: MatDrawer; + + constructor( + private _formBuilder: FormBuilder, + private notify: NotificationService, + public http: HttpClient, + ) { + const valEmail: ValidatorFn[] = [Validators.pattern(/^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$/), Validators.required]; + + this.stepFormGroup = this._formBuilder.group({ + firstCtrl: ['success', Validators.required], + type: ['smtp', Validators.required], + host: ['', Validators.required], + auth: [true], + user: ['', Validators.required], + password: ['', Validators.required], + secure: ['ssl', Validators.required], + port: ['465', Validators.required], + charset: ['utf-8', Validators.required], + from: ['', valEmail], + }); + } + + ngOnInit(): void { + this.stepFormGroup.valueChanges.subscribe(() => { + if (this.checkMailserverContent.opened) { + this.checkMailserverContent.close(); + this.emailSendLoading = false; + this.emailSendResult = { + icon: 'fa-paper-plane primary', + msg: this.lang.emailSendInProgress, + debug: '' + }; + } + }); + this.stepFormGroup.controls['type'].valueChanges.pipe( + tap((data: any) => { + if (['smtp', 'mail'].indexOf(data) === -1) { + this.stepFormGroup.controls['secure'].disable(); + this.stepFormGroup.controls['host'].disable(); + this.stepFormGroup.controls['port'].disable(); + this.stepFormGroup.controls['auth'].disable(); + this.stepFormGroup.controls['user'].disable(); + this.stepFormGroup.controls['password'].disable(); + } else { + this.stepFormGroup.controls['secure'].enable(); + this.stepFormGroup.controls['host'].enable(); + this.stepFormGroup.controls['port'].enable(); + this.stepFormGroup.controls['auth'].enable(); + if (this.stepFormGroup.controls['auth'].value) { + this.stepFormGroup.controls['user'].enable(); + this.stepFormGroup.controls['password'].enable(); + } + } + }) + ).subscribe(); + this.stepFormGroup.controls['auth'].valueChanges.pipe( + tap((data: any) => { + if (!data) { + this.stepFormGroup.controls['user'].disable(); + this.stepFormGroup.controls['password'].disable(); + } else { + this.stepFormGroup.controls['user'].enable(); + this.stepFormGroup.controls['password'].enable(); + } + }) + ).subscribe(); + } + + testEmailSend() { + this.emailSendResult = { + icon: 'fa-paper-plane primary', + msg: this.lang.emailSendInProgress, + debug: '' + }; + const email = { + 'sender': { 'email': this.stepFormGroup.controls['from'] }, + 'recipients': [this.testRecipient], + 'object': '[' + this.lang.doNotReply + '] ' + this.lang.emailSendTest, + 'status': 'EXPRESS', + 'body': this.lang.emailSendTest, + 'isHtml': false + }; + this.emailSendLoading = true; + + this.http.get(`../rest/emails`).pipe( + tap((data: any) => { + this.emailSendLoading = false; + this.emailSendResult = { + icon: 'fa-check green', + msg: this.lang.emailSendSuccess, + debug: '' + }; + }), + catchError((err: any) => { + console.log(err); + + this.emailSendLoading = false; + this.emailSendResult = { + icon: 'fa-times red', + msg: this.lang.emailSendFailed, + debug: err.error.errors + }; + return of(false); + }) + ).subscribe(); + } + + initStep() { + return false; + } + + isValidStep() { + return this.stepFormGroup === undefined ? false : this.stepFormGroup.valid; + } + + getFormGroup() { + return this.stepFormGroup; + } + + checkStep() { + return this.stepFormGroup.valid; + } + + getInfoToInstall(): StepAction[] { + return []; + } +} diff --git a/src/frontend/lang/lang-fr.ts b/src/frontend/lang/lang-fr.ts index d18b0046f8d..b6433f79030 100755 --- a/src/frontend/lang/lang-fr.ts +++ b/src/frontend/lang/lang-fr.ts @@ -1804,4 +1804,7 @@ export const LANG_FR = { "customAlreadyExist": "Ce custom semble déjà exister.", "onlySpecialCharAllowed": "Seul les caractères spéciaux {0} sont autorisés.", "dbNotEmpty": "Cette base de données existe déjà et n'est pas vide", + "stepMailServer": "Serveur de mail", + "stepMailServer_desc": "Configurer votre serveur de mail afin de prévenir les utilisateurs par mail des différents échanges survenus dans l'application.<br/>Cette étape peut être passé et être configurée plus tard.", + "stepMailServer_warning": "Si aucun serveur de mail n'est renseigné, les nouveaux utilisateurs ne recevront pas leur jeton de première connexion !", }; diff --git a/src/frontend/service/functions.service.ts b/src/frontend/service/functions.service.ts index 2cbcde82a5c..fbb57282969 100644 --- a/src/frontend/service/functions.service.ts +++ b/src/frontend/service/functions.service.ts @@ -120,18 +120,27 @@ export class FunctionsService { } debug(msg: string, route: string) { - const info: any = { + let info: any = { route : route, - session : { - id : this.authService.getAppSession(), - expireIn : new Date((JSON.parse(atob(this.authService.getToken().split('.')[1])).exp) * 1000) - }, - refreshSession : { - id : this.authService.getAppSession(), - expireIn : new Date((JSON.parse(atob(this.authService.getRefreshToken().split('.')[1])).exp) * 1000) - }, - user : this.headerService.user, + session : 'No user logged !', + refreshSession : 'No user logged !', + user : 'No user logged !' }; + if (this.authService.getToken() != null) { + info = { + route : route, + session : { + id : this.authService.getAppSession(), + expireIn : new Date((JSON.parse(atob(this.authService.getToken().split('.')[1])).exp) * 1000) + }, + refreshSession : { + id : this.authService.getAppSession(), + expireIn : new Date((JSON.parse(atob(this.authService.getRefreshToken().split('.')[1])).exp) * 1000) + }, + user : this.headerService.user, + }; + } + if (msg !== '') { console.log(msg, info); } else { -- GitLab