@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';
@@ -775,6 +775,18 @@ const DEFAULT_DICTIONARY = {
775
775
  'gesdem-confirmation.resume-my-demand.label': 'Vous pouvez reprendre votre demande en cliquant sur le lien ci-dessous',
776
776
  'gesdem-confirmation.resume-my-demand.button': 'Reprendre ma demande',
777
777
  'gesdem.download-pdf.button.title': 'Télécharger le PDF',
778
+ 'gesdem-action-recovery-registration.modalHeaderText': 'Informations pour la reprise de la demande',
779
+ 'gesdem-action-recovery-registration.connected.info': '<p>Vos données ont été sauvegardées, vous pouvez accéder à cette demande dans la liste de ' +
780
+ '<a href="/100002/demandes/search/MINE/INITIAL"> ' +
781
+ 'vos demandes en brouillon</a>.',
782
+ 'gesdem-action-recovery-registration.not-connected.info': "Les informations demandées sont uniquement utilisées pour vous permettre d'effectuer la reprise de demande.",
783
+ '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>' +
784
+ '<p>Vous pouvez cliquer sur ce lien pour reprendre la demande en saisissant le code qui sera envoyé à votre téléphone.</p>',
785
+ 'gesdem-action-recovery-registration.not-connected.email.label': 'Email',
786
+ 'gesdem-action-recovery-registration.not-connected.email.help-text': 'Par exemple, john@doe.ch',
787
+ 'gesdem-action-recovery-registration.not-connected.mobile.label': 'Numéro de téléphone mobile',
788
+ 'gesdem-action-recovery-registration.cancel.button': 'Fermer',
789
+ 'gesdem-action-recovery-registration.save.button': 'Sauvegarder',
778
790
  'foehn-date-picker-button.icon-title': 'Afficher le calendrier',
779
791
  'foehn-date-picker-button.screen-reader.selected-date': 'Date sélectionnée : {selectedDate}',
780
792
  'foehn-date-picker.container.aria-label': 'Calendrier',
@@ -809,6 +821,10 @@ const DEFAULT_DICTIONARY = {
809
821
  'foehn-uploader.abbr-megaoctet-title': 'Megaoctet',
810
822
  'foehn-uploader.delete-icon-title': 'Supprimer {docName}',
811
823
  'foehn-uploader.max-upload-selection-reached': 'Vous ne pouvez pas télécharger plus de {maxSelection} fichiers à la fois.',
824
+ 'foehn-uploader.files-saved-success-message': '{successfulDocumentsCount} fichier(s) sauvegardé(s) avec succès',
825
+ 'foehn-uploader.transmission-error-message': 'Une erreur est survenue lors de la transmission de vos documents',
826
+ 'foehn-uploader.files-deleted-success-message': 'Suppression du fichier {filename} réussie',
827
+ 'foehn-uploader.delete-error-message': 'Une erreur est survenue lors de la suppression de votre document',
812
828
  'use-login.text.decision-electronique-available': 'Pour obtenir la notification de la décision sous forme électronique ' +
813
829
  '(fichier au format pdf), vous devez demander la prestation en étant connecté au portail sécurisé.',
814
830
  'use-login.text': 'Cette prestation est également utilisable <strong>en se connectant</strong> au portail sécurisé de l’État de Vaud pour autant ' +
@@ -882,7 +898,10 @@ const DEFAULT_DICTIONARY = {
882
898
  'foehn-textarea.chars-remaining.exceeded': 'Vous avez dépassé le nombre de caractères autorisés de {charCountLeft}',
883
899
  'foehn-upload-progress-bar.title': 'Traitement de votre envoi',
884
900
  'foehn-upload-progress-bar.upload': 'Enregistrement en cours...',
901
+ 'foehn-upload-progress-bar.group.upload': 'Lot {packageIndex}/{nbPackages} : Enregistrement en cours...',
885
902
  'foehn-upload-progress-bar.analysis': 'Analyse en cours... Merci de patienter.',
903
+ 'foehn-upload-progress-bar.group.analysis': 'Lot {packageIndex}/{nbPackages} : Analyse en cours... Merci de patienter.',
904
+ 'foehn-upload-progress-bar.group.info': 'Le téléchargement se fait en plusieurs lots en fonction du nombre de fichiers chargés',
886
905
  'errors.NotNull': 'Ce champ doit être rempli',
887
906
  'foehn-header.logo.title': "Aller à la page d'accueil du Site du Canton de Vaud",
888
907
  'foehn-header.cyber-secured-area.identity.srOnly': 'Votre identité',
@@ -2437,7 +2456,7 @@ class UploadProgressService {
2437
2456
  get showProgressSubject() {
2438
2457
  return this.showProgress.asObservable();
2439
2458
  }
2440
- manageUploadEventFilter(event) {
2459
+ manageUploadEventFilter(event, packageIndex = 0, nbPackages = 1) {
2441
2460
  switch (event.type) {
2442
2461
  case HttpEventType.Sent:
2443
2462
  this.showProgress.next(true);
@@ -2445,7 +2464,9 @@ class UploadProgressService {
2445
2464
  case HttpEventType.UploadProgress:
2446
2465
  const progress = {
2447
2466
  loaded: event.loaded,
2448
- total: event.total
2467
+ total: event.total,
2468
+ nbPackages,
2469
+ packageIndex
2449
2470
  };
2450
2471
  this.uploadProgress.next(progress);
2451
2472
  return false;
@@ -2457,7 +2478,9 @@ class UploadProgressService {
2457
2478
  case HttpEventType.User:
2458
2479
  default:
2459
2480
  this.analysisProgress.next(false);
2460
- this.showProgress.next(false);
2481
+ if (packageIndex + 1 === nbPackages) {
2482
+ this.showProgress.next(false);
2483
+ }
2461
2484
  return true;
2462
2485
  }
2463
2486
  }
@@ -2481,34 +2504,49 @@ class MultiUploadService {
2481
2504
  this.uploadProgressService = uploadProgressService;
2482
2505
  // A way to have a unique Id per file
2483
2506
  this.globalSequence = 0;
2507
+ this.NB_CONCURRENT_FILES_TO_UPLOAD = 3;
2508
+ this.mergeDocumentsWithErrors = (arrayOfDocumentsWithErrors) => {
2509
+ const mergedResponse = new DocumentsWithErrors();
2510
+ arrayOfDocumentsWithErrors.forEach(item => {
2511
+ var _a, _b;
2512
+ if (!!((_a = item.documents) === null || _a === void 0 ? void 0 : _a.length)) {
2513
+ if (!mergedResponse.documents) {
2514
+ mergedResponse.documents = [];
2515
+ }
2516
+ mergedResponse.documents = mergedResponse.documents.concat(item.documents);
2517
+ }
2518
+ if (!!((_b = item.errors) === null || _b === void 0 ? void 0 : _b.length)) {
2519
+ if (!mergedResponse.errors) {
2520
+ mergedResponse.errors = [];
2521
+ }
2522
+ mergedResponse.errors = mergedResponse.errors.concat(item.errors);
2523
+ }
2524
+ });
2525
+ return mergedResponse;
2526
+ };
2484
2527
  this.uploaderHelper = new UploaderHelper(dictionaryService, applicationInfoService);
2485
2528
  }
2486
2529
  uploadDocuments(baseUrl, formKey, label, files, key, isMultiple, language, shouldDisplayFileSavedConfirmation) {
2487
2530
  const reference = this.gesdemHandlerService.lastResponse.meta.reference;
2488
2531
  if (!!(reference === null || reference === void 0 ? void 0 : reference.length)) {
2489
- const documents = files.map(file => this.uploaderHelper.mapToDocumentReference(file, label, key, isMultiple, new Date().getTime(), this.globalSequence++));
2490
- const formData = this.uploaderHelper.mapToFormData(documents, formKey, language);
2491
2532
  const url = `${baseUrl}/upload/${reference}`;
2492
- return this.httpClient
2493
- .post(url, formData, {
2494
- reportProgress: true,
2495
- observe: 'events',
2496
- responseType: 'json'
2497
- })
2498
- .pipe(filter((e) => this.uploadProgressService.manageUploadEventFilter(e)), map((e) => e.body), tap(result => {
2499
- const successfulDocumentsCount = result.documents && result.documents.length;
2500
- if (successfulDocumentsCount &&
2501
- shouldDisplayFileSavedConfirmation) {
2502
- const message = `${successfulDocumentsCount} fichier(s) sauvegardé(s) avec succès`;
2503
- this.growlService.addWithType(GrowlType.SUCCESS, message);
2504
- }
2505
- }), catchError((e) => {
2506
- this.uploadProgressService.analysisProgress.next(false);
2507
- this.uploadProgressService.showProgress.next(false);
2508
- const message = 'Une erreur est survenue lors de la transmission de vos documents';
2509
- this.growlService.addWithType(GrowlType.DANGER, message);
2510
- return throwError(() => e);
2511
- }));
2533
+ const filesToGroup = [...files];
2534
+ const groupsOfFiles = [];
2535
+ while (!!filesToGroup.length) {
2536
+ groupsOfFiles.push(filesToGroup.splice(0, this.NB_CONCURRENT_FILES_TO_UPLOAD));
2537
+ }
2538
+ const arrayOfDocumentsWithErrorsObservable = groupsOfFiles.map((groupOfFile, index) => {
2539
+ const documents = groupOfFile.map(file => this.uploaderHelper.mapToDocumentReference(file, label, key, isMultiple, new Date().getTime(), this.globalSequence++));
2540
+ const formData = this.uploaderHelper.mapToFormData(documents, formKey, language);
2541
+ return this.getDocumentsWithErrorsObservable(url, formData, shouldDisplayFileSavedConfirmation, index, groupsOfFiles.length);
2542
+ });
2543
+ if (arrayOfDocumentsWithErrorsObservable.length === 1) {
2544
+ return arrayOfDocumentsWithErrorsObservable[0];
2545
+ }
2546
+ // concat() operator sequentially emits all values from the given Observable and then proceed to the next one.
2547
+ return concat(...arrayOfDocumentsWithErrorsObservable).pipe(
2548
+ // toArray() operator collects all the values emitted by the source observable into an array and sends it to the observer
2549
+ toArray(), map(this.mergeDocumentsWithErrors.bind(this)));
2512
2550
  }
2513
2551
  return EMPTY;
2514
2552
  }
@@ -2518,10 +2556,10 @@ class MultiUploadService {
2518
2556
  return this.httpClient.delete(url).pipe(
2519
2557
  // Reflect the document once the update is done to ease chaining observables.
2520
2558
  map(() => document), tap(() => {
2521
- const message = `Suppression du fichier ${document.filename} réussie`;
2559
+ const message = this.dictionaryService.getKeySync('foehn-uploader.files-deleted-success-message', { filename: document.filename });
2522
2560
  this.growlService.addWithType(GrowlType.SUCCESS, message);
2523
2561
  }), catchError((e) => {
2524
- const message = 'Une erreur est survenue lors de la suppression de votre document';
2562
+ const message = this.dictionaryService.getKeySync('foehn-uploader.delete-error-message');
2525
2563
  this.growlService.addWithType(GrowlType.DANGER, message);
2526
2564
  return throwError(() => e);
2527
2565
  }));
@@ -2530,6 +2568,30 @@ class MultiUploadService {
2530
2568
  const reference = this.gesdemHandlerService.lastResponse.meta.reference;
2531
2569
  return `${baseUrl}/download/${reference}/doc/${document.reference}`;
2532
2570
  }
2571
+ getDocumentsWithErrorsObservable(url, formData, shouldDisplayFileSavedConfirmation, packageIndex = 0, nbPackages = 1) {
2572
+ return this.httpClient
2573
+ .post(url, formData, {
2574
+ reportProgress: true,
2575
+ observe: 'events',
2576
+ responseType: 'json'
2577
+ })
2578
+ .pipe(filter((e) => this.uploadProgressService.manageUploadEventFilter(e, packageIndex, nbPackages)), map((e) => e.body), tap(result => {
2579
+ const successfulDocumentsCount = result.documents && result.documents.length;
2580
+ if (successfulDocumentsCount &&
2581
+ shouldDisplayFileSavedConfirmation) {
2582
+ const message = this.dictionaryService.getKeySync('foehn-uploader.files-saved-success-message', {
2583
+ successfulDocumentsCount: successfulDocumentsCount.toString()
2584
+ });
2585
+ this.growlService.addWithType(GrowlType.SUCCESS, message);
2586
+ }
2587
+ }), catchError((e) => {
2588
+ this.uploadProgressService.analysisProgress.next(false);
2589
+ this.uploadProgressService.showProgress.next(false);
2590
+ const message = this.dictionaryService.getKeySync('foehn-uploader.transmission-error-message');
2591
+ this.growlService.addWithType(GrowlType.DANGER, message);
2592
+ return throwError(() => e);
2593
+ }));
2594
+ }
2533
2595
  }
2534
2596
  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 });
2535
2597
  MultiUploadService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: MultiUploadService, providedIn: 'root' });
@@ -10619,15 +10681,21 @@ class GesdemActionRecoveryRegistrationComponent {
10619
10681
  sendAndClose() {
10620
10682
  this.actionRecoveryService
10621
10683
  .registerForRecovery(this.reference, this.model)
10622
- .pipe(tap(err => {
10684
+ .pipe(tap(formRecoveryErrors => {
10623
10685
  this.form.reset();
10624
10686
  this.validationHandler.shouldDisplayErrors(true);
10625
10687
  this.validationHandler.updateErrors([
10626
- ...err,
10688
+ ...formRecoveryErrors,
10627
10689
  ...this.gesdemService.lastResponse.errors
10628
10690
  ]);
10629
10691
  this.form.focusFirstInError();
10630
- this.mailSent = !err.length;
10692
+ const registrationSuccessfull = !formRecoveryErrors.length;
10693
+ this.mailSent = registrationSuccessfull;
10694
+ if (registrationSuccessfull) {
10695
+ // the form could have been updated by the backend on recovery registration
10696
+ // eslint-disable-next-line rxjs-angular/prefer-async-pipe
10697
+ this.gesdemService.retrieve(this.reference).subscribe();
10698
+ }
10631
10699
  }))
10632
10700
  // eslint-disable-next-line rxjs-angular/prefer-async-pipe
10633
10701
  .subscribe();
@@ -10661,10 +10729,10 @@ class GesdemActionRecoveryRegistrationComponent {
10661
10729
  }
10662
10730
  }
10663
10731
  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 });
10664
- 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" }] });
10732
+ 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" }] });
10665
10733
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: GesdemActionRecoveryRegistrationComponent, decorators: [{
10666
10734
  type: Component,
10667
- 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"] }]
10735
+ 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"] }]
10668
10736
  }], ctorParameters: function () { return [{ type: GesdemActionRecoveryService }, { type: ValidationHandlerService }, { type: FoehnPageService }, { type: GesdemEventService }, { type: GesdemHandlerService }, { type: ApplicationInfoService }, { type: SessionInfo }]; }, propDecorators: { continueLaterLabel: [{
10669
10737
  type: Input
10670
10738
  }], modalTrigger: [{
@@ -10684,14 +10752,18 @@ GesdemActionRecoveryModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.
10684
10752
  FoehnInputModule,
10685
10753
  FoehnIconsModule,
10686
10754
  FoehnFormModule,
10687
- FoehnModalModule], exports: [GesdemActionRecoveryLoginComponent,
10755
+ FoehnModalModule,
10756
+ SdkDictionaryModule,
10757
+ PipeModule], exports: [GesdemActionRecoveryLoginComponent,
10688
10758
  GesdemActionRecoveryRegistrationComponent] });
10689
10759
  GesdemActionRecoveryModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: GesdemActionRecoveryModule, imports: [CommonModule,
10690
10760
  RouterModule,
10691
10761
  FoehnInputModule,
10692
10762
  FoehnIconsModule,
10693
10763
  FoehnFormModule,
10694
- FoehnModalModule] });
10764
+ FoehnModalModule,
10765
+ SdkDictionaryModule,
10766
+ PipeModule] });
10695
10767
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: GesdemActionRecoveryModule, decorators: [{
10696
10768
  type: NgModule,
10697
10769
  args: [{
@@ -10701,7 +10773,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImpor
10701
10773
  FoehnInputModule,
10702
10774
  FoehnIconsModule,
10703
10775
  FoehnFormModule,
10704
- FoehnModalModule
10776
+ FoehnModalModule,
10777
+ SdkDictionaryModule,
10778
+ PipeModule
10705
10779
  ],
10706
10780
  declarations: [
10707
10781
  GesdemActionRecoveryLoginComponent,
@@ -11907,7 +11981,10 @@ class FoehnUploadProgressBarComponent {
11907
11981
  }
11908
11982
  }), shareReplay(1));
11909
11983
  this.analysisProgress = this.uploadProgressService.analysisProgressSubject.pipe(shareReplay(1));
11910
- this.currentUploadPercentage = this.uploadProgressService.uploadProgressSubject.pipe(map$1((progress) => this.calculateProgressPercentage(progress)), shareReplay(1));
11984
+ const uploadProgress = this.uploadProgressService.uploadProgressSubject.pipe(shareReplay(1));
11985
+ this.currentUploadPercentage = uploadProgress.pipe(map$1((progress) => this.calculateProgressPercentage(progress)), shareReplay(1));
11986
+ this.uploadPackage = uploadProgress.pipe(filter((progress) => !!progress), shareReplay(1));
11987
+ this.hasUploadPackages = this.uploadPackage.pipe(map$1((progress) => !!progress.nbPackages && progress.nbPackages > 1), shareReplay(1));
11911
11988
  this.progressBarTriggerSubscription = combineLatest([
11912
11989
  this.showProgress,
11913
11990
  this.analysisProgress,
@@ -11938,8 +12015,12 @@ class FoehnUploadProgressBarComponent {
11938
12015
  if (!progress) {
11939
12016
  return 0;
11940
12017
  }
11941
- const percent = Math.round((progress.loaded * 100) / progress.total);
11942
- if (percent === 100) {
12018
+ const percentPerGroup = 100 / progress.nbPackages;
12019
+ const loadedPerGroup = (progress.loaded * percentPerGroup) / progress.total;
12020
+ const loaded = loadedPerGroup + progress.packageIndex * percentPerGroup;
12021
+ const percent = Math.round(loaded);
12022
+ if (percent ===
12023
+ Math.round(percentPerGroup * (progress.packageIndex + 1))) {
11943
12024
  this.uploadProgressService.analysisProgress.next(true);
11944
12025
  }
11945
12026
  return percent;
@@ -11954,10 +12035,10 @@ class FoehnUploadProgressBarComponent {
11954
12035
  }
11955
12036
  }
11956
12037
  FoehnUploadProgressBarComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: FoehnUploadProgressBarComponent, deps: [{ token: UploadProgressService }], target: i0.ɵɵFactoryTarget.Component });
11957
- 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" }] });
12038
+ 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" }] });
11958
12039
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: FoehnUploadProgressBarComponent, decorators: [{
11959
12040
  type: Component,
11960
- 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"] }]
12041
+ 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"] }]
11961
12042
  }], ctorParameters: function () { return [{ type: UploadProgressService }]; }, propDecorators: { progressBarTriggerHtmlElement: [{
11962
12043
  type: Input
11963
12044
  }], progressBarPanel: [{
@@ -12218,6 +12299,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImpor
12218
12299
  }]
12219
12300
  }] });
12220
12301
 
12302
+ // eslint-disable max-classes-per-file
12303
+ class BoDocumentError {
12304
+ }
12305
+ class BoDocumentsWithErrors {
12306
+ }
12307
+
12221
12308
  class BoMultiUploadService {
12222
12309
  constructor(httpClient, growlService, applicationInfoService, dictionaryService, uploadProgressService) {
12223
12310
  this.httpClient = httpClient;
@@ -12227,46 +12314,87 @@ class BoMultiUploadService {
12227
12314
  this.uploadProgressService = uploadProgressService;
12228
12315
  // A way to have a unique Id per file
12229
12316
  this.globalSequence = 0;
12317
+ this.NB_CONCURRENT_FILES_TO_UPLOAD = 3;
12318
+ this.mergeDocumentsWithErrors = (arrayOfDocumentsWithErrors) => {
12319
+ const mergedResponse = new BoDocumentsWithErrors();
12320
+ arrayOfDocumentsWithErrors.forEach(item => {
12321
+ var _a, _b;
12322
+ if (!!((_a = item.documents) === null || _a === void 0 ? void 0 : _a.length)) {
12323
+ if (!mergedResponse.documents) {
12324
+ mergedResponse.documents = [];
12325
+ }
12326
+ mergedResponse.documents = mergedResponse.documents.concat(item.documents);
12327
+ }
12328
+ if (!!((_b = item.errors) === null || _b === void 0 ? void 0 : _b.length)) {
12329
+ if (!mergedResponse.errors) {
12330
+ mergedResponse.errors = [];
12331
+ }
12332
+ mergedResponse.errors = mergedResponse.errors.concat(item.errors);
12333
+ }
12334
+ });
12335
+ return mergedResponse;
12336
+ };
12230
12337
  this.uploaderHelper = new UploaderHelper(dictionaryService, applicationInfoService);
12231
12338
  }
12232
12339
  uploadDocuments(url, formKey, label, files, key, isMultiple, language, shouldDisplayFileSavedConfirmation) {
12233
- const documents = files.map(file => this.uploaderHelper.mapToDocumentReference(file, label, key, isMultiple, new Date().getTime(), this.globalSequence++));
12234
- const formData = this.uploaderHelper.mapToFormData(documents, formKey, language);
12340
+ const filesToGroup = [...files];
12341
+ const groupsOfFiles = [];
12342
+ while (!!filesToGroup.length) {
12343
+ groupsOfFiles.push(filesToGroup.splice(0, this.NB_CONCURRENT_FILES_TO_UPLOAD));
12344
+ }
12345
+ const arrayOfDocumentsWithErrorsObservable = groupsOfFiles.map((groupOfFile, index) => {
12346
+ const documents = groupOfFile.map(file => this.uploaderHelper.mapToDocumentReference(file, label, key, isMultiple, new Date().getTime(), this.globalSequence++));
12347
+ const formData = this.uploaderHelper.mapToFormData(documents, formKey, language);
12348
+ return this.getDocumentsWithErrorsObservable(url, formData, shouldDisplayFileSavedConfirmation, index, groupsOfFiles.length);
12349
+ });
12350
+ if (arrayOfDocumentsWithErrorsObservable.length === 1) {
12351
+ return arrayOfDocumentsWithErrorsObservable[0];
12352
+ }
12353
+ // concat() operator sequentially emits all values from the given Observable and then proceed to the next one.
12354
+ return concat(...arrayOfDocumentsWithErrorsObservable).pipe(
12355
+ // toArray() operator collects all the values emitted by the source observable into an array and sends it to the observer
12356
+ toArray(), map(this.mergeDocumentsWithErrors.bind(this)));
12357
+ }
12358
+ deleteDocument(baseUrl, document) {
12359
+ const url = `${baseUrl}/${document.reference}`;
12360
+ return this.httpClient.delete(url).pipe(
12361
+ // Reflect the document once the update is done to ease chaining observables.
12362
+ map(() => document), tap(() => {
12363
+ const message = this.dictionaryService.getKeySync('foehn-uploader.files-deleted-success-message', { filename: document.filename });
12364
+ this.growlService.addWithType(GrowlType.SUCCESS, message);
12365
+ }), catchError((e) => {
12366
+ const message = this.dictionaryService.getKeySync('foehn-uploader.delete-error-message');
12367
+ this.growlService.addWithType(GrowlType.DANGER, message);
12368
+ return throwError(() => e);
12369
+ }));
12370
+ }
12371
+ getDownloadUrl(baseUrl, document) {
12372
+ return `${baseUrl}/${document.reference}`;
12373
+ }
12374
+ getDocumentsWithErrorsObservable(url, formData, shouldDisplayFileSavedConfirmation, packageIndex = 0, nbPackages = 1) {
12235
12375
  return this.httpClient
12236
12376
  .post(url, formData, {
12237
12377
  reportProgress: true,
12238
12378
  observe: 'events',
12239
12379
  responseType: 'json'
12240
12380
  })
12241
- .pipe(filter((e) => this.uploadProgressService.manageUploadEventFilter(e)), map((e) => e.body), tap(result => {
12381
+ .pipe(filter((e) => this.uploadProgressService.manageUploadEventFilter(e, packageIndex, nbPackages)), map((e) => e.body), tap(result => {
12242
12382
  const successfulDocumentsCount = result.documents && result.documents.length;
12243
12383
  if (successfulDocumentsCount &&
12244
12384
  shouldDisplayFileSavedConfirmation) {
12245
- const message = `${successfulDocumentsCount} fichier(s) sauvegardé(s) avec succès`;
12385
+ const message = this.dictionaryService.getKeySync('foehn-uploader.files-saved-success-message', {
12386
+ successfulDocumentsCount: successfulDocumentsCount.toString()
12387
+ });
12246
12388
  this.growlService.addWithType(GrowlType.SUCCESS, message);
12247
12389
  }
12248
12390
  }), catchError((e) => {
12249
- const message = 'Une erreur est survenue lors de la transmission de vos documents';
12250
- this.growlService.addWithType(GrowlType.DANGER, message);
12251
- return throwError(() => e);
12252
- }));
12253
- }
12254
- deleteDocument(baseUrl, document) {
12255
- const url = `${baseUrl}/${document.reference}`;
12256
- return this.httpClient.delete(url).pipe(
12257
- // Reflect the document once the update is done to ease chaining observables.
12258
- map(() => document), tap(() => {
12259
- const message = `Suppression du fichier ${document.filename} réussie`;
12260
- this.growlService.addWithType(GrowlType.SUCCESS, message);
12261
- }), catchError((e) => {
12262
- const message = 'Une erreur est survenue lors de la suppression de votre document';
12391
+ this.uploadProgressService.analysisProgress.next(false);
12392
+ this.uploadProgressService.showProgress.next(false);
12393
+ const message = this.dictionaryService.getKeySync('foehn-uploader.transmission-error-message');
12263
12394
  this.growlService.addWithType(GrowlType.DANGER, message);
12264
12395
  return throwError(() => e);
12265
12396
  }));
12266
12397
  }
12267
- getDownloadUrl(baseUrl, document) {
12268
- return `${baseUrl}/${document.reference}`;
12269
- }
12270
12398
  }
12271
12399
  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 });
12272
12400
  BoMultiUploadService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: BoMultiUploadService, providedIn: 'root' });
@@ -12277,12 +12405,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImpor
12277
12405
  }]
12278
12406
  }], ctorParameters: function () { return [{ type: i1.HttpClient }, { type: GrowlBrokerService }, { type: ApplicationInfoService }, { type: SdkDictionaryService }, { type: UploadProgressService }]; } });
12279
12407
 
12280
- // eslint-disable max-classes-per-file
12281
- class BoDocumentError {
12282
- }
12283
- class BoDocumentsWithErrors {
12284
- }
12285
-
12286
12408
  class FoehnBoMultiUploadComponent extends AbstractFoehnUploaderComponent {
12287
12409
  constructor(boMultiUploadService, applicationInfoService, confirmModalService, dictionaryService, growlService) {
12288
12410
  super(applicationInfoService, confirmModalService, dictionaryService, growlService);
@@ -12378,6 +12500,14 @@ class FoehnBoMultiUploadComponent extends AbstractFoehnUploaderComponent {
12378
12500
  this.model = [...this.model, ...(documents || [])];
12379
12501
  this.triggerUserInput(this.model);
12380
12502
  }
12503
+ removeDocumentFromModel(document) {
12504
+ const index = this.model.indexOf(document);
12505
+ if (index > -1) {
12506
+ this.model.splice(index, 1);
12507
+ this.model = [...this.model];
12508
+ this.triggerUserInput(this.model);
12509
+ }
12510
+ }
12381
12511
  displayErrorsFromServer(errors) {
12382
12512
  if (!errors || !errors.length) {
12383
12513
  // PRESTAKIT-309: Simulate user interaction with component
@@ -12389,14 +12519,6 @@ class FoehnBoMultiUploadComponent extends AbstractFoehnUploaderComponent {
12389
12519
  errors.forEach(error => this.uploaderHelper.addCustomErrorOrDefault(this.name, newErrors, `${error.errorCode}`, error.label, this.customErrors, this.overrideAcceptedExtensions, this.overrideMaxFileNameLength, this.overrideIllegalCharacters));
12390
12520
  this.refreshErrors([newErrors, true]);
12391
12521
  }
12392
- removeDocumentFromModel(document) {
12393
- const index = this.model.indexOf(document);
12394
- if (index > -1) {
12395
- this.model.splice(index, 1);
12396
- this.model = [...this.model];
12397
- this.triggerUserInput(this.model);
12398
- }
12399
- }
12400
12522
  manageSingleFile(files) {
12401
12523
  // Edge browser lets you drop files from dialog box when selecting a file.
12402
12524
  // We need to make sure we only keep last selected file from user
@@ -12696,6 +12818,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImpor
12696
12818
  }] });
12697
12819
 
12698
12820
  class UploadProgress {
12821
+ constructor() {
12822
+ this.packageIndex = 0;
12823
+ this.nbPackages = 1;
12824
+ }
12699
12825
  }
12700
12826
 
12701
12827
  class EPaymentService {