@dsivd/prestations-ng 16.1.0-beta.2 → 16.1.0-beta.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (24) hide show
  1. package/CHANGELOG.md +32 -2
  2. package/dsivd-prestations-ng-v16.1.0-beta.3.tgz +0 -0
  3. package/esm2020/foehn-upload/foehn-bo-multi-upload/bo-multi-upload.service.mjs +64 -23
  4. package/esm2020/foehn-upload/foehn-bo-multi-upload/foehn-bo-multi-upload.component.mjs +9 -9
  5. package/esm2020/foehn-upload/foehn-multi-upload/multi-upload.service.mjs +65 -26
  6. package/esm2020/foehn-upload/foehn-upload-progress-bar/foehn-upload-progress-bar.component.mjs +14 -7
  7. package/esm2020/foehn-upload/foehn-upload-progress-bar/upload-progress.service.mjs +8 -4
  8. package/esm2020/foehn-upload/foehn-upload-progress-bar/upload-progress.type.mjs +5 -1
  9. package/esm2020/gesdem-action-recovery/gesdem-action-recovery-registration/gesdem-action-recovery-registration.component.mjs +14 -7
  10. package/esm2020/gesdem-action-recovery/gesdem-action-recovery.module.mjs +12 -4
  11. package/esm2020/sdk-dictionary/default-dictionary.mjs +20 -1
  12. package/fesm2015/dsivd-prestations-ng.mjs +202 -76
  13. package/fesm2015/dsivd-prestations-ng.mjs.map +1 -1
  14. package/fesm2020/dsivd-prestations-ng.mjs +200 -76
  15. package/fesm2020/dsivd-prestations-ng.mjs.map +1 -1
  16. package/foehn-upload/foehn-bo-multi-upload/bo-multi-upload.service.d.ts +3 -0
  17. package/foehn-upload/foehn-bo-multi-upload/foehn-bo-multi-upload.component.d.ts +1 -1
  18. package/foehn-upload/foehn-multi-upload/multi-upload.service.d.ts +3 -0
  19. package/foehn-upload/foehn-upload-progress-bar/foehn-upload-progress-bar.component.d.ts +3 -0
  20. package/foehn-upload/foehn-upload-progress-bar/upload-progress.service.d.ts +5 -5
  21. package/foehn-upload/foehn-upload-progress-bar/upload-progress.type.d.ts +2 -0
  22. package/gesdem-action-recovery/gesdem-action-recovery.module.d.ts +3 -1
  23. package/package.json +1 -1
  24. package/dsivd-prestations-ng-v16.1.0-beta.2.tgz +0 -0
@@ -2,7 +2,7 @@ import * as i0 from '@angular/core';
2
2
  import { Injectable, Optional, Inject, EventEmitter, Directive, Input, ViewChildren, ViewChild, forwardRef, Output, HostBinding, Pipe, Component, ContentChildren, HostListener, NgModule, TemplateRef, ContentChild } from '@angular/core';
3
3
  import * as i1$1 from '@angular/router';
4
4
  import { ActivatedRoute, NavigationStart, RouterModule, NavigationEnd, RouterLink } from '@angular/router';
5
- import { of, BehaviorSubject, combineLatest, Subject, throwError, EMPTY, merge, tap as tap$1, debounceTime as debounceTime$1, map as map$1 } from 'rxjs';
5
+ import { of, BehaviorSubject, combineLatest, Subject, throwError, concat, toArray, EMPTY, merge, tap as tap$1, debounceTime as debounceTime$1, map as map$1 } from 'rxjs';
6
6
  import { map, shareReplay, debounceTime, catchError, switchMap, tap, filter, mergeMap, throttleTime, share, first, finalize, distinctUntilChanged } from 'rxjs/operators';
7
7
  import * as i1 from '@angular/common/http';
8
8
  import { HttpParams, HttpEventType, HttpResponse, HttpErrorResponse, HTTP_INTERCEPTORS, HttpClientModule, HttpClient } from '@angular/common/http';
@@ -773,6 +773,18 @@ const DEFAULT_DICTIONARY = {
773
773
  'gesdem-confirmation.resume-my-demand.label': 'Vous pouvez reprendre votre demande en cliquant sur le lien ci-dessous',
774
774
  'gesdem-confirmation.resume-my-demand.button': 'Reprendre ma demande',
775
775
  'gesdem.download-pdf.button.title': 'Télécharger le PDF',
776
+ 'gesdem-action-recovery-registration.modalHeaderText': 'Informations pour la reprise de la demande',
777
+ 'gesdem-action-recovery-registration.connected.info': '<p>Vos données ont été sauvegardées, vous pouvez accéder à cette demande dans la liste de ' +
778
+ '<a href="/100002/demandes/search/MINE/INITIAL"> ' +
779
+ 'vos demandes en brouillon</a>.',
780
+ 'gesdem-action-recovery-registration.not-connected.info': "Les informations demandées sont uniquement utilisées pour vous permettre d'effectuer la reprise de demande.",
781
+ 'gesdem-action-recovery-registration.not-connected.info.sent': '<p>Un message contenant le lien de reprise de la demande a été envoyé à votre email.</p>' +
782
+ '<p>Vous pouvez cliquer sur ce lien pour reprendre la demande en saisissant le code qui sera envoyé à votre téléphone.</p>',
783
+ 'gesdem-action-recovery-registration.not-connected.email.label': 'Email',
784
+ 'gesdem-action-recovery-registration.not-connected.email.help-text': 'Par exemple, john@doe.ch',
785
+ 'gesdem-action-recovery-registration.not-connected.mobile.label': 'Numéro de téléphone mobile',
786
+ 'gesdem-action-recovery-registration.cancel.button': 'Fermer',
787
+ 'gesdem-action-recovery-registration.save.button': 'Sauvegarder',
776
788
  'foehn-date-picker-button.icon-title': 'Afficher le calendrier',
777
789
  'foehn-date-picker-button.screen-reader.selected-date': 'Date sélectionnée : {selectedDate}',
778
790
  'foehn-date-picker.container.aria-label': 'Calendrier',
@@ -807,6 +819,10 @@ const DEFAULT_DICTIONARY = {
807
819
  'foehn-uploader.abbr-megaoctet-title': 'Megaoctet',
808
820
  'foehn-uploader.delete-icon-title': 'Supprimer {docName}',
809
821
  'foehn-uploader.max-upload-selection-reached': 'Vous ne pouvez pas télécharger plus de {maxSelection} fichiers à la fois.',
822
+ 'foehn-uploader.files-saved-success-message': '{successfulDocumentsCount} fichier(s) sauvegardé(s) avec succès',
823
+ 'foehn-uploader.transmission-error-message': 'Une erreur est survenue lors de la transmission de vos documents',
824
+ 'foehn-uploader.files-deleted-success-message': 'Suppression du fichier {filename} réussie',
825
+ 'foehn-uploader.delete-error-message': 'Une erreur est survenue lors de la suppression de votre document',
810
826
  'use-login.text.decision-electronique-available': 'Pour obtenir la notification de la décision sous forme électronique ' +
811
827
  '(fichier au format pdf), vous devez demander la prestation en étant connecté au portail sécurisé.',
812
828
  'use-login.text': 'Cette prestation est également utilisable <strong>en se connectant</strong> au portail sécurisé de l’État de Vaud pour autant ' +
@@ -880,7 +896,10 @@ const DEFAULT_DICTIONARY = {
880
896
  'foehn-textarea.chars-remaining.exceeded': 'Vous avez dépassé le nombre de caractères autorisés de {charCountLeft}',
881
897
  'foehn-upload-progress-bar.title': 'Traitement de votre envoi',
882
898
  'foehn-upload-progress-bar.upload': 'Enregistrement en cours...',
899
+ 'foehn-upload-progress-bar.group.upload': 'Lot {packageIndex}/{nbPackages} : Enregistrement en cours...',
883
900
  'foehn-upload-progress-bar.analysis': 'Analyse en cours... Merci de patienter.',
901
+ 'foehn-upload-progress-bar.group.analysis': 'Lot {packageIndex}/{nbPackages} : Analyse en cours... Merci de patienter.',
902
+ 'foehn-upload-progress-bar.group.info': 'Le téléchargement se fait en plusieurs lots en fonction du nombre de fichiers chargés',
884
903
  'errors.NotNull': 'Ce champ doit être rempli',
885
904
  'foehn-header.logo.title': "Aller à la page d'accueil du Site du Canton de Vaud",
886
905
  'foehn-header.cyber-secured-area.identity.srOnly': 'Votre identité',
@@ -2425,7 +2444,7 @@ class UploadProgressService {
2425
2444
  get showProgressSubject() {
2426
2445
  return this.showProgress.asObservable();
2427
2446
  }
2428
- manageUploadEventFilter(event) {
2447
+ manageUploadEventFilter(event, packageIndex = 0, nbPackages = 1) {
2429
2448
  switch (event.type) {
2430
2449
  case HttpEventType.Sent:
2431
2450
  this.showProgress.next(true);
@@ -2433,7 +2452,9 @@ class UploadProgressService {
2433
2452
  case HttpEventType.UploadProgress:
2434
2453
  const progress = {
2435
2454
  loaded: event.loaded,
2436
- total: event.total
2455
+ total: event.total,
2456
+ nbPackages,
2457
+ packageIndex
2437
2458
  };
2438
2459
  this.uploadProgress.next(progress);
2439
2460
  return false;
@@ -2445,7 +2466,9 @@ class UploadProgressService {
2445
2466
  case HttpEventType.User:
2446
2467
  default:
2447
2468
  this.analysisProgress.next(false);
2448
- this.showProgress.next(false);
2469
+ if (packageIndex + 1 === nbPackages) {
2470
+ this.showProgress.next(false);
2471
+ }
2449
2472
  return true;
2450
2473
  }
2451
2474
  }
@@ -2469,34 +2492,48 @@ class MultiUploadService {
2469
2492
  this.uploadProgressService = uploadProgressService;
2470
2493
  // A way to have a unique Id per file
2471
2494
  this.globalSequence = 0;
2495
+ this.NB_CONCURRENT_FILES_TO_UPLOAD = 3;
2496
+ this.mergeDocumentsWithErrors = (arrayOfDocumentsWithErrors) => {
2497
+ const mergedResponse = new DocumentsWithErrors();
2498
+ arrayOfDocumentsWithErrors.forEach(item => {
2499
+ if (!!item.documents?.length) {
2500
+ if (!mergedResponse.documents) {
2501
+ mergedResponse.documents = [];
2502
+ }
2503
+ mergedResponse.documents = mergedResponse.documents.concat(item.documents);
2504
+ }
2505
+ if (!!item.errors?.length) {
2506
+ if (!mergedResponse.errors) {
2507
+ mergedResponse.errors = [];
2508
+ }
2509
+ mergedResponse.errors = mergedResponse.errors.concat(item.errors);
2510
+ }
2511
+ });
2512
+ return mergedResponse;
2513
+ };
2472
2514
  this.uploaderHelper = new UploaderHelper(dictionaryService, applicationInfoService);
2473
2515
  }
2474
2516
  uploadDocuments(baseUrl, formKey, label, files, key, isMultiple, language, shouldDisplayFileSavedConfirmation) {
2475
2517
  const reference = this.gesdemHandlerService.lastResponse.meta.reference;
2476
2518
  if (!!reference?.length) {
2477
- const documents = files.map(file => this.uploaderHelper.mapToDocumentReference(file, label, key, isMultiple, new Date().getTime(), this.globalSequence++));
2478
- const formData = this.uploaderHelper.mapToFormData(documents, formKey, language);
2479
2519
  const url = `${baseUrl}/upload/${reference}`;
2480
- return this.httpClient
2481
- .post(url, formData, {
2482
- reportProgress: true,
2483
- observe: 'events',
2484
- responseType: 'json'
2485
- })
2486
- .pipe(filter((e) => this.uploadProgressService.manageUploadEventFilter(e)), map((e) => e.body), tap(result => {
2487
- const successfulDocumentsCount = result.documents && result.documents.length;
2488
- if (successfulDocumentsCount &&
2489
- shouldDisplayFileSavedConfirmation) {
2490
- const message = `${successfulDocumentsCount} fichier(s) sauvegardé(s) avec succès`;
2491
- this.growlService.addWithType(GrowlType.SUCCESS, message);
2492
- }
2493
- }), catchError((e) => {
2494
- this.uploadProgressService.analysisProgress.next(false);
2495
- this.uploadProgressService.showProgress.next(false);
2496
- const message = 'Une erreur est survenue lors de la transmission de vos documents';
2497
- this.growlService.addWithType(GrowlType.DANGER, message);
2498
- return throwError(() => e);
2499
- }));
2520
+ const filesToGroup = [...files];
2521
+ const groupsOfFiles = [];
2522
+ while (!!filesToGroup.length) {
2523
+ groupsOfFiles.push(filesToGroup.splice(0, this.NB_CONCURRENT_FILES_TO_UPLOAD));
2524
+ }
2525
+ const arrayOfDocumentsWithErrorsObservable = groupsOfFiles.map((groupOfFile, index) => {
2526
+ const documents = groupOfFile.map(file => this.uploaderHelper.mapToDocumentReference(file, label, key, isMultiple, new Date().getTime(), this.globalSequence++));
2527
+ const formData = this.uploaderHelper.mapToFormData(documents, formKey, language);
2528
+ return this.getDocumentsWithErrorsObservable(url, formData, shouldDisplayFileSavedConfirmation, index, groupsOfFiles.length);
2529
+ });
2530
+ if (arrayOfDocumentsWithErrorsObservable.length === 1) {
2531
+ return arrayOfDocumentsWithErrorsObservable[0];
2532
+ }
2533
+ // concat() operator sequentially emits all values from the given Observable and then proceed to the next one.
2534
+ return concat(...arrayOfDocumentsWithErrorsObservable).pipe(
2535
+ // toArray() operator collects all the values emitted by the source observable into an array and sends it to the observer
2536
+ toArray(), map(this.mergeDocumentsWithErrors.bind(this)));
2500
2537
  }
2501
2538
  return EMPTY;
2502
2539
  }
@@ -2506,10 +2543,10 @@ class MultiUploadService {
2506
2543
  return this.httpClient.delete(url).pipe(
2507
2544
  // Reflect the document once the update is done to ease chaining observables.
2508
2545
  map(() => document), tap(() => {
2509
- const message = `Suppression du fichier ${document.filename} réussie`;
2546
+ const message = this.dictionaryService.getKeySync('foehn-uploader.files-deleted-success-message', { filename: document.filename });
2510
2547
  this.growlService.addWithType(GrowlType.SUCCESS, message);
2511
2548
  }), catchError((e) => {
2512
- const message = 'Une erreur est survenue lors de la suppression de votre document';
2549
+ const message = this.dictionaryService.getKeySync('foehn-uploader.delete-error-message');
2513
2550
  this.growlService.addWithType(GrowlType.DANGER, message);
2514
2551
  return throwError(() => e);
2515
2552
  }));
@@ -2518,6 +2555,30 @@ class MultiUploadService {
2518
2555
  const reference = this.gesdemHandlerService.lastResponse.meta.reference;
2519
2556
  return `${baseUrl}/download/${reference}/doc/${document.reference}`;
2520
2557
  }
2558
+ getDocumentsWithErrorsObservable(url, formData, shouldDisplayFileSavedConfirmation, packageIndex = 0, nbPackages = 1) {
2559
+ return this.httpClient
2560
+ .post(url, formData, {
2561
+ reportProgress: true,
2562
+ observe: 'events',
2563
+ responseType: 'json'
2564
+ })
2565
+ .pipe(filter((e) => this.uploadProgressService.manageUploadEventFilter(e, packageIndex, nbPackages)), map((e) => e.body), tap(result => {
2566
+ const successfulDocumentsCount = result.documents && result.documents.length;
2567
+ if (successfulDocumentsCount &&
2568
+ shouldDisplayFileSavedConfirmation) {
2569
+ const message = this.dictionaryService.getKeySync('foehn-uploader.files-saved-success-message', {
2570
+ successfulDocumentsCount: successfulDocumentsCount.toString()
2571
+ });
2572
+ this.growlService.addWithType(GrowlType.SUCCESS, message);
2573
+ }
2574
+ }), catchError((e) => {
2575
+ this.uploadProgressService.analysisProgress.next(false);
2576
+ this.uploadProgressService.showProgress.next(false);
2577
+ const message = this.dictionaryService.getKeySync('foehn-uploader.transmission-error-message');
2578
+ this.growlService.addWithType(GrowlType.DANGER, message);
2579
+ return throwError(() => e);
2580
+ }));
2581
+ }
2521
2582
  }
2522
2583
  MultiUploadService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: MultiUploadService, deps: [{ token: i1.HttpClient }, { token: GrowlBrokerService }, { token: GesdemHandlerService }, { token: ApplicationInfoService }, { token: SdkDictionaryService }, { token: UploadProgressService }], target: i0.ɵɵFactoryTarget.Injectable });
2523
2584
  MultiUploadService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: MultiUploadService, providedIn: 'root' });
@@ -10594,15 +10655,21 @@ class GesdemActionRecoveryRegistrationComponent {
10594
10655
  sendAndClose() {
10595
10656
  this.actionRecoveryService
10596
10657
  .registerForRecovery(this.reference, this.model)
10597
- .pipe(tap(err => {
10658
+ .pipe(tap(formRecoveryErrors => {
10598
10659
  this.form.reset();
10599
10660
  this.validationHandler.shouldDisplayErrors(true);
10600
10661
  this.validationHandler.updateErrors([
10601
- ...err,
10662
+ ...formRecoveryErrors,
10602
10663
  ...this.gesdemService.lastResponse.errors
10603
10664
  ]);
10604
10665
  this.form.focusFirstInError();
10605
- this.mailSent = !err.length;
10666
+ const registrationSuccessfull = !formRecoveryErrors.length;
10667
+ this.mailSent = registrationSuccessfull;
10668
+ if (registrationSuccessfull) {
10669
+ // the form could have been updated by the backend on recovery registration
10670
+ // eslint-disable-next-line rxjs-angular/prefer-async-pipe
10671
+ this.gesdemService.retrieve(this.reference).subscribe();
10672
+ }
10606
10673
  }))
10607
10674
  // eslint-disable-next-line rxjs-angular/prefer-async-pipe
10608
10675
  .subscribe();
@@ -10636,10 +10703,10 @@ class GesdemActionRecoveryRegistrationComponent {
10636
10703
  }
10637
10704
  }
10638
10705
  GesdemActionRecoveryRegistrationComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: GesdemActionRecoveryRegistrationComponent, deps: [{ token: GesdemActionRecoveryService }, { token: ValidationHandlerService }, { token: FoehnPageService }, { token: GesdemEventService }, { token: GesdemHandlerService }, { token: ApplicationInfoService }, { token: SessionInfo }], target: i0.ɵɵFactoryTarget.Component });
10639
- GesdemActionRecoveryRegistrationComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.9", type: GesdemActionRecoveryRegistrationComponent, selector: "gesdem-action-recovery-registration", inputs: { continueLaterLabel: "continueLaterLabel" }, viewQueries: [{ propertyName: "modalTrigger", first: true, predicate: ["modalTrigger"], descendants: true }, { propertyName: "form", first: true, predicate: FoehnFormComponent, descendants: true }], ngImport: i0, template: "<button\n type=\"button\"\n id=\"continueLaterButton\"\n class=\"btn btn-link pr-0 pl-0 no-text-transform\"\n *ngIf=\"canContinueLater | async\"\n (click)=\"open()\"\n #modalTrigger\n>\n {{ continueLaterLabel }}\n</button>\n\n<foehn-modal\n id=\"action-recovery-registration-modal\"\n [modalHeaderText]=\"'Informations pour la reprise de la demande'\"\n [isModalVisible]=\"isModalVisible\"\n (isModalVisibleChange)=\"updateVisibilityStatus($event)\"\n>\n <ng-container *ngIf=\"isConnectedCyber | async; else notConnectedContent\">\n <p>\n Vos donn\u00E9es ont \u00E9t\u00E9 sauvegard\u00E9es, vous pouvez acc\u00E9der \u00E0 cette\n demande dans la liste de\n <a href=\"/100002/demandes/search/MINE/INITIAL\">\n vos demandes en brouillon\n </a>\n .\n </p>\n </ng-container>\n <ng-template #notConnectedContent>\n <div class=\"alert alert-info\">\n <p *ngIf=\"!mailSent\">\n Les informations demand\u00E9es sont uniquement utilis\u00E9es pour vous\n permettre d'effectuer la reprise de demande.\n </p>\n\n <div *ngIf=\"mailSent\">\n <p>\n Un message contenant le lien de reprise de la demande a \u00E9t\u00E9\n envoy\u00E9 \u00E0 votre email.\n </p>\n <p>\n Vous pouvez cliquer sur ce lien pour reprendre la demande en\n saisissant le code qui sera envoy\u00E9 \u00E0 votre t\u00E9l\u00E9phone.\n </p>\n </div>\n </div>\n\n <foehn-form *ngIf=\"!mailSent\" [shouldDisplayAlertSummary]=\"false\">\n <foehn-input-text\n label=\"Email\"\n helpText=\"Par exemple, john@doe.ch\"\n [(model)]=\"model.email\"\n name=\"email\"\n [required]=\"true\"\n ></foehn-input-text>\n\n <foehn-input-phone\n label=\"Num\u00E9ro de t\u00E9l\u00E9phone mobile\"\n [acceptInternational]=\"true\"\n [acceptMobilePhone]=\"true\"\n [acceptPhone]=\"false\"\n [(model)]=\"model.mobile\"\n name=\"mobile\"\n [required]=\"true\"\n ></foehn-input-phone>\n </foehn-form>\n </ng-template>\n\n <div modal-footer class=\"w-100\">\n <div class=\"d-md-flex\">\n <div class=\"ml-md-auto mr-md-2 mb-2 mt-2\">\n <button (click)=\"close()\" class=\"btn btn-secondary w-100\">\n Fermer\n </button>\n </div>\n <div\n *ngIf=\"!(isConnectedCyber | async)\"\n class=\"ml-md-0 mr-md-2 mb-2 mt-2\"\n >\n <button\n type=\"submit\"\n (click)=\"sendAndClose()\"\n class=\"btn btn-success w-100\"\n *ngIf=\"!mailSent\"\n >\n Sauvegarder\n </button>\n </div>\n </div>\n </div>\n</foehn-modal>\n", styles: [".no-text-transform{text-transform:none;cursor:pointer}\n"], dependencies: [{ kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: FoehnInputTextComponent, selector: "foehn-input-text", inputs: ["numberOnly"] }, { kind: "component", type: FoehnInputPhoneComponent, selector: "foehn-input-phone", inputs: ["acceptInternational", "acceptMobilePhone", "acceptPhone"] }, { kind: "component", type: FoehnFormComponent, selector: "foehn-form", inputs: ["shouldDisplayAlertSummary"] }, { kind: "component", type: FoehnModalComponent, selector: "foehn-modal", inputs: ["id", "name", "modalSize", "modalBodyText", "modalHeaderText", "closeable", "modalTriggerHtmlElement", "isModalVisible"], outputs: ["isModalVisibleChange"] }, { kind: "pipe", type: i2.AsyncPipe, name: "async" }] });
10706
+ GesdemActionRecoveryRegistrationComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.9", type: GesdemActionRecoveryRegistrationComponent, selector: "gesdem-action-recovery-registration", inputs: { continueLaterLabel: "continueLaterLabel" }, viewQueries: [{ propertyName: "modalTrigger", first: true, predicate: ["modalTrigger"], descendants: true }, { propertyName: "form", first: true, predicate: FoehnFormComponent, descendants: true }], ngImport: i0, template: "<button\n type=\"button\"\n id=\"continueLaterButton\"\n class=\"btn btn-link pr-0 pl-0 no-text-transform\"\n *ngIf=\"canContinueLater | async\"\n (click)=\"open()\"\n #modalTrigger\n>\n {{ continueLaterLabel }}\n</button>\n\n<foehn-modal\n id=\"action-recovery-registration-modal\"\n [modalHeaderText]=\"\n 'gesdem-action-recovery-registration.modalHeaderText' | fromDictionary\n \"\n [isModalVisible]=\"isModalVisible\"\n (isModalVisibleChange)=\"updateVisibilityStatus($event)\"\n>\n <ng-container *ngIf=\"isConnectedCyber | async; else notConnectedContent\">\n <span\n [innerHTML]=\"\n 'gesdem-action-recovery-registration.connected.info'\n | fromDictionary\n \"\n ></span>\n </ng-container>\n <ng-template #notConnectedContent>\n <div class=\"alert alert-info\">\n <p\n *ngIf=\"!mailSent\"\n [innerHTML]=\"\n 'gesdem-action-recovery-registration.not-connected.info'\n | fromDictionary\n \"\n ></p>\n\n <div\n *ngIf=\"mailSent\"\n [innerHTML]=\"\n 'gesdem-action-recovery-registration.not-connected.info.sent'\n | fromDictionary\n \"\n ></div>\n </div>\n\n <foehn-form *ngIf=\"!mailSent\" [shouldDisplayAlertSummary]=\"false\">\n <foehn-input-email\n [label]=\"\n 'gesdem-action-recovery-registration.not-connected.email.label'\n | fromDictionary\n \"\n [helpText]=\"\n 'gesdem-action-recovery-registration.not-connected.email.help-text'\n | fromDictionary\n \"\n [(model)]=\"model.email\"\n name=\"email\"\n [required]=\"true\"\n ></foehn-input-email>\n\n <foehn-input-phone\n [label]=\"\n 'gesdem-action-recovery-registration.not-connected.mobile.label'\n | fromDictionary\n \"\n [acceptInternational]=\"true\"\n [acceptMobilePhone]=\"true\"\n [acceptPhone]=\"false\"\n [(model)]=\"model.mobile\"\n name=\"mobile\"\n [required]=\"true\"\n ></foehn-input-phone>\n </foehn-form>\n </ng-template>\n\n <div modal-footer class=\"w-100\">\n <div class=\"d-md-flex\">\n <div class=\"ml-md-auto mr-md-2 mb-2 mt-2\">\n <button\n (click)=\"close()\"\n class=\"btn btn-secondary w-100\"\n [innerHTML]=\"\n 'gesdem-action-recovery-registration.cancel.button'\n | fromDictionary\n \"\n ></button>\n </div>\n <div\n *ngIf=\"!(isConnectedCyber | async)\"\n class=\"ml-md-0 mr-md-2 mb-2 mt-2\"\n >\n <button\n type=\"submit\"\n (click)=\"sendAndClose()\"\n class=\"btn btn-success w-100\"\n *ngIf=\"!mailSent\"\n [innerHTML]=\"\n 'gesdem-action-recovery-registration.save.button'\n | fromDictionary\n \"\n ></button>\n </div>\n </div>\n </div>\n</foehn-modal>\n", styles: [".no-text-transform{text-transform:none;cursor:pointer}\n"], dependencies: [{ kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: FoehnInputEmailComponent, selector: "foehn-input-email" }, { kind: "component", type: FoehnInputPhoneComponent, selector: "foehn-input-phone", inputs: ["acceptInternational", "acceptMobilePhone", "acceptPhone"] }, { kind: "component", type: FoehnFormComponent, selector: "foehn-form", inputs: ["shouldDisplayAlertSummary"] }, { kind: "component", type: FoehnModalComponent, selector: "foehn-modal", inputs: ["id", "name", "modalSize", "modalBodyText", "modalHeaderText", "closeable", "modalTriggerHtmlElement", "isModalVisible"], outputs: ["isModalVisibleChange"] }, { kind: "pipe", type: i2.AsyncPipe, name: "async" }, { kind: "pipe", type: SdkDictionaryPipe, name: "fromDictionary" }] });
10640
10707
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: GesdemActionRecoveryRegistrationComponent, decorators: [{
10641
10708
  type: Component,
10642
- args: [{ selector: 'gesdem-action-recovery-registration', template: "<button\n type=\"button\"\n id=\"continueLaterButton\"\n class=\"btn btn-link pr-0 pl-0 no-text-transform\"\n *ngIf=\"canContinueLater | async\"\n (click)=\"open()\"\n #modalTrigger\n>\n {{ continueLaterLabel }}\n</button>\n\n<foehn-modal\n id=\"action-recovery-registration-modal\"\n [modalHeaderText]=\"'Informations pour la reprise de la demande'\"\n [isModalVisible]=\"isModalVisible\"\n (isModalVisibleChange)=\"updateVisibilityStatus($event)\"\n>\n <ng-container *ngIf=\"isConnectedCyber | async; else notConnectedContent\">\n <p>\n Vos donn\u00E9es ont \u00E9t\u00E9 sauvegard\u00E9es, vous pouvez acc\u00E9der \u00E0 cette\n demande dans la liste de\n <a href=\"/100002/demandes/search/MINE/INITIAL\">\n vos demandes en brouillon\n </a>\n .\n </p>\n </ng-container>\n <ng-template #notConnectedContent>\n <div class=\"alert alert-info\">\n <p *ngIf=\"!mailSent\">\n Les informations demand\u00E9es sont uniquement utilis\u00E9es pour vous\n permettre d'effectuer la reprise de demande.\n </p>\n\n <div *ngIf=\"mailSent\">\n <p>\n Un message contenant le lien de reprise de la demande a \u00E9t\u00E9\n envoy\u00E9 \u00E0 votre email.\n </p>\n <p>\n Vous pouvez cliquer sur ce lien pour reprendre la demande en\n saisissant le code qui sera envoy\u00E9 \u00E0 votre t\u00E9l\u00E9phone.\n </p>\n </div>\n </div>\n\n <foehn-form *ngIf=\"!mailSent\" [shouldDisplayAlertSummary]=\"false\">\n <foehn-input-text\n label=\"Email\"\n helpText=\"Par exemple, john@doe.ch\"\n [(model)]=\"model.email\"\n name=\"email\"\n [required]=\"true\"\n ></foehn-input-text>\n\n <foehn-input-phone\n label=\"Num\u00E9ro de t\u00E9l\u00E9phone mobile\"\n [acceptInternational]=\"true\"\n [acceptMobilePhone]=\"true\"\n [acceptPhone]=\"false\"\n [(model)]=\"model.mobile\"\n name=\"mobile\"\n [required]=\"true\"\n ></foehn-input-phone>\n </foehn-form>\n </ng-template>\n\n <div modal-footer class=\"w-100\">\n <div class=\"d-md-flex\">\n <div class=\"ml-md-auto mr-md-2 mb-2 mt-2\">\n <button (click)=\"close()\" class=\"btn btn-secondary w-100\">\n Fermer\n </button>\n </div>\n <div\n *ngIf=\"!(isConnectedCyber | async)\"\n class=\"ml-md-0 mr-md-2 mb-2 mt-2\"\n >\n <button\n type=\"submit\"\n (click)=\"sendAndClose()\"\n class=\"btn btn-success w-100\"\n *ngIf=\"!mailSent\"\n >\n Sauvegarder\n </button>\n </div>\n </div>\n </div>\n</foehn-modal>\n", styles: [".no-text-transform{text-transform:none;cursor:pointer}\n"] }]
10709
+ args: [{ selector: 'gesdem-action-recovery-registration', template: "<button\n type=\"button\"\n id=\"continueLaterButton\"\n class=\"btn btn-link pr-0 pl-0 no-text-transform\"\n *ngIf=\"canContinueLater | async\"\n (click)=\"open()\"\n #modalTrigger\n>\n {{ continueLaterLabel }}\n</button>\n\n<foehn-modal\n id=\"action-recovery-registration-modal\"\n [modalHeaderText]=\"\n 'gesdem-action-recovery-registration.modalHeaderText' | fromDictionary\n \"\n [isModalVisible]=\"isModalVisible\"\n (isModalVisibleChange)=\"updateVisibilityStatus($event)\"\n>\n <ng-container *ngIf=\"isConnectedCyber | async; else notConnectedContent\">\n <span\n [innerHTML]=\"\n 'gesdem-action-recovery-registration.connected.info'\n | fromDictionary\n \"\n ></span>\n </ng-container>\n <ng-template #notConnectedContent>\n <div class=\"alert alert-info\">\n <p\n *ngIf=\"!mailSent\"\n [innerHTML]=\"\n 'gesdem-action-recovery-registration.not-connected.info'\n | fromDictionary\n \"\n ></p>\n\n <div\n *ngIf=\"mailSent\"\n [innerHTML]=\"\n 'gesdem-action-recovery-registration.not-connected.info.sent'\n | fromDictionary\n \"\n ></div>\n </div>\n\n <foehn-form *ngIf=\"!mailSent\" [shouldDisplayAlertSummary]=\"false\">\n <foehn-input-email\n [label]=\"\n 'gesdem-action-recovery-registration.not-connected.email.label'\n | fromDictionary\n \"\n [helpText]=\"\n 'gesdem-action-recovery-registration.not-connected.email.help-text'\n | fromDictionary\n \"\n [(model)]=\"model.email\"\n name=\"email\"\n [required]=\"true\"\n ></foehn-input-email>\n\n <foehn-input-phone\n [label]=\"\n 'gesdem-action-recovery-registration.not-connected.mobile.label'\n | fromDictionary\n \"\n [acceptInternational]=\"true\"\n [acceptMobilePhone]=\"true\"\n [acceptPhone]=\"false\"\n [(model)]=\"model.mobile\"\n name=\"mobile\"\n [required]=\"true\"\n ></foehn-input-phone>\n </foehn-form>\n </ng-template>\n\n <div modal-footer class=\"w-100\">\n <div class=\"d-md-flex\">\n <div class=\"ml-md-auto mr-md-2 mb-2 mt-2\">\n <button\n (click)=\"close()\"\n class=\"btn btn-secondary w-100\"\n [innerHTML]=\"\n 'gesdem-action-recovery-registration.cancel.button'\n | fromDictionary\n \"\n ></button>\n </div>\n <div\n *ngIf=\"!(isConnectedCyber | async)\"\n class=\"ml-md-0 mr-md-2 mb-2 mt-2\"\n >\n <button\n type=\"submit\"\n (click)=\"sendAndClose()\"\n class=\"btn btn-success w-100\"\n *ngIf=\"!mailSent\"\n [innerHTML]=\"\n 'gesdem-action-recovery-registration.save.button'\n | fromDictionary\n \"\n ></button>\n </div>\n </div>\n </div>\n</foehn-modal>\n", styles: [".no-text-transform{text-transform:none;cursor:pointer}\n"] }]
10643
10710
  }], ctorParameters: function () { return [{ type: GesdemActionRecoveryService }, { type: ValidationHandlerService }, { type: FoehnPageService }, { type: GesdemEventService }, { type: GesdemHandlerService }, { type: ApplicationInfoService }, { type: SessionInfo }]; }, propDecorators: { continueLaterLabel: [{
10644
10711
  type: Input
10645
10712
  }], modalTrigger: [{
@@ -10659,14 +10726,18 @@ GesdemActionRecoveryModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.
10659
10726
  FoehnInputModule,
10660
10727
  FoehnIconsModule,
10661
10728
  FoehnFormModule,
10662
- FoehnModalModule], exports: [GesdemActionRecoveryLoginComponent,
10729
+ FoehnModalModule,
10730
+ SdkDictionaryModule,
10731
+ PipeModule], exports: [GesdemActionRecoveryLoginComponent,
10663
10732
  GesdemActionRecoveryRegistrationComponent] });
10664
10733
  GesdemActionRecoveryModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: GesdemActionRecoveryModule, imports: [CommonModule,
10665
10734
  RouterModule,
10666
10735
  FoehnInputModule,
10667
10736
  FoehnIconsModule,
10668
10737
  FoehnFormModule,
10669
- FoehnModalModule] });
10738
+ FoehnModalModule,
10739
+ SdkDictionaryModule,
10740
+ PipeModule] });
10670
10741
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: GesdemActionRecoveryModule, decorators: [{
10671
10742
  type: NgModule,
10672
10743
  args: [{
@@ -10676,7 +10747,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImpor
10676
10747
  FoehnInputModule,
10677
10748
  FoehnIconsModule,
10678
10749
  FoehnFormModule,
10679
- FoehnModalModule
10750
+ FoehnModalModule,
10751
+ SdkDictionaryModule,
10752
+ PipeModule
10680
10753
  ],
10681
10754
  declarations: [
10682
10755
  GesdemActionRecoveryLoginComponent,
@@ -11880,7 +11953,10 @@ class FoehnUploadProgressBarComponent {
11880
11953
  }
11881
11954
  }), shareReplay(1));
11882
11955
  this.analysisProgress = this.uploadProgressService.analysisProgressSubject.pipe(shareReplay(1));
11883
- this.currentUploadPercentage = this.uploadProgressService.uploadProgressSubject.pipe(map$1((progress) => this.calculateProgressPercentage(progress)), shareReplay(1));
11956
+ const uploadProgress = this.uploadProgressService.uploadProgressSubject.pipe(shareReplay(1));
11957
+ this.currentUploadPercentage = uploadProgress.pipe(map$1((progress) => this.calculateProgressPercentage(progress)), shareReplay(1));
11958
+ this.uploadPackage = uploadProgress.pipe(filter((progress) => !!progress), shareReplay(1));
11959
+ this.hasUploadPackages = this.uploadPackage.pipe(map$1((progress) => !!progress.nbPackages && progress.nbPackages > 1), shareReplay(1));
11884
11960
  this.progressBarTriggerSubscription = combineLatest([
11885
11961
  this.showProgress,
11886
11962
  this.analysisProgress,
@@ -11911,8 +11987,12 @@ class FoehnUploadProgressBarComponent {
11911
11987
  if (!progress) {
11912
11988
  return 0;
11913
11989
  }
11914
- const percent = Math.round((progress.loaded * 100) / progress.total);
11915
- if (percent === 100) {
11990
+ const percentPerGroup = 100 / progress.nbPackages;
11991
+ const loadedPerGroup = (progress.loaded * percentPerGroup) / progress.total;
11992
+ const loaded = loadedPerGroup + progress.packageIndex * percentPerGroup;
11993
+ const percent = Math.round(loaded);
11994
+ if (percent ===
11995
+ Math.round(percentPerGroup * (progress.packageIndex + 1))) {
11916
11996
  this.uploadProgressService.analysisProgress.next(true);
11917
11997
  }
11918
11998
  return percent;
@@ -11927,10 +12007,10 @@ class FoehnUploadProgressBarComponent {
11927
12007
  }
11928
12008
  }
11929
12009
  FoehnUploadProgressBarComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: FoehnUploadProgressBarComponent, deps: [{ token: UploadProgressService }], target: i0.ɵɵFactoryTarget.Component });
11930
- FoehnUploadProgressBarComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.9", type: FoehnUploadProgressBarComponent, selector: "foehn-upload-progress-bar", inputs: { progressBarTriggerHtmlElement: "progressBarTriggerHtmlElement" }, viewQueries: [{ propertyName: "progressBarPanel", first: true, predicate: ["progressBarPanel"], descendants: true }], ngImport: i0, template: "<div\n *ngIf=\"(showProgress | async) === true\"\n role=\"dialog\"\n class=\"progress-bar-container d-flex justify-content-center\"\n tabindex=\"-1\"\n cdkTrapFocus\n>\n <div\n class=\"progress-bar-panel d-flex flex-column align-self-center\"\n tabindex=\"-1\"\n #progressBarPanel\n >\n <div class=\"progress-bar-panel-title py-2 px-3\">\n <h2\n class=\"h5\"\n [innerHTML]=\"'foehn-upload-progress-bar.title' | fromDictionary\"\n ></h2>\n </div>\n <div class=\"progress-bar-panel-body p-3\">\n <p\n *ngIf=\"(analysisProgress | async) === false\"\n [innerHTML]=\"\n 'foehn-upload-progress-bar.upload' | fromDictionary\n \"\n ></p>\n <p\n *ngIf=\"(analysisProgress | async) === true\"\n [innerHTML]=\"\n 'foehn-upload-progress-bar.analysis' | fromDictionary\n \"\n ></p>\n <!-- Need to add a tabindex=\"0\" (here on progress) otherwise cdkTrapFocus will not work -->\n <div class=\"progress\" tabindex=\"0\">\n <div\n *ngIf=\"currentUploadPercentage | async as progress\"\n role=\"progressbar\"\n class=\"progress-bar bg-success\"\n [class.progress-bar-animated]=\"\n (analysisProgress | async) === true\n \"\n [class.progress-bar-striped]=\"\n (analysisProgress | async) === true\n \"\n [style.width]=\"progress + '%'\"\n [attr.aria-valuenow]=\"progress\"\n aria-valuemin=\"0\"\n aria-valuemax=\"100\"\n >\n <ng-container *ngIf=\"(analysisProgress | async) === false\">\n {{ progress + '%' }}\n </ng-container>\n </div>\n </div>\n </div>\n </div>\n</div>\n", styles: [".progress-bar-container{top:0;left:0;height:100%;width:100%;position:fixed;z-index:10000;overflow:auto;background-color:#000;background-color:#0006}.progress-bar-panel{width:30%;background-color:#fff}.progress-bar-panel-title{background-color:var(--vd-neutral-lighter)}.progress-bar-panel-title h2{margin-top:.5rem}.progress{width:100%;background-color:var(--vd-neutral-lighter);box-shadow:none}.progress:focus{outline:0;box-shadow:inset 0 1px 1px #00000013,0 0 0 .2rem var(--vd-focus)}\n"], dependencies: [{ kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2$1.CdkTrapFocus, selector: "[cdkTrapFocus]", inputs: ["cdkTrapFocus", "cdkTrapFocusAutoCapture"], exportAs: ["cdkTrapFocus"] }, { kind: "pipe", type: i2.AsyncPipe, name: "async" }, { kind: "pipe", type: SdkDictionaryPipe, name: "fromDictionary" }] });
12010
+ FoehnUploadProgressBarComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.9", type: FoehnUploadProgressBarComponent, selector: "foehn-upload-progress-bar", inputs: { progressBarTriggerHtmlElement: "progressBarTriggerHtmlElement" }, viewQueries: [{ propertyName: "progressBarPanel", first: true, predicate: ["progressBarPanel"], descendants: true }], ngImport: i0, template: "<div\n *ngIf=\"(showProgress | async) === true\"\n role=\"dialog\"\n class=\"progress-bar-container d-flex justify-content-center\"\n tabindex=\"-1\"\n cdkTrapFocus\n>\n <div\n class=\"progress-bar-panel d-flex flex-column align-self-center\"\n tabindex=\"-1\"\n #progressBarPanel\n >\n <div class=\"progress-bar-panel-title py-2 px-3\">\n <h2\n class=\"h5 mb-0 py-1\"\n [innerHTML]=\"'foehn-upload-progress-bar.title' | fromDictionary\"\n ></h2>\n </div>\n <div class=\"progress-bar-panel-body p-3\">\n <ng-container *ngIf=\"(hasUploadPackages | async) === false\">\n <p\n *ngIf=\"(analysisProgress | async) === false\"\n [innerHTML]=\"\n 'foehn-upload-progress-bar.upload' | fromDictionary\n \"\n ></p>\n <p\n *ngIf=\"(analysisProgress | async) === true\"\n [innerHTML]=\"\n 'foehn-upload-progress-bar.analysis' | fromDictionary\n \"\n ></p>\n </ng-container>\n <ng-container *ngIf=\"(hasUploadPackages | async) === true\">\n <ng-container *ngIf=\"(analysisProgress | async) === false\">\n <p\n *ngIf=\"uploadPackage | async as uploadPackage\"\n [innerHTML]=\"\n 'foehn-upload-progress-bar.group.upload'\n | fromDictionary\n : {\n packageIndex: (\n uploadPackage.packageIndex + 1\n ).toString(),\n nbPackages: uploadPackage.nbPackages.toString()\n }\n \"\n ></p>\n </ng-container>\n <ng-container *ngIf=\"(analysisProgress | async) === true\">\n <p\n *ngIf=\"uploadPackage | async as uploadPackage\"\n [innerHTML]=\"\n 'foehn-upload-progress-bar.group.analysis'\n | fromDictionary\n : {\n packageIndex: (\n uploadPackage.packageIndex + 1\n ).toString(),\n nbPackages: uploadPackage.nbPackages.toString()\n }\n \"\n ></p>\n </ng-container>\n </ng-container>\n <!-- Need to add a tabindex=\"0\" (here on progress) otherwise cdkTrapFocus will not work -->\n <div class=\"progress\" tabindex=\"0\">\n <div\n *ngIf=\"currentUploadPercentage | async as progress\"\n role=\"progressbar\"\n class=\"progress-bar bg-success\"\n [class.progress-bar-animated]=\"\n (analysisProgress | async) === true\n \"\n [class.progress-bar-striped]=\"\n (analysisProgress | async) === true\n \"\n [style.width]=\"progress + '%'\"\n [attr.aria-valuenow]=\"progress\"\n aria-valuemin=\"0\"\n aria-valuemax=\"100\"\n >\n <ng-container *ngIf=\"(analysisProgress | async) === false\">\n {{ progress + '%' }}\n </ng-container>\n </div>\n </div>\n <small\n class=\"form-text text-secondary\"\n *ngIf=\"(hasUploadPackages | async) === true\"\n [innerHTML]=\"\n 'foehn-upload-progress-bar.group.info' | fromDictionary\n \"\n ></small>\n </div>\n </div>\n</div>\n", styles: [".progress-bar-container{top:0;left:0;height:100%;width:100%;position:fixed;z-index:10000;overflow:auto;background-color:#000;background-color:#0006}.progress-bar-panel{width:30%;background-color:#fff}.progress-bar-panel-title{background-color:var(--vd-neutral-lighter)}.progress-bar-panel-title h2{margin-top:.5rem}.progress{width:100%;background-color:var(--vd-neutral-lighter);box-shadow:none}.progress:focus{outline:0;box-shadow:inset 0 1px 1px #00000013,0 0 0 .2rem var(--vd-focus)}\n"], dependencies: [{ kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2$1.CdkTrapFocus, selector: "[cdkTrapFocus]", inputs: ["cdkTrapFocus", "cdkTrapFocusAutoCapture"], exportAs: ["cdkTrapFocus"] }, { kind: "pipe", type: i2.AsyncPipe, name: "async" }, { kind: "pipe", type: SdkDictionaryPipe, name: "fromDictionary" }] });
11931
12011
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: FoehnUploadProgressBarComponent, decorators: [{
11932
12012
  type: Component,
11933
- args: [{ selector: 'foehn-upload-progress-bar', template: "<div\n *ngIf=\"(showProgress | async) === true\"\n role=\"dialog\"\n class=\"progress-bar-container d-flex justify-content-center\"\n tabindex=\"-1\"\n cdkTrapFocus\n>\n <div\n class=\"progress-bar-panel d-flex flex-column align-self-center\"\n tabindex=\"-1\"\n #progressBarPanel\n >\n <div class=\"progress-bar-panel-title py-2 px-3\">\n <h2\n class=\"h5\"\n [innerHTML]=\"'foehn-upload-progress-bar.title' | fromDictionary\"\n ></h2>\n </div>\n <div class=\"progress-bar-panel-body p-3\">\n <p\n *ngIf=\"(analysisProgress | async) === false\"\n [innerHTML]=\"\n 'foehn-upload-progress-bar.upload' | fromDictionary\n \"\n ></p>\n <p\n *ngIf=\"(analysisProgress | async) === true\"\n [innerHTML]=\"\n 'foehn-upload-progress-bar.analysis' | fromDictionary\n \"\n ></p>\n <!-- Need to add a tabindex=\"0\" (here on progress) otherwise cdkTrapFocus will not work -->\n <div class=\"progress\" tabindex=\"0\">\n <div\n *ngIf=\"currentUploadPercentage | async as progress\"\n role=\"progressbar\"\n class=\"progress-bar bg-success\"\n [class.progress-bar-animated]=\"\n (analysisProgress | async) === true\n \"\n [class.progress-bar-striped]=\"\n (analysisProgress | async) === true\n \"\n [style.width]=\"progress + '%'\"\n [attr.aria-valuenow]=\"progress\"\n aria-valuemin=\"0\"\n aria-valuemax=\"100\"\n >\n <ng-container *ngIf=\"(analysisProgress | async) === false\">\n {{ progress + '%' }}\n </ng-container>\n </div>\n </div>\n </div>\n </div>\n</div>\n", styles: [".progress-bar-container{top:0;left:0;height:100%;width:100%;position:fixed;z-index:10000;overflow:auto;background-color:#000;background-color:#0006}.progress-bar-panel{width:30%;background-color:#fff}.progress-bar-panel-title{background-color:var(--vd-neutral-lighter)}.progress-bar-panel-title h2{margin-top:.5rem}.progress{width:100%;background-color:var(--vd-neutral-lighter);box-shadow:none}.progress:focus{outline:0;box-shadow:inset 0 1px 1px #00000013,0 0 0 .2rem var(--vd-focus)}\n"] }]
12013
+ args: [{ selector: 'foehn-upload-progress-bar', template: "<div\n *ngIf=\"(showProgress | async) === true\"\n role=\"dialog\"\n class=\"progress-bar-container d-flex justify-content-center\"\n tabindex=\"-1\"\n cdkTrapFocus\n>\n <div\n class=\"progress-bar-panel d-flex flex-column align-self-center\"\n tabindex=\"-1\"\n #progressBarPanel\n >\n <div class=\"progress-bar-panel-title py-2 px-3\">\n <h2\n class=\"h5 mb-0 py-1\"\n [innerHTML]=\"'foehn-upload-progress-bar.title' | fromDictionary\"\n ></h2>\n </div>\n <div class=\"progress-bar-panel-body p-3\">\n <ng-container *ngIf=\"(hasUploadPackages | async) === false\">\n <p\n *ngIf=\"(analysisProgress | async) === false\"\n [innerHTML]=\"\n 'foehn-upload-progress-bar.upload' | fromDictionary\n \"\n ></p>\n <p\n *ngIf=\"(analysisProgress | async) === true\"\n [innerHTML]=\"\n 'foehn-upload-progress-bar.analysis' | fromDictionary\n \"\n ></p>\n </ng-container>\n <ng-container *ngIf=\"(hasUploadPackages | async) === true\">\n <ng-container *ngIf=\"(analysisProgress | async) === false\">\n <p\n *ngIf=\"uploadPackage | async as uploadPackage\"\n [innerHTML]=\"\n 'foehn-upload-progress-bar.group.upload'\n | fromDictionary\n : {\n packageIndex: (\n uploadPackage.packageIndex + 1\n ).toString(),\n nbPackages: uploadPackage.nbPackages.toString()\n }\n \"\n ></p>\n </ng-container>\n <ng-container *ngIf=\"(analysisProgress | async) === true\">\n <p\n *ngIf=\"uploadPackage | async as uploadPackage\"\n [innerHTML]=\"\n 'foehn-upload-progress-bar.group.analysis'\n | fromDictionary\n : {\n packageIndex: (\n uploadPackage.packageIndex + 1\n ).toString(),\n nbPackages: uploadPackage.nbPackages.toString()\n }\n \"\n ></p>\n </ng-container>\n </ng-container>\n <!-- Need to add a tabindex=\"0\" (here on progress) otherwise cdkTrapFocus will not work -->\n <div class=\"progress\" tabindex=\"0\">\n <div\n *ngIf=\"currentUploadPercentage | async as progress\"\n role=\"progressbar\"\n class=\"progress-bar bg-success\"\n [class.progress-bar-animated]=\"\n (analysisProgress | async) === true\n \"\n [class.progress-bar-striped]=\"\n (analysisProgress | async) === true\n \"\n [style.width]=\"progress + '%'\"\n [attr.aria-valuenow]=\"progress\"\n aria-valuemin=\"0\"\n aria-valuemax=\"100\"\n >\n <ng-container *ngIf=\"(analysisProgress | async) === false\">\n {{ progress + '%' }}\n </ng-container>\n </div>\n </div>\n <small\n class=\"form-text text-secondary\"\n *ngIf=\"(hasUploadPackages | async) === true\"\n [innerHTML]=\"\n 'foehn-upload-progress-bar.group.info' | fromDictionary\n \"\n ></small>\n </div>\n </div>\n</div>\n", styles: [".progress-bar-container{top:0;left:0;height:100%;width:100%;position:fixed;z-index:10000;overflow:auto;background-color:#000;background-color:#0006}.progress-bar-panel{width:30%;background-color:#fff}.progress-bar-panel-title{background-color:var(--vd-neutral-lighter)}.progress-bar-panel-title h2{margin-top:.5rem}.progress{width:100%;background-color:var(--vd-neutral-lighter);box-shadow:none}.progress:focus{outline:0;box-shadow:inset 0 1px 1px #00000013,0 0 0 .2rem var(--vd-focus)}\n"] }]
11934
12014
  }], ctorParameters: function () { return [{ type: UploadProgressService }]; }, propDecorators: { progressBarTriggerHtmlElement: [{
11935
12015
  type: Input
11936
12016
  }], progressBarPanel: [{
@@ -12191,6 +12271,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImpor
12191
12271
  }]
12192
12272
  }] });
12193
12273
 
12274
+ // eslint-disable max-classes-per-file
12275
+ class BoDocumentError {
12276
+ }
12277
+ class BoDocumentsWithErrors {
12278
+ }
12279
+
12194
12280
  class BoMultiUploadService {
12195
12281
  constructor(httpClient, growlService, applicationInfoService, dictionaryService, uploadProgressService) {
12196
12282
  this.httpClient = httpClient;
@@ -12200,46 +12286,86 @@ class BoMultiUploadService {
12200
12286
  this.uploadProgressService = uploadProgressService;
12201
12287
  // A way to have a unique Id per file
12202
12288
  this.globalSequence = 0;
12289
+ this.NB_CONCURRENT_FILES_TO_UPLOAD = 3;
12290
+ this.mergeDocumentsWithErrors = (arrayOfDocumentsWithErrors) => {
12291
+ const mergedResponse = new BoDocumentsWithErrors();
12292
+ arrayOfDocumentsWithErrors.forEach(item => {
12293
+ if (!!item.documents?.length) {
12294
+ if (!mergedResponse.documents) {
12295
+ mergedResponse.documents = [];
12296
+ }
12297
+ mergedResponse.documents = mergedResponse.documents.concat(item.documents);
12298
+ }
12299
+ if (!!item.errors?.length) {
12300
+ if (!mergedResponse.errors) {
12301
+ mergedResponse.errors = [];
12302
+ }
12303
+ mergedResponse.errors = mergedResponse.errors.concat(item.errors);
12304
+ }
12305
+ });
12306
+ return mergedResponse;
12307
+ };
12203
12308
  this.uploaderHelper = new UploaderHelper(dictionaryService, applicationInfoService);
12204
12309
  }
12205
12310
  uploadDocuments(url, formKey, label, files, key, isMultiple, language, shouldDisplayFileSavedConfirmation) {
12206
- const documents = files.map(file => this.uploaderHelper.mapToDocumentReference(file, label, key, isMultiple, new Date().getTime(), this.globalSequence++));
12207
- const formData = this.uploaderHelper.mapToFormData(documents, formKey, language);
12311
+ const filesToGroup = [...files];
12312
+ const groupsOfFiles = [];
12313
+ while (!!filesToGroup.length) {
12314
+ groupsOfFiles.push(filesToGroup.splice(0, this.NB_CONCURRENT_FILES_TO_UPLOAD));
12315
+ }
12316
+ const arrayOfDocumentsWithErrorsObservable = groupsOfFiles.map((groupOfFile, index) => {
12317
+ const documents = groupOfFile.map(file => this.uploaderHelper.mapToDocumentReference(file, label, key, isMultiple, new Date().getTime(), this.globalSequence++));
12318
+ const formData = this.uploaderHelper.mapToFormData(documents, formKey, language);
12319
+ return this.getDocumentsWithErrorsObservable(url, formData, shouldDisplayFileSavedConfirmation, index, groupsOfFiles.length);
12320
+ });
12321
+ if (arrayOfDocumentsWithErrorsObservable.length === 1) {
12322
+ return arrayOfDocumentsWithErrorsObservable[0];
12323
+ }
12324
+ // concat() operator sequentially emits all values from the given Observable and then proceed to the next one.
12325
+ return concat(...arrayOfDocumentsWithErrorsObservable).pipe(
12326
+ // toArray() operator collects all the values emitted by the source observable into an array and sends it to the observer
12327
+ toArray(), map(this.mergeDocumentsWithErrors.bind(this)));
12328
+ }
12329
+ deleteDocument(baseUrl, document) {
12330
+ const url = `${baseUrl}/${document.reference}`;
12331
+ return this.httpClient.delete(url).pipe(
12332
+ // Reflect the document once the update is done to ease chaining observables.
12333
+ map(() => document), tap(() => {
12334
+ const message = this.dictionaryService.getKeySync('foehn-uploader.files-deleted-success-message', { filename: document.filename });
12335
+ this.growlService.addWithType(GrowlType.SUCCESS, message);
12336
+ }), catchError((e) => {
12337
+ const message = this.dictionaryService.getKeySync('foehn-uploader.delete-error-message');
12338
+ this.growlService.addWithType(GrowlType.DANGER, message);
12339
+ return throwError(() => e);
12340
+ }));
12341
+ }
12342
+ getDownloadUrl(baseUrl, document) {
12343
+ return `${baseUrl}/${document.reference}`;
12344
+ }
12345
+ getDocumentsWithErrorsObservable(url, formData, shouldDisplayFileSavedConfirmation, packageIndex = 0, nbPackages = 1) {
12208
12346
  return this.httpClient
12209
12347
  .post(url, formData, {
12210
12348
  reportProgress: true,
12211
12349
  observe: 'events',
12212
12350
  responseType: 'json'
12213
12351
  })
12214
- .pipe(filter((e) => this.uploadProgressService.manageUploadEventFilter(e)), map((e) => e.body), tap(result => {
12352
+ .pipe(filter((e) => this.uploadProgressService.manageUploadEventFilter(e, packageIndex, nbPackages)), map((e) => e.body), tap(result => {
12215
12353
  const successfulDocumentsCount = result.documents && result.documents.length;
12216
12354
  if (successfulDocumentsCount &&
12217
12355
  shouldDisplayFileSavedConfirmation) {
12218
- const message = `${successfulDocumentsCount} fichier(s) sauvegardé(s) avec succès`;
12356
+ const message = this.dictionaryService.getKeySync('foehn-uploader.files-saved-success-message', {
12357
+ successfulDocumentsCount: successfulDocumentsCount.toString()
12358
+ });
12219
12359
  this.growlService.addWithType(GrowlType.SUCCESS, message);
12220
12360
  }
12221
12361
  }), catchError((e) => {
12222
- const message = 'Une erreur est survenue lors de la transmission de vos documents';
12223
- this.growlService.addWithType(GrowlType.DANGER, message);
12224
- return throwError(() => e);
12225
- }));
12226
- }
12227
- deleteDocument(baseUrl, document) {
12228
- const url = `${baseUrl}/${document.reference}`;
12229
- return this.httpClient.delete(url).pipe(
12230
- // Reflect the document once the update is done to ease chaining observables.
12231
- map(() => document), tap(() => {
12232
- const message = `Suppression du fichier ${document.filename} réussie`;
12233
- this.growlService.addWithType(GrowlType.SUCCESS, message);
12234
- }), catchError((e) => {
12235
- const message = 'Une erreur est survenue lors de la suppression de votre document';
12362
+ this.uploadProgressService.analysisProgress.next(false);
12363
+ this.uploadProgressService.showProgress.next(false);
12364
+ const message = this.dictionaryService.getKeySync('foehn-uploader.transmission-error-message');
12236
12365
  this.growlService.addWithType(GrowlType.DANGER, message);
12237
12366
  return throwError(() => e);
12238
12367
  }));
12239
12368
  }
12240
- getDownloadUrl(baseUrl, document) {
12241
- return `${baseUrl}/${document.reference}`;
12242
- }
12243
12369
  }
12244
12370
  BoMultiUploadService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: BoMultiUploadService, deps: [{ token: i1.HttpClient }, { token: GrowlBrokerService }, { token: ApplicationInfoService }, { token: SdkDictionaryService }, { token: UploadProgressService }], target: i0.ɵɵFactoryTarget.Injectable });
12245
12371
  BoMultiUploadService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: BoMultiUploadService, providedIn: 'root' });
@@ -12250,12 +12376,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImpor
12250
12376
  }]
12251
12377
  }], ctorParameters: function () { return [{ type: i1.HttpClient }, { type: GrowlBrokerService }, { type: ApplicationInfoService }, { type: SdkDictionaryService }, { type: UploadProgressService }]; } });
12252
12378
 
12253
- // eslint-disable max-classes-per-file
12254
- class BoDocumentError {
12255
- }
12256
- class BoDocumentsWithErrors {
12257
- }
12258
-
12259
12379
  class FoehnBoMultiUploadComponent extends AbstractFoehnUploaderComponent {
12260
12380
  constructor(boMultiUploadService, applicationInfoService, confirmModalService, dictionaryService, growlService) {
12261
12381
  super(applicationInfoService, confirmModalService, dictionaryService, growlService);
@@ -12351,6 +12471,14 @@ class FoehnBoMultiUploadComponent extends AbstractFoehnUploaderComponent {
12351
12471
  this.model = [...this.model, ...(documents || [])];
12352
12472
  this.triggerUserInput(this.model);
12353
12473
  }
12474
+ removeDocumentFromModel(document) {
12475
+ const index = this.model.indexOf(document);
12476
+ if (index > -1) {
12477
+ this.model.splice(index, 1);
12478
+ this.model = [...this.model];
12479
+ this.triggerUserInput(this.model);
12480
+ }
12481
+ }
12354
12482
  displayErrorsFromServer(errors) {
12355
12483
  if (!errors || !errors.length) {
12356
12484
  // PRESTAKIT-309: Simulate user interaction with component
@@ -12362,14 +12490,6 @@ class FoehnBoMultiUploadComponent extends AbstractFoehnUploaderComponent {
12362
12490
  errors.forEach(error => this.uploaderHelper.addCustomErrorOrDefault(this.name, newErrors, `${error.errorCode}`, error.label, this.customErrors, this.overrideAcceptedExtensions, this.overrideMaxFileNameLength, this.overrideIllegalCharacters));
12363
12491
  this.refreshErrors([newErrors, true]);
12364
12492
  }
12365
- removeDocumentFromModel(document) {
12366
- const index = this.model.indexOf(document);
12367
- if (index > -1) {
12368
- this.model.splice(index, 1);
12369
- this.model = [...this.model];
12370
- this.triggerUserInput(this.model);
12371
- }
12372
- }
12373
12493
  manageSingleFile(files) {
12374
12494
  // Edge browser lets you drop files from dialog box when selecting a file.
12375
12495
  // We need to make sure we only keep last selected file from user
@@ -12668,6 +12788,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImpor
12668
12788
  }] });
12669
12789
 
12670
12790
  class UploadProgress {
12791
+ constructor() {
12792
+ this.packageIndex = 0;
12793
+ this.nbPackages = 1;
12794
+ }
12671
12795
  }
12672
12796
 
12673
12797
  class EPaymentService {