indexation.component.ts 16.4 KB
Newer Older
1
import { DatePipe } from '@angular/common';
2
import { HttpClient } from '@angular/common/http';
3
import { Component, ElementRef, OnInit, TemplateRef, ViewChild, ViewContainerRef } from '@angular/core';
Alex ORLUC's avatar
Alex ORLUC committed
4
import { Router } from '@angular/router';
5
import { AlertController, LoadingController, MenuController, ModalController } from '@ionic/angular';
6
import { TranslateService } from '@ngx-translate/core';
7
8
import { of } from 'rxjs';
import { catchError, finalize, tap } from 'rxjs/operators';
9
import { VisaWorkflowComponent } from '../document/visa-workflow/visa-workflow.component';
10
import { AuthService } from '../service/auth.service';
11
import { NotificationService } from '../service/notification.service';
12
import { SignaturesContentService } from '../service/signatures.service';
13
import { SignaturePositionComponent } from './signature-position/signature-position.component';
14
import { ActionsService } from '../service/actions.service';
15
import { FunctionsService } from '../service/functions.service';
16
17
18
19

@Component({
    templateUrl: 'indexation.component.html',
    styleUrls: ['indexation.component.scss'],
20
    providers: [DatePipe]
21
22
23
})
export class IndexationComponent implements OnInit {

24
25
26
27
    @ViewChild('appVisaWorkflow', { static: false }) appVisaWorkflow: VisaWorkflowComponent;
    @ViewChild('rightContent', { static: true }) rightContent: TemplateRef<any>;
    @ViewChild('docToUpload') fileImport: ElementRef;

28
    loading: boolean = false;
29
    filesToUpload: any[] = [];
30
    errors: any[] = [];
31
    fromDocument: number = null;
32

33
    constructor(
34
        public http: HttpClient,
35
        private translate: TranslateService,
36
        public router: Router,
37
38
39
        private menu: MenuController,
        public signaturesService: SignaturesContentService,
        public viewContainerRef: ViewContainerRef,
40
        public notificationService: NotificationService,
41
        public authService: AuthService,
42
        public loadingController: LoadingController,
43
44
        public alertController: AlertController,
        public datePipe: DatePipe,
45
        public modalController: ModalController,
46
47
        public actionsService: ActionsService,
        private functionsService: FunctionsService
48
49
    ) { }

50
51
52
    ngOnInit(): void { }

    ionViewWillEnter() {
53
54
55
        this.menu.enable(true, 'left-menu');
        this.menu.enable(true, 'right-menu');

Alex ORLUC's avatar
Alex ORLUC committed
56
        this.filesToUpload = [];
57
        this.signaturesService.initTemplate(this.rightContent, this.viewContainerRef, 'rightContent');
58
59
60
61
62
63
64
65
66
67
68

        if (window.history.state.documentId !== undefined) {
            this.fromDocument = window.history.state.documentId;
            this.getDocumentData(this.fromDocument);
        }
    }

    getDocumentData(resId: number) {
        return new Promise((resolve) => {
            this.http.get(`../rest/documents/${resId}`).pipe(
                tap((data: any) => {
69
70
71
72
73
74
75
76
                    let ref = '';
                    let arrRef = data.document.reference.split('/');
                    arrRef = arrRef.slice(3, arrRef.length);

                    if (arrRef.length > 0) {
                        ref = arrRef.join('/');
                    }

77
78
                    this.filesToUpload.push({
                        title: data.document.title,
79
                        reference: ref,
80
81
                        mainDocument: true,
                        content: '',
82
83
                        linkId: data.document.linkId,
                        metadata: data.document.metadata,
84
85
86
87
                    });
                    this.getDocumentContent(resId);
                    this.appVisaWorkflow.loadWorkflow(data.document.workflow.map((item: any) => {
                        item.userSignatureModes.unshift('visa');
88
                        item.signatureMode = item.userId === null && item.signatureMode === 'stamp' ? 'sign' : item.signatureMode;
89
90
91
92
93
                        return {
                            ...item,
                            'processDate': null,
                            'current': false,
                            'role': item.mode === 'visa' ? 'visa' : item.signatureMode,
94
                            'modes': item.userId === null ? ['sign', 'visa'] : item.userSignatureModes
95
96
97
98
99
                        };
                    }));
                    for (let index = 0; index < data.document.attachments.length; index++) {
                        this.getAttachment(data.document.attachments[index].id);
                    }
100
101
102
103
104
105
106

                    const externalUsers: any[] = this.appVisaWorkflow.getCurrentWorkflow().filter((user: any) => user.userId === null);
                    if (externalUsers.length > 0) {
                        externalUsers.forEach(async (element: any) => {
                            const obj: any = await this.appVisaWorkflow.formatData(element);
                            element = obj;
                        });
107
                    }
108
109
110
111
112
113
114
115
116
117
118
119
                    resolve(true);
                }),
                catchError((err: any) => {
                    this.notificationService.handleErrors(err);
                    return of(false);
                })
            ).subscribe();
        });
    }

    getDocumentContent(resId: number) {
        return new Promise((resolve) => {
120
            this.http.get(`../rest/documents/${resId}/content?type=original`).pipe(
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
                tap((data: any) => {
                    this.filesToUpload[0].content = data.encodedDocument;
                    resolve(true);
                }),
                catchError((err: any) => {
                    this.notificationService.handleErrors(err);
                    return of(false);
                })
            ).subscribe();
        });
    }

    getAttachment(attachId: number) {
        return new Promise((resolve) => {
            this.http.get(`../rest/attachments/${attachId}`).pipe(
                tap((data: any) => {
                    this.filesToUpload.push({
                        title: data.attachment.title,
                        mainDocument: false,
                        content: data.attachment.encodedDocument
                    });
                    resolve(true);
                }),
                catchError((err: any) => {
                    this.notificationService.handleErrors(err);
                    return of(false);
                })
            ).subscribe();
        });
150
151
152
153
154
    }

    ionViewWillLeave() {
        this.signaturesService.detachTemplate('rightContent');
    }
155

156
    onSubmit() {
157
        if (this.isValid()) {
158
            this.promptSaveDoc();
159
160
161
        }
    }

162
163
    async promptSaveDoc() {
        const alert = await this.alertController.create({
164
165
            cssClass: 'alert-info-no-msg',
            header: this.translate.instant('lang.areYouSure'),
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
            inputs: [
                {
                    name: 'note',
                    id: 'note',
                    type: 'textarea',
                    placeholder: this.translate.instant('lang.addNote')
                },
            ],
            buttons: [
                {
                    text: this.translate.instant('lang.cancel'),
                    role: 'cancel',
                    cssClass: 'secondary',
                    handler: () => { }
                },
                {
                    text: this.translate.instant('lang.validate'),
                    handler: (data: any) => {
                        this.loadingController.create({
Alex ORLUC's avatar
Alex ORLUC committed
185
                            message: this.translate.instant('lang.processing'),
186
187
188
189
190
191
                            spinner: 'dots'
                        }).then(async (load: HTMLIonLoadingElement) => {
                            load.present();
                            const objTosend = this.formatData(data.note);
                            for (let index = 0; index < objTosend.length; index++) {
                                await this.saveDocument(objTosend[index], index);
192
193
194
                                if (objTosend[0].workflow[0].userId === this.authService.user.id) {
                                    this.actionsService.setEvent('refreshList');
                                }
195
196
197
                            }
                            load.dismiss();
                            if (this.errors.length === 0) {
Alex ORLUC's avatar
Alex ORLUC committed
198
                                this.notificationService.success('lang.documentsImported');
199
200
201
202
203
204
205
206
207
208
                                this.router.navigate(['/home']);
                            }
                        });
                    }
                }
            ]
        });
        await alert.present();
    }

209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
    saveDocument(data: any, index: number) {
        return new Promise((resolve) => {
            this.http.post('../rest/documents', data).pipe(
                tap(() => {
                }),
                finalize(() => resolve(true)),
                catchError((err: any) => {
                    this.errors.push(data.title);
                    this.notificationService.handleErrors(err);
                    return of(false);
                })
            ).subscribe();
        });
    }

224
    formatData(note: string) {
225
        const today: Date = new Date();
226
        let noteObj: any = null;
227
        let linkId: string = null;
228
229

        if (note !== '') {
230
231
232
233
            noteObj = {
                value: note,
                creator: `${this.authService.user.firstname} ${this.authService.user.lastname}`,
                creationDate: this.datePipe.transform(today, 'dd-MM-y')
234
235
            };
        }
236

237
238
239
240
        const formattedObj: any[] = [];
        const signedFiles = this.filesToUpload.filter((item: any) => item.mainDocument);
        const attachFiles = this.filesToUpload.filter((item: any) => !item.mainDocument);

241
242
243
244
        if (signedFiles.length > 1) {
            linkId = this.datePipe.transform(today, 'ddMMYhmmss') + '_' + Math.random().toString(36).substr(2, 9);
        }

245
        signedFiles.forEach((file: any) => {
246
247
248
249
250
251
            const metadata = {};
            if (this.fromDocument !== null) {
                file.metadata.forEach((element: any) => {
                    metadata[element.label] = element.value;
                });
            }
252
253
254
255
            let formattedReference = '';
            if (file.reference !== '') {
                formattedReference = this.datePipe.transform(today, 'y/MM/dd') + '/' + file.reference;
            }
256
257
            formattedObj.push({
                title: file.title,
258
                reference: formattedReference,
259
                encodedDocument: file.content,
260
                isZipped: false,
261
                linkId: this.fromDocument !== null ? file.linkId : linkId,
262
                sender: `${this.authService.user.firstname} ${this.authService.user.lastname}`,
263
                notes: noteObj,
264
265
266
267
268
                attachments: attachFiles.map((item: any) => ({
                    title: item.title,
                    encodedDocument: item.content
                })),
                workflow: this.appVisaWorkflow.getCurrentWorkflow().map((item: any, index: number) => ({
269
                    externalInformations: item.otp === undefined ? item.externalInformations : item.otp,
270
                    userId: item.userId,
271
                    mode: this.authService.getWorkflowMode(item.role),
272
273
274
275
276
277
278
                    signatureMode: this.authService.getSignatureMode(item.role),
                    signaturePositions: file.signPos !== undefined ? file.signPos.filter((userItem: any) => userItem.sequence === index).map((itemFile: any) => ({
                        page: itemFile.page,
                        positionX: itemFile.position.positionX,
                        positionY: itemFile.position.positionY,
                    })) : []
                })),
279
                metadata: metadata
280
281
282
283
284
285
            });
        });

        return formattedObj;
    }

286
287
288
289
290
291
292
293
294
295
296
297
    dndUploadFile(event: any) {
        const fileInput = {
            target: {
                files: [
                    event[0]
                ]
            }
        };
        this.uploadTrigger(fileInput);
    }

    uploadTrigger(fileInput: any) {
298
        if (fileInput.target.files && fileInput.target.files[0] && this.isExtensionAllowed(fileInput.target.files)) {
299
            for (let index = 0; index < fileInput.target.files.length; index++) {
300
301
                const filename = fileInput.target.files[index].name;
                const file = {
302
                    title: filename.substr(0, filename.lastIndexOf('.')),
303
                    reference: filename.substr(0, filename.lastIndexOf('.')).substr(0, 53),
304
305
306
307
308
309
310
                    mainDocument: true,
                    content: ''
                };
                const reader = new FileReader();
                reader.readAsArrayBuffer(fileInput.target.files[index]);
                reader.onload = (value: any) => {
                    file.mainDocument = this.filesToUpload.length === 0;
311
312
                    file.reference = this.filesToUpload.length === 0 ? file.reference : '';
                    file.content = this.getBase64Document(value.target.result);
313
                    this.filesToUpload.push(file);
314
315
316
317
318
                    if (this.filesToUpload.length === 1) {
                        setTimeout(() => {
                            this.menu.open('right-menu');
                        }, 500);
                    }
319
320
                };
            }
321
            this.fileImport.nativeElement.value = '';
322
323
324
325
326
        } else {
            this.loading = false;
        }
    }

327
328
329
    isExtensionAllowed(files: any[]) {
        for (let index = 0; index < files.length; index++) {
            if (files[index].name.toLowerCase().split('.').pop() !== 'pdf') {
Alex ORLUC's avatar
Alex ORLUC committed
330
                this.notificationService.error('lang.onlyPdfAuthorized');
331
332
333
334
335
336
                return false;
            }
        }
        return true;
    }

337
338
    getBase64Document(buffer: ArrayBuffer) {
        const TYPED_ARRAY = new Uint8Array(buffer);
339
        const STRING_CHAR = TYPED_ARRAY.reduce((data, byte) => data + String.fromCharCode(byte), '');
340
341
342
343
344
345
346
347

        return btoa(STRING_CHAR);
    }

    deleteFile(index: number) {
        this.filesToUpload.splice(index, 1);
    }

348
349
350
351
352
353
    async signPos(index: number) {
        if (this.appVisaWorkflow.getCurrentWorkflow().length > 0) {
            const modal = await this.modalController.create({
                component: SignaturePositionComponent,
                cssClass: 'custom-alert-fullscreen',
                componentProps: {
354
355
356
357
                    'workflow': this.appVisaWorkflow.getCurrentWorkflow().map((item: any) => ({
                        userDisplay: item.userDisplay,
                        mode: this.authService.getWorkflowMode(item.role),
                    })),
358
                    'signPos': this.filesToUpload[index].signPos,
359
                    'pdfTitle': this.filesToUpload[index].title,
360
361
362
363
364
365
366
367
368
                    'pdfContent': 'data:application/pdf;base64,' + this.filesToUpload[index].content,
                }
            });
            await modal.present();
            const { data } = await modal.onWillDismiss();
            if (data !== undefined) {
                this.filesToUpload[index].signPos = data;
            }
        } else {
Alex ORLUC's avatar
Alex ORLUC committed
369
            this.notificationService.error('lang.mustSetWorkflowBeforeSignPositions');
370
371
372
        }
    }

373
    isValid() {
374
375
376
377
378
        if (this.filesToUpload.filter((item: any) => item.title === '').length > 0) {
            this.notificationService.error('lang.subjectMandatory');
            return false;
        } else if (this.filesToUpload.filter((item: any) => item.mainDocument).length === 0) {
            this.notificationService.error('lang.mainDocumentMandatory');
379
380
            return false;
        } else if (this.appVisaWorkflow.getCurrentWorkflow().length === 0) {
381
            this.notificationService.error('lang.workflowUserstMandatory');
382
383
            this.menu.open('right-menu');
            return false;
384
        } else if (this.appVisaWorkflow.getCurrentWorkflow().filter((user: any) => user.userId === null && user.noConnector !== undefined).length > 0) {
385
386
            this.notificationService.error('lang.noConnector');
            return false;
387
388
389
        } else if (this.hasEmptyOtpSignaturePosition()) {
            this.notificationService.error('lang.otpSignaturePositionMandatory');
            return false;
390
391
392
393
        } else {
            return true;
        }
    }
394
395
396
397
398
399
400
401
402
403
404


    hasEmptyOtpSignaturePosition() {
        const workflow = this.formatData(null)[0].workflow;

        const isSign = /_sign_/g;

        const hasEmptyPosition = workflow.filter((item: any) => item.signaturePositions.length === 0 && !this.functionsService.empty(item.externalInformations) && item.mode.match(isSign) !== null).length > 0;

        return hasEmptyPosition;
    }
405
}