@sumaris-net/ngx-components 2.5.0-beta3 → 2.5.0

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.
@@ -60,7 +60,7 @@ import { timer, merge, fromEvent, BehaviorSubject, Subscription, Subject, isObse
60
60
  import { filter, map, takeUntil, first, switchMap, tap, debounceTime, startWith, distinctUntilChanged, mergeMap, catchError, throttleTime, skip, bufferWhen, mapTo, take } from 'rxjs/operators';
61
61
  import { trigger, transition, style, animate, state } from '@angular/animations';
62
62
  import * as i1 from '@ionic/angular';
63
- import { IonicModule, Platform, ToastController, IonicSafeString, createAnimation, IonicRouteStrategy, ModalController, AlertController, IonContent, IonItem, IonModal, IonInfiniteScroll } from '@ionic/angular';
63
+ import { IonicModule, Platform, ToastController, IonicSafeString, createAnimation, IonicRouteStrategy, ModalController, AlertController, IonContent, IonRouterOutlet, IonItem, IonModal, IonInfiniteScroll } from '@ionic/angular';
64
64
  import { Capacitor } from '@capacitor/core';
65
65
  import { Keyboard } from '@capacitor/keyboard';
66
66
  import * as i1$2 from '@ngx-translate/core';
@@ -2492,7 +2492,7 @@ class MatAutocompleteField {
2492
2492
  return;
2493
2493
  // Hide the panel (will be show when ready)
2494
2494
  this.matSelect.panelClass = 'cdk-visually-hidden';
2495
- let revertOverlayCallback;
2495
+ let subscription;
2496
2496
  this._subscription.add(this.matSelect.openedChange
2497
2497
  .subscribe(async (open) => {
2498
2498
  if (open) {
@@ -2503,13 +2503,17 @@ class MatAutocompleteField {
2503
2503
  this._fixMatSelectPanelPosition(overlayPane);
2504
2504
  // Fix overlay, for searchbar
2505
2505
  if (this.showSearchBar) {
2506
- revertOverlayCallback = await this._fixSearchbarOverlay(panelElement, overlayPane);
2506
+ subscription = await this._fixSearchbarOverlay(panelElement, overlayPane);
2507
+ this._subscription.add(subscription);
2507
2508
  }
2508
2509
  // Show the panel
2509
2510
  this.renderer.removeClass(panelElement, 'cdk-visually-hidden');
2510
2511
  }
2511
- else if (revertOverlayCallback) {
2512
- revertOverlayCallback();
2512
+ // ON close
2513
+ else if (subscription) {
2514
+ subscription.unsubscribe();
2515
+ this._subscription.remove(subscription);
2516
+ subscription = null;
2513
2517
  }
2514
2518
  }));
2515
2519
  }
@@ -2547,11 +2551,11 @@ class MatAutocompleteField {
2547
2551
  this.renderer.setStyle(overlayPane, 'margin-top', `-${shiftTop}px`);
2548
2552
  this.renderer.setStyle(overlayPane, 'margin-left', `-${shiftLeft}px`);
2549
2553
  // Return the reverse function, to replace the container in body
2550
- return () => {
2554
+ return new Subscription(() => {
2551
2555
  // DEBUG
2552
2556
  console.debug(`${this.logPrefix} moving the "cdk-overlay" container from the "ion-modal" to the "body" container`);
2553
2557
  this.renderer.appendChild(originalParent /*this.document.body*/, overlayContainer);
2554
- };
2558
+ });
2555
2559
  }
2556
2560
  }
2557
2561
  MatAutocompleteField.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: MatAutocompleteField, deps: [{ token: i0.ChangeDetectorRef }, { token: i1.ModalController }, { token: i0.Renderer2 }, { token: DOCUMENT }, { token: ChangeDetectorRef }, { token: i1$3.FormGroupDirective, optional: true }], target: i0.ɵɵFactoryTarget.Component });
@@ -2744,6 +2748,12 @@ class DateUtils {
2744
2748
  value[MOMENT_NO_TIME_PROPERTY] = true;
2745
2749
  return value;
2746
2750
  }
2751
+ static markTime(value) {
2752
+ if (!value)
2753
+ return undefined;
2754
+ delete value[MOMENT_NO_TIME_PROPERTY];
2755
+ return value;
2756
+ }
2747
2757
  static isNoTime(value) {
2748
2758
  return value?.[MOMENT_NO_TIME_PROPERTY] === true;
2749
2759
  }
@@ -6518,9 +6528,9 @@ class MatDateTime {
6518
6528
  .subscribe((_) => this.onFormChange()));
6519
6529
  // Listen status changes (when done outside the component - e.g. when setErrors() is calling on the formControl)
6520
6530
  this._subscription.add(this.formControl.statusChanges
6521
- .pipe(filter((_) => !this.readonly && !this._writing && !this._disabling) // Skip
6531
+ .pipe(filter((_) => !this._readonly && !this._writing && !this._disabling) // Skip
6522
6532
  )
6523
- .subscribe(() => this.markForCheck()));
6533
+ .subscribe((_) => this.markForCheck()));
6524
6534
  this._writing = false;
6525
6535
  }
6526
6536
  ngAfterViewInit() {
@@ -19074,28 +19084,29 @@ class ToolbarComponent {
19074
19084
  const replaceUrl = !this.routerOutlet.canGoBack();
19075
19085
  // Relative href
19076
19086
  if (this._backHref.startsWith('.')) {
19077
- await this.router.navigate([this._backHref], { relativeTo: this.route, replaceUrl });
19087
+ return this.router.navigate([this._backHref], { relativeTo: this.route, replaceUrl });
19078
19088
  }
19079
19089
  else {
19080
- await this.router.navigateByUrl(this._backHref, { replaceUrl });
19090
+ return this.router.navigateByUrl(this._backHref, { replaceUrl });
19081
19091
  }
19082
19092
  }
19083
19093
  else if (this.routerOutlet.canGoBack()) {
19084
- await this.routerOutlet.pop();
19094
+ return this.routerOutlet.pop();
19085
19095
  }
19086
19096
  else if (this._defaultBackHref) {
19087
19097
  // Relative href
19088
19098
  if (this._defaultBackHref.startsWith('.')) {
19089
- await this.router.navigate([this._defaultBackHref], { relativeTo: this.route, replaceUrl: true });
19099
+ return this.router.navigate([this._defaultBackHref], { relativeTo: this.route, replaceUrl: true });
19090
19100
  }
19091
19101
  else {
19092
- await this.router.navigateByUrl(this._defaultBackHref, {
19102
+ return this.router.navigateByUrl(this._defaultBackHref, {
19093
19103
  replaceUrl: true
19094
19104
  });
19095
19105
  }
19096
19106
  }
19097
19107
  else {
19098
19108
  console.error('[toolbar] Cannot go back. Missing attribute \'defaultBackHref\' or \'backHref\'');
19109
+ return false;
19099
19110
  }
19100
19111
  }
19101
19112
  tapClose(event) {
@@ -19715,9 +19726,9 @@ class CustomReuseStrategy extends IonicRouteStrategy {
19715
19726
  * @param curr
19716
19727
  */
19717
19728
  shouldReuseRoute(future, curr) {
19718
- const result = super.shouldReuseRoute(future, curr);
19729
+ const reuse = super.shouldReuseRoute(future, curr);
19719
19730
  // Is sam route config
19720
- if (!result && future.routeConfig && future.routeConfig === curr.routeConfig) {
19731
+ if (!reuse && future.routeConfig && future.routeConfig === curr.routeConfig) {
19721
19732
  // Read the parameter name, where id is stored
19722
19733
  const pathIdParam = future.routeConfig.data && future.routeConfig.data.pathIdParam || 'id';
19723
19734
  // Read the current route id
@@ -19728,11 +19739,17 @@ class CustomReuseStrategy extends IonicRouteStrategy {
19728
19739
  const futureId = future.params[pathIdParam] === 'new'
19729
19740
  ? (future.queryParams[pathIdParam] || future.queryParams['id'] || 'new') // e.g. path like '/new/?id=<ID>'
19730
19741
  : future.params[pathIdParam]; // e.g. path like '/<ID>'
19731
- // Reuse if same ID, but never when 'new' expected
19732
- return futureId !== 'new' && currId !== 'new'
19733
- && futureId === currId;
19742
+ // Reuse if same ID, using a futureId, if exists
19743
+ if (isNotNil(futureId)) {
19744
+ // Allow reuse when changing from /new to /new?id=:id
19745
+ if (currId === 'new' && isNil(curr.queryParams[pathIdParam]) && future.params[pathIdParam] === 'new' && isNotNil(future.queryParams[pathIdParam])) {
19746
+ return true;
19747
+ }
19748
+ // Allow reuse same id, expect when expected '/new'
19749
+ return futureId !== 'new' && futureId === currId;
19750
+ }
19734
19751
  }
19735
- return result;
19752
+ return reuse;
19736
19753
  }
19737
19754
  }
19738
19755
  CustomReuseStrategy.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: CustomReuseStrategy, deps: null, target: i0.ɵɵFactoryTarget.Injectable });
@@ -26849,7 +26866,7 @@ class AccountPage extends AppForm {
26849
26866
  return this.form.get('settings');
26850
26867
  }
26851
26868
  get valid() {
26852
- return super.valid && this.propertiesTable?.valid;
26869
+ return super.valid && (this.propertiesTable?.valid || true);
26853
26870
  }
26854
26871
  ngOnInit() {
26855
26872
  super.ngOnInit();
@@ -26933,8 +26950,10 @@ class AccountPage extends AppForm {
26933
26950
  propertiesEntities.push(PropertyEntity.fromObject({ id: key, value: properties[key] }));
26934
26951
  }
26935
26952
  });
26936
- await this.propertiesTable.ready();
26937
- this.propertiesTable.value = propertiesEntities;
26953
+ if (this.propertiesTable) {
26954
+ await this.propertiesTable.ready();
26955
+ this.propertiesTable.value = propertiesEntities;
26956
+ }
26938
26957
  }
26939
26958
  async refresh(event) {
26940
26959
  this.disable();
@@ -26989,14 +27008,16 @@ class AccountPage extends AppForm {
26989
27008
  ...(this.accountService.account.asObject()),
26990
27009
  ...(this.form.value)
26991
27010
  });
26992
- // merge properties
26993
- await this.propertiesTable.save();
26994
- const propertyEntities = this.propertiesTable.value || [];
26995
- const properties = propertyEntities.reduce((res, item) => {
26996
- res[item.id] = item.value;
26997
- return res;
26998
- }, {});
26999
- newAccount.settings.merge({ properties }, ['properties']);
27011
+ if (this.propertiesTable) {
27012
+ // merge properties
27013
+ await this.propertiesTable.save();
27014
+ const propertyEntities = this.propertiesTable.value || [];
27015
+ const properties = propertyEntities.reduce((res, item) => {
27016
+ res[item.id] = item.value;
27017
+ return res;
27018
+ }, {});
27019
+ newAccount.settings.merge({ properties }, ['properties']);
27020
+ }
27000
27021
  console.debug('[account] Saving account...', newAccount);
27001
27022
  try {
27002
27023
  this.disable();
@@ -27058,10 +27079,10 @@ class AccountPage extends AppForm {
27058
27079
  }
27059
27080
  }
27060
27081
  AccountPage.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: AccountPage, deps: [{ token: i0.Injector }, { token: i1$3.UntypedFormBuilder }, { token: AccountService }, { token: NetworkService }, { token: i1$6.Router }, { token: AccountValidatorService }, { token: ConfigService }, { token: i0.ChangeDetectorRef }, { token: APP_LOCALES }], target: i0.ɵɵFactoryTarget.Component });
27061
- AccountPage.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.2.12", type: AccountPage, selector: "app-account-page", viewQueries: [{ propertyName: "tabGroup", first: true, predicate: ["tabGroup"], descendants: true, static: true }, { propertyName: "propertiesTable", first: true, predicate: ["propertiesTable"], descendants: true, static: true }], usesInheritance: true, ngImport: i0, template: "<app-toolbar [title]=\"'ACCOUNT.TITLE'|translate\" color=\"primary\"\n [hasValidate]=\"dirty && !saving\"\n [hasClose]=\"!dirty && !saving\"\n (onValidate)=\"save($event)\"\n [canGoBack]=\"false\"\n (onClose)=\"close($event)\">\n\n <ion-buttons slot=\"end\">\n <!-- loader -->\n <ion-spinner *ngIf=\"loading || saving; else endButtons\"></ion-spinner>\n\n <ng-template #endButtons>\n <!-- refresh button (if online) -->\n <ion-button [matTooltip]=\"'COMMON.BTN_REFRESH'|translate\"\n *ngIf=\"network.online\"\n (click)=\"refresh($event)\">\n <mat-icon slot=\"icon-only\">refresh</mat-icon>\n </ion-button>\n </ng-template>\n </ion-buttons>\n</app-toolbar>\n\n<ion-content>\n\n <!-- error -->\n <ion-item *ngIf=\"error && mobile\" lines=\"none\">\n <ion-icon color=\"danger\" slot=\"start\" name=\"alert-circle\"></ion-icon>\n <ion-label color=\"danger\" class=\"error\" [innerHTML]=\"error|translate\"></ion-label>\n </ion-item>\n\n <form [formGroup]=\"form\" novalidate class=\"form-container\">\n\n <mat-tab-group #tabGroup [(selectedIndex)]=\"selectedTabIndex\" dynamicHeight>\n\n <!-- TAB: user details -->\n <mat-tab label=\"{{'ACCOUNT.USER_DETAILS.TITLE'|translate}}\" class=\"ion-padding\">\n <ng-template mat-tab-label>\n <mat-icon>\n <ion-icon matPrefix slot=\"start\" name=\"person-circle\"></ion-icon>\n </mat-icon>\n <ion-label>{{'ACCOUNT.USER_DETAILS.TITLE'|translate}}</ion-label>\n <ion-icon slot=\"end\" name=\"alert-circle\" color=\"danger\" *ngIf=\"submitted && form.invalid\"></ion-icon>\n </ng-template>\n\n <div class=\"ion-padding\">\n\n <p [innerHTML]=\"'ACCOUNT.USER_DETAILS.DESCRIPTION'|translate\"></p>\n\n <!--h1>Identit\u00E9</h1-->\n\n <!-- Email -->\n <mat-form-field>\n <input matInput [placeholder]=\"'USER.EMAIL'|translate\"\n formControlName=\"email\" autocomplete=\"section-red email\">\n <mat-error *ngIf=\"form.controls.email.hasError('required') && form.controls.email.dirty\" translate>ERROR.FIELD_REQUIRED</mat-error>\n <mat-error *ngIf=\"form.controls.email.hasError('email') && form.controls.email.dirty\">\n <span>{{'ERROR.FIELD_NOT_VALID_EMAIL' | translate }}</span>\n </mat-error>\n </mat-form-field>\n\n <ion-grid *ngIf=\"email.notConfirmed\" class=\"ion-no-padding ion-padding-bottom\">\n <ion-row>\n <ion-col color=\"danger\">\n <ion-icon slot=\"start\" color=\"danger\" name=\"alert-circle\" color=\"danger\"></ion-icon>\n <ion-text [innerHTML]=\"'ACCOUNT.EMAIL_NOT_CONFIRMED_LABEL'|translate\"></ion-text>\n </ion-col>\n </ion-row>\n\n <ion-row style=\"height: 51px;\">\n <ion-col style=\"text-align: right;\">\n <ion-text>\n <small [innerHTML]=\"'ACCOUNT.EMAIL_NOT_RECEIVED_QUESTION'|translate\"></small>\n </ion-text>\n </ion-col>\n <ion-col size=\"auto\">\n <ion-button fill=\"solid\" color=\"secondary\" *ngIf=\"!email.sending\" (click)=\"sendConfirmationEmail($event)\">\n {{'ACCOUNT.BTN_RESEND'|translate}}\n </ion-button>\n <ion-spinner class=\"ion-no-padding\" *ngIf=\"email.sending\"></ion-spinner>\n </ion-col>\n </ion-row>\n\n <ion-row *ngIf=\"email.error && !email.sending\">\n <ion-col>\n <span *ngIf=\"email.error && !email.sending\" [innerHTML]=\"email.error|translate\"></span>\n </ion-col>\n </ion-row>\n </ion-grid>\n\n <!-- Last name -->\n <mat-form-field>\n <input matInput [appAutofocus]=\"true\" [autofocusDelay]=\"500\" [placeholder]=\"'USER.LAST_NAME'|translate\"\n formControlName=\"lastName\"\n autocomplete=\"section-blue family-name\"\n required>\n <mat-error *ngIf=\"form.controls.lastName.hasError('required') && form.controls.lastName.dirty\"\n translate>ERROR.FIELD_REQUIRED\n </mat-error>\n <mat-error *ngIf=\"form.controls.lastName.hasError('minlength') && form.controls.lastName.dirty\">\n <span>{{'ERROR.FIELD_MIN_LENGTH' | translate: {minLength: 2} }}</span>\n </mat-error>\n </mat-form-field>\n\n <!-- First name -->\n <mat-form-field>\n <input matInput [placeholder]=\"'USER.FIRST_NAME'|translate\" formControlName=\"firstName\" autocomplete=\"section-blue given-name\"\n required>\n <mat-error *ngIf=\"form.controls.firstName.hasError('required') && form.controls.firstName.dirty\"\n translate>ERROR.FIELD_REQUIRED\n </mat-error>\n <mat-error *ngIf=\"form.controls.firstName.hasError('minlength') && form.controls.firstName.dirty\">\n <span>{{'ERROR.FIELD_MIN_LENGTH' | translate: {minLength: 2} }}</span>\n </mat-error>\n </mat-form-field>\n\n\n <!-- Additional fields -->\n <ng-container *ngFor=\"let definition of additionalFields\">\n <app-form-field [definition]=\"definition\"\n [formControlName]=\"definition.key\"\n [required]=\"definition.extra && definition.extra.account && definition.extra.account.required || false\">\n </app-form-field>\n </ng-container>\n\n <h3 translate>ACCOUNT.USER_DETAILS.TECHNICAL_DIVIDER</h3>\n\n <!-- profile -->\n <mat-form-field>\n <input matInput hidden readonly=\"true\" [placeholder]=\"'ACCOUNT.USER_DETAILS.PROFILE'|translate\"\n formControlName=\"mainProfile\" required>\n <span>{{'USER.PROFILE_ENUM.' + form.controls.mainProfile.value | translate}}</span>\n <mat-error *ngIf=\"form.controls.firstName.hasError('mainProfile') && form.controls.mainProfile.dirty\"\n translate>ERROR.FIELD_REQUIRED\n </mat-error>\n </mat-form-field>\n\n <!-- pubkey -->\n <mat-form-field>\n <input matInput readonly=\"true\" [placeholder]=\"'ACCOUNT.USER_DETAILS.PUBKEY'|translate\" formControlName=\"pubkey\"\n required>\n <mat-error *ngIf=\"form.controls.firstName.hasError('pubkey') && form.controls.firstName.dirty\"\n translate>ERROR.FIELD_REQUIRED\n </mat-error>\n <mat-error *ngIf=\"form.controls.firstName.hasError('pubkey') && form.controls.firstName.dirty\">\n <span translate>ERROR.FIELD_NOT_VALID_PUBKEY</span>\n </mat-error>\n </mat-form-field>\n\n </div>\n </mat-tab>\n\n <!-- TAB: settings -->\n <mat-tab label=\"{{'ACCOUNT.SETTINGS.TITLE'|translate}}\" formGroupName=\"settings\">\n <ng-template mat-tab-label>\n <mat-icon>\n <ion-icon matPrefix slot=\"start\" name=\"settings\"></ion-icon>\n </mat-icon>\n <ion-label translate>ACCOUNT.SETTINGS.TITLE</ion-label>\n </ng-template>\n\n <div class=\"ion-padding\">\n\n <p [innerHTML]=\"'ACCOUNT.SETTINGS.DESCRIPTION'|translate\"></p>\n\n <mat-form-field>\n <mat-select [placeholder]=\"'ACCOUNT.SETTINGS.LOCALE'|translate\" formControlName=\"locale\" required>\n <mat-option *ngFor=\"let item of locales\" [value]=\"item.key\">\n {{item.value}}\n </mat-option>\n </mat-select>\n <mat-error *ngIf=\"settingsForm?.controls.locale.hasError('required') && settingsForm?.controls.locale.dirty\"\n translate>ERROR.FIELD_REQUIRED\n </mat-error>\n </mat-form-field>\n\n <!-- lat/long format-->\n <mat-form-field>\n <mat-select [placeholder]=\"'ACCOUNT.SETTINGS.LAT_LONG_FORMAT'|translate\" formControlName=\"latLongFormat\"\n required>\n <mat-option *ngFor=\"let item of latLongFormats\" [value]=\"item\">\n {{'COMMON.LAT_LONG.' + item + '_PLACEHOLDER'|translate}}\n </mat-option>\n </mat-select>\n <mat-error *ngIf=\"settingsForm?.controls.latLongFormat.hasError('required') && settingsForm?.controls.latLongFormat.dirty\"\n translate>ERROR.FIELD_REQUIRED\n </mat-error>\n </mat-form-field>\n\n </div>\n\n <!-- Options table -->\n <div class=\"options-table\">\n <app-properties-table\n #propertiesTable\n i18nColumnPrefix=\"ACCOUNT.SETTINGS.OPTIONS.\"\n [definitions]=\"optionDefinitions\"\n [canEdit]=\"true\"\n (onDirty)=\"$event ? markAsDirty() : undefined\"\n ></app-properties-table>\n </div>\n\n </mat-tab>\n </mat-tab-group>\n\n\n </form>\n</ion-content>\n\n<ion-footer hidden-xs hidden-sm hidden-mobile>\n <app-form-buttons-bar (onCancel)=\"cancel()\" (onSave)=\"save($event)\" [disabled]=\"!form.dirty || !valid || saving\">\n <!-- error -->\n <ion-item *ngIf=\"error && !mobile\" lines=\"none\">\n <ion-icon color=\"danger\" slot=\"start\" name=\"alert-circle\"></ion-icon>\n <ion-label color=\"danger\" class=\"error\" [innerHTML]=\"error|translate\"></ion-label>\n </ion-item>\n </app-form-buttons-bar>\n</ion-footer>\n", styles: ["mat-tab-group .mat-tab-body-content{padding:var(--ion-grid-padding);display:grid}form{width:100%}form mat-form-field{width:100%}div.options-table{height:calc(100vh - 380px)}\n"], dependencies: [{ kind: "directive", type: i3.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i1.IonButton, selector: "ion-button", inputs: ["buttonType", "color", "disabled", "download", "expand", "fill", "form", "href", "mode", "rel", "routerAnimation", "routerDirection", "shape", "size", "strong", "target", "type"] }, { kind: "component", type: i1.IonButtons, selector: "ion-buttons", inputs: ["collapse"] }, { kind: "component", type: i1.IonCol, selector: "ion-col", inputs: ["offset", "offsetLg", "offsetMd", "offsetSm", "offsetXl", "offsetXs", "pull", "pullLg", "pullMd", "pullSm", "pullXl", "pullXs", "push", "pushLg", "pushMd", "pushSm", "pushXl", "pushXs", "size", "sizeLg", "sizeMd", "sizeSm", "sizeXl", "sizeXs"] }, { kind: "component", type: i1.IonContent, selector: "ion-content", inputs: ["color", "forceOverscroll", "fullscreen", "scrollEvents", "scrollX", "scrollY"] }, { kind: "component", type: i1.IonFooter, selector: "ion-footer", inputs: ["collapse", "mode", "translucent"] }, { kind: "component", type: i1.IonGrid, selector: "ion-grid", inputs: ["fixed"] }, { kind: "component", type: i1.IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "component", type: i1.IonItem, selector: "ion-item", inputs: ["button", "color", "counter", "counterFormatter", "detail", "detailIcon", "disabled", "download", "fill", "href", "lines", "mode", "rel", "routerAnimation", "routerDirection", "shape", "target", "type"] }, { kind: "component", type: i1.IonLabel, selector: "ion-label", inputs: ["color", "mode", "position"] }, { kind: "component", type: i1.IonRow, selector: "ion-row" }, { kind: "component", type: i1.IonSpinner, selector: "ion-spinner", inputs: ["color", "duration", "name", "paused"] }, { kind: "component", type: i1.IonText, selector: "ion-text", inputs: ["color", "mode"] }, { kind: "directive", type: i1$2.TranslateDirective, selector: "[translate],[ngx-translate]", inputs: ["translate", "translateParams"] }, { kind: "directive", type: i1$3.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$3.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$3.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$3.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1$3.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$3.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i1$3.FormGroupName, selector: "[formGroupName]", inputs: ["formGroupName"] }, { kind: "directive", type: i6$1.MatError, selector: "mat-error", inputs: ["id"] }, { kind: "component", type: i6$1.MatFormField, selector: "mat-form-field", inputs: ["color", "appearance", "hideRequiredMarker", "hintLabel", "floatLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i6$1.MatPrefix, selector: "[matPrefix]" }, { kind: "directive", type: i7.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { kind: "component", type: i8.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i8$1.MatSelect, selector: "mat-select", inputs: ["disabled", "disableRipple", "tabIndex"], exportAs: ["matSelect"] }, { kind: "component", type: i2.MatOption, selector: "mat-option", exportAs: ["matOption"] }, { kind: "component", type: i15.MatTabGroup, selector: "mat-tab-group", inputs: ["color", "disableRipple"], exportAs: ["matTabGroup"] }, { kind: "directive", type: i15.MatTabLabel, selector: "[mat-tab-label], [matTabLabel]" }, { kind: "component", type: i15.MatTab, selector: "mat-tab", inputs: ["disabled", "label", "aria-label", "aria-labelledby", "labelClass", "bodyClass"], exportAs: ["matTab"] }, { kind: "directive", type: i6$3.MatTooltip, selector: "[matTooltip]", exportAs: ["matTooltip"] }, { kind: "directive", type: AutofocusDirective, selector: "[autofocus], input[appAutofocus]", inputs: ["appAutofocus", "autofocusDelay"] }, { kind: "component", type: ToolbarComponent, selector: "app-toolbar", inputs: ["progressBarMode", "title", "color", "class", "backHref", "defaultBackHref", "hasValidate", "hasClose", "hasSearch", "canGoBack", "canShowMenu"], outputs: ["onValidate", "onClose", "onValidateAndClose", "onBackClick", "onSearch"] }, { kind: "component", type: AppFormField, selector: "app-form-field", inputs: ["definition", "required", "readonly", "disabled", "formControl", "formControlName", "placeholder", "compact", "floatLabel", "tabindex", "autofocus", "chipColor", "class"], outputs: ["keyup.enter"] }, { kind: "component", type: FormButtonsBarComponent, selector: "app-form-buttons-bar", inputs: ["disabled", "disabledCancel", "classList"], outputs: ["onCancel", "onSave", "onNext", "onBack"] }, { kind: "component", type: AppPropertiesTable, selector: "app-properties-table", inputs: ["definitions", "showToolbar"] }, { kind: "pipe", type: i1$2.TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
27082
+ AccountPage.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.2.12", type: AccountPage, selector: "app-account-page", viewQueries: [{ propertyName: "tabGroup", first: true, predicate: ["tabGroup"], descendants: true, static: true }, { propertyName: "propertiesTable", first: true, predicate: ["propertiesTable"], descendants: true, static: true }], usesInheritance: true, ngImport: i0, template: "<app-toolbar [title]=\"'ACCOUNT.TITLE'|translate\" color=\"primary\"\n [hasValidate]=\"dirty && !saving\"\n [hasClose]=\"!dirty && !saving\"\n (onValidate)=\"save($event)\"\n [canGoBack]=\"false\"\n (onClose)=\"close($event)\">\n\n <ion-buttons slot=\"end\">\n <!-- loader -->\n <ion-spinner *ngIf=\"loading || saving; else endButtons\"></ion-spinner>\n\n <ng-template #endButtons>\n <!-- refresh button (if online) -->\n <ion-button [matTooltip]=\"'COMMON.BTN_REFRESH'|translate\"\n *ngIf=\"network.online\"\n (click)=\"refresh($event)\">\n <mat-icon slot=\"icon-only\">refresh</mat-icon>\n </ion-button>\n </ng-template>\n </ion-buttons>\n</app-toolbar>\n\n<ion-content>\n\n <!-- error -->\n <ion-item *ngIf=\"error && mobile\" lines=\"none\">\n <ion-icon color=\"danger\" slot=\"start\" name=\"alert-circle\"></ion-icon>\n <ion-label color=\"danger\" class=\"error\" [innerHTML]=\"error|translate\"></ion-label>\n </ion-item>\n\n <form [formGroup]=\"form\" novalidate class=\"form-container\">\n\n <mat-tab-group #tabGroup [(selectedIndex)]=\"selectedTabIndex\" dynamicHeight>\n\n <!-- TAB: user details -->\n <mat-tab label=\"{{'ACCOUNT.USER_DETAILS.TITLE'|translate}}\" class=\"ion-padding\">\n <ng-template mat-tab-label>\n <mat-icon>\n <ion-icon matPrefix slot=\"start\" name=\"person-circle\"></ion-icon>\n </mat-icon>\n <ion-label>{{'ACCOUNT.USER_DETAILS.TITLE'|translate}}</ion-label>\n <ion-icon slot=\"end\" name=\"alert-circle\" color=\"danger\" *ngIf=\"submitted && form.invalid\"></ion-icon>\n </ng-template>\n\n <div class=\"ion-padding\">\n\n <p [innerHTML]=\"'ACCOUNT.USER_DETAILS.DESCRIPTION'|translate\"></p>\n\n <!--h1>Identit\u00E9</h1-->\n\n <!-- Email -->\n <mat-form-field>\n <input matInput [placeholder]=\"'USER.EMAIL'|translate\"\n formControlName=\"email\" autocomplete=\"section-red email\">\n <mat-error *ngIf=\"form.controls.email.hasError('required') && form.controls.email.dirty\" translate>ERROR.FIELD_REQUIRED</mat-error>\n <mat-error *ngIf=\"form.controls.email.hasError('email') && form.controls.email.dirty\">\n <span>{{'ERROR.FIELD_NOT_VALID_EMAIL' | translate }}</span>\n </mat-error>\n </mat-form-field>\n\n <ion-grid *ngIf=\"email.notConfirmed\" class=\"ion-no-padding ion-padding-bottom\">\n <ion-row>\n <ion-col color=\"danger\">\n <ion-icon slot=\"start\" color=\"danger\" name=\"alert-circle\" color=\"danger\"></ion-icon>\n <ion-text [innerHTML]=\"'ACCOUNT.EMAIL_NOT_CONFIRMED_LABEL'|translate\"></ion-text>\n </ion-col>\n </ion-row>\n\n <ion-row style=\"height: 51px;\">\n <ion-col style=\"text-align: right;\">\n <ion-text>\n <small [innerHTML]=\"'ACCOUNT.EMAIL_NOT_RECEIVED_QUESTION'|translate\"></small>\n </ion-text>\n </ion-col>\n <ion-col size=\"auto\">\n <ion-button fill=\"solid\" color=\"secondary\" *ngIf=\"!email.sending\" (click)=\"sendConfirmationEmail($event)\">\n {{'ACCOUNT.BTN_RESEND'|translate}}\n </ion-button>\n <ion-spinner class=\"ion-no-padding\" *ngIf=\"email.sending\"></ion-spinner>\n </ion-col>\n </ion-row>\n\n <ion-row *ngIf=\"email.error && !email.sending\">\n <ion-col>\n <span *ngIf=\"email.error && !email.sending\" [innerHTML]=\"email.error|translate\"></span>\n </ion-col>\n </ion-row>\n </ion-grid>\n\n <!-- Last name -->\n <mat-form-field>\n <input matInput [appAutofocus]=\"true\" [autofocusDelay]=\"500\" [placeholder]=\"'USER.LAST_NAME'|translate\"\n formControlName=\"lastName\"\n autocomplete=\"section-blue family-name\"\n required>\n <mat-error *ngIf=\"form.controls.lastName.hasError('required') && form.controls.lastName.dirty\"\n translate>ERROR.FIELD_REQUIRED\n </mat-error>\n <mat-error *ngIf=\"form.controls.lastName.hasError('minlength') && form.controls.lastName.dirty\">\n <span>{{'ERROR.FIELD_MIN_LENGTH' | translate: {minLength: 2} }}</span>\n </mat-error>\n </mat-form-field>\n\n <!-- First name -->\n <mat-form-field>\n <input matInput [placeholder]=\"'USER.FIRST_NAME'|translate\" formControlName=\"firstName\" autocomplete=\"section-blue given-name\"\n required>\n <mat-error *ngIf=\"form.controls.firstName.hasError('required') && form.controls.firstName.dirty\"\n translate>ERROR.FIELD_REQUIRED\n </mat-error>\n <mat-error *ngIf=\"form.controls.firstName.hasError('minlength') && form.controls.firstName.dirty\">\n <span>{{'ERROR.FIELD_MIN_LENGTH' | translate: {minLength: 2} }}</span>\n </mat-error>\n </mat-form-field>\n\n\n <!-- Additional fields -->\n <ng-container *ngFor=\"let definition of additionalFields\">\n <app-form-field [definition]=\"definition\"\n [formControlName]=\"definition.key\"\n [required]=\"definition.extra && definition.extra.account && definition.extra.account.required || false\">\n </app-form-field>\n </ng-container>\n\n <h3 translate>ACCOUNT.USER_DETAILS.TECHNICAL_DIVIDER</h3>\n\n <!-- profile -->\n <mat-form-field>\n <input matInput hidden readonly=\"true\" [placeholder]=\"'ACCOUNT.USER_DETAILS.PROFILE'|translate\"\n formControlName=\"mainProfile\" required>\n <span>{{'USER.PROFILE_ENUM.' + form.controls.mainProfile.value | translate}}</span>\n <mat-error *ngIf=\"form.controls.firstName.hasError('mainProfile') && form.controls.mainProfile.dirty\"\n translate>ERROR.FIELD_REQUIRED\n </mat-error>\n </mat-form-field>\n\n <!-- pubkey -->\n <mat-form-field>\n <input matInput readonly=\"true\" [placeholder]=\"'ACCOUNT.USER_DETAILS.PUBKEY'|translate\" formControlName=\"pubkey\"\n required>\n <mat-error *ngIf=\"form.controls.firstName.hasError('pubkey') && form.controls.firstName.dirty\"\n translate>ERROR.FIELD_REQUIRED\n </mat-error>\n <mat-error *ngIf=\"form.controls.firstName.hasError('pubkey') && form.controls.firstName.dirty\">\n <span translate>ERROR.FIELD_NOT_VALID_PUBKEY</span>\n </mat-error>\n </mat-form-field>\n\n </div>\n </mat-tab>\n\n <!-- TAB: settings -->\n <mat-tab label=\"{{'ACCOUNT.SETTINGS.TITLE'|translate}}\" formGroupName=\"settings\">\n <ng-template mat-tab-label>\n <mat-icon>\n <ion-icon matPrefix slot=\"start\" name=\"settings\"></ion-icon>\n </mat-icon>\n <ion-label translate>ACCOUNT.SETTINGS.TITLE</ion-label>\n </ng-template>\n\n <div class=\"ion-padding\">\n\n <p [innerHTML]=\"'ACCOUNT.SETTINGS.DESCRIPTION'|translate\"></p>\n\n <mat-form-field>\n <mat-select [placeholder]=\"'ACCOUNT.SETTINGS.LOCALE'|translate\" formControlName=\"locale\" required>\n <mat-option *ngFor=\"let item of locales\" [value]=\"item.key\">\n {{item.value}}\n </mat-option>\n </mat-select>\n <mat-error *ngIf=\"settingsForm?.controls.locale.hasError('required') && settingsForm?.controls.locale.dirty\"\n translate>ERROR.FIELD_REQUIRED\n </mat-error>\n </mat-form-field>\n\n <!-- lat/long format-->\n <mat-form-field>\n <mat-select [placeholder]=\"'ACCOUNT.SETTINGS.LAT_LONG_FORMAT'|translate\" formControlName=\"latLongFormat\"\n required>\n <mat-option *ngFor=\"let item of latLongFormats\" [value]=\"item\">\n {{'COMMON.LAT_LONG.' + item + '_PLACEHOLDER'|translate}}\n </mat-option>\n </mat-select>\n <mat-error *ngIf=\"settingsForm?.controls.latLongFormat.hasError('required') && settingsForm?.controls.latLongFormat.dirty\"\n translate>ERROR.FIELD_REQUIRED\n </mat-error>\n </mat-form-field>\n\n </div>\n\n <!-- Options table -->\n <div class=\"options-table\" *ngIf=\"optionDefinitions | isNotEmptyArray\">\n <app-properties-table\n #propertiesTable\n i18nColumnPrefix=\"ACCOUNT.SETTINGS.OPTIONS.\"\n [definitions]=\"optionDefinitions\"\n [canEdit]=\"true\"\n (onDirty)=\"$event ? markAsDirty() : undefined\"\n ></app-properties-table>\n </div>\n\n </mat-tab>\n </mat-tab-group>\n\n\n </form>\n</ion-content>\n\n<ion-footer hidden-xs hidden-sm hidden-mobile>\n <app-form-buttons-bar (onCancel)=\"cancel()\" (onSave)=\"save($event)\" [disabled]=\"!form.dirty || !valid || saving\">\n <!-- error -->\n <ion-item *ngIf=\"error && !mobile\" lines=\"none\">\n <ion-icon color=\"danger\" slot=\"start\" name=\"alert-circle\"></ion-icon>\n <ion-label color=\"danger\" class=\"error\" [innerHTML]=\"error|translate\"></ion-label>\n </ion-item>\n </app-form-buttons-bar>\n</ion-footer>\n", styles: ["mat-tab-group .mat-tab-body-content{padding:var(--ion-grid-padding);display:grid}form{width:100%}form mat-form-field{width:100%}div.options-table{height:calc(100vh - 380px)}\n"], dependencies: [{ kind: "directive", type: i3.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i1.IonButton, selector: "ion-button", inputs: ["buttonType", "color", "disabled", "download", "expand", "fill", "form", "href", "mode", "rel", "routerAnimation", "routerDirection", "shape", "size", "strong", "target", "type"] }, { kind: "component", type: i1.IonButtons, selector: "ion-buttons", inputs: ["collapse"] }, { kind: "component", type: i1.IonCol, selector: "ion-col", inputs: ["offset", "offsetLg", "offsetMd", "offsetSm", "offsetXl", "offsetXs", "pull", "pullLg", "pullMd", "pullSm", "pullXl", "pullXs", "push", "pushLg", "pushMd", "pushSm", "pushXl", "pushXs", "size", "sizeLg", "sizeMd", "sizeSm", "sizeXl", "sizeXs"] }, { kind: "component", type: i1.IonContent, selector: "ion-content", inputs: ["color", "forceOverscroll", "fullscreen", "scrollEvents", "scrollX", "scrollY"] }, { kind: "component", type: i1.IonFooter, selector: "ion-footer", inputs: ["collapse", "mode", "translucent"] }, { kind: "component", type: i1.IonGrid, selector: "ion-grid", inputs: ["fixed"] }, { kind: "component", type: i1.IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "component", type: i1.IonItem, selector: "ion-item", inputs: ["button", "color", "counter", "counterFormatter", "detail", "detailIcon", "disabled", "download", "fill", "href", "lines", "mode", "rel", "routerAnimation", "routerDirection", "shape", "target", "type"] }, { kind: "component", type: i1.IonLabel, selector: "ion-label", inputs: ["color", "mode", "position"] }, { kind: "component", type: i1.IonRow, selector: "ion-row" }, { kind: "component", type: i1.IonSpinner, selector: "ion-spinner", inputs: ["color", "duration", "name", "paused"] }, { kind: "component", type: i1.IonText, selector: "ion-text", inputs: ["color", "mode"] }, { kind: "directive", type: i1$2.TranslateDirective, selector: "[translate],[ngx-translate]", inputs: ["translate", "translateParams"] }, { kind: "directive", type: i1$3.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$3.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$3.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$3.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1$3.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$3.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i1$3.FormGroupName, selector: "[formGroupName]", inputs: ["formGroupName"] }, { kind: "directive", type: i6$1.MatError, selector: "mat-error", inputs: ["id"] }, { kind: "component", type: i6$1.MatFormField, selector: "mat-form-field", inputs: ["color", "appearance", "hideRequiredMarker", "hintLabel", "floatLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i6$1.MatPrefix, selector: "[matPrefix]" }, { kind: "directive", type: i7.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { kind: "component", type: i8.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i8$1.MatSelect, selector: "mat-select", inputs: ["disabled", "disableRipple", "tabIndex"], exportAs: ["matSelect"] }, { kind: "component", type: i2.MatOption, selector: "mat-option", exportAs: ["matOption"] }, { kind: "component", type: i15.MatTabGroup, selector: "mat-tab-group", inputs: ["color", "disableRipple"], exportAs: ["matTabGroup"] }, { kind: "directive", type: i15.MatTabLabel, selector: "[mat-tab-label], [matTabLabel]" }, { kind: "component", type: i15.MatTab, selector: "mat-tab", inputs: ["disabled", "label", "aria-label", "aria-labelledby", "labelClass", "bodyClass"], exportAs: ["matTab"] }, { kind: "directive", type: i6$3.MatTooltip, selector: "[matTooltip]", exportAs: ["matTooltip"] }, { kind: "directive", type: AutofocusDirective, selector: "[autofocus], input[appAutofocus]", inputs: ["appAutofocus", "autofocusDelay"] }, { kind: "component", type: ToolbarComponent, selector: "app-toolbar", inputs: ["progressBarMode", "title", "color", "class", "backHref", "defaultBackHref", "hasValidate", "hasClose", "hasSearch", "canGoBack", "canShowMenu"], outputs: ["onValidate", "onClose", "onValidateAndClose", "onBackClick", "onSearch"] }, { kind: "component", type: AppFormField, selector: "app-form-field", inputs: ["definition", "required", "readonly", "disabled", "formControl", "formControlName", "placeholder", "compact", "floatLabel", "tabindex", "autofocus", "chipColor", "class"], outputs: ["keyup.enter"] }, { kind: "component", type: FormButtonsBarComponent, selector: "app-form-buttons-bar", inputs: ["disabled", "disabledCancel", "classList"], outputs: ["onCancel", "onSave", "onNext", "onBack"] }, { kind: "component", type: AppPropertiesTable, selector: "app-properties-table", inputs: ["definitions", "showToolbar"] }, { kind: "pipe", type: i1$2.TranslatePipe, name: "translate" }, { kind: "pipe", type: NotEmptyArrayPipe, name: "isNotEmptyArray" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
27062
27083
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: AccountPage, decorators: [{
27063
27084
  type: Component,
27064
- args: [{ selector: 'app-account-page', changeDetection: ChangeDetectionStrategy.OnPush, template: "<app-toolbar [title]=\"'ACCOUNT.TITLE'|translate\" color=\"primary\"\n [hasValidate]=\"dirty && !saving\"\n [hasClose]=\"!dirty && !saving\"\n (onValidate)=\"save($event)\"\n [canGoBack]=\"false\"\n (onClose)=\"close($event)\">\n\n <ion-buttons slot=\"end\">\n <!-- loader -->\n <ion-spinner *ngIf=\"loading || saving; else endButtons\"></ion-spinner>\n\n <ng-template #endButtons>\n <!-- refresh button (if online) -->\n <ion-button [matTooltip]=\"'COMMON.BTN_REFRESH'|translate\"\n *ngIf=\"network.online\"\n (click)=\"refresh($event)\">\n <mat-icon slot=\"icon-only\">refresh</mat-icon>\n </ion-button>\n </ng-template>\n </ion-buttons>\n</app-toolbar>\n\n<ion-content>\n\n <!-- error -->\n <ion-item *ngIf=\"error && mobile\" lines=\"none\">\n <ion-icon color=\"danger\" slot=\"start\" name=\"alert-circle\"></ion-icon>\n <ion-label color=\"danger\" class=\"error\" [innerHTML]=\"error|translate\"></ion-label>\n </ion-item>\n\n <form [formGroup]=\"form\" novalidate class=\"form-container\">\n\n <mat-tab-group #tabGroup [(selectedIndex)]=\"selectedTabIndex\" dynamicHeight>\n\n <!-- TAB: user details -->\n <mat-tab label=\"{{'ACCOUNT.USER_DETAILS.TITLE'|translate}}\" class=\"ion-padding\">\n <ng-template mat-tab-label>\n <mat-icon>\n <ion-icon matPrefix slot=\"start\" name=\"person-circle\"></ion-icon>\n </mat-icon>\n <ion-label>{{'ACCOUNT.USER_DETAILS.TITLE'|translate}}</ion-label>\n <ion-icon slot=\"end\" name=\"alert-circle\" color=\"danger\" *ngIf=\"submitted && form.invalid\"></ion-icon>\n </ng-template>\n\n <div class=\"ion-padding\">\n\n <p [innerHTML]=\"'ACCOUNT.USER_DETAILS.DESCRIPTION'|translate\"></p>\n\n <!--h1>Identit\u00E9</h1-->\n\n <!-- Email -->\n <mat-form-field>\n <input matInput [placeholder]=\"'USER.EMAIL'|translate\"\n formControlName=\"email\" autocomplete=\"section-red email\">\n <mat-error *ngIf=\"form.controls.email.hasError('required') && form.controls.email.dirty\" translate>ERROR.FIELD_REQUIRED</mat-error>\n <mat-error *ngIf=\"form.controls.email.hasError('email') && form.controls.email.dirty\">\n <span>{{'ERROR.FIELD_NOT_VALID_EMAIL' | translate }}</span>\n </mat-error>\n </mat-form-field>\n\n <ion-grid *ngIf=\"email.notConfirmed\" class=\"ion-no-padding ion-padding-bottom\">\n <ion-row>\n <ion-col color=\"danger\">\n <ion-icon slot=\"start\" color=\"danger\" name=\"alert-circle\" color=\"danger\"></ion-icon>\n <ion-text [innerHTML]=\"'ACCOUNT.EMAIL_NOT_CONFIRMED_LABEL'|translate\"></ion-text>\n </ion-col>\n </ion-row>\n\n <ion-row style=\"height: 51px;\">\n <ion-col style=\"text-align: right;\">\n <ion-text>\n <small [innerHTML]=\"'ACCOUNT.EMAIL_NOT_RECEIVED_QUESTION'|translate\"></small>\n </ion-text>\n </ion-col>\n <ion-col size=\"auto\">\n <ion-button fill=\"solid\" color=\"secondary\" *ngIf=\"!email.sending\" (click)=\"sendConfirmationEmail($event)\">\n {{'ACCOUNT.BTN_RESEND'|translate}}\n </ion-button>\n <ion-spinner class=\"ion-no-padding\" *ngIf=\"email.sending\"></ion-spinner>\n </ion-col>\n </ion-row>\n\n <ion-row *ngIf=\"email.error && !email.sending\">\n <ion-col>\n <span *ngIf=\"email.error && !email.sending\" [innerHTML]=\"email.error|translate\"></span>\n </ion-col>\n </ion-row>\n </ion-grid>\n\n <!-- Last name -->\n <mat-form-field>\n <input matInput [appAutofocus]=\"true\" [autofocusDelay]=\"500\" [placeholder]=\"'USER.LAST_NAME'|translate\"\n formControlName=\"lastName\"\n autocomplete=\"section-blue family-name\"\n required>\n <mat-error *ngIf=\"form.controls.lastName.hasError('required') && form.controls.lastName.dirty\"\n translate>ERROR.FIELD_REQUIRED\n </mat-error>\n <mat-error *ngIf=\"form.controls.lastName.hasError('minlength') && form.controls.lastName.dirty\">\n <span>{{'ERROR.FIELD_MIN_LENGTH' | translate: {minLength: 2} }}</span>\n </mat-error>\n </mat-form-field>\n\n <!-- First name -->\n <mat-form-field>\n <input matInput [placeholder]=\"'USER.FIRST_NAME'|translate\" formControlName=\"firstName\" autocomplete=\"section-blue given-name\"\n required>\n <mat-error *ngIf=\"form.controls.firstName.hasError('required') && form.controls.firstName.dirty\"\n translate>ERROR.FIELD_REQUIRED\n </mat-error>\n <mat-error *ngIf=\"form.controls.firstName.hasError('minlength') && form.controls.firstName.dirty\">\n <span>{{'ERROR.FIELD_MIN_LENGTH' | translate: {minLength: 2} }}</span>\n </mat-error>\n </mat-form-field>\n\n\n <!-- Additional fields -->\n <ng-container *ngFor=\"let definition of additionalFields\">\n <app-form-field [definition]=\"definition\"\n [formControlName]=\"definition.key\"\n [required]=\"definition.extra && definition.extra.account && definition.extra.account.required || false\">\n </app-form-field>\n </ng-container>\n\n <h3 translate>ACCOUNT.USER_DETAILS.TECHNICAL_DIVIDER</h3>\n\n <!-- profile -->\n <mat-form-field>\n <input matInput hidden readonly=\"true\" [placeholder]=\"'ACCOUNT.USER_DETAILS.PROFILE'|translate\"\n formControlName=\"mainProfile\" required>\n <span>{{'USER.PROFILE_ENUM.' + form.controls.mainProfile.value | translate}}</span>\n <mat-error *ngIf=\"form.controls.firstName.hasError('mainProfile') && form.controls.mainProfile.dirty\"\n translate>ERROR.FIELD_REQUIRED\n </mat-error>\n </mat-form-field>\n\n <!-- pubkey -->\n <mat-form-field>\n <input matInput readonly=\"true\" [placeholder]=\"'ACCOUNT.USER_DETAILS.PUBKEY'|translate\" formControlName=\"pubkey\"\n required>\n <mat-error *ngIf=\"form.controls.firstName.hasError('pubkey') && form.controls.firstName.dirty\"\n translate>ERROR.FIELD_REQUIRED\n </mat-error>\n <mat-error *ngIf=\"form.controls.firstName.hasError('pubkey') && form.controls.firstName.dirty\">\n <span translate>ERROR.FIELD_NOT_VALID_PUBKEY</span>\n </mat-error>\n </mat-form-field>\n\n </div>\n </mat-tab>\n\n <!-- TAB: settings -->\n <mat-tab label=\"{{'ACCOUNT.SETTINGS.TITLE'|translate}}\" formGroupName=\"settings\">\n <ng-template mat-tab-label>\n <mat-icon>\n <ion-icon matPrefix slot=\"start\" name=\"settings\"></ion-icon>\n </mat-icon>\n <ion-label translate>ACCOUNT.SETTINGS.TITLE</ion-label>\n </ng-template>\n\n <div class=\"ion-padding\">\n\n <p [innerHTML]=\"'ACCOUNT.SETTINGS.DESCRIPTION'|translate\"></p>\n\n <mat-form-field>\n <mat-select [placeholder]=\"'ACCOUNT.SETTINGS.LOCALE'|translate\" formControlName=\"locale\" required>\n <mat-option *ngFor=\"let item of locales\" [value]=\"item.key\">\n {{item.value}}\n </mat-option>\n </mat-select>\n <mat-error *ngIf=\"settingsForm?.controls.locale.hasError('required') && settingsForm?.controls.locale.dirty\"\n translate>ERROR.FIELD_REQUIRED\n </mat-error>\n </mat-form-field>\n\n <!-- lat/long format-->\n <mat-form-field>\n <mat-select [placeholder]=\"'ACCOUNT.SETTINGS.LAT_LONG_FORMAT'|translate\" formControlName=\"latLongFormat\"\n required>\n <mat-option *ngFor=\"let item of latLongFormats\" [value]=\"item\">\n {{'COMMON.LAT_LONG.' + item + '_PLACEHOLDER'|translate}}\n </mat-option>\n </mat-select>\n <mat-error *ngIf=\"settingsForm?.controls.latLongFormat.hasError('required') && settingsForm?.controls.latLongFormat.dirty\"\n translate>ERROR.FIELD_REQUIRED\n </mat-error>\n </mat-form-field>\n\n </div>\n\n <!-- Options table -->\n <div class=\"options-table\">\n <app-properties-table\n #propertiesTable\n i18nColumnPrefix=\"ACCOUNT.SETTINGS.OPTIONS.\"\n [definitions]=\"optionDefinitions\"\n [canEdit]=\"true\"\n (onDirty)=\"$event ? markAsDirty() : undefined\"\n ></app-properties-table>\n </div>\n\n </mat-tab>\n </mat-tab-group>\n\n\n </form>\n</ion-content>\n\n<ion-footer hidden-xs hidden-sm hidden-mobile>\n <app-form-buttons-bar (onCancel)=\"cancel()\" (onSave)=\"save($event)\" [disabled]=\"!form.dirty || !valid || saving\">\n <!-- error -->\n <ion-item *ngIf=\"error && !mobile\" lines=\"none\">\n <ion-icon color=\"danger\" slot=\"start\" name=\"alert-circle\"></ion-icon>\n <ion-label color=\"danger\" class=\"error\" [innerHTML]=\"error|translate\"></ion-label>\n </ion-item>\n </app-form-buttons-bar>\n</ion-footer>\n", styles: ["mat-tab-group .mat-tab-body-content{padding:var(--ion-grid-padding);display:grid}form{width:100%}form mat-form-field{width:100%}div.options-table{height:calc(100vh - 380px)}\n"] }]
27085
+ args: [{ selector: 'app-account-page', changeDetection: ChangeDetectionStrategy.OnPush, template: "<app-toolbar [title]=\"'ACCOUNT.TITLE'|translate\" color=\"primary\"\n [hasValidate]=\"dirty && !saving\"\n [hasClose]=\"!dirty && !saving\"\n (onValidate)=\"save($event)\"\n [canGoBack]=\"false\"\n (onClose)=\"close($event)\">\n\n <ion-buttons slot=\"end\">\n <!-- loader -->\n <ion-spinner *ngIf=\"loading || saving; else endButtons\"></ion-spinner>\n\n <ng-template #endButtons>\n <!-- refresh button (if online) -->\n <ion-button [matTooltip]=\"'COMMON.BTN_REFRESH'|translate\"\n *ngIf=\"network.online\"\n (click)=\"refresh($event)\">\n <mat-icon slot=\"icon-only\">refresh</mat-icon>\n </ion-button>\n </ng-template>\n </ion-buttons>\n</app-toolbar>\n\n<ion-content>\n\n <!-- error -->\n <ion-item *ngIf=\"error && mobile\" lines=\"none\">\n <ion-icon color=\"danger\" slot=\"start\" name=\"alert-circle\"></ion-icon>\n <ion-label color=\"danger\" class=\"error\" [innerHTML]=\"error|translate\"></ion-label>\n </ion-item>\n\n <form [formGroup]=\"form\" novalidate class=\"form-container\">\n\n <mat-tab-group #tabGroup [(selectedIndex)]=\"selectedTabIndex\" dynamicHeight>\n\n <!-- TAB: user details -->\n <mat-tab label=\"{{'ACCOUNT.USER_DETAILS.TITLE'|translate}}\" class=\"ion-padding\">\n <ng-template mat-tab-label>\n <mat-icon>\n <ion-icon matPrefix slot=\"start\" name=\"person-circle\"></ion-icon>\n </mat-icon>\n <ion-label>{{'ACCOUNT.USER_DETAILS.TITLE'|translate}}</ion-label>\n <ion-icon slot=\"end\" name=\"alert-circle\" color=\"danger\" *ngIf=\"submitted && form.invalid\"></ion-icon>\n </ng-template>\n\n <div class=\"ion-padding\">\n\n <p [innerHTML]=\"'ACCOUNT.USER_DETAILS.DESCRIPTION'|translate\"></p>\n\n <!--h1>Identit\u00E9</h1-->\n\n <!-- Email -->\n <mat-form-field>\n <input matInput [placeholder]=\"'USER.EMAIL'|translate\"\n formControlName=\"email\" autocomplete=\"section-red email\">\n <mat-error *ngIf=\"form.controls.email.hasError('required') && form.controls.email.dirty\" translate>ERROR.FIELD_REQUIRED</mat-error>\n <mat-error *ngIf=\"form.controls.email.hasError('email') && form.controls.email.dirty\">\n <span>{{'ERROR.FIELD_NOT_VALID_EMAIL' | translate }}</span>\n </mat-error>\n </mat-form-field>\n\n <ion-grid *ngIf=\"email.notConfirmed\" class=\"ion-no-padding ion-padding-bottom\">\n <ion-row>\n <ion-col color=\"danger\">\n <ion-icon slot=\"start\" color=\"danger\" name=\"alert-circle\" color=\"danger\"></ion-icon>\n <ion-text [innerHTML]=\"'ACCOUNT.EMAIL_NOT_CONFIRMED_LABEL'|translate\"></ion-text>\n </ion-col>\n </ion-row>\n\n <ion-row style=\"height: 51px;\">\n <ion-col style=\"text-align: right;\">\n <ion-text>\n <small [innerHTML]=\"'ACCOUNT.EMAIL_NOT_RECEIVED_QUESTION'|translate\"></small>\n </ion-text>\n </ion-col>\n <ion-col size=\"auto\">\n <ion-button fill=\"solid\" color=\"secondary\" *ngIf=\"!email.sending\" (click)=\"sendConfirmationEmail($event)\">\n {{'ACCOUNT.BTN_RESEND'|translate}}\n </ion-button>\n <ion-spinner class=\"ion-no-padding\" *ngIf=\"email.sending\"></ion-spinner>\n </ion-col>\n </ion-row>\n\n <ion-row *ngIf=\"email.error && !email.sending\">\n <ion-col>\n <span *ngIf=\"email.error && !email.sending\" [innerHTML]=\"email.error|translate\"></span>\n </ion-col>\n </ion-row>\n </ion-grid>\n\n <!-- Last name -->\n <mat-form-field>\n <input matInput [appAutofocus]=\"true\" [autofocusDelay]=\"500\" [placeholder]=\"'USER.LAST_NAME'|translate\"\n formControlName=\"lastName\"\n autocomplete=\"section-blue family-name\"\n required>\n <mat-error *ngIf=\"form.controls.lastName.hasError('required') && form.controls.lastName.dirty\"\n translate>ERROR.FIELD_REQUIRED\n </mat-error>\n <mat-error *ngIf=\"form.controls.lastName.hasError('minlength') && form.controls.lastName.dirty\">\n <span>{{'ERROR.FIELD_MIN_LENGTH' | translate: {minLength: 2} }}</span>\n </mat-error>\n </mat-form-field>\n\n <!-- First name -->\n <mat-form-field>\n <input matInput [placeholder]=\"'USER.FIRST_NAME'|translate\" formControlName=\"firstName\" autocomplete=\"section-blue given-name\"\n required>\n <mat-error *ngIf=\"form.controls.firstName.hasError('required') && form.controls.firstName.dirty\"\n translate>ERROR.FIELD_REQUIRED\n </mat-error>\n <mat-error *ngIf=\"form.controls.firstName.hasError('minlength') && form.controls.firstName.dirty\">\n <span>{{'ERROR.FIELD_MIN_LENGTH' | translate: {minLength: 2} }}</span>\n </mat-error>\n </mat-form-field>\n\n\n <!-- Additional fields -->\n <ng-container *ngFor=\"let definition of additionalFields\">\n <app-form-field [definition]=\"definition\"\n [formControlName]=\"definition.key\"\n [required]=\"definition.extra && definition.extra.account && definition.extra.account.required || false\">\n </app-form-field>\n </ng-container>\n\n <h3 translate>ACCOUNT.USER_DETAILS.TECHNICAL_DIVIDER</h3>\n\n <!-- profile -->\n <mat-form-field>\n <input matInput hidden readonly=\"true\" [placeholder]=\"'ACCOUNT.USER_DETAILS.PROFILE'|translate\"\n formControlName=\"mainProfile\" required>\n <span>{{'USER.PROFILE_ENUM.' + form.controls.mainProfile.value | translate}}</span>\n <mat-error *ngIf=\"form.controls.firstName.hasError('mainProfile') && form.controls.mainProfile.dirty\"\n translate>ERROR.FIELD_REQUIRED\n </mat-error>\n </mat-form-field>\n\n <!-- pubkey -->\n <mat-form-field>\n <input matInput readonly=\"true\" [placeholder]=\"'ACCOUNT.USER_DETAILS.PUBKEY'|translate\" formControlName=\"pubkey\"\n required>\n <mat-error *ngIf=\"form.controls.firstName.hasError('pubkey') && form.controls.firstName.dirty\"\n translate>ERROR.FIELD_REQUIRED\n </mat-error>\n <mat-error *ngIf=\"form.controls.firstName.hasError('pubkey') && form.controls.firstName.dirty\">\n <span translate>ERROR.FIELD_NOT_VALID_PUBKEY</span>\n </mat-error>\n </mat-form-field>\n\n </div>\n </mat-tab>\n\n <!-- TAB: settings -->\n <mat-tab label=\"{{'ACCOUNT.SETTINGS.TITLE'|translate}}\" formGroupName=\"settings\">\n <ng-template mat-tab-label>\n <mat-icon>\n <ion-icon matPrefix slot=\"start\" name=\"settings\"></ion-icon>\n </mat-icon>\n <ion-label translate>ACCOUNT.SETTINGS.TITLE</ion-label>\n </ng-template>\n\n <div class=\"ion-padding\">\n\n <p [innerHTML]=\"'ACCOUNT.SETTINGS.DESCRIPTION'|translate\"></p>\n\n <mat-form-field>\n <mat-select [placeholder]=\"'ACCOUNT.SETTINGS.LOCALE'|translate\" formControlName=\"locale\" required>\n <mat-option *ngFor=\"let item of locales\" [value]=\"item.key\">\n {{item.value}}\n </mat-option>\n </mat-select>\n <mat-error *ngIf=\"settingsForm?.controls.locale.hasError('required') && settingsForm?.controls.locale.dirty\"\n translate>ERROR.FIELD_REQUIRED\n </mat-error>\n </mat-form-field>\n\n <!-- lat/long format-->\n <mat-form-field>\n <mat-select [placeholder]=\"'ACCOUNT.SETTINGS.LAT_LONG_FORMAT'|translate\" formControlName=\"latLongFormat\"\n required>\n <mat-option *ngFor=\"let item of latLongFormats\" [value]=\"item\">\n {{'COMMON.LAT_LONG.' + item + '_PLACEHOLDER'|translate}}\n </mat-option>\n </mat-select>\n <mat-error *ngIf=\"settingsForm?.controls.latLongFormat.hasError('required') && settingsForm?.controls.latLongFormat.dirty\"\n translate>ERROR.FIELD_REQUIRED\n </mat-error>\n </mat-form-field>\n\n </div>\n\n <!-- Options table -->\n <div class=\"options-table\" *ngIf=\"optionDefinitions | isNotEmptyArray\">\n <app-properties-table\n #propertiesTable\n i18nColumnPrefix=\"ACCOUNT.SETTINGS.OPTIONS.\"\n [definitions]=\"optionDefinitions\"\n [canEdit]=\"true\"\n (onDirty)=\"$event ? markAsDirty() : undefined\"\n ></app-properties-table>\n </div>\n\n </mat-tab>\n </mat-tab-group>\n\n\n </form>\n</ion-content>\n\n<ion-footer hidden-xs hidden-sm hidden-mobile>\n <app-form-buttons-bar (onCancel)=\"cancel()\" (onSave)=\"save($event)\" [disabled]=\"!form.dirty || !valid || saving\">\n <!-- error -->\n <ion-item *ngIf=\"error && !mobile\" lines=\"none\">\n <ion-icon color=\"danger\" slot=\"start\" name=\"alert-circle\"></ion-icon>\n <ion-label color=\"danger\" class=\"error\" [innerHTML]=\"error|translate\"></ion-label>\n </ion-item>\n </app-form-buttons-bar>\n</ion-footer>\n", styles: ["mat-tab-group .mat-tab-body-content{padding:var(--ion-grid-padding);display:grid}form{width:100%}form mat-form-field{width:100%}div.options-table{height:calc(100vh - 380px)}\n"] }]
27065
27086
  }], ctorParameters: function () { return [{ type: i0.Injector }, { type: i1$3.UntypedFormBuilder }, { type: AccountService }, { type: NetworkService }, { type: i1$6.Router }, { type: AccountValidatorService }, { type: ConfigService }, { type: i0.ChangeDetectorRef }, { type: undefined, decorators: [{
27066
27087
  type: Inject,
27067
27088
  args: [APP_LOCALES]
@@ -28447,6 +28468,7 @@ class AppEntityEditor extends AppTabEditor {
28447
28468
  };
28448
28469
  this.settings = injector.get(LocalSettingsService);
28449
28470
  this.errorTranslator = injector.get(FormErrorTranslator);
28471
+ this.routerOutlet = injector.get(IonRouterOutlet);
28450
28472
  this.cd = injector.get(ChangeDetectorRef);
28451
28473
  this.dateFormat = injector.get(DateFormatService);
28452
28474
  this.toastController = injector.get(ToastController);
@@ -28682,40 +28704,17 @@ class AppEntityEditor extends AppTabEditor {
28682
28704
  * Update the route location, and open the next tab
28683
28705
  */
28684
28706
  async updateTabAndRoute(data, opts) {
28685
- this.queryParams = this.queryParams || {};
28707
+ const queryParams = { ...this.queryParams };
28686
28708
  // Open the next tab
28687
28709
  this.updateTabIndex(opts && opts.openTabIndex);
28688
- // Save the opened tab into the queryParams
28689
- this.queryParams.tab = this.selectedTabIndex;
28690
28710
  // Update route location
28691
- if (isNotNil(data?.id)) {
28692
- const queryParams = { ...this.queryParams };
28693
- queryParams[this._pathIdAttribute] = data.id;
28694
- if (this.debug)
28695
- console.debug('[entity-editor] Updating route using params: ', queryParams);
28696
- await this.router.navigate(['.'], {
28697
- relativeTo: this.route,
28698
- queryParams
28699
- });
28700
- }
28701
- // Move to ../new
28702
- else {
28703
- const queryParams = { ...this.queryParams };
28704
- queryParams[this._pathIdAttribute] = 'new';
28705
- if (this.debug)
28706
- console.debug('[entity-editor] Updating route to \'../new\' using params: ', queryParams);
28707
- await this.router.navigate(['..', 'new'], {
28708
- relativeTo: this.route,
28709
- queryParams
28710
- });
28711
- }
28712
- await this.updateRoute(data, this.queryParams);
28711
+ await this.updateRoute(data, { ...queryParams, tab: this.selectedTabIndex });
28713
28712
  }
28714
28713
  /**
28715
28714
  * Update the route location, and open the next tab
28716
28715
  */
28717
28716
  updateTabIndex(tabIndex) {
28718
- if (isNotNil(tabIndex) && tabIndex !== this.selectedTabIndex) {
28717
+ if (isNotNil(tabIndex) && tabIndex >= 0 && tabIndex !== this.selectedTabIndex) {
28719
28718
  this.selectedTabIndex = tabIndex;
28720
28719
  this.markForCheck();
28721
28720
  }
@@ -29005,7 +29004,7 @@ class AppEntityEditor extends AppTabEditor {
29005
29004
  let parentUrl = this.defaultBackHref;
29006
29005
  // Remove query params
29007
29006
  if (withQueryParams !== true && parentUrl && parentUrl.indexOf('?') !== -1) {
29008
- parentUrl = parentUrl.substr(0, parentUrl.indexOf('?'));
29007
+ parentUrl = parentUrl.substring(0, parentUrl.indexOf('?'));
29009
29008
  }
29010
29009
  return parentUrl;
29011
29010
  }
@@ -29031,17 +29030,55 @@ class AppEntityEditor extends AppTabEditor {
29031
29030
  this.markForCheck();
29032
29031
  }
29033
29032
  }
29033
+ /**
29034
+ * Update the route, without reloading the component
29035
+ * @param data
29036
+ * @param queryParams
29037
+ * @protected
29038
+ */
29034
29039
  async updateRoute(data, queryParams) {
29035
- const path = this.computePageUrl(isNotNil(data.id) ? data.id : 'new');
29036
- const commands = (path && typeof path === 'string') ? path.split('/') : path;
29037
- if (isNotEmptyArray(commands)) {
29038
- return await this.router.navigate(commands, {
29039
- replaceUrl: true,
29040
- queryParams: this.queryParams
29041
- });
29040
+ const currId = this.route.snapshot.paramMap.get(this.pathIdAttribute);
29041
+ const futureId = isNotNil(data.id) ? data.id.toString() : 'new';
29042
+ this.queryParams = {
29043
+ ...this.queryParams,
29044
+ ...queryParams
29045
+ };
29046
+ if (currId === futureId) {
29047
+ // Update queryParam only (not the path)
29048
+ if (!equals(this.route.snapshot.queryParams, this.queryParams)) {
29049
+ if (this.debug)
29050
+ console.debug('[entity-editor] Updating route using queryParams: ', queryParams);
29051
+ return await this.router.navigate(['.'], {
29052
+ relativeTo: this.route,
29053
+ queryParams: this.queryParams
29054
+ });
29055
+ }
29042
29056
  }
29043
29057
  else {
29044
- console.warn('Skip page route update. Invalid page path: ', path);
29058
+ // Current route was '/new' => change to '/new?id=:id' (to allow CustomReuseStrategy to detect that route can be reused)
29059
+ if (currId === 'new') {
29060
+ const res = await this.router.navigate(['.'], {
29061
+ relativeTo: this.route,
29062
+ replaceUrl: true,
29063
+ queryParams: {
29064
+ ...this.queryParams,
29065
+ [this.pathIdAttribute]: futureId
29066
+ }
29067
+ });
29068
+ if (!res)
29069
+ return false;
29070
+ }
29071
+ const path = this.computePageUrl(isNotNil(data.id) ? data.id : 'new');
29072
+ const commands = (path && typeof path === 'string') ? path.split('/').slice(1) : path;
29073
+ if (isNotEmptyArray(commands)) {
29074
+ if (this.debug)
29075
+ console.debug('[entity-editor] Updating route to: ' + path);
29076
+ return await this.router.navigate(commands, {
29077
+ replaceUrl: true,
29078
+ queryParams: this.queryParams
29079
+ });
29080
+ }
29081
+ return Promise.reject('Missing page URL');
29045
29082
  }
29046
29083
  }
29047
29084
  }