From 44ec32d0afa66b4f41c44f321aa7f35b8227564e Mon Sep 17 00:00:00 2001
From: Alex ORLUC <alex.orluc@maarch.org>
Date: Fri, 19 Jun 2020 15:45:24 +0200
Subject: [PATCH] FEAT #13671 TIME 4 front installer actions + some fixes

---
 src/frontend/app/app.module.ts                |  9 ++-
 .../customization.component.html              |  4 ++
 .../customization/customization.component.ts  | 16 ++++-
 .../database/database.component.html          | 12 +++-
 .../installer/database/database.component.ts  | 31 ++++++++
 .../docservers/docservers.component.ts        | 10 +++
 .../install-action.component.html             | 21 ++++++
 .../install-action.component.scss             | 14 ++++
 .../install-action.component.ts               | 72 +++++++++++++++++++
 .../app/installer/installer.component.html    | 12 ++--
 .../app/installer/installer.component.ts      | 53 ++++++++++++--
 .../prerequisite/prerequisite.component.html  | 12 +---
 .../prerequisite/prerequisite.component.ts    |  4 ++
 src/frontend/app/installer/types.ts           | 14 ++++
 .../useradmin/useradmin.component.ts          | 17 ++++-
 .../installer/welcome/welcome.component.ts    | 11 ++-
 src/frontend/lang/lang-fr.ts                  |  5 +-
 src/frontend/plugins/sorting.pipe.ts          | 69 +++++++++---------
 18 files changed, 319 insertions(+), 67 deletions(-)
 create mode 100644 src/frontend/app/installer/install-action/install-action.component.html
 create mode 100644 src/frontend/app/installer/install-action/install-action.component.scss
 create mode 100644 src/frontend/app/installer/install-action/install-action.component.ts
 create mode 100644 src/frontend/app/installer/types.ts

diff --git a/src/frontend/app/app.module.ts b/src/frontend/app/app.module.ts
index bca4997872b..37e2b5d2f67 100755
--- a/src/frontend/app/app.module.ts
+++ b/src/frontend/app/app.module.ts
@@ -123,7 +123,8 @@ import { DatabaseComponent } from './installer/database/database.component';
 import { DocserversComponent } from './installer/docservers/docservers.component';
 import { CustomizationComponent } from './installer/customization/customization.component';
 import { UseradminComponent } from './installer/useradmin/useradmin.component';
-import {RedirectIndexingModelComponent} from './administration/indexingModel/redirectIndexingModel/redirect-indexing-model.component';
+import { RedirectIndexingModelComponent } from './administration/indexingModel/redirectIndexingModel/redirect-indexing-model.component';
+import { InstallActionComponent } from './installer/install-action/install-action.component';
 
 
 
@@ -236,7 +237,8 @@ import {RedirectIndexingModelComponent} from './administration/indexingModel/red
         DocserversComponent,
         CustomizationComponent,
         UseradminComponent,
-        RedirectIndexingModelComponent
+        RedirectIndexingModelComponent,
+        InstallActionComponent
     ],
     entryComponents: [
         InfoChangePasswordModalComponent,
@@ -286,7 +288,8 @@ import {RedirectIndexingModelComponent} from './administration/indexingModel/red
         FolderCreateModalComponent,
         ReconcileActionComponent,
         ThesaurusModalComponent,
-        RedirectIndexingModelComponent
+        RedirectIndexingModelComponent,
+        InstallActionComponent
     ],
     providers: [FiltersListService, FoldersService, ActionsService, PrivilegeService],
     bootstrap: [AppComponent]
diff --git a/src/frontend/app/installer/customization/customization.component.html b/src/frontend/app/installer/customization/customization.component.html
index e6c00ebb723..dc08bb78a2d 100644
--- a/src/frontend/app/installer/customization/customization.component.html
+++ b/src/frontend/app/installer/customization/customization.component.html
@@ -4,6 +4,10 @@
         {{lang.stepCustomization_desc}}
     </div>
     <div class="col-md-6">
+        <mat-form-field appearance="outline">
+            <mat-label>{{lang.instanceName}}</mat-label>
+            <input matInput [(ngModel)]="customId">
+        </mat-form-field>
         <mat-form-field appearance="outline">
             <mat-label>{{lang.applicationName}}</mat-label>
             <input matInput [(ngModel)]="appName">
diff --git a/src/frontend/app/installer/customization/customization.component.ts b/src/frontend/app/installer/customization/customization.component.ts
index e3b1774fded..374efc484dc 100644
--- a/src/frontend/app/installer/customization/customization.component.ts
+++ b/src/frontend/app/installer/customization/customization.component.ts
@@ -2,7 +2,7 @@ import { Component, OnInit } from '@angular/core';
 import { FormBuilder, FormGroup, Validators } from '@angular/forms';
 import { NotificationService } from '../../notification.service';
 import { LANG } from '../../translate.component';
-
+import { StepAction } from '../types';
 
 declare var tinymce: any;
 
@@ -15,8 +15,7 @@ export class CustomizationComponent implements OnInit {
     lang: any = LANG;
     stepFormGroup: FormGroup;
 
-    docserversPath: string = '/opt/maaarch/docservers/';
-
+    customId: string = 'cs_maarchcourrier';
     appName: string = 'Maarch Courrier 20.10';
     loginMsg: string = '<span style="color:#24b0ed"><strong>Découvrez votre application via</strong></span>&nbsp;<a title="le guide de visite" href="https://docs.maarch.org/gitbook/html/MaarchCourrier/19.04/guu/home.html" target="_blank"><span style="color:#f99830;"><strong>le guide de visite en ligne</strong></span></a>';
     homeMsg: string = '<p>D&eacute;couvrez <strong>Maarch Courrier 20.10</strong> avec <a title="notre guide de visite" href="https://docs.maarch.org/" target="_blank"><span style="color:#f99830;"><strong>notre guide de visite en ligne</strong></span></a>.</p>';
@@ -83,4 +82,15 @@ export class CustomizationComponent implements OnInit {
         });
     }
 
+    getInfoToInstall(): StepAction[] {
+        return [{
+            body : {
+                customName: this.customId,
+            },
+            description : 'Initialisation de l\'instance',
+            route : '../rest/installer/custom',
+            installPriority : 1
+        }];
+    }
+
 }
diff --git a/src/frontend/app/installer/database/database.component.html b/src/frontend/app/installer/database/database.component.html
index c7dbac20cb0..f2ac0085f4d 100644
--- a/src/frontend/app/installer/database/database.component.html
+++ b/src/frontend/app/installer/database/database.component.html
@@ -14,7 +14,7 @@
         </mat-form-field>
         <mat-form-field appearance="outline">
             <mat-label>{{lang.user}}</mat-label>
-            <input matInput formControlName="dbLoginCtrl"  required>
+            <input matInput formControlName="dbLoginCtrl" required>
         </mat-form-field>
         <mat-form-field appearance="outline">
             <mat-label>{{lang.password}}</mat-label>
@@ -27,8 +27,16 @@
             <mat-label>{{lang.dbName}}</mat-label>
             <input matInput formControlName="dbNameCtrl" required>
         </mat-form-field>
+        <mat-form-field appearance="outline" floatLabel="never">
+            <mat-label>{{lang.dbSample}}</mat-label>
+            <mat-select formControlName="dbSampleCtrl">
+                <mat-option *ngFor="let sample of dataSamples" [value]="sample">
+                    {{sample}}
+                </mat-option>
+            </mat-select>
+        </mat-form-field>
         <div style="text-align:center;">
-            <button mat-raised-button type="button" color="primary" (click)="checkConnection()">
+            <button mat-raised-button type="button" color="primary" (click)="checkConnection()" [disabled]="isEmptyConnInfo()">
                 {{lang.checkInformations}}
             </button>
         </div>
diff --git a/src/frontend/app/installer/database/database.component.ts b/src/frontend/app/installer/database/database.component.ts
index 0eec37c4da2..7d8751110ae 100644
--- a/src/frontend/app/installer/database/database.component.ts
+++ b/src/frontend/app/installer/database/database.component.ts
@@ -6,6 +6,7 @@ import { tap } from 'rxjs/internal/operators/tap';
 import { catchError } from 'rxjs/internal/operators/catchError';
 import { of } from 'rxjs/internal/observable/of';
 import { LANG } from '../../translate.component';
+import { StepAction } from '../types';
 
 @Component({
     selector: 'app-database',
@@ -19,6 +20,11 @@ export class DatabaseComponent implements OnInit {
 
     connectionState: boolean = false;
 
+    dataSamples: string[] = [
+        'data_fr.sql',
+        'data_en.sql'
+    ];
+
     constructor(
         public http: HttpClient,
         private _formBuilder: FormBuilder,
@@ -30,6 +36,7 @@ export class DatabaseComponent implements OnInit {
             dbPortCtrl: ['5432', Validators.required],
             dbPasswordCtrl: ['', Validators.required],
             dbNameCtrl: ['', Validators.required],
+            dbSampleCtrl: ['data_fr.sql', Validators.required],
             stateStep: ['', Validators.required]
         });
     }
@@ -97,8 +104,32 @@ export class DatabaseComponent implements OnInit {
         return this.stepFormGroup === undefined ? false : this.stepFormGroup.valid;
     }
 
+    isEmptyConnInfo() {
+        return this.stepFormGroup.controls['dbHostCtrl'].invalid ||
+            this.stepFormGroup.controls['dbPortCtrl'].invalid ||
+            this.stepFormGroup.controls['dbLoginCtrl'].invalid ||
+            this.stepFormGroup.controls['dbPasswordCtrl'].invalid ||
+            this.stepFormGroup.controls['dbNameCtrl'].invalid;
+    }
+
     getFormGroup() {
         return this.stepFormGroup;
     }
 
+    getInfoToInstall(): StepAction[] {
+        return [{
+            body: {
+                server: this.stepFormGroup.controls['dbHostCtrl'].value,
+                port: this.stepFormGroup.controls['dbPortCtrl'].value,
+                user: this.stepFormGroup.controls['dbLoginCtrl'].value,
+                password: this.stepFormGroup.controls['dbPasswordCtrl'].value,
+                name: this.stepFormGroup.controls['dbNameCtrl'].value,
+                data: this.stepFormGroup.controls['dbSampleCtrl'].value
+            },
+            route: '../rest/installer/database',
+            description: this.lang.stepDatabaseActionDesc,
+            installPriority: 2
+        }];
+    }
+
 }
diff --git a/src/frontend/app/installer/docservers/docservers.component.ts b/src/frontend/app/installer/docservers/docservers.component.ts
index 1f959f8d73e..70237fd5984 100644
--- a/src/frontend/app/installer/docservers/docservers.component.ts
+++ b/src/frontend/app/installer/docservers/docservers.component.ts
@@ -45,4 +45,14 @@ export class DocserversComponent implements OnInit {
         this.notify.success(this.lang.rightInformations);
     }
 
+    getInfoToInstall(): any[] {
+        return [];
+        /*return {
+            body : {
+                appName: this.stepFormGroup.controls['docserversPath'].value,
+            },
+            route : '/installer/docservers'
+        };*/
+    }
+
 }
diff --git a/src/frontend/app/installer/install-action/install-action.component.html b/src/frontend/app/installer/install-action/install-action.component.html
new file mode 100644
index 00000000000..2a5b44dfde3
--- /dev/null
+++ b/src/frontend/app/installer/install-action/install-action.component.html
@@ -0,0 +1,21 @@
+<div class="mat-dialog-content-container">
+    <div mat-dialog-content>
+        <mat-list-item *ngFor="let step of steps">
+            <div mat-line class="step" [class.endStep]="step.state==='OK' || step.state==='KO'"
+                [class.currentStep]="step.state==='inProgress'">{{step.label}} <ng-container
+                    *ngIf="step.state==='inProgress'">...</ng-container>
+                <i *ngIf="step.state==='OK'" class="fa fa-check" style="color: green"></i>
+                <i *ngIf="step.state==='KO'" class="fa fa-times" style="color: red"></i>
+                <div *ngIf="step.msgErr!==''" class="alert-message alert-message-danger" role="alert" style="margin-top: 30px;min-width: 100%;">
+                    {{step.msgErr}}
+                </div>
+            </div>
+        </mat-list-item>
+    </div>
+    <ng-container *ngIf="isInstallComplete() && isInstallError()">
+        <span class="divider-modal"></span>
+        <div mat-dialog-actions class="actions">
+            <button mat-raised-button mat-button [disabled]="loading" [mat-dialog-close]="">{{lang.cancel}}</button>
+        </div>
+    </ng-container>
+</div>
\ No newline at end of file
diff --git a/src/frontend/app/installer/install-action/install-action.component.scss b/src/frontend/app/installer/install-action/install-action.component.scss
new file mode 100644
index 00000000000..d694d35462f
--- /dev/null
+++ b/src/frontend/app/installer/install-action/install-action.component.scss
@@ -0,0 +1,14 @@
+.step {
+    opacity: 0.5;
+    transition: all 0.2s;
+}
+
+.currentStep {
+    opacity: 1;
+    font-size: 150%;
+    transition: all 0.2s;
+}
+
+.endStep {
+    opacity: 1;
+}
\ No newline at end of file
diff --git a/src/frontend/app/installer/install-action/install-action.component.ts b/src/frontend/app/installer/install-action/install-action.component.ts
new file mode 100644
index 00000000000..a781b7ba658
--- /dev/null
+++ b/src/frontend/app/installer/install-action/install-action.component.ts
@@ -0,0 +1,72 @@
+import { Component, OnInit, Inject } from '@angular/core';
+import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
+import { LANG } from '../../../app/translate.component';
+import { HttpClient } from '@angular/common/http';
+import { tap } from 'rxjs/internal/operators/tap';
+import { catchError } from 'rxjs/internal/operators/catchError';
+import { of } from 'rxjs/internal/observable/of';
+
+@Component({
+    selector: 'app-install-action',
+    templateUrl: './install-action.component.html',
+    styleUrls: ['./install-action.component.scss']
+})
+export class InstallActionComponent implements OnInit {
+    lang: any = LANG;
+    steps: any[] = [];
+    customId: string = '';
+
+    constructor(@Inject(MAT_DIALOG_DATA) public data: any, public dialogRef: MatDialogRef<InstallActionComponent>, public http: HttpClient) { }
+
+    async ngOnInit(): Promise<void> {
+        this.initSteps();
+
+        for (let index = 0; index < this.data.length; index++) {
+            this.steps[index].state = 'inProgress';
+            await this.doStep(index);
+        }
+    }
+
+    initSteps() {
+        this.data.forEach((step: any, index: number) => {
+            if (index === 0) {
+                this.customId = step.body.customName;
+            } else {
+                step.body.customName = this.customId;
+            }
+            this.steps.push(
+                {
+                    label: step.description,
+                    state: '',
+                    msgErr: '',
+                }
+            );
+        });
+    }
+
+    doStep(index: number) {
+        return new Promise((resolve, reject) => {
+            console.log(this.steps[index]);
+            this.http.post(this.data[index].route, this.data[index].body).pipe(
+                tap((data: any) => {
+                    this.steps[index].state = 'OK';
+                    resolve(true);
+                }),
+                catchError((err: any) => {
+                    this.steps[index].state = 'KO';
+                    resolve(true);
+                    this.steps[index].msgErr = err.error.errors;
+                    return of(false);
+                })
+            ).subscribe();
+        });
+    }
+
+    isInstallComplete() {
+        return this.steps.filter(step => step.state === '' ).length === 0;
+    }
+
+    isInstallError() {
+        return this.steps.filter(step => step.state === 'KO' ).length > 0;
+    }
+}
diff --git a/src/frontend/app/installer/installer.component.html b/src/frontend/app/installer/installer.component.html
index d144878ceba..aafc6c6b2db 100644
--- a/src/frontend/app/installer/installer.component.html
+++ b/src/frontend/app/installer/installer.component.html
@@ -11,7 +11,7 @@
                         <ng-template matStepLabel>Installation</ng-template>
                         <div class="stepContainer">
                             <div class="stepContent">
-                                <app-welcome></app-welcome>
+                                <app-welcome #stepContent></app-welcome>
                             </div>
                             <button mat-fab matStepperNext class="nextStepButton" color="primary">
                                 <mat-icon class="fa fa-arrow-right"></mat-icon>
@@ -22,7 +22,7 @@
                         <ng-template matStepLabel>{{lang.prerequisite}}</ng-template>
                         <div class="stepContainer">
                             <div class="stepContent">
-                                <app-prerequisite #appPrerequisite></app-prerequisite>
+                                <app-prerequisite #appPrerequisite #stepContent></app-prerequisite>
                             </div>
                             <button mat-fab matStepperPrevious class="previousStepButton" color="primary">
                                 <mat-icon class="fa fa-arrow-left"></mat-icon>
@@ -36,7 +36,7 @@
                         <ng-template matStepLabel>{{lang.database}}</ng-template>
                         <div class="stepContainer">
                             <div class="stepContent">
-                                <app-database #appDatabase></app-database>
+                                <app-database #appDatabase #stepContent></app-database>
                             </div>
                             <button mat-fab matStepperPrevious class="previousStepButton" color="primary">
                                 <mat-icon class="fa fa-arrow-left"></mat-icon>
@@ -50,7 +50,7 @@
                         <ng-template matStepLabel>{{lang.docserver}}</ng-template>
                         <div class="stepContainer">
                             <div class="stepContent">
-                                <app-docservers #appDocservers></app-docservers>
+                                <app-docservers #appDocservers #stepContent></app-docservers>
                             </div>
                             <button mat-fab matStepperPrevious class="previousStepButton" color="primary">
                                 <mat-icon class="fa fa-arrow-left"></mat-icon>
@@ -64,7 +64,7 @@
                         <ng-template matStepLabel>{{lang.customization}}</ng-template>
                         <div class="stepContainer">
                             <div class="stepContent">
-                                <app-customization #appCustomization></app-customization>
+                                <app-customization #appCustomization #stepContent></app-customization>
                             </div>
                             <button mat-fab matStepperPrevious class="previousStepButton" color="primary">
                                 <mat-icon class="fa fa-arrow-left"></mat-icon>
@@ -78,7 +78,7 @@
                         <ng-template matStepLabel>{{lang.userAdmin}}</ng-template>
                         <div class="stepContainer">
                             <div class="stepContent">
-                                <app-useradmin #appUseradmin></app-useradmin>
+                                <app-useradmin #appUseradmin #stepContent (tiggerInstall)="endInstall()"></app-useradmin>
                             </div>
                             <button mat-fab matStepperPrevious class="previousStepButton" color="primary">
                                 <mat-icon class="fa fa-arrow-left"></mat-icon>
diff --git a/src/frontend/app/installer/installer.component.ts b/src/frontend/app/installer/installer.component.ts
index 8b9ba01c291..6c3ffae6f08 100644
--- a/src/frontend/app/installer/installer.component.ts
+++ b/src/frontend/app/installer/installer.component.ts
@@ -1,4 +1,4 @@
-import { Component, OnInit, ViewChild, AfterViewInit } from '@angular/core';
+import { Component, OnInit, ViewChild, AfterViewInit, ViewChildren } from '@angular/core';
 import { HttpClient } from '@angular/common/http';
 import { Router } from '@angular/router';
 import { HeaderService } from '../../service/header.service';
@@ -7,19 +7,32 @@ import { STEPPER_GLOBAL_OPTIONS } from '@angular/cdk/stepper';
 import { MatStepper } from '@angular/material/stepper';
 import { AppService } from '../../service/app.service';
 import { LANG } from '../translate.component';
+import { SortPipe } from '../../plugins/sorting.pipe';
+import { StepAction } from './types';
+import { MatDialog } from '@angular/material/dialog';
+import { InstallActionComponent } from './install-action/install-action.component';
+import { filter } from 'rxjs/internal/operators/filter';
+import { tap } from 'rxjs/internal/operators/tap';
+import { finalize } from 'rxjs/internal/operators/finalize';
+import { catchError } from 'rxjs/internal/operators/catchError';
+import { of } from 'rxjs/internal/observable/of';
+import { FunctionsService } from '../../service/functions.service';
 
 @Component({
     templateUrl: './installer.component.html',
     styleUrls: ['./installer.component.scss'],
-    providers: [{
-        provide: STEPPER_GLOBAL_OPTIONS, useValue: { showError: true }
-    }]
+    providers: [
+        {
+            provide: STEPPER_GLOBAL_OPTIONS, useValue: { showError: true },
+        },
+        SortPipe
+    ]
 })
 export class InstallerComponent implements OnInit, AfterViewInit {
 
     lang: any = LANG;
 
-    @ViewChild('stepper', { static: true }) stepper: MatStepper;
+    @ViewChildren('stepContent') stepContent: any;
 
     constructor(
         private http: HttpClient,
@@ -27,6 +40,9 @@ export class InstallerComponent implements OnInit, AfterViewInit {
         private headerService: HeaderService,
         private notify: NotificationService,
         public appService: AppService,
+        private sortPipe: SortPipe,
+        public dialog: MatDialog,
+        private functionService: FunctionsService
     ) { }
 
     ngOnInit(): void {
@@ -54,7 +70,32 @@ export class InstallerComponent implements OnInit, AfterViewInit {
     }
 
     endInstall() {
-        this.stepper.next();
+        let installContent: StepAction[] = [];
+        this.stepContent.toArray().forEach((component: any) => {
+            installContent = installContent.concat(component.getInfoToInstall());
+        });
+
+        installContent = this.sortPipe.transform(installContent, 'installPriority');
+
+        console.log(installContent);
+
+        // this.stepper.next();
+
+        const dialogRef = this.dialog.open(InstallActionComponent, {
+            panelClass: 'maarch-modal',
+            disableClose: true,
+            width: '500px',
+            data: installContent
+        });
+        dialogRef.afterClosed().pipe(
+            filter((result: any) => !this.functionService.empty(result)),
+            tap((result: any) => {
+            }),
+            catchError((err: any) => {
+                this.notify.handleErrors(err);
+                return of(false);
+            })
+        ).subscribe();
     }
 
 }
diff --git a/src/frontend/app/installer/prerequisite/prerequisite.component.html b/src/frontend/app/installer/prerequisite/prerequisite.component.html
index f5234684781..7a40fd37f87 100644
--- a/src/frontend/app/installer/prerequisite/prerequisite.component.html
+++ b/src/frontend/app/installer/prerequisite/prerequisite.component.html
@@ -10,17 +10,11 @@
                 <mat-list-item>
                     <mat-icon mat-list-icon class="fa iconCheckPackage icon_{{package.state}}"></mat-icon>
                     <div mat-line class="packageName">{{lang['install_'+package.label]}} <i class="fa fa-info-circle" [title]="lang['install_'+package.label+'_desc']"></i></div>
-                    <!--<div mat-line style="color:#666;">{{lang['install_'+package.label+'_desc']}}</div>-->
                 </mat-list-item>  
             </mat-grid-tile>
           </mat-grid-list>
-          
-        <!--<div style="display: flex;">
-            <mat-list-item *ngFor="let package of packagesList[groupPackage.key]">
-                <mat-icon mat-list-icon class="fa iconCheckPackage icon_{{package.state}}"></mat-icon>
-                <div mat-line style="font-size: 120%;">{{lang['install_'+package.label]}}</div>
-                <div mat-line style="color:#666;">{{lang['install_'+package.label+'_desc']}}</div>
-            </mat-list-item>    
-        </div>-->
     </mat-list>
+    <div style="text-align: center;">
+        <button mat-raised-button type="button" color="primary" (click)="getStepData()">{{lang.updateInformations}}</button>
+    </div>
 </div>
diff --git a/src/frontend/app/installer/prerequisite/prerequisite.component.ts b/src/frontend/app/installer/prerequisite/prerequisite.component.ts
index c4a48ef8fc6..0576112f56c 100644
--- a/src/frontend/app/installer/prerequisite/prerequisite.component.ts
+++ b/src/frontend/app/installer/prerequisite/prerequisite.component.ts
@@ -160,4 +160,8 @@ export class PrerequisiteComponent implements OnInit {
     getFormGroup() {
         return this.stepFormGroup;
     }
+
+    getInfoToInstall(): any[] {
+        return [];
+    }
 }
diff --git a/src/frontend/app/installer/types.ts b/src/frontend/app/installer/types.ts
new file mode 100644
index 00000000000..aa91a4d37b8
--- /dev/null
+++ b/src/frontend/app/installer/types.ts
@@ -0,0 +1,14 @@
+/**
+ * Launch actions after stepper checked
+ * Gets script version
+ * @param route route to launch action
+ * @param body data json sent to the route
+ * @param description decscription of install action
+ * @param installPriority action order (/!\ NEVER USE 1 IT IS FOR ROUTE /installer/initCustom)
+ */
+export class StepAction {
+    route: string;
+    body: any;
+    description: any;
+    installPriority: 1 | 2 | 3;
+}
diff --git a/src/frontend/app/installer/useradmin/useradmin.component.ts b/src/frontend/app/installer/useradmin/useradmin.component.ts
index ff67cdfdda9..83a4b43f468 100644
--- a/src/frontend/app/installer/useradmin/useradmin.component.ts
+++ b/src/frontend/app/installer/useradmin/useradmin.component.ts
@@ -1,4 +1,4 @@
-import { Component, OnInit } from '@angular/core';
+import { Component, OnInit, EventEmitter, Output } from '@angular/core';
 import { FormGroup, FormBuilder, Validators } from '@angular/forms';
 import { NotificationService } from '../../notification.service';
 import { LANG } from '../../translate.component';
@@ -15,6 +15,8 @@ export class UseradminComponent implements OnInit {
 
     hide: boolean = true;
 
+    @Output() tiggerInstall = new EventEmitter<string>();
+
     constructor(
         private _formBuilder: FormBuilder,
         private notify: NotificationService,
@@ -64,7 +66,18 @@ export class UseradminComponent implements OnInit {
         return this.stepFormGroup;
     }
 
-    launchInstall() {
+    getInfoToInstall(): any[] {
+        return [];
+        /*return {
+            body : {
+                login: this.stepFormGroup.controls['login'].value,
+                password: this.stepFormGroup.controls['password'].value,
+            },
+            route : '/installer/useradmin'
+        };*/
+    }
 
+    launchInstall() {
+        this.tiggerInstall.emit();
     }
 }
diff --git a/src/frontend/app/installer/welcome/welcome.component.ts b/src/frontend/app/installer/welcome/welcome.component.ts
index e1a13865202..862b9ae90de 100644
--- a/src/frontend/app/installer/welcome/welcome.component.ts
+++ b/src/frontend/app/installer/welcome/welcome.component.ts
@@ -14,7 +14,16 @@ export class WelcomeComponent implements OnInit {
 
     constructor() { }
 
-    ngOnInit(): void {
+    ngOnInit(): void { }
+
+    getInfoToInstall(): any[] {
+        return [];
+        /*return {
+            body : {
+                lang: this.selectedLang,
+            },
+            route : '/installer/lang'
+        };*/
     }
 
 }
diff --git a/src/frontend/lang/lang-fr.ts b/src/frontend/lang/lang-fr.ts
index 4eff1d4036c..43f00607b38 100755
--- a/src/frontend/lang/lang-fr.ts
+++ b/src/frontend/lang/lang-fr.ts
@@ -1768,6 +1768,7 @@ export const LANG_FR = {
     "phpConfiguration": "Configuration PHP",
     "dbName": "Nom de la base de données",
     "stepDatabase_desc": "Maarch Courrier nécessite une connexion à une base de données afin de stocker les métas-données des documents stockés ainsi que la configuration de l'application.",
+    "stepDatabaseActionDesc": "Création de la base de données",
     "checkInformations": "Vérifier les informations",
     "badInformations": "Les informations sont incorrectes",
     "rightInformations": "Les informations sont correctes",
@@ -1787,5 +1788,7 @@ export const LANG_FR = {
     "mailsWithStatus": " courrier(s) avec le statut ",
     "indexingModelReplaceToDelete": "Pour le supprimer vous devez le remplacer par un autre modèle.",
     "indexingModelFieldsReset": "Les champs suivants ne sont pas dans le modèle sélectionné et seront réinitialisé pour tous les courriers : ",
-    "indexingModelReassign": "Réaffection du modèle d'enregistrement"
+    "indexingModelReassign": "Réaffection du modèle d'enregistrement",
+    "updateInformations": "Actualiser les informations",
+    "dbSample": "Jeu de données"
 };
diff --git a/src/frontend/plugins/sorting.pipe.ts b/src/frontend/plugins/sorting.pipe.ts
index 8c60342dae8..4c01c1fd7d3 100755
--- a/src/frontend/plugins/sorting.pipe.ts
+++ b/src/frontend/plugins/sorting.pipe.ts
@@ -1,42 +1,43 @@
 import { Pipe } from '@angular/core';
-import { LatinisePipe } from "ngx-pipes";
+import { LatinisePipe } from 'ngx-pipes';
 import { FunctionsService } from '../service/functions.service';
 
-@Pipe({ name: "sortBy" })
+@Pipe({ name: 'sortBy' })
 export class SortPipe {
 
-	constructor(
-		private latinisePipe: LatinisePipe,
-		public functions: FunctionsService
-		) { }
+    constructor(
+        private latinisePipe: LatinisePipe,
+        public functions: FunctionsService
+    ) { }
 
 
-	transform(array: Array<string>, args: string): Array<string> {
-		let normA = '';
-		let normB = '';
-		
-		if (!this.functions.empty(array)) {
-			array.sort((a: any, b: any) => {
-				if (args === undefined) {
-					normA = this.latinisePipe.transform(a).toLocaleLowerCase();
-					normB = this.latinisePipe.transform(b).toLocaleLowerCase();
-				} else {
-					a[args] = a[args] !== null ? a[args] : '';
-					b[args] = b[args] !== null ? b[args] : '';
-					normA = this.latinisePipe.transform(a[args]).toLocaleLowerCase();
-					normB = this.latinisePipe.transform(b[args]).toLocaleLowerCase();
-				}
-				if (normA < normB) {
-					return -1;
-				} else if (normA > normB) {
-					return 1;
-				} else {
-					return 0;
-				}
-			});
-			return array;
-		} else {
-			return [];
-		}
-	}
+    transform(array: Array<any>, args: string): Array<any> {
+        let normA = '';
+        let normB = '';
+
+        if (!this.functions.empty(array)) {
+            array.sort((a: any, b: any) => {
+
+                if (args === undefined) {
+                    normA = this.latinisePipe.transform(a).toLocaleLowerCase();
+                    normB = this.latinisePipe.transform(b).toLocaleLowerCase();
+                } else {
+                    a[args] = a[args] !== null ? a[args] : '';
+                    b[args] = b[args] !== null ? b[args] : '';
+                    normA = typeof a[args] !== 'number' ? this.latinisePipe.transform(a[args]).toLocaleLowerCase() : a[args];
+                    normB = typeof b[args] !== 'number' ? this.latinisePipe.transform(b[args]).toLocaleLowerCase() : b[args];
+                }
+                if (normA < normB) {
+                    return -1;
+                } else if (normA > normB) {
+                    return 1;
+                } else {
+                    return 0;
+                }
+            });
+            return array;
+        } else {
+            return [];
+        }
+    }
 }
-- 
GitLab