From 64dd8b2212608904650e4c789224cc83e62a6fd2 Mon Sep 17 00:00:00 2001
From: Alex ORLUC <alex.orluc@maarch.org>
Date: Fri, 7 Feb 2020 18:20:43 +0100
Subject: [PATCH] FEAT #12072 TIME 4 begin  front list sended resources

---
 src/frontend/app/app.module.ts                |   4 +-
 .../app/process/process.component.html        |  29 ++-
 .../sended-resource-list.component.html       |  66 +++++++
 .../sended-resource-list.component.scss       | 112 ++++++++++++
 .../sended-resource-list.component.ts         | 165 ++++++++++++++++++
 src/frontend/lang/lang-fr.ts                  |   2 +-
 6 files changed, 369 insertions(+), 9 deletions(-)
 create mode 100644 src/frontend/app/sendedResource/sended-resource-list.component.html
 create mode 100644 src/frontend/app/sendedResource/sended-resource-list.component.scss
 create mode 100644 src/frontend/app/sendedResource/sended-resource-list.component.ts

diff --git a/src/frontend/app/app.module.ts b/src/frontend/app/app.module.ts
index 97a4b48ab78..47497af1cd2 100755
--- a/src/frontend/app/app.module.ts
+++ b/src/frontend/app/app.module.ts
@@ -107,6 +107,7 @@ import { LinkedResourceListComponent } from './linkedResource/linked-resource-li
 import { LinkResourceModalComponent } from './linkedResource/linkResourceModal/link-resource-modal.component';
 
 import { DocumentViewerModalComponent } from './viewer/modal/document-viewer-modal.component';
+import { SendedResourceListComponent } from './sendedResource/sended-resource-list.component';
 
 
 
@@ -203,7 +204,8 @@ import { DocumentViewerModalComponent } from './viewer/modal/document-viewer-mod
         SearchAdvListComponent,
         LinkedResourceListComponent,
         LinkResourceModalComponent,
-        DocumentViewerModalComponent
+        DocumentViewerModalComponent,
+        SendedResourceListComponent
     ],
     entryComponents: [
         ConfirmModalComponent,
diff --git a/src/frontend/app/process/process.component.html b/src/frontend/app/process/process.component.html
index 0a75007aba2..4c3900e7c5f 100644
--- a/src/frontend/app/process/process.component.html
+++ b/src/frontend/app/process/process.component.html
@@ -9,7 +9,8 @@
             <div class="processTool">
                 <div class="processTool-module jiggle" *ngFor="let module of processTool"
                     [class.processTool-module-active]="module.id === currentTool" matRipple
-                    (click)="isToolEnabled(module.id) ? changeTab(module.id) : false" [class.tool-disabled]="!isToolEnabled(module.id)">
+                    (click)="isToolEnabled(module.id) ? changeTab(module.id) : false"
+                    [class.tool-disabled]="!isToolEnabled(module.id)">
                     <i *ngIf="module.count > 0" class="fas fa-circle haveContent"></i>
                     <i [class]="module.icon"></i>
                     <span>{{module.label}}</span>
@@ -77,11 +78,15 @@
                     [resId]="currentResourceInformations.resId">
                 </app-notes-list>
                 <app-linked-resource-list *ngIf="currentTool === 'linkedResources' && !loading" #appLinkedResourceList
-                    [resId]="currentResourceInformations.resId" (reloadBadgeLinkedResources)="refreshBadge($event,'linkedResources')">
+                    [resId]="currentResourceInformations.resId"
+                    (reloadBadgeLinkedResources)="refreshBadge($event,'linkedResources')">
                 </app-linked-resource-list>
                 <app-diffusions-list *ngIf="currentTool === 'diffusionList' && !loading" #appDiffusionsList
                     [adminMode]="false" [resId]="currentResourceInformations.resId" [expanded]="true">
                 </app-diffusions-list>
+                <app-sended-resource-list *ngIf="currentTool === 'mails' && !loading" #appSendedResource
+                    [resId]="currentResourceInformations.resId">
+                </app-sended-resource-list>
                 <app-visa-workflow *ngIf="currentTool === 'visaCircuit' && !loading" #appVisaWorkflow
                     [resId]="currentResourceInformations.resId"
                     [adminMode]="privilegeService.hasCurrentUserPrivilege('config_visa_workflow')"></app-visa-workflow>
@@ -210,9 +215,14 @@
                                     </div>
                                 </ng-template>
                             </div>
-                            <div style="position: absolute;right: 0px;top: 0px;height: 100%;display: flex;flex-direction: column;justify-content: center;">
-                                <button mat-icon-button *ngFor="let inteKey of integrationsInfo | keyvalue" [matTooltip]="lang[inteKey.key]" (click)="toggleIntegration(inteKey.key)">
-                                    <mat-icon [class]="inteKey.value.icon" [class.checked]="currentResourceInformations.integrations[inteKey.key]" [class.unchecked]="!currentResourceInformations.integrations[inteKey.key]"></mat-icon>
+                            <div
+                                style="position: absolute;right: 0px;top: 0px;height: 100%;display: flex;flex-direction: column;justify-content: center;">
+                                <button mat-icon-button *ngFor="let inteKey of integrationsInfo | keyvalue"
+                                    [matTooltip]="lang[inteKey.key]" (click)="toggleIntegration(inteKey.key)">
+                                    <mat-icon [class]="inteKey.value.icon"
+                                        [class.checked]="currentResourceInformations.integrations[inteKey.key]"
+                                        [class.unchecked]="!currentResourceInformations.integrations[inteKey.key]">
+                                    </mat-icon>
                                 </button>
                             </div>
                         </div>
@@ -229,7 +239,8 @@
             <div class="content">
                 <app-document-viewer #appDocumentViewer style="height:100%;width:100%;" [editMode]="canEditData"
                     [resId]="currentResourceInformations.resId"
-                    [title]="currentResourceInformations.chrono + ' - ' + currentResourceInformations.subject" [sidenavLeft]="sidenavLeft">
+                    [title]="currentResourceInformations.chrono + ' - ' + currentResourceInformations.subject"
+                    [sidenavLeft]="sidenavLeft">
                 </app-document-viewer>
             </div>
         </div>
@@ -258,10 +269,14 @@
             [resId]="currentResourceInformations.resId">
         </app-notes-list>
         <app-linked-resource-list *ngIf="modal.id === 'linkedResources' && !loading" #appLinkedResourceList
-            [resId]="currentResourceInformations.resId" (reloadBadgeLinkedResources)="refreshBadge($event,'linkedResources')"></app-linked-resource-list>
+            [resId]="currentResourceInformations.resId"
+            (reloadBadgeLinkedResources)="refreshBadge($event,'linkedResources')"></app-linked-resource-list>
         <app-diffusions-list *ngIf="modal.id === 'diffusionList' && !loading" #appDiffusionsList [adminMode]="false"
             [resId]="currentResourceInformations.resId" [expanded]="true">
         </app-diffusions-list>
+        <app-sended-resource-list *ngIf="modal.id === 'mails' && !loading" #appSendedResource
+            [resId]="currentResourceInformations.resId">
+        </app-sended-resource-list>
         <app-visa-workflow *ngIf="modal.id === 'visaCircuit' && !loading"
             [adminMode]="privilegeService.hasCurrentUserPrivilege('config_visa_workflow')" #appVisaWorkflow
             [resId]="currentResourceInformations.resId">
diff --git a/src/frontend/app/sendedResource/sended-resource-list.component.html b/src/frontend/app/sendedResource/sended-resource-list.component.html
new file mode 100644
index 00000000000..e8ea2806c61
--- /dev/null
+++ b/src/frontend/app/sendedResource/sended-resource-list.component.html
@@ -0,0 +1,66 @@
+<ng-container *ngIf="loading; else elseLoading">
+    <div class="loading">
+        <mat-spinner></mat-spinner>
+    </div>
+</ng-container>
+<ng-template #elseLoading>
+    <div class="row">
+        <div class="col-md-12" style="padding-bottom: 10px;">
+            <mat-button-toggle-group *ngIf="sendedResources.length > 0" class="filterTypes" (change)="filterType($event)">
+                <mat-button-toggle [checked]="currentFilter === ''" [value]="''">Tous</mat-button-toggle>
+                <mat-button-toggle *ngFor="let type of filterTypes | sortBy : 'label'"
+                    [checked]="currentFilter === type.id" [value]="type.id">{{type.label}}
+                </mat-button-toggle>
+            </mat-button-toggle-group>
+        </div>
+    </div>
+    <mat-table #table [dataSource]="dataSource" matSort matSortActive="creationDate" matSortDirection="desc">
+        <ng-container matColumnDef="creationDate">
+            <mat-cell *matCellDef="let row" class="dataLine" style="flex: 1;padding: 0px;flex-direction: column;">
+                <div class="subinfo">
+                    <span style="flex:1" [title]="row.creationDate | fullDate">
+                        Créé : <b>{{row.creationDate | timeAgo : 'full'}}</b>
+                    </span>
+                    <span *ngIf="row.sendDate !== null" style="flex:1;color:green" [title]="row.sendDate | fullDate">
+                        Envoyé : <b>{{row.sendDate | timeAgo : 'full'}}</b>
+                    </span>
+                    <span *ngIf="row.status === 'DRAFT'" style="flex:1;color:orange">
+                        Brouillon
+                    </span>
+                    <span *ngIf="row.sendDate === null" style="flex:1;color:red">
+                        Non envoyé
+                    </span>
+                    <span style="flex:1" *ngIf="!functions.empty(row.sendBackDate)" [title]="row.creationDate | fullDate">
+                        Pris en charge : <b>{{row.creationDate | timeAgo : 'full'}}</b>
+                    </span>
+                </div>
+                <div style="display: grid;grid-template-columns: 100px 1fr 170px;width: 100%;grid-gap: 10px;align-items: center;">
+                    <div class="dateType">
+                        <span class="type">
+                            <span class="badge" [style.background]="row.typeColor">{{lang[row.type]}}</span>
+                            <div class="attach">
+                                <i *ngIf="row.hasMainDoc" class="fas fa-file" title="Document attaché"></i>
+                                <i *ngIf="row.hasAttach" class="fas fa-paperclip" title="Pièce(s) jointe(s) attachée(s)"></i>
+                                <i *ngIf="row.hasNote" class="fas fa-pen-square" title="Note(s) attachée(s)"></i>
+                            </div>
+                        </span>
+                    </div>
+                    <div class="desc">
+    
+                        {{row.desc}}
+                        
+                    </div>
+                    <div class="contact">
+                        <span *ngIf="row.sender" style="white-space: pre;overflow: hidden;text-overflow: ellipsis;">
+                            De : {{row.sender}}
+                        </span>
+                        <span style="white-space: pre;overflow: hidden;text-overflow: ellipsis;">
+                            Pour : {{row.recipients}}
+                        </span>
+                    </div>
+                </div>
+            </mat-cell>
+        </ng-container>
+        <mat-row *matRowDef="let row; columns: displayedColumns;" style="cursor: pointer;"></mat-row>
+    </mat-table>
+</ng-template>
\ No newline at end of file
diff --git a/src/frontend/app/sendedResource/sended-resource-list.component.scss b/src/frontend/app/sendedResource/sended-resource-list.component.scss
new file mode 100644
index 00000000000..282d79f38cf
--- /dev/null
+++ b/src/frontend/app/sendedResource/sended-resource-list.component.scss
@@ -0,0 +1,112 @@
+@import '../../css/vars.scss';
+
+
+.dateType {
+    width: 100px;
+    display: flex;
+    flex-direction: column;
+    font-size: 10px !important;
+    justify-content: center;
+    text-align: center;
+
+    .type {
+        .badge {
+            font-size: 10px !important;
+            color: white;
+            font-weight: normal;
+            width: 100px;
+        }
+
+    }
+
+    .date {
+        opacity: 0.5;
+    }
+}
+
+.desc {
+    font-size: 13px;
+    flex: 1;
+    display: flex;
+    flex-direction: column;
+}
+
+.error {
+    color: red;
+}
+
+.success {
+    color: green;
+}
+
+.contact {
+    font-size: 10px;
+    flex-direction: column;
+    display: flex;
+}
+
+.filterTypes {
+    overflow: auto;
+    overflow-y: hidden;
+    width: auto;
+    max-width: 100%;
+    margin-left: 10px;
+
+    ::ng-deep.mat-button-toggle-checked {
+        background: $secondary;
+        color: white;
+        font-weight: bold;
+        height: 25px;
+        font-size: 10px;
+
+        .mat-button-toggle-label-content {
+            line-height: 0px;
+        }
+
+        .mat-button-toggle-button {
+            height: 100%;
+        }
+    }
+
+    :not(::ng-deep.mat-button-toggle-checked) {
+        ::ng-deep.mat-button-toggle-button {
+            color: $primary;
+            font-weight: bold;
+            height: 25px;
+            font-size: 10px;
+
+            .mat-button-toggle-label-content {
+                line-height: 0px;
+            }
+        }
+    }
+}
+
+.subinfo {
+    padding: 5px;
+    display: flex;
+    font-size: 10px;
+    opacity: 0.5;
+    width: 100%;
+}
+
+.dataLine {
+    transition: all 0.5s;
+
+    &:hover {
+        background: rgba($primary, 0.1);
+        transition: all 0.5s;
+    }
+}
+
+.attach {
+    font-size: 13px;
+    display: flex;
+    padding: 5px;
+    color: $primary;
+
+    i {
+        flex: 1;
+        cursor: help;
+    }
+}
\ No newline at end of file
diff --git a/src/frontend/app/sendedResource/sended-resource-list.component.ts b/src/frontend/app/sendedResource/sended-resource-list.component.ts
new file mode 100644
index 00000000000..58496104166
--- /dev/null
+++ b/src/frontend/app/sendedResource/sended-resource-list.component.ts
@@ -0,0 +1,165 @@
+import { Component, OnInit, ViewChild, EventEmitter, ElementRef, Input } from '@angular/core';
+import { HttpClient } from '@angular/common/http';
+import { LANG } from '../translate.component';
+import { NotificationService } from '../notification.service';
+import { HeaderService } from '../../service/header.service';
+import { Observable, merge, Subject, of as observableOf, of } from 'rxjs';
+import { MatPaginator, MatSort, MatDialog, MatTableDataSource } from '@angular/material';
+import { takeUntil, startWith, switchMap, map, catchError, filter, exhaustMap, tap, debounceTime, distinctUntilChanged, finalize } from 'rxjs/operators';
+import { FormControl } from '@angular/forms';
+import { FunctionsService } from '../../service/functions.service';
+import { LatinisePipe } from 'ngx-pipes';
+import { PrivilegeService } from '../../service/privileges.service';
+
+@Component({
+    selector: 'app-sended-resource-list',
+    templateUrl: "sended-resource-list.component.html",
+    styleUrls: ['sended-resource-list.component.scss'],
+})
+export class SendedResourceListComponent implements OnInit {
+
+    lang: any = LANG;
+    loading: boolean = true;
+
+    filtersChange = new EventEmitter();
+
+    
+    dataSource: any;
+    displayedColumns: string[] = ['creationDate'];
+
+    sendedResources: any[] = [];
+
+    resultsLength = 0;
+
+    typeColor = {
+        startDate: '#b5cfd8',
+        endDate: '#7393a7',
+        actions: '#7d5ba6',
+        systemActions: '#7d5ba6',
+        users: '#009dc5',
+    };
+
+    currentFilter: string = '';
+    filterTypes: any[] = [];
+
+
+    @Input('resId') resId: number = null;
+
+    @ViewChild(MatSort, { static: false }) sort: MatSort;
+
+    constructor(
+        public http: HttpClient,
+        private notify: NotificationService,
+        private headerService: HeaderService,
+        public dialog: MatDialog,
+        public functions: FunctionsService,
+        private latinisePipe: LatinisePipe,
+        public privilegeService: PrivilegeService) { }
+
+    async ngOnInit(): Promise<void> {
+        this.sendedResources = [];
+        await this.initAcknowledgementReceipList();
+        await this.initEmailList();
+        this.initFilter();
+
+        setTimeout(() => {
+            this.dataSource = new MatTableDataSource(this.sendedResources);
+            this.dataSource.sort = this.sort;
+        }, 0);
+        
+        this.loading = false;
+        
+    }
+
+    initAcknowledgementReceipList() {
+        return new Promise((resolve, reject) => {
+            this.http.get(`../../rest/resources/${this.resId}/acknowledgementReceipts`).pipe(
+                map((data: any) => {
+                    data = data.map((item: any) => {
+                        return {
+                            id: item.id,
+                            sender : false,
+                            recipients : item.format === 'html' ? item.contact.email : `${item.contact.firstname} ${item.contact.lastname}`,
+                            creationDate : item.creationDate,
+                            sendDate : item.sendDate,
+                            type: 'acknowledgementReceipt',
+                            typeColor: '#7d5ba6',
+                            desc: item.format === 'html' ? this.lang.ARelectronic : this.lang.ARPaper,
+                            status : item.format === 'html' && item.sendDate === null ? 'ERROR' : 'SENT',
+                            hasAttach : false,
+                            hasNote : false,
+                            hasMainDoc : false
+                        }
+                    })
+                    return data;
+                }),
+                tap((data: any) => {
+                    this.sendedResources = this.sendedResources.concat(data);
+                    
+                    resolve(true);
+                }),
+                catchError((err: any) => {
+                    this.notify.handleSoftErrors(err);
+                    resolve(false);
+                    return of(false);
+                })
+            ).subscribe();
+        });        
+    }
+
+    initEmailList() {
+        return new Promise((resolve, reject) => {
+            this.http.get(`../../rest/resources/${this.resId}/emails`).pipe(
+                map((data: any) => {
+                    data.emails = data.emails.map((item: any) => {
+                        return {
+                            id: item.id,
+                            sender : item.sender.email,
+                            recipients : item.recipients,
+                            creationDate : item.creation_date,
+                            sendDate : item.send_date,
+                            type: 'email',
+                            typeColor: '#5bc0de',
+                            desc: item.object,
+                            status : item.status,
+                            hasAttach : !this.functions.empty(item.document.attachments),
+                            hasNote : !this.functions.empty(item.document.notes),
+                            hasMainDoc : item.document.isLinked
+                        }
+                    })
+                    return data.emails;
+                }),
+                tap((data: any) => {
+                    this.sendedResources = this.sendedResources.concat(data);
+                    
+                    resolve(true);
+                }),
+                catchError((err: any) => {
+                    this.notify.handleSoftErrors(err);
+                    resolve(false);
+                    return of(false);
+                })
+            ).subscribe();
+        });        
+    }
+
+    initFilter() {
+        this.sendedResources.forEach((element: any) => {
+            if (this.filterTypes.filter(type => type.id === element.type).length === 0) {
+                this.filterTypes.push( {
+                    id: element.type,
+                    label: this.lang[element.type]
+                });
+            }
+        });
+    }
+
+    processPostData(data: any) {
+        return data;
+    }
+
+    filterType(ev: any) {
+        this.currentFilter = ev.value;
+        this.dataSource.filter = ev.value;
+    }
+}
\ No newline at end of file
diff --git a/src/frontend/lang/lang-fr.ts b/src/frontend/lang/lang-fr.ts
index 02ee216032d..690e57c19c3 100755
--- a/src/frontend/lang/lang-fr.ts
+++ b/src/frontend/lang/lang-fr.ts
@@ -1515,7 +1515,7 @@ export const LANG_FR = {
     "onlyofficeEditDenied": "Le document avec l'extension",
     "onlyofficeEditDenied2": "ne peut pas être édité avec onlyoffice",
     "NOTE_version": "Version annotée",
-    "SIGN_version": "Version original",
+    "SIGN_version": "Version originale",
     "versions": "Versions",
     "itemRemovedFromVisaTemplate": "Les utilisateurs suivants ont été retirés car ils n'ont pas le droit de viser ou signer",
     "itemRemovedFromAvisTemplate": "Les utilisateurs suivants ont été retirés car ils n'ont pas le droit de donner un avis",
-- 
GitLab