@sumaris-net/ngx-components 2.18.0-beta5 → 2.18.0-beta6

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 (51) hide show
  1. package/esm2022/public_api.mjs +2 -1
  2. package/esm2022/src/app/core/account/account.page.mjs +1 -2
  3. package/esm2022/src/app/core/auth/auth.form.mjs +1 -2
  4. package/esm2022/src/app/core/form/array/testing/form-array.test.mjs +1 -2
  5. package/esm2022/src/app/core/form/entity/entity-editor-modal.class.mjs +1 -2
  6. package/esm2022/src/app/core/form/entity/entity-editor.class.mjs +1 -2
  7. package/esm2022/src/app/core/form/entity/tab-editor.class.mjs +1 -2
  8. package/esm2022/src/app/core/form/properties/properties.utils.mjs +60 -0
  9. package/esm2022/src/app/core/form/text-popover/text-popover.component.mjs +1 -2
  10. package/esm2022/src/app/core/menu/menu.component.mjs +1 -2
  11. package/esm2022/src/app/core/menu/menu.service.mjs +1 -2
  12. package/esm2022/src/app/core/services/account.service.mjs +3 -3
  13. package/esm2022/src/app/core/services/config.service.mjs +1 -2
  14. package/esm2022/src/app/core/services/model/entity.model.mjs +3 -9
  15. package/esm2022/src/app/core/services/model/peer.model.mjs +11 -2
  16. package/esm2022/src/app/core/services/network.service.mjs +4 -3
  17. package/esm2022/src/app/core/services/platform.service.mjs +1 -2
  18. package/esm2022/src/app/core/services/validator/local-settings.validator.mjs +8 -7
  19. package/esm2022/src/app/core/settings/settings.page.mjs +5 -5
  20. package/esm2022/src/app/core/table/async-table.class.mjs +1 -2
  21. package/esm2022/src/app/core/table/entities-table-datasource.class.mjs +1 -2
  22. package/esm2022/src/app/core/table/table.class.mjs +1 -2
  23. package/esm2022/src/app/shared/form/field.component.mjs +1 -2
  24. package/esm2022/src/app/shared/functions.mjs +1 -2
  25. package/esm2022/src/app/shared/hotkeys/dialog/hotkeys-dialog.component.mjs +3 -3
  26. package/esm2022/src/app/shared/hotkeys/hotkeys.service.mjs +37 -9
  27. package/esm2022/src/app/shared/image/gallery/image-gallery.component.mjs +1 -2
  28. package/esm2022/src/app/shared/material/autocomplete/material.autocomplete.mjs +1 -2
  29. package/esm2022/src/app/shared/material/boolean/material.boolean.mjs +1 -2
  30. package/esm2022/src/app/shared/material/datetime/material.date.mjs +1 -2
  31. package/esm2022/src/app/shared/material/datetime/material.dateshort.mjs +4 -3
  32. package/esm2022/src/app/shared/material/datetime/material.datetime.mjs +1 -2
  33. package/esm2022/src/app/shared/material/duration/material.duration.mjs +1 -2
  34. package/esm2022/src/app/shared/material/latlong/testing/latlong.test.mjs +1 -2
  35. package/esm2022/src/app/shared/material/swipe/material.swipe.mjs +1 -2
  36. package/esm2022/src/app/shared/toolbar/toolbar.mjs +1 -2
  37. package/esm2022/src/app/shared/upload-file/testing/upload-file.testing.mjs +1 -2
  38. package/esm2022/src/app/shared/validator/validators.mjs +1 -2
  39. package/esm2022/src/app/social/job/progression/job-progression.icon.mjs +1 -2
  40. package/esm2022/src/app/social/message/message.modal.mjs +1 -2
  41. package/esm2022/src/app/social/user-event/notification/user-event-notification.icon.mjs +1 -2
  42. package/fesm2022/sumaris-net.ngx-components.mjs +180 -89
  43. package/fesm2022/sumaris-net.ngx-components.mjs.map +1 -1
  44. package/package.json +2 -2
  45. package/public_api.d.ts +1 -0
  46. package/src/app/core/form/properties/properties.utils.d.ts +27 -0
  47. package/src/app/core/services/model/entity.model.d.ts +3 -2
  48. package/src/app/core/services/model/peer.model.d.ts +1 -0
  49. package/src/app/shared/hotkeys/hotkeys.service.d.ts +16 -2
  50. package/src/app/shared/inputs.d.ts +1 -1
  51. package/src/assets/manifest.json +1 -1
@@ -2,7 +2,6 @@ import * as i0 from '@angular/core';
2
2
  import { InjectionToken, Directive, Pipe, Injectable, EventEmitter, Output, Optional, Inject, NgModule, forwardRef, Component, ChangeDetectionStrategy, Input, ViewChildren, HostBinding, HostListener, ElementRef, booleanAttribute, numberAttribute, ViewChild, ANIMATION_MODULE_TYPE, RendererStyleFlags2, CUSTOM_ELEMENTS_SCHEMA, inject, ViewEncapsulation, APP_INITIALIZER, ChangeDetectorRef } from '@angular/core';
3
3
  import { firstValueFrom, shareReplay, tap, of, timer, Subject, merge, delay, isObservable, from, Subscription, BehaviorSubject, fromEvent, noop as noop$a, Observable, forkJoin, defer, timeout, debounceTime as debounceTime$1, distinctUntilChanged as distinctUntilChanged$1, fromEventPattern, interval, combineLatest, mergeMap as mergeMap$1, EMPTY, switchMap as switchMap$1 } from 'rxjs';
4
4
  import { catchError, map, filter, takeUntil, first, switchMap, tap as tap$1, debounceTime, startWith, distinctUntilChanged, mergeMap, skip, finalize, throttleTime, bufferWhen, mapTo, distinctUntilKeyChanged, take } from 'rxjs/operators';
5
- import { setTimeout as setTimeout$1 } from '@rx-angular/cdk/zone-less/browser';
6
5
  import * as i3 from '@angular/common';
7
6
  import { CommonModule, DOCUMENT, Location } from '@angular/common';
8
7
  import { CdkTableModule } from '@angular/cdk/table';
@@ -558,7 +557,7 @@ function setPropertyByPath(obj, path, value) {
558
557
  function sleep(ms) {
559
558
  if (ms <= 0)
560
559
  return Promise.resolve();
561
- return new Promise((resolve) => setTimeout$1(resolve, ms));
560
+ return new Promise((resolve) => setTimeout(resolve, ms));
562
561
  }
563
562
  function round(value) {
564
563
  if (isNotNilOrNaN(value)) {
@@ -3024,7 +3023,7 @@ class SharedAsyncValidators {
3024
3023
  // Clear added validator. Must be done NOW (without delay) because generally a new Job is given just after
3025
3024
  form.clearAsyncValidators();
3026
3025
  // Stop the job, with a delay to let the last execution finished
3027
- setTimeout$1(() => {
3026
+ setTimeout(() => {
3028
3027
  $dispose.next();
3029
3028
  $dispose.unsubscribe();
3030
3029
  }, debounceTime);
@@ -5263,7 +5262,7 @@ class MatDuration {
5263
5262
  set tabindex(value) {
5264
5263
  if (this._tabindex !== value) {
5265
5264
  this._tabindex = value;
5266
- setTimeout$1(() => this.updateTabIndex());
5265
+ setTimeout(() => this.updateTabIndex());
5267
5266
  }
5268
5267
  }
5269
5268
  get tabindex() {
@@ -5415,7 +5414,7 @@ class MatDuration {
5415
5414
  focus() {
5416
5415
  if (!this.matInputs.length)
5417
5416
  return;
5418
- setTimeout$1(() => {
5417
+ setTimeout(() => {
5419
5418
  const elementRef = this.matInputs[0]; // get the first element
5420
5419
  if (isFocusableElement(elementRef)) {
5421
5420
  elementRef.focus();
@@ -5431,7 +5430,7 @@ class MatDuration {
5431
5430
  if (isNil(this._tabindex) || this._tabindex === -1)
5432
5431
  return; // skip
5433
5432
  // Focus to first input
5434
- setTimeout$1(() => {
5433
+ setTimeout(() => {
5435
5434
  this.matInputs.forEach((elementRef, index) => {
5436
5435
  setTabIndex(elementRef, this._tabindex + index);
5437
5436
  });
@@ -5831,7 +5830,7 @@ class MatBooleanField {
5831
5830
  set tabindex(value) {
5832
5831
  if (this._tabindex !== value) {
5833
5832
  this._tabindex = value;
5834
- setTimeout$1(() => this.updateTabIndex());
5833
+ setTimeout(() => this.updateTabIndex());
5835
5834
  }
5836
5835
  }
5837
5836
  get tabindex() {
@@ -5907,7 +5906,7 @@ class MatBooleanField {
5907
5906
  this.checkboxButton.checked = value;
5908
5907
  }
5909
5908
  }
5910
- setTimeout$1(() => {
5909
+ setTimeout(() => {
5911
5910
  this.updateFakeInput();
5912
5911
  this.updateTabIndex();
5913
5912
  });
@@ -5947,7 +5946,7 @@ class MatBooleanField {
5947
5946
  this._focused = true;
5948
5947
  this._onTouchedCallback();
5949
5948
  this.markForCheck();
5950
- setTimeout$1(() => {
5949
+ setTimeout(() => {
5951
5950
  // Add a blur listener on each inputs
5952
5951
  const inputElements = this.inputsElements;
5953
5952
  inputElements.forEach((el) => (el.onblur = (e) => {
@@ -7163,7 +7162,7 @@ class MatAutocompleteField {
7163
7162
  if (!event || event.defaultPrevented)
7164
7163
  return;
7165
7164
  // Need a timeout to prevent early blur event without triggering formChange event
7166
- setTimeout$1(() => {
7165
+ setTimeout(() => {
7167
7166
  // Ignore event from mat-option
7168
7167
  if ((event.relatedTarget instanceof HTMLElement && event.relatedTarget.tagName === 'MAT-OPTION') ||
7169
7168
  // Or autocomplete panel is open because event.relatedTarget is null (cf. https://github.com/angular/components/issues/24182)
@@ -8350,7 +8349,7 @@ class MatDate {
8350
8349
  focus() {
8351
8350
  if (!this._matInput)
8352
8351
  return;
8353
- setTimeout$1(() => {
8352
+ setTimeout(() => {
8354
8353
  if (isFocusableElement(this._matInput.nativeElement)) {
8355
8354
  this._matInput.nativeElement.focus();
8356
8355
  }
@@ -8521,7 +8520,7 @@ class MatDate {
8521
8520
  if (isNil(this._tabindex) || this._tabindex === -1)
8522
8521
  return; // skip
8523
8522
  // Focus to input
8524
- setTimeout$1(() => {
8523
+ setTimeout(() => {
8525
8524
  setTabIndex(this._matInput, this._tabindex);
8526
8525
  this.markForCheck();
8527
8526
  });
@@ -8821,7 +8820,7 @@ class MatDateTime {
8821
8820
  const matInput = this._matInputs.first;
8822
8821
  if (!matInput)
8823
8822
  return;
8824
- setTimeout$1(() => {
8823
+ setTimeout(() => {
8825
8824
  if (isFocusableElement(matInput.nativeElement)) {
8826
8825
  matInput.nativeElement.focus();
8827
8826
  }
@@ -9164,7 +9163,7 @@ class MatDateTime {
9164
9163
  if (isNil(this._tabindex) || this._tabindex === -1)
9165
9164
  return; // skip
9166
9165
  // Focus to first input
9167
- setTimeout$1(() => {
9166
+ setTimeout(() => {
9168
9167
  this._matInputs.forEach((elementRef, index) => {
9169
9168
  setTabIndex(elementRef, this._tabindex + index);
9170
9169
  });
@@ -9436,7 +9435,7 @@ class MatDateShort {
9436
9435
  focus() {
9437
9436
  if (!this._matInput)
9438
9437
  return;
9439
- setTimeout$1(() => {
9438
+ setTimeout(() => {
9440
9439
  if (isFocusableElement(this._matInput.nativeElement)) {
9441
9440
  this._matInput.nativeElement.focus();
9442
9441
  }
@@ -9512,7 +9511,9 @@ class MatDateShort {
9512
9511
  updateTranslations(translations) {
9513
9512
  const datePattern = translations['COMMON.DATE_YEAR_PATTERN'] !== 'COMMON.DATE_YEAR_PATTERN' ? translations['COMMON.DATE_YEAR_PATTERN'] : 'YYYY';
9514
9513
  this.updatePattern(datePattern);
9515
- const yearPlaceholder = translations['COMMON.DATE_YEAR_PLACEHOLDER'] !== 'COMMON.DATE_YEAR_PLACEHOLDER' ? translations['COMMON.DATE_YEAR_PLACEHOLDER'] : datePattern.toLowerCase();
9514
+ const yearPlaceholder = translations['COMMON.DATE_YEAR_PLACEHOLDER'] !== 'COMMON.DATE_YEAR_PLACEHOLDER'
9515
+ ? translations['COMMON.DATE_YEAR_PLACEHOLDER']
9516
+ : datePattern.toLowerCase();
9516
9517
  this.updateMaskOptions(yearPlaceholder);
9517
9518
  }
9518
9519
  updatePattern(pattern) {
@@ -9594,7 +9595,7 @@ class MatDateShort {
9594
9595
  if (isNil(this._tabindex) || this._tabindex === -1)
9595
9596
  return; // skip
9596
9597
  // Focus to input
9597
- setTimeout$1(() => {
9598
+ setTimeout(() => {
9598
9599
  setTabIndex(this._matInput, this._tabindex);
9599
9600
  this.markForCheck();
9600
9601
  });
@@ -9761,7 +9762,7 @@ class MatSwipeField {
9761
9762
  set tabindex(value) {
9762
9763
  if (this._tabindex !== value) {
9763
9764
  this._tabindex = value;
9764
- setTimeout$1(() => this.updateTabIndex());
9765
+ setTimeout(() => this.updateTabIndex());
9765
9766
  }
9766
9767
  }
9767
9768
  get tabindex() {
@@ -9843,7 +9844,7 @@ class MatSwipeField {
9843
9844
  focus() {
9844
9845
  // show slides component
9845
9846
  this.showSlides = true;
9846
- setTimeout$1(() => {
9847
+ setTimeout(() => {
9847
9848
  if (this.prevButton) {
9848
9849
  this.prevButton.focus();
9849
9850
  }
@@ -9886,7 +9887,7 @@ class MatSwipeField {
9886
9887
  this._value = value;
9887
9888
  this.showSlides = isNotNil(this._value);
9888
9889
  this.updateSlides();
9889
- setTimeout$1(() => this.updateTabIndex());
9890
+ setTimeout(() => this.updateTabIndex());
9890
9891
  }
9891
9892
  this._writing = false;
9892
9893
  this.markForCheck();
@@ -9899,10 +9900,10 @@ class MatSwipeField {
9899
9900
  this._value = undefined;
9900
9901
  this.formControl.patchValue(null, { emitEvent: false });
9901
9902
  this.showSlides = false;
9902
- setTimeout$1(() => {
9903
+ setTimeout(() => {
9903
9904
  this.updateTabIndex();
9904
9905
  this.slideTo(0);
9905
- setTimeout$1(() => {
9906
+ setTimeout(() => {
9906
9907
  this._writing = false;
9907
9908
  }, 100);
9908
9909
  });
@@ -11112,6 +11113,65 @@ class TreeItemEntityUtils {
11112
11113
  }
11113
11114
  }
11114
11115
 
11116
+ class AppPropertiesUtils {
11117
+ /**
11118
+ * Converts an array of Property objects to an object map.
11119
+ *
11120
+ * @param {Property[]} [sources] - The array of Property objects to convert.
11121
+ * @param {Object} [opts] - Options for the conversion.
11122
+ * @param {boolean} [opts.omitNilOrBlank] - If set to true, properties with nil or blank values will be omitted from the resulting object.
11123
+ * @return {PropertiesMap} The resulting object map where keys are property keys and values are property values.
11124
+ */
11125
+ static arrayAsObject(sources, opts) {
11126
+ return ((sources || [])
11127
+ // Serialize each item
11128
+ .map(AppPropertyUtils.asObject)
11129
+ // Fill a JSON object
11130
+ .reduce((res, item) => {
11131
+ if (isNilOrBlank(item.key))
11132
+ return res;
11133
+ if (isNilOrBlank(item.value) && opts?.omitNilOrBlank !== false)
11134
+ return res;
11135
+ res[item.key] = item.value;
11136
+ return res;
11137
+ }, {}));
11138
+ }
11139
+ /**
11140
+ * Converts an object into an array of properties.
11141
+ *
11142
+ * @param {PropertiesMap} [source] - The source object containing properties to convert.
11143
+ * @return {Property[]} An array of properties derived from the source object.
11144
+ */
11145
+ static arrayFromObject(source) {
11146
+ if (Array.isArray(source))
11147
+ return source; // Already an array
11148
+ return Object.getOwnPropertyNames(source || {}).map((key) => ({
11149
+ key,
11150
+ value: source[key],
11151
+ }));
11152
+ }
11153
+ }
11154
+ class AppPropertyUtils {
11155
+ static asObject(source) {
11156
+ if (!source)
11157
+ return undefined;
11158
+ // Serialize key (WARNING: can be an object, when using autocomplete field to edit a key - see AppPropertiesForm)
11159
+ const key = source.key?.key ?? source.key;
11160
+ // Serialize the value
11161
+ let value = source.value;
11162
+ if (Array.isArray(value)) {
11163
+ value = value
11164
+ .map((v) => v?.id ?? v)
11165
+ .filter(isNotNil)
11166
+ .join(',');
11167
+ }
11168
+ else {
11169
+ value = value?.id ?? value;
11170
+ }
11171
+ return { key, value };
11172
+ }
11173
+ }
11174
+
11115
11175
  function entityToString(obj, properties) {
11116
11176
  return (obj && obj.id && joinPropertiesPath(obj, properties || ['name'])) || undefined;
11117
11177
  }
@@ -11195,14 +11255,7 @@ class EntityUtils {
11195
11255
  value: source[key],
11196
11256
  }));
11197
11257
  }
11198
- static getPropertyArrayAsObject(source) {
11199
- return (source || []).reduce((res, item) => {
11200
- // Warning: when using <app-properties-form> key can be an object, used by autocomplete field
11201
- const key = typeof item.key === 'object' ? item.key?.key : item.key;
11202
- res[key] = item.value;
11203
- return res;
11204
- }, {});
11205
- }
11258
+ static getPropertyArrayAsObject = AppPropertiesUtils.arrayAsObject;
11206
11259
  static copyIdAndUpdateDate(source, target) {
11207
11260
  if (!source)
11208
11261
  return;
@@ -11576,6 +11629,9 @@ let Peer = class Peer extends Entity {
11576
11629
  .filter(isNotNilOrBlank);
11577
11630
  return [noTrailingSlash(this.fromObject(peer).url)].concat(...paths).join('/');
11578
11631
  }
11632
+ static equals(p1, p2) {
11633
+ return p1 && p2 && Peer_1.fromObject(p1).equals(p2);
11634
+ }
11579
11635
  dns;
11580
11636
  ipv4;
11581
11637
  ipv6;
@@ -11606,7 +11662,13 @@ let Peer = class Peer extends Entity {
11606
11662
  this.path = source.path || '';
11607
11663
  }
11608
11664
  equals(other) {
11609
- return super.equals(other) && this.pubkey === other.pubkey && this.url === other.url;
11665
+ return (
11666
+ // Same entity (by id)
11667
+ (isNotNil(this.id) && isNotNil(other.id) && this.id === other.id) ||
11668
+ // Same pubkey (if defined)
11669
+ ((!this.pubkey || !other.pubkey || this.pubkey === other.pubkey) &&
11670
+ // Same url
11671
+ this.url === other.url));
11610
11672
  }
11611
11673
  /**
11612
11674
  * Return the peer URL (without trailing slash)
@@ -13294,7 +13356,7 @@ class AppFormField {
13294
13356
  return;
13295
13357
  this._onDefinitionChanged(this._definition);
13296
13358
  if (this.autocompleteField) {
13297
- setTimeout$1(() => this.autocompleteField?.reloadItems(value));
13359
+ setTimeout(() => this.autocompleteField?.reloadItems(value));
13298
13360
  }
13299
13361
  }
13300
13362
  /* -- protected method -- */
@@ -13372,7 +13434,7 @@ class AppFormField {
13372
13434
  }
13373
13435
  updateTabIndex(timeout) {
13374
13436
  if (this.tabindex && this.tabindex !== -1) {
13375
- setTimeout$1(() => {
13437
+ setTimeout(() => {
13376
13438
  const element = asInputElement(this.matInput);
13377
13439
  if (element) {
13378
13440
  element.tabIndex = this.tabindex;
@@ -13697,16 +13759,17 @@ class HotkeysDialogComponent {
13697
13759
  this.hotkeys = Array.from(this.data);
13698
13760
  }
13699
13761
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.8", ngImport: i0, type: HotkeysDialogComponent, deps: [{ token: MAT_DIALOG_DATA }], target: i0.ɵɵFactoryTarget.Component });
13700
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.8", type: HotkeysDialogComponent, selector: "ng-component", ngImport: i0, template: "<table>\n <tbody>\n <tr *ngFor=\"let keys of hotkeys\">\n <td>{{ keys[1] | translate }}</td>\n\n <td class=\"text-right\">\n <kbd>{{ keys[0] }}</kbd>\n </td>\n </tr>\n </tbody>\n</table>\n", styles: [":host table{border-collapse:collapse;width:100%;margin-bottom:1rem;color:#212529}:host th{font-weight:500;text-align:left;vertical-align:bottom;padding:.75rem;border-top:1px solid #dee2e6;border-bottom:2px solid #dee2e6}:host td{padding:.75rem;vertical-align:top;border-top:1px solid #dee2e6;padding-left:0}:host kbd{margin-right:6px;background-color:#fafbfc;border:1px solid #d1d5da;border-bottom-color:#c6cbd1;border-radius:3px;box-shadow:inset 0 -1px #c6cbd1;color:#444d56;display:inline-block;font-size:12px;line-height:10px;padding:3px 5px;vertical-align:middle}\n"], dependencies: [{ kind: "directive", type: i3.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "pipe", type: i1$1.TranslatePipe, name: "translate" }] });
13762
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.8", type: HotkeysDialogComponent, selector: "ng-component", ngImport: i0, template: "<table class=\"ion-padding\">\n <tbody>\n <tr *ngFor=\"let keys of hotkeys\">\n <td>{{ keys[1] | translate }}</td>\n\n <td class=\"text-right\">\n <kbd>{{ keys[0] }}</kbd>\n </td>\n </tr>\n </tbody>\n</table>\n", styles: [":host table{border-collapse:collapse;width:100%;color:#212529}:host th{font-weight:500;text-align:left;vertical-align:bottom;padding:.75rem;border-top:1px solid #dee2e6;border-bottom:2px solid #dee2e6}:host td{vertical-align:top;border-top:1px solid #dee2e6;padding:.75rem}:host kbd{margin-right:6px;background-color:#fafbfc;border:1px solid #d1d5da;border-bottom-color:#c6cbd1;border-radius:3px;box-shadow:inset 0 -1px #c6cbd1;color:#444d56;display:inline-block;font-size:12px;line-height:10px;padding:3px 5px;vertical-align:middle}\n"], dependencies: [{ kind: "directive", type: i3.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "pipe", type: i1$1.TranslatePipe, name: "translate" }] });
13701
13763
  }
13702
13764
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.8", ngImport: i0, type: HotkeysDialogComponent, decorators: [{
13703
13765
  type: Component,
13704
- args: [{ template: "<table>\n <tbody>\n <tr *ngFor=\"let keys of hotkeys\">\n <td>{{ keys[1] | translate }}</td>\n\n <td class=\"text-right\">\n <kbd>{{ keys[0] }}</kbd>\n </td>\n </tr>\n </tbody>\n</table>\n", styles: [":host table{border-collapse:collapse;width:100%;margin-bottom:1rem;color:#212529}:host th{font-weight:500;text-align:left;vertical-align:bottom;padding:.75rem;border-top:1px solid #dee2e6;border-bottom:2px solid #dee2e6}:host td{padding:.75rem;vertical-align:top;border-top:1px solid #dee2e6;padding-left:0}:host kbd{margin-right:6px;background-color:#fafbfc;border:1px solid #d1d5da;border-bottom-color:#c6cbd1;border-radius:3px;box-shadow:inset 0 -1px #c6cbd1;color:#444d56;display:inline-block;font-size:12px;line-height:10px;padding:3px 5px;vertical-align:middle}\n"] }]
13766
+ args: [{ template: "<table class=\"ion-padding\">\n <tbody>\n <tr *ngFor=\"let keys of hotkeys\">\n <td>{{ keys[1] | translate }}</td>\n\n <td class=\"text-right\">\n <kbd>{{ keys[0] }}</kbd>\n </td>\n </tr>\n </tbody>\n</table>\n", styles: [":host table{border-collapse:collapse;width:100%;color:#212529}:host th{font-weight:500;text-align:left;vertical-align:bottom;padding:.75rem;border-top:1px solid #dee2e6;border-bottom:2px solid #dee2e6}:host td{vertical-align:top;border-top:1px solid #dee2e6;padding:.75rem}:host kbd{margin-right:6px;background-color:#fafbfc;border:1px solid #d1d5da;border-bottom-color:#c6cbd1;border-radius:3px;box-shadow:inset 0 -1px #c6cbd1;color:#444d56;display:inline-block;font-size:12px;line-height:10px;padding:3px 5px;vertical-align:middle}\n"] }]
13705
13767
  }], ctorParameters: () => [{ type: undefined, decorators: [{
13706
13768
  type: Inject,
13707
13769
  args: [MAT_DIALOG_DATA]
13708
13770
  }] }] });
13709
13771
 
13772
+ const APP_HOTKEYS_CONFIG = new InjectionToken('HotKeysConfig');
13710
13773
  class Hotkeys {
13711
13774
  eventManager;
13712
13775
  dialog;
@@ -13719,14 +13782,24 @@ class Hotkeys {
13719
13782
  element: this._document,
13720
13783
  preventDefault: true,
13721
13784
  };
13722
- constructor(eventManager, dialog, modalController, popoverController) {
13785
+ _dialogRef;
13786
+ _config;
13787
+ constructor(eventManager, dialog, modalController, popoverController, config) {
13723
13788
  this.eventManager = eventManager;
13724
13789
  this.dialog = dialog;
13725
13790
  this.modalController = modalController;
13726
13791
  this.popoverController = popoverController;
13727
- if (this._debug)
13728
- console.debug('[hotkeys] Starting hotkeys service... Press Shift+? to get help modal.');
13729
- this.addShortcut({ keys: 'shift.?' }).subscribe(() => this.openHelpModal());
13792
+ this._config = {
13793
+ enableHelpModal: true,
13794
+ openHelpModalShortcut: 'F1',
13795
+ ...config,
13796
+ };
13797
+ // Add shortcut to open help modal
13798
+ if (this._config.enableHelpModal) {
13799
+ this.addShortcut({ keys: this._config.openHelpModalShortcut }).subscribe(() => this.openHelpModal());
13800
+ if (this._debug)
13801
+ console.debug(`[hotkeys] Starting hotkeys service... Press ${this._config.openHelpModalShortcut} to get help modal.`);
13802
+ }
13730
13803
  // For DEV only
13731
13804
  //this._debug = !environment.production;
13732
13805
  }
@@ -13767,12 +13840,23 @@ class Hotkeys {
13767
13840
  });
13768
13841
  }
13769
13842
  openHelpModal() {
13770
- this.dialog.open(HotkeysDialogComponent, {
13843
+ if (this._dialogRef) {
13844
+ this._dialogRef.close(true);
13845
+ return;
13846
+ }
13847
+ this._dialogRef = this.dialog.open(HotkeysDialogComponent, {
13771
13848
  width: '500px',
13772
13849
  data: this._hotkeys,
13773
13850
  });
13851
+ this._dialogRef
13852
+ .afterClosed()
13853
+ .pipe(first())
13854
+ .subscribe(() => {
13855
+ // Forget the dialog ref
13856
+ this._dialogRef = null;
13857
+ });
13774
13858
  }
13775
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.8", ngImport: i0, type: Hotkeys, deps: [{ token: i1$2.EventManager }, { token: i2$4.MatDialog }, { token: i2$1.ModalController }, { token: i2$1.PopoverController }], target: i0.ɵɵFactoryTarget.Injectable });
13859
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.8", ngImport: i0, type: Hotkeys, deps: [{ token: i1$2.EventManager }, { token: i2$4.MatDialog }, { token: i2$1.ModalController }, { token: i2$1.PopoverController }, { token: APP_HOTKEYS_CONFIG, optional: true }], target: i0.ɵɵFactoryTarget.Injectable });
13776
13860
  static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.8", ngImport: i0, type: Hotkeys, providedIn: 'root' });
13777
13861
  }
13778
13862
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.8", ngImport: i0, type: Hotkeys, decorators: [{
@@ -13780,7 +13864,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.8", ngImpor
13780
13864
  args: [{
13781
13865
  providedIn: 'root',
13782
13866
  }]
13783
- }], ctorParameters: () => [{ type: i1$2.EventManager }, { type: i2$4.MatDialog }, { type: i2$1.ModalController }, { type: i2$1.PopoverController }] });
13867
+ }], ctorParameters: () => [{ type: i1$2.EventManager }, { type: i2$4.MatDialog }, { type: i2$1.ModalController }, { type: i2$1.PopoverController }, { type: undefined, decorators: [{
13868
+ type: Optional
13869
+ }, {
13870
+ type: Inject,
13871
+ args: [APP_HOTKEYS_CONFIG]
13872
+ }] }] });
13784
13873
 
13785
13874
  class SharedHotkeysModule {
13786
13875
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.8", ngImport: i0, type: SharedHotkeysModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
@@ -16434,7 +16523,7 @@ class TextPopover {
16434
16523
  this.enable();
16435
16524
  }
16436
16525
  ngAfterViewInit() {
16437
- setTimeout$1(() => this.form.setValue({ text: this.text }), 0);
16526
+ setTimeout(() => this.form.setValue({ text: this.text }), 0);
16438
16527
  }
16439
16528
  async onValidate(event) {
16440
16529
  await waitWhilePending(this.form);
@@ -16887,7 +16976,9 @@ class NetworkService extends StartableObservableService {
16887
16976
  return this.dataSubject.value?.clone();
16888
16977
  }
16889
16978
  set peer(peer) {
16890
- this.restart(peer);
16979
+ if (!Peer.equals(this.peer, peer)) {
16980
+ this.restart(peer);
16981
+ }
16891
16982
  }
16892
16983
  get connectionTimeout() {
16893
16984
  return this._connectionTimeout;
@@ -17029,7 +17120,7 @@ class NetworkService extends StartableObservableService {
17029
17120
  if (online) {
17030
17121
  // Call success callback (async)
17031
17122
  if (opts && opts.onRetrySuccess) {
17032
- setTimeout$1(opts.onRetrySuccess);
17123
+ setTimeout(opts.onRetrySuccess);
17033
17124
  }
17034
17125
  return true;
17035
17126
  }
@@ -19646,7 +19737,7 @@ class AccountService extends BaseGraphqlService {
19646
19737
  this.onAuthTokenChange.subscribe((token) => this.graphql.setAuthToken(token));
19647
19738
  this.onAuthBasicChange.subscribe((basic) => this.graphql.setAuthBasic(basic));
19648
19739
  // Force network to wait account service, after getting connection to the peer
19649
- this.network.on('beforeTryOnlineFinish', async (online) => {
19740
+ this.registerSubscription(this.network.on('beforeTryOnlineFinish', async (online) => {
19650
19741
  // If online, wait a full restart, because it can force offline mode
19651
19742
  if (online && (!this.started || this.isLogin())) {
19652
19743
  console.debug('[account] Force networkService.tryOnline() to wait, that graphql and account service is restarted...');
@@ -19654,7 +19745,7 @@ class AccountService extends BaseGraphqlService {
19654
19745
  if (!this.started)
19655
19746
  await this.ready();
19656
19747
  }
19657
- });
19748
+ }));
19658
19749
  }
19659
19750
  async ngOnStart() {
19660
19751
  await Promise.all([
@@ -21013,7 +21104,7 @@ class ConfigService extends BaseGraphqlService {
21013
21104
  }
21014
21105
  // Save it into local storage, for next startup
21015
21106
  if (data) {
21016
- setTimeout$1(() => this.storeLocally(data), 2000);
21107
+ setTimeout(() => this.storeLocally(data), 2000);
21017
21108
  }
21018
21109
  // If not loaded remotely: try to restore it
21019
21110
  else {
@@ -21338,7 +21429,7 @@ class PlatformService extends StartableService {
21338
21429
  }));
21339
21430
  if (this._mobile) {
21340
21431
  // Hide the splashscreen (if mobile) - after 1s - and play start sound
21341
- setTimeout$1(async () => {
21432
+ setTimeout(async () => {
21342
21433
  await SplashScreen.hide();
21343
21434
  // Play startup sound
21344
21435
  this.audioProvider.playStartupSound();
@@ -21994,7 +22085,7 @@ class ToolbarComponent {
21994
22085
  async toggleSearchBar() {
21995
22086
  this.showSearchBar = !this.showSearchBar;
21996
22087
  if (this.showSearchBar && this.searchbar) {
21997
- setTimeout$1(() => {
22088
+ setTimeout(() => {
21998
22089
  this.searchbar.setFocus();
21999
22090
  this.markForCheck();
22000
22091
  }, 300);
@@ -22046,7 +22137,7 @@ class ToolbarComponent {
22046
22137
  return;
22047
22138
  // Distinguish simple and double tap
22048
22139
  this._closeTapCount = event.tapCount;
22049
- setTimeout$1(() => {
22140
+ setTimeout(() => {
22050
22141
  // Event is obsolete (a new tap event occur)
22051
22142
  if (event.tapCount < this._closeTapCount) {
22052
22143
  // Ignore event
@@ -22068,7 +22159,7 @@ class ToolbarComponent {
22068
22159
  // Distinguish simple and double tap
22069
22160
  else {
22070
22161
  this._validateTapCount = event.tapCount;
22071
- setTimeout$1(() => {
22162
+ setTimeout(() => {
22072
22163
  // Event is obsolete (a new tap event occur)
22073
22164
  if (event.tapCount < this._validateTapCount) {
22074
22165
  // Ignore event
@@ -23975,7 +24066,7 @@ class AppImageGalleryComponent {
23975
24066
  this.onAfterEditRow.emit(row);
23976
24067
  }
23977
24068
  // Hide the toolbar, because the focus have been given to the event's origin (the edit button)
23978
- setTimeout$1(() => this.hideCardToolbar(cardToolbar), 750);
24069
+ setTimeout(() => this.hideCardToolbar(cardToolbar), 750);
23979
24070
  }
23980
24071
  showCardToolbar(cardToolbar) {
23981
24072
  const el = cardToolbar['el'];
@@ -26167,7 +26258,7 @@ class MenuService extends StartableObservableService {
26167
26258
  handler: () => {
26168
26259
  this.accountService.logout();
26169
26260
  // Back to home
26170
- setTimeout$1(() => this.navController.navigateRoot('/'), 100);
26261
+ setTimeout(() => this.navController.navigateRoot('/'), 100);
26171
26262
  },
26172
26263
  },
26173
26264
  ],
@@ -26694,7 +26785,7 @@ class MenuComponent {
26694
26785
  this.splitPane.when = value;
26695
26786
  this.detectChanges();
26696
26787
  // Propagate to the menu service
26697
- setTimeout$1(() => this.menuService.setSplitPaneShowWhen(value), 200);
26788
+ setTimeout(() => this.menuService.setSplitPaneShowWhen(value), 200);
26698
26789
  }
26699
26790
  }
26700
26791
  toggleSplitPaneShow(event) {
@@ -26734,7 +26825,7 @@ class MenuComponent {
26734
26825
  }
26735
26826
  markAsLoaded(opts) {
26736
26827
  if (this.loading) {
26737
- setTimeout$1(() => {
26828
+ setTimeout(() => {
26738
26829
  this.loading = false;
26739
26830
  if (!opts || opts.emitEvent !== false)
26740
26831
  this.markForCheck();
@@ -27959,7 +28050,7 @@ class AppAuthForm extends AppForm {
27959
28050
  const data = this.form.value;
27960
28051
  this.showPwd = false; // Hide password
27961
28052
  this.error = null; // Reset error
27962
- setTimeout$1(() => this.onSubmit.emit({
28053
+ setTimeout(() => this.onSubmit.emit({
27963
28054
  username: data.username,
27964
28055
  password: data.password,
27965
28056
  offline: data.offline,
@@ -27967,7 +28058,7 @@ class AppAuthForm extends AppForm {
27967
28058
  }
27968
28059
  register() {
27969
28060
  this.onCancel.emit();
27970
- setTimeout$1(async () => {
28061
+ setTimeout(async () => {
27971
28062
  const modal = await this.modalCtrl.create({
27972
28063
  component: RegisterModal,
27973
28064
  backdropDismiss: false,
@@ -27978,7 +28069,7 @@ class AppAuthForm extends AppForm {
27978
28069
  resetPassword() {
27979
28070
  this.onCancel.emit();
27980
28071
  const data = this.form.value;
27981
- setTimeout$1(async () => {
28072
+ setTimeout(async () => {
27982
28073
  const modal = await this.modalCtrl.create({
27983
28074
  component: AppResetPasswordModal,
27984
28075
  componentProps: {
@@ -28604,15 +28695,16 @@ class LocalSettingsValidatorService extends AppValidatorService {
28604
28695
  });
28605
28696
  }
28606
28697
  getPropertiesArray(data) {
28607
- const propertiesFormArray = new AppFormArray((value) => this.propertyValidator.getFormGroup(value, { valueMaxLength: 2000 }), (v1, v2) => this.propertyValidator.equals(v1, v2), (value) => this.propertyValidator.isEmpty(value), {
28698
+ const fromArray = new AppFormArray((value) => this.propertyValidator.getFormGroup(value, { valueMaxLength: 2000 }), (v1, v2) => this.propertyValidator.equals(v1, v2), (value) => this.propertyValidator.isEmpty(value), {
28608
28699
  allowReuseControls: false,
28609
28700
  allowEmptyArray: true,
28610
28701
  });
28611
28702
  if (data) {
28612
- const values = EntityUtils.getMapAsArray(data);
28613
- propertiesFormArray.patchValue(values);
28703
+ const values = AppPropertiesUtils.arrayFromObject(data);
28704
+ if (isNotEmptyArray(values))
28705
+ fromArray.patchValue(values);
28614
28706
  }
28615
- return propertiesFormArray;
28707
+ return fromArray;
28616
28708
  }
28617
28709
  getPropertyFormGroup(data) {
28618
28710
  return this.formBuilder.group({
@@ -29091,7 +29183,7 @@ class SettingsPage extends AppForm {
29091
29183
  // Apply inheritance
29092
29184
  this.setAccountInheritance(data.accountInheritance, { emitEvent: false });
29093
29185
  // Add a delay, because of option menu that is always opened after save!!
29094
- setTimeout$1(() => {
29186
+ setTimeout(() => {
29095
29187
  this.saving = false;
29096
29188
  this.markForCheck();
29097
29189
  }, 400);
@@ -29181,7 +29273,7 @@ class SettingsPage extends AppForm {
29181
29273
  }
29182
29274
  async getValue() {
29183
29275
  const json = this.form.value;
29184
- json.properties = EntityUtils.getPropertyArrayAsObject(json.properties);
29276
+ json.properties = AppPropertiesUtils.arrayAsObject(json.properties);
29185
29277
  // Override properties from account
29186
29278
  if (json.accountInheritance && this.isLogin) {
29187
29279
  const account = this.accountService.account;
@@ -29235,11 +29327,11 @@ class SettingsPage extends AppForm {
29235
29327
  this.cd.markForCheck();
29236
29328
  }
29237
29329
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.8", ngImport: i0, type: SettingsPage, deps: [{ token: i0.Injector }, { token: PlatformService }, { token: i2$1.NavController }, { token: LocalSettingsValidatorService }, { token: i2$1.AlertController }, { token: i1$1.TranslateService }, { token: i1$3.UntypedFormBuilder }, { token: AccountService }, { token: LocalSettingsService }, { token: i0.ChangeDetectorRef }, { token: NetworkService }, { token: APP_LOCALES }, { token: APP_SETTINGS_MENU_ITEMS, optional: true }], target: i0.ɵɵFactoryTarget.Component });
29238
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.8", type: SettingsPage, selector: "page-settings", providers: [{ provide: ValidatorService, useExisting: LocalSettingsValidatorService }], viewQueries: [{ propertyName: "propertiesForm", first: true, predicate: ["propertiesForm"], descendants: true, static: true }], usesInheritance: true, ngImport: i0, template: "<app-toolbar\n [title]=\"'SETTINGS.TITLE' | translate\"\n color=\"primary\"\n [hasValidate]=\"dirty && !saving\"\n [hasClose]=\"!dirty && !saving\"\n (onValidate)=\"save($event)\"\n (onClose)=\"close($event)\"\n>\n <ion-buttons slot=\"end\">\n <!-- options menu -->\n <ion-button [matMenuTriggerFor]=\"optionsMenu\">\n <mat-icon slot=\"icon-only\">more_vert</mat-icon>\n </ion-button>\n </ion-buttons>\n</app-toolbar>\n\n<!-- Options menu -->\n<mat-menu #optionsMenu=\"matMenu\">\n <!-- Clear cache -->\n <button mat-menu-item [disabled]=\"saving\" (click)=\"clearCache($event)\">\n <mat-icon><ion-icon name=\"trash-outline\"></ion-icon></mat-icon>\n <ion-label translate>SETTINGS.BTN_CLEAR_CACHE</ion-label>\n </button>\n\n <!-- Reset -->\n <button mat-menu-item [disabled]=\"saving || !dirty\" (click)=\"cancel($event)\">\n <mat-icon><ion-icon name=\"refresh\"></ion-icon></mat-icon>\n <mat-label translate>COMMON.BTN_RESET</mat-label>\n </button>\n\n <!-- additional items -->\n @if (!loading) {\n @for (item of menuItems; track item) {\n @if (item.path) {\n <a mat-menu-item class=\"{{ item.cssClass }} {{ item.color }}\" (click)=\"executeAction($event, item)\">\n <mat-icon *ngIf=\"item.icon\"><ion-icon [name]=\"item.icon\"></ion-icon></mat-icon>\n <mat-icon *ngIf=\"item.matIcon\">{{ item.matIcon }}</mat-icon>\n <mat-label translate>{{ item.title }}</mat-label>\n </a>\n } @else if (!item.action) {\n <!-- divider -->\n <mat-divider class=\"{{ item.cssClass }} {{ item.color }}\">\n <mat-label translate>{{ item.title }}</mat-label>\n </mat-divider>\n }\n }\n }\n</mat-menu>\n\n<ion-content>\n <form [formGroup]=\"form\" novalidate (ngSubmit)=\"save($event)\" class=\"form-container\">\n <ion-grid class=\"ion-no-padding\">\n <ion-row>\n <!-- left margin -->\n <ion-col size=\"0\" size-lg=\"1\" size-xl=\"2\">&nbsp;</ion-col>\n\n <ion-col class=\"ion-padding\">\n <!-- error -->\n <ion-item *ngIf=\"error\" 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 <ion-list-header class=\"hidden-xs hidden-xxs\" translate>SETTINGS.DESCRIPTION</ion-list-header>\n\n <ion-list [inset]=\"mobile\">\n <ion-item lines=\"none\">\n <!-- account inheritance (desktop) -->\n @if (!mobile) {\n <mat-form-field [hidden]=\"!isLogin\">\n <input matInput hidden formControlName=\"accountInheritance\" type=\"text\" />\n\n <!-- check box (if desktop) -->\n <mat-checkbox (change)=\"setAccountInheritance($event.checked)\" [checked]=\"accountInheritance\">\n <span translate>SETTINGS.INHERIT_FROM_ACCOUNT</span>\n </mat-checkbox>\n\n <mat-error *ngIf=\"form.controls.accountInheritance.hasError('required')\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n </mat-form-field>\n } @else {\n <!-- account inheritance (if mobile) -->\n <mat-form-field [hidden]=\"!isLogin\">\n <input matInput hidden formControlName=\"accountInheritance\" type=\"text\" />\n\n <!-- slide toggle -->\n <ion-text translate>SETTINGS.INHERIT_FROM_ACCOUNT</ion-text>\n <mat-slide-toggle\n matSuffix\n (change)=\"setAccountInheritance($event.checked)\"\n [checked]=\"accountInheritance\"\n ></mat-slide-toggle>\n <mat-error *ngIf=\"form.controls.accountInheritance.hasError('required')\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n </mat-form-field>\n }\n </ion-item>\n </ion-list>\n\n @if (settings.enableDarkMode) {\n <ion-list-header><h3 translate>SETTINGS.DISPLAY_DIVIDER</h3></ion-list-header>\n\n <ion-list [inset]=\"mobile\">\n <!-- locale -->\n <ion-item lines=\"none\">\n <mat-form-field>\n <ion-icon matPrefix name=\"language\"></ion-icon>\n <mat-label>{{ 'SETTINGS.LOCALE' | translate }}</mat-label>\n <mat-select 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=\"form.controls.locale.hasError('required')\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n </mat-form-field>\n </ion-item>\n\n <!-- dark mode -->\n <ion-item lines=\"none\">\n <!-- dark mode (if mobile) -->\n <mat-form-field>\n <ion-icon matPrefix name=\"moon\"></ion-icon>\n\n <input matInput hidden formControlName=\"darkMode\" type=\"text\" />\n\n <!-- slide toggle -->\n <ion-text translate>SETTINGS.BTN_DARK_MODE</ion-text>\n <mat-slide-toggle\n matSuffix\n (change)=\"toggleDarkMode($event.checked)\"\n [checked]=\"darkMode\"\n ></mat-slide-toggle>\n </mat-form-field>\n </ion-item>\n </ion-list>\n }\n\n <!-- Network entry -->\n <ion-list-header><h3 translate>SETTINGS.NETWORK_DIVIDER</h3></ion-list-header>\n\n <ion-list [inset]=\"mobile\">\n <!-- Peer address -->\n <ion-item lines=\"none\">\n <mat-form-field>\n <ion-icon matPrefix name=\"cloud\"></ion-icon>\n\n <mat-label>{{ 'SETTINGS.PEER_URL' | translate }}</mat-label>\n <input matInput type=\"text\" formControlName=\"peerUrl\" required />\n\n <button\n mat-icon-button\n type=\"button\"\n matSuffix\n (click)=\"showSelectPeerModal()\"\n tabindex=\"-1\"\n [title]=\"'SETTINGS.BTN_CHANGE_PEER' | translate\"\n >\n <mat-icon>search</mat-icon>\n </button>\n\n <mat-error *ngIf=\"form.controls.peerUrl.hasError('required')\" translate>ERROR.FIELD_REQUIRED</mat-error>\n <mat-error *ngIf=\"form.controls.peerUrl.hasError('peerAlive')\" translate>\n SETTINGS.ERROR.PEER_NOT_REACHABLE\n </mat-error>\n <mat-error *ngIf=\"form.controls.peerUrl.hasError('peerNotCompatible')\" translate>\n SETTINGS.ERROR.PEER_NOT_COMPATIBLE\n </mat-error>\n </mat-form-field>\n </ion-item>\n\n <!-- Offline mode (if mobile) -->\n @if (mobile) {\n <ion-item lines=\"none\">\n <mat-form-field>\n <input matInput hidden formControlName=\"accountInheritance\" type=\"text\" />\n\n <!-- slide toggle -->\n <ion-text translate>SETTINGS.OFFLINE_MODE</ion-text>\n <mat-slide-toggle\n matSuffix\n (change)=\"network.setForceOffline($event.checked)\"\n [checked]=\"network.offline\"\n ></mat-slide-toggle>\n </mat-form-field>\n </ion-item>\n }\n </ion-list>\n\n <!-- Data entry -->\n <ion-list-header>\n <h3 translate>SETTINGS.DATA_ENTRY_DIVIDER</h3>\n </ion-list-header>\n\n <ion-list [inset]=\"mobile\">\n <!-- Usage mode -->\n <ion-item lines=\"none\">\n <mat-form-field>\n <ion-icon matPrefix name=\"id-card\"></ion-icon>\n <mat-label>{{ 'SETTINGS.USAGE_MODE' | translate }}</mat-label>\n <mat-select formControlName=\"usageMode\" required>\n <mat-option *ngFor=\"let item of usageModes\" [value]=\"item\">\n {{ 'SETTINGS.USAGE_MODES.' + item | translate }}\n </mat-option>\n </mat-select>\n <mat-error *ngIf=\"form.controls.usageMode.hasError('required')\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n </mat-form-field>\n </ion-item>\n\n <!-- lat/long format-->\n <ion-item lines=\"none\">\n <mat-form-field>\n <ion-icon matPrefix name=\"locate\"></ion-icon>\n <mat-label>{{ 'SETTINGS.LAT_LONG_FORMAT' | translate }}</mat-label>\n <mat-select formControlName=\"latLongFormat\" 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=\"form.controls.latLongFormat.hasError('required')\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n </mat-form-field>\n </ion-item>\n </ion-list>\n\n <!-- fields options -->\n <app-properties-form\n #propertiesForm\n formArrayName=\"properties\"\n [definitions]=\"propertyDefinitions\"\n [options]=\"{ allowEmptyArray: true }\"\n [mobile]=\"mobile\"\n [showAddButton]=\"!mobile\"\n [showHintKey]=\"isAdmin\"\n ></app-properties-form>\n </ion-col>\n\n <!-- right margin -->\n <ion-col size=\"0\" size-lg=\"1\" size-xl=\"2\">&nbsp;</ion-col>\n </ion-row>\n </ion-grid>\n </form>\n</ion-content>\n\n<ion-footer hidden-xs hidden-sm hidden-mobile>\n <app-form-buttons-bar\n (onCancel)=\"cancel()\"\n (onSave)=\"save($event)\"\n [disabled]=\"!form.dirty || saving\"\n ></app-form-buttons-bar>\n</ion-footer>\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: i2$1.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: i2$1.IonButtons, selector: "ion-buttons", inputs: ["collapse"] }, { kind: "component", type: i2$1.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: i2$1.IonContent, selector: "ion-content", inputs: ["color", "fixedSlotPlacement", "forceOverscroll", "fullscreen", "scrollEvents", "scrollX", "scrollY"] }, { kind: "component", type: i2$1.IonFooter, selector: "ion-footer", inputs: ["collapse", "mode", "translucent"] }, { kind: "component", type: i2$1.IonGrid, selector: "ion-grid", inputs: ["fixed"] }, { kind: "component", type: i2$1.IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "component", type: i2$1.IonItem, selector: "ion-item", inputs: ["button", "color", "detail", "detailIcon", "disabled", "download", "href", "lines", "mode", "rel", "routerAnimation", "routerDirection", "target", "type"] }, { kind: "component", type: i2$1.IonLabel, selector: "ion-label", inputs: ["color", "mode", "position"] }, { kind: "component", type: i2$1.IonList, selector: "ion-list", inputs: ["inset", "lines", "mode"] }, { kind: "component", type: i2$1.IonListHeader, selector: "ion-list-header", inputs: ["color", "lines", "mode"] }, { kind: "component", type: i2$1.IonRow, selector: "ion-row" }, { kind: "component", type: i2$1.IonText, selector: "ion-text", inputs: ["color", "mode"] }, { kind: "directive", type: i1$1.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.FormArrayName, selector: "[formArrayName]", inputs: ["formArrayName"] }, { kind: "component", type: i6.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i6.MatLabel, selector: "mat-label" }, { kind: "directive", type: i6.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "directive", type: i6.MatPrefix, selector: "[matPrefix], [matIconPrefix], [matTextPrefix]", inputs: ["matTextPrefix"] }, { kind: "directive", type: i6.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "directive", type: i4.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: i5.MatCheckbox, selector: "mat-checkbox", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "id", "required", "labelPosition", "name", "value", "disableRipple", "tabIndex", "color", "disabledInteractive", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }, { kind: "component", type: i4$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i9.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "component", type: i8$1.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: i8$1.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i8$1.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "component", type: i12.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i2.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "component", type: i9$1.MatDivider, selector: "mat-divider", inputs: ["vertical", "inset"] }, { kind: "component", type: i12$3.MatSlideToggle, selector: "mat-slide-toggle", inputs: ["name", "id", "labelPosition", "aria-label", "aria-labelledby", "aria-describedby", "required", "color", "disabled", "disableRipple", "tabIndex", "checked", "hideIcon", "disabledInteractive"], outputs: ["change", "toggleChange"], exportAs: ["matSlideToggle"] }, { 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: FormButtonsBarComponent, selector: "app-form-buttons-bar", inputs: ["disabled", "disabledCancel", "disabledEscape", "classList", "saveButtonColor", "backText", "cancelText", "nextText", "showBack", "showCancel", "showNext", "showSave"], outputs: ["onCancel", "onSave", "onNext", "onBack", "onSaveAndClose", "onSaveAndNext"] }, { kind: "component", type: AppPropertiesForm, selector: "app-properties-form", inputs: ["formArrayName", "formArray", "options", "chipColor", "mobile", "appearance", "subscriptSizing", "showHintKey", "hintKeyPrefix", "showMoreButton", "showMoreButtonTitle", "showAddButton", "definitions"] }, { kind: "pipe", type: i1$1.TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
29330
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.8", type: SettingsPage, selector: "page-settings", providers: [{ provide: ValidatorService, useExisting: LocalSettingsValidatorService }], viewQueries: [{ propertyName: "propertiesForm", first: true, predicate: ["propertiesForm"], descendants: true, static: true }], usesInheritance: true, ngImport: i0, template: "<app-toolbar\n [title]=\"'SETTINGS.TITLE' | translate\"\n color=\"primary\"\n [hasValidate]=\"dirty && !saving\"\n [hasClose]=\"!dirty && !saving\"\n (onValidate)=\"save($event)\"\n (onClose)=\"close($event)\"\n>\n <ion-buttons slot=\"end\">\n <!-- options menu -->\n <ion-button [matMenuTriggerFor]=\"optionsMenu\">\n <mat-icon slot=\"icon-only\">more_vert</mat-icon>\n </ion-button>\n </ion-buttons>\n</app-toolbar>\n\n<!-- Options menu -->\n<mat-menu #optionsMenu=\"matMenu\">\n <!-- Clear cache -->\n <button mat-menu-item [disabled]=\"saving\" (click)=\"clearCache($event)\">\n <mat-icon><ion-icon name=\"trash-outline\"></ion-icon></mat-icon>\n <ion-label translate>SETTINGS.BTN_CLEAR_CACHE</ion-label>\n </button>\n\n <!-- Reset -->\n <button mat-menu-item [disabled]=\"saving || !dirty\" (click)=\"cancel($event)\">\n <mat-icon><ion-icon name=\"refresh\"></ion-icon></mat-icon>\n <mat-label translate>COMMON.BTN_RESET</mat-label>\n </button>\n\n <!-- additional items -->\n @if (!loading) {\n @for (item of menuItems; track item) {\n @if (item.path) {\n <a mat-menu-item class=\"{{ item.cssClass }} {{ item.color }}\" (click)=\"executeAction($event, item)\">\n <mat-icon *ngIf=\"item.icon\"><ion-icon [name]=\"item.icon\"></ion-icon></mat-icon>\n <mat-icon *ngIf=\"item.matIcon\">{{ item.matIcon }}</mat-icon>\n <mat-label translate>{{ item.title }}</mat-label>\n </a>\n } @else if (!item.action) {\n <!-- divider -->\n <mat-divider class=\"{{ item.cssClass }} {{ item.color }}\">\n <mat-label translate>{{ item.title }}</mat-label>\n </mat-divider>\n }\n }\n }\n</mat-menu>\n\n<ion-content>\n <form [formGroup]=\"form\" novalidate (ngSubmit)=\"save($event)\" class=\"form-container\">\n <ion-grid class=\"ion-no-padding\">\n <ion-row>\n <!-- left margin -->\n <ion-col size=\"0\" size-lg=\"1\" size-xl=\"2\">&nbsp;</ion-col>\n\n <ion-col class=\"ion-padding\">\n <!-- error -->\n <ion-item *ngIf=\"error\" 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 <ion-list-header class=\"hidden-xs hidden-xxs\" translate>SETTINGS.DESCRIPTION</ion-list-header>\n\n <ion-list [inset]=\"mobile\">\n <ion-item lines=\"none\">\n <!-- account inheritance (desktop) -->\n @if (!mobile) {\n <mat-form-field [hidden]=\"!isLogin\">\n <input matInput hidden formControlName=\"accountInheritance\" type=\"text\" />\n\n <!-- check box (if desktop) -->\n <mat-checkbox (change)=\"setAccountInheritance($event.checked)\" [checked]=\"accountInheritance\">\n <span translate>SETTINGS.INHERIT_FROM_ACCOUNT</span>\n </mat-checkbox>\n\n <mat-error *ngIf=\"form.controls.accountInheritance.hasError('required')\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n </mat-form-field>\n } @else {\n <!-- account inheritance (if mobile) -->\n <mat-form-field [hidden]=\"!isLogin\">\n <input matInput hidden formControlName=\"accountInheritance\" type=\"text\" />\n\n <!-- slide toggle -->\n <ion-text translate>SETTINGS.INHERIT_FROM_ACCOUNT</ion-text>\n <mat-slide-toggle\n matSuffix\n (change)=\"setAccountInheritance($event.checked)\"\n [checked]=\"accountInheritance\"\n ></mat-slide-toggle>\n <mat-error *ngIf=\"form.controls.accountInheritance.hasError('required')\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n </mat-form-field>\n }\n </ion-item>\n </ion-list>\n\n @if (settings.enableDarkMode) {\n <ion-list-header><h3 translate>SETTINGS.DISPLAY_DIVIDER</h3></ion-list-header>\n\n <ion-list [inset]=\"mobile\">\n <!-- locale -->\n <ion-item lines=\"none\">\n <mat-form-field>\n <ion-icon matPrefix name=\"language\"></ion-icon>\n <mat-label>{{ 'SETTINGS.LOCALE' | translate }}</mat-label>\n <mat-select 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=\"form.controls.locale.hasError('required')\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n </mat-form-field>\n </ion-item>\n\n <!-- dark mode -->\n <ion-item lines=\"none\">\n <mat-form-field>\n <ion-icon matPrefix name=\"moon\"></ion-icon>\n\n <input matInput hidden formControlName=\"darkMode\" type=\"text\" />\n\n <!-- slide toggle -->\n <ion-text translate>SETTINGS.BTN_DARK_MODE</ion-text>\n <mat-slide-toggle\n matSuffix\n (change)=\"toggleDarkMode($event.checked)\"\n [checked]=\"darkMode\"\n ></mat-slide-toggle>\n </mat-form-field>\n </ion-item>\n </ion-list>\n }\n\n <!-- Network entry -->\n <ion-list-header><h3 translate>SETTINGS.NETWORK_DIVIDER</h3></ion-list-header>\n\n <ion-list [inset]=\"mobile\">\n <!-- Peer address -->\n <ion-item lines=\"none\">\n <mat-form-field>\n <ion-icon matPrefix name=\"cloud\"></ion-icon>\n\n <mat-label>{{ 'SETTINGS.PEER_URL' | translate }}</mat-label>\n <input matInput type=\"text\" formControlName=\"peerUrl\" required />\n\n <button\n mat-icon-button\n type=\"button\"\n matSuffix\n (click)=\"showSelectPeerModal()\"\n tabindex=\"-1\"\n [title]=\"'SETTINGS.BTN_CHANGE_PEER' | translate\"\n >\n <mat-icon>search</mat-icon>\n </button>\n\n <mat-error *ngIf=\"form.controls.peerUrl.hasError('required')\" translate>ERROR.FIELD_REQUIRED</mat-error>\n <mat-error *ngIf=\"form.controls.peerUrl.hasError('peerAlive')\" translate>\n SETTINGS.ERROR.PEER_NOT_REACHABLE\n </mat-error>\n <mat-error *ngIf=\"form.controls.peerUrl.hasError('peerNotCompatible')\" translate>\n SETTINGS.ERROR.PEER_NOT_COMPATIBLE\n </mat-error>\n </mat-form-field>\n </ion-item>\n\n <!-- Offline mode (if mobile) -->\n @if (mobile) {\n <ion-item lines=\"none\">\n <mat-form-field>\n <input matInput hidden formControlName=\"accountInheritance\" type=\"text\" />\n\n <!-- slide toggle -->\n <ion-text translate>SETTINGS.OFFLINE_MODE</ion-text>\n <mat-slide-toggle\n matSuffix\n (change)=\"network.setForceOffline($event.checked)\"\n [checked]=\"network.offline\"\n ></mat-slide-toggle>\n </mat-form-field>\n </ion-item>\n }\n </ion-list>\n\n <!-- Data entry -->\n <ion-list-header>\n <h3 translate>SETTINGS.DATA_ENTRY_DIVIDER</h3>\n </ion-list-header>\n\n <ion-list [inset]=\"mobile\">\n <!-- Usage mode -->\n <ion-item lines=\"none\">\n <mat-form-field>\n <ion-icon matPrefix name=\"id-card\"></ion-icon>\n <mat-label>{{ 'SETTINGS.USAGE_MODE' | translate }}</mat-label>\n <mat-select formControlName=\"usageMode\" required>\n <mat-option *ngFor=\"let item of usageModes\" [value]=\"item\">\n {{ 'SETTINGS.USAGE_MODES.' + item | translate }}\n </mat-option>\n </mat-select>\n <mat-error *ngIf=\"form.controls.usageMode.hasError('required')\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n </mat-form-field>\n </ion-item>\n\n <!-- lat/long format-->\n <ion-item lines=\"none\">\n <mat-form-field>\n <ion-icon matPrefix name=\"locate\"></ion-icon>\n <mat-label>{{ 'SETTINGS.LAT_LONG_FORMAT' | translate }}</mat-label>\n <mat-select formControlName=\"latLongFormat\" 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=\"form.controls.latLongFormat.hasError('required')\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n </mat-form-field>\n </ion-item>\n </ion-list>\n\n <!-- fields options -->\n <app-properties-form\n #propertiesForm\n formArrayName=\"properties\"\n [definitions]=\"propertyDefinitions\"\n [options]=\"{ allowEmptyArray: true }\"\n [mobile]=\"mobile\"\n [showAddButton]=\"!mobile\"\n [showHintKey]=\"isAdmin\"\n ></app-properties-form>\n </ion-col>\n\n <!-- right margin -->\n <ion-col size=\"0\" size-lg=\"1\" size-xl=\"2\">&nbsp;</ion-col>\n </ion-row>\n </ion-grid>\n </form>\n</ion-content>\n\n<ion-footer hidden-xs hidden-sm hidden-mobile>\n <app-form-buttons-bar\n (onCancel)=\"cancel()\"\n (onSave)=\"save($event)\"\n [disabled]=\"!form.dirty || saving\"\n ></app-form-buttons-bar>\n</ion-footer>\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: i2$1.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: i2$1.IonButtons, selector: "ion-buttons", inputs: ["collapse"] }, { kind: "component", type: i2$1.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: i2$1.IonContent, selector: "ion-content", inputs: ["color", "fixedSlotPlacement", "forceOverscroll", "fullscreen", "scrollEvents", "scrollX", "scrollY"] }, { kind: "component", type: i2$1.IonFooter, selector: "ion-footer", inputs: ["collapse", "mode", "translucent"] }, { kind: "component", type: i2$1.IonGrid, selector: "ion-grid", inputs: ["fixed"] }, { kind: "component", type: i2$1.IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "component", type: i2$1.IonItem, selector: "ion-item", inputs: ["button", "color", "detail", "detailIcon", "disabled", "download", "href", "lines", "mode", "rel", "routerAnimation", "routerDirection", "target", "type"] }, { kind: "component", type: i2$1.IonLabel, selector: "ion-label", inputs: ["color", "mode", "position"] }, { kind: "component", type: i2$1.IonList, selector: "ion-list", inputs: ["inset", "lines", "mode"] }, { kind: "component", type: i2$1.IonListHeader, selector: "ion-list-header", inputs: ["color", "lines", "mode"] }, { kind: "component", type: i2$1.IonRow, selector: "ion-row" }, { kind: "component", type: i2$1.IonText, selector: "ion-text", inputs: ["color", "mode"] }, { kind: "directive", type: i1$1.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.FormArrayName, selector: "[formArrayName]", inputs: ["formArrayName"] }, { kind: "component", type: i6.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i6.MatLabel, selector: "mat-label" }, { kind: "directive", type: i6.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "directive", type: i6.MatPrefix, selector: "[matPrefix], [matIconPrefix], [matTextPrefix]", inputs: ["matTextPrefix"] }, { kind: "directive", type: i6.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "directive", type: i4.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: i5.MatCheckbox, selector: "mat-checkbox", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "id", "required", "labelPosition", "name", "value", "disableRipple", "tabIndex", "color", "disabledInteractive", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }, { kind: "component", type: i4$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i9.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "component", type: i8$1.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: i8$1.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i8$1.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "component", type: i12.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i2.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "component", type: i9$1.MatDivider, selector: "mat-divider", inputs: ["vertical", "inset"] }, { kind: "component", type: i12$3.MatSlideToggle, selector: "mat-slide-toggle", inputs: ["name", "id", "labelPosition", "aria-label", "aria-labelledby", "aria-describedby", "required", "color", "disabled", "disableRipple", "tabIndex", "checked", "hideIcon", "disabledInteractive"], outputs: ["change", "toggleChange"], exportAs: ["matSlideToggle"] }, { 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: FormButtonsBarComponent, selector: "app-form-buttons-bar", inputs: ["disabled", "disabledCancel", "disabledEscape", "classList", "saveButtonColor", "backText", "cancelText", "nextText", "showBack", "showCancel", "showNext", "showSave"], outputs: ["onCancel", "onSave", "onNext", "onBack", "onSaveAndClose", "onSaveAndNext"] }, { kind: "component", type: AppPropertiesForm, selector: "app-properties-form", inputs: ["formArrayName", "formArray", "options", "chipColor", "mobile", "appearance", "subscriptSizing", "showHintKey", "hintKeyPrefix", "showMoreButton", "showMoreButtonTitle", "showAddButton", "definitions"] }, { kind: "pipe", type: i1$1.TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
29239
29331
  }
29240
29332
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.8", ngImport: i0, type: SettingsPage, decorators: [{
29241
29333
  type: Component,
29242
- args: [{ selector: 'page-settings', providers: [{ provide: ValidatorService, useExisting: LocalSettingsValidatorService }], changeDetection: ChangeDetectionStrategy.OnPush, template: "<app-toolbar\n [title]=\"'SETTINGS.TITLE' | translate\"\n color=\"primary\"\n [hasValidate]=\"dirty && !saving\"\n [hasClose]=\"!dirty && !saving\"\n (onValidate)=\"save($event)\"\n (onClose)=\"close($event)\"\n>\n <ion-buttons slot=\"end\">\n <!-- options menu -->\n <ion-button [matMenuTriggerFor]=\"optionsMenu\">\n <mat-icon slot=\"icon-only\">more_vert</mat-icon>\n </ion-button>\n </ion-buttons>\n</app-toolbar>\n\n<!-- Options menu -->\n<mat-menu #optionsMenu=\"matMenu\">\n <!-- Clear cache -->\n <button mat-menu-item [disabled]=\"saving\" (click)=\"clearCache($event)\">\n <mat-icon><ion-icon name=\"trash-outline\"></ion-icon></mat-icon>\n <ion-label translate>SETTINGS.BTN_CLEAR_CACHE</ion-label>\n </button>\n\n <!-- Reset -->\n <button mat-menu-item [disabled]=\"saving || !dirty\" (click)=\"cancel($event)\">\n <mat-icon><ion-icon name=\"refresh\"></ion-icon></mat-icon>\n <mat-label translate>COMMON.BTN_RESET</mat-label>\n </button>\n\n <!-- additional items -->\n @if (!loading) {\n @for (item of menuItems; track item) {\n @if (item.path) {\n <a mat-menu-item class=\"{{ item.cssClass }} {{ item.color }}\" (click)=\"executeAction($event, item)\">\n <mat-icon *ngIf=\"item.icon\"><ion-icon [name]=\"item.icon\"></ion-icon></mat-icon>\n <mat-icon *ngIf=\"item.matIcon\">{{ item.matIcon }}</mat-icon>\n <mat-label translate>{{ item.title }}</mat-label>\n </a>\n } @else if (!item.action) {\n <!-- divider -->\n <mat-divider class=\"{{ item.cssClass }} {{ item.color }}\">\n <mat-label translate>{{ item.title }}</mat-label>\n </mat-divider>\n }\n }\n }\n</mat-menu>\n\n<ion-content>\n <form [formGroup]=\"form\" novalidate (ngSubmit)=\"save($event)\" class=\"form-container\">\n <ion-grid class=\"ion-no-padding\">\n <ion-row>\n <!-- left margin -->\n <ion-col size=\"0\" size-lg=\"1\" size-xl=\"2\">&nbsp;</ion-col>\n\n <ion-col class=\"ion-padding\">\n <!-- error -->\n <ion-item *ngIf=\"error\" 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 <ion-list-header class=\"hidden-xs hidden-xxs\" translate>SETTINGS.DESCRIPTION</ion-list-header>\n\n <ion-list [inset]=\"mobile\">\n <ion-item lines=\"none\">\n <!-- account inheritance (desktop) -->\n @if (!mobile) {\n <mat-form-field [hidden]=\"!isLogin\">\n <input matInput hidden formControlName=\"accountInheritance\" type=\"text\" />\n\n <!-- check box (if desktop) -->\n <mat-checkbox (change)=\"setAccountInheritance($event.checked)\" [checked]=\"accountInheritance\">\n <span translate>SETTINGS.INHERIT_FROM_ACCOUNT</span>\n </mat-checkbox>\n\n <mat-error *ngIf=\"form.controls.accountInheritance.hasError('required')\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n </mat-form-field>\n } @else {\n <!-- account inheritance (if mobile) -->\n <mat-form-field [hidden]=\"!isLogin\">\n <input matInput hidden formControlName=\"accountInheritance\" type=\"text\" />\n\n <!-- slide toggle -->\n <ion-text translate>SETTINGS.INHERIT_FROM_ACCOUNT</ion-text>\n <mat-slide-toggle\n matSuffix\n (change)=\"setAccountInheritance($event.checked)\"\n [checked]=\"accountInheritance\"\n ></mat-slide-toggle>\n <mat-error *ngIf=\"form.controls.accountInheritance.hasError('required')\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n </mat-form-field>\n }\n </ion-item>\n </ion-list>\n\n @if (settings.enableDarkMode) {\n <ion-list-header><h3 translate>SETTINGS.DISPLAY_DIVIDER</h3></ion-list-header>\n\n <ion-list [inset]=\"mobile\">\n <!-- locale -->\n <ion-item lines=\"none\">\n <mat-form-field>\n <ion-icon matPrefix name=\"language\"></ion-icon>\n <mat-label>{{ 'SETTINGS.LOCALE' | translate }}</mat-label>\n <mat-select 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=\"form.controls.locale.hasError('required')\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n </mat-form-field>\n </ion-item>\n\n <!-- dark mode -->\n <ion-item lines=\"none\">\n <!-- dark mode (if mobile) -->\n <mat-form-field>\n <ion-icon matPrefix name=\"moon\"></ion-icon>\n\n <input matInput hidden formControlName=\"darkMode\" type=\"text\" />\n\n <!-- slide toggle -->\n <ion-text translate>SETTINGS.BTN_DARK_MODE</ion-text>\n <mat-slide-toggle\n matSuffix\n (change)=\"toggleDarkMode($event.checked)\"\n [checked]=\"darkMode\"\n ></mat-slide-toggle>\n </mat-form-field>\n </ion-item>\n </ion-list>\n }\n\n <!-- Network entry -->\n <ion-list-header><h3 translate>SETTINGS.NETWORK_DIVIDER</h3></ion-list-header>\n\n <ion-list [inset]=\"mobile\">\n <!-- Peer address -->\n <ion-item lines=\"none\">\n <mat-form-field>\n <ion-icon matPrefix name=\"cloud\"></ion-icon>\n\n <mat-label>{{ 'SETTINGS.PEER_URL' | translate }}</mat-label>\n <input matInput type=\"text\" formControlName=\"peerUrl\" required />\n\n <button\n mat-icon-button\n type=\"button\"\n matSuffix\n (click)=\"showSelectPeerModal()\"\n tabindex=\"-1\"\n [title]=\"'SETTINGS.BTN_CHANGE_PEER' | translate\"\n >\n <mat-icon>search</mat-icon>\n </button>\n\n <mat-error *ngIf=\"form.controls.peerUrl.hasError('required')\" translate>ERROR.FIELD_REQUIRED</mat-error>\n <mat-error *ngIf=\"form.controls.peerUrl.hasError('peerAlive')\" translate>\n SETTINGS.ERROR.PEER_NOT_REACHABLE\n </mat-error>\n <mat-error *ngIf=\"form.controls.peerUrl.hasError('peerNotCompatible')\" translate>\n SETTINGS.ERROR.PEER_NOT_COMPATIBLE\n </mat-error>\n </mat-form-field>\n </ion-item>\n\n <!-- Offline mode (if mobile) -->\n @if (mobile) {\n <ion-item lines=\"none\">\n <mat-form-field>\n <input matInput hidden formControlName=\"accountInheritance\" type=\"text\" />\n\n <!-- slide toggle -->\n <ion-text translate>SETTINGS.OFFLINE_MODE</ion-text>\n <mat-slide-toggle\n matSuffix\n (change)=\"network.setForceOffline($event.checked)\"\n [checked]=\"network.offline\"\n ></mat-slide-toggle>\n </mat-form-field>\n </ion-item>\n }\n </ion-list>\n\n <!-- Data entry -->\n <ion-list-header>\n <h3 translate>SETTINGS.DATA_ENTRY_DIVIDER</h3>\n </ion-list-header>\n\n <ion-list [inset]=\"mobile\">\n <!-- Usage mode -->\n <ion-item lines=\"none\">\n <mat-form-field>\n <ion-icon matPrefix name=\"id-card\"></ion-icon>\n <mat-label>{{ 'SETTINGS.USAGE_MODE' | translate }}</mat-label>\n <mat-select formControlName=\"usageMode\" required>\n <mat-option *ngFor=\"let item of usageModes\" [value]=\"item\">\n {{ 'SETTINGS.USAGE_MODES.' + item | translate }}\n </mat-option>\n </mat-select>\n <mat-error *ngIf=\"form.controls.usageMode.hasError('required')\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n </mat-form-field>\n </ion-item>\n\n <!-- lat/long format-->\n <ion-item lines=\"none\">\n <mat-form-field>\n <ion-icon matPrefix name=\"locate\"></ion-icon>\n <mat-label>{{ 'SETTINGS.LAT_LONG_FORMAT' | translate }}</mat-label>\n <mat-select formControlName=\"latLongFormat\" 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=\"form.controls.latLongFormat.hasError('required')\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n </mat-form-field>\n </ion-item>\n </ion-list>\n\n <!-- fields options -->\n <app-properties-form\n #propertiesForm\n formArrayName=\"properties\"\n [definitions]=\"propertyDefinitions\"\n [options]=\"{ allowEmptyArray: true }\"\n [mobile]=\"mobile\"\n [showAddButton]=\"!mobile\"\n [showHintKey]=\"isAdmin\"\n ></app-properties-form>\n </ion-col>\n\n <!-- right margin -->\n <ion-col size=\"0\" size-lg=\"1\" size-xl=\"2\">&nbsp;</ion-col>\n </ion-row>\n </ion-grid>\n </form>\n</ion-content>\n\n<ion-footer hidden-xs hidden-sm hidden-mobile>\n <app-form-buttons-bar\n (onCancel)=\"cancel()\"\n (onSave)=\"save($event)\"\n [disabled]=\"!form.dirty || saving\"\n ></app-form-buttons-bar>\n</ion-footer>\n" }]
29334
+ args: [{ selector: 'page-settings', providers: [{ provide: ValidatorService, useExisting: LocalSettingsValidatorService }], changeDetection: ChangeDetectionStrategy.OnPush, template: "<app-toolbar\n [title]=\"'SETTINGS.TITLE' | translate\"\n color=\"primary\"\n [hasValidate]=\"dirty && !saving\"\n [hasClose]=\"!dirty && !saving\"\n (onValidate)=\"save($event)\"\n (onClose)=\"close($event)\"\n>\n <ion-buttons slot=\"end\">\n <!-- options menu -->\n <ion-button [matMenuTriggerFor]=\"optionsMenu\">\n <mat-icon slot=\"icon-only\">more_vert</mat-icon>\n </ion-button>\n </ion-buttons>\n</app-toolbar>\n\n<!-- Options menu -->\n<mat-menu #optionsMenu=\"matMenu\">\n <!-- Clear cache -->\n <button mat-menu-item [disabled]=\"saving\" (click)=\"clearCache($event)\">\n <mat-icon><ion-icon name=\"trash-outline\"></ion-icon></mat-icon>\n <ion-label translate>SETTINGS.BTN_CLEAR_CACHE</ion-label>\n </button>\n\n <!-- Reset -->\n <button mat-menu-item [disabled]=\"saving || !dirty\" (click)=\"cancel($event)\">\n <mat-icon><ion-icon name=\"refresh\"></ion-icon></mat-icon>\n <mat-label translate>COMMON.BTN_RESET</mat-label>\n </button>\n\n <!-- additional items -->\n @if (!loading) {\n @for (item of menuItems; track item) {\n @if (item.path) {\n <a mat-menu-item class=\"{{ item.cssClass }} {{ item.color }}\" (click)=\"executeAction($event, item)\">\n <mat-icon *ngIf=\"item.icon\"><ion-icon [name]=\"item.icon\"></ion-icon></mat-icon>\n <mat-icon *ngIf=\"item.matIcon\">{{ item.matIcon }}</mat-icon>\n <mat-label translate>{{ item.title }}</mat-label>\n </a>\n } @else if (!item.action) {\n <!-- divider -->\n <mat-divider class=\"{{ item.cssClass }} {{ item.color }}\">\n <mat-label translate>{{ item.title }}</mat-label>\n </mat-divider>\n }\n }\n }\n</mat-menu>\n\n<ion-content>\n <form [formGroup]=\"form\" novalidate (ngSubmit)=\"save($event)\" class=\"form-container\">\n <ion-grid class=\"ion-no-padding\">\n <ion-row>\n <!-- left margin -->\n <ion-col size=\"0\" size-lg=\"1\" size-xl=\"2\">&nbsp;</ion-col>\n\n <ion-col class=\"ion-padding\">\n <!-- error -->\n <ion-item *ngIf=\"error\" 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 <ion-list-header class=\"hidden-xs hidden-xxs\" translate>SETTINGS.DESCRIPTION</ion-list-header>\n\n <ion-list [inset]=\"mobile\">\n <ion-item lines=\"none\">\n <!-- account inheritance (desktop) -->\n @if (!mobile) {\n <mat-form-field [hidden]=\"!isLogin\">\n <input matInput hidden formControlName=\"accountInheritance\" type=\"text\" />\n\n <!-- check box (if desktop) -->\n <mat-checkbox (change)=\"setAccountInheritance($event.checked)\" [checked]=\"accountInheritance\">\n <span translate>SETTINGS.INHERIT_FROM_ACCOUNT</span>\n </mat-checkbox>\n\n <mat-error *ngIf=\"form.controls.accountInheritance.hasError('required')\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n </mat-form-field>\n } @else {\n <!-- account inheritance (if mobile) -->\n <mat-form-field [hidden]=\"!isLogin\">\n <input matInput hidden formControlName=\"accountInheritance\" type=\"text\" />\n\n <!-- slide toggle -->\n <ion-text translate>SETTINGS.INHERIT_FROM_ACCOUNT</ion-text>\n <mat-slide-toggle\n matSuffix\n (change)=\"setAccountInheritance($event.checked)\"\n [checked]=\"accountInheritance\"\n ></mat-slide-toggle>\n <mat-error *ngIf=\"form.controls.accountInheritance.hasError('required')\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n </mat-form-field>\n }\n </ion-item>\n </ion-list>\n\n @if (settings.enableDarkMode) {\n <ion-list-header><h3 translate>SETTINGS.DISPLAY_DIVIDER</h3></ion-list-header>\n\n <ion-list [inset]=\"mobile\">\n <!-- locale -->\n <ion-item lines=\"none\">\n <mat-form-field>\n <ion-icon matPrefix name=\"language\"></ion-icon>\n <mat-label>{{ 'SETTINGS.LOCALE' | translate }}</mat-label>\n <mat-select 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=\"form.controls.locale.hasError('required')\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n </mat-form-field>\n </ion-item>\n\n <!-- dark mode -->\n <ion-item lines=\"none\">\n <mat-form-field>\n <ion-icon matPrefix name=\"moon\"></ion-icon>\n\n <input matInput hidden formControlName=\"darkMode\" type=\"text\" />\n\n <!-- slide toggle -->\n <ion-text translate>SETTINGS.BTN_DARK_MODE</ion-text>\n <mat-slide-toggle\n matSuffix\n (change)=\"toggleDarkMode($event.checked)\"\n [checked]=\"darkMode\"\n ></mat-slide-toggle>\n </mat-form-field>\n </ion-item>\n </ion-list>\n }\n\n <!-- Network entry -->\n <ion-list-header><h3 translate>SETTINGS.NETWORK_DIVIDER</h3></ion-list-header>\n\n <ion-list [inset]=\"mobile\">\n <!-- Peer address -->\n <ion-item lines=\"none\">\n <mat-form-field>\n <ion-icon matPrefix name=\"cloud\"></ion-icon>\n\n <mat-label>{{ 'SETTINGS.PEER_URL' | translate }}</mat-label>\n <input matInput type=\"text\" formControlName=\"peerUrl\" required />\n\n <button\n mat-icon-button\n type=\"button\"\n matSuffix\n (click)=\"showSelectPeerModal()\"\n tabindex=\"-1\"\n [title]=\"'SETTINGS.BTN_CHANGE_PEER' | translate\"\n >\n <mat-icon>search</mat-icon>\n </button>\n\n <mat-error *ngIf=\"form.controls.peerUrl.hasError('required')\" translate>ERROR.FIELD_REQUIRED</mat-error>\n <mat-error *ngIf=\"form.controls.peerUrl.hasError('peerAlive')\" translate>\n SETTINGS.ERROR.PEER_NOT_REACHABLE\n </mat-error>\n <mat-error *ngIf=\"form.controls.peerUrl.hasError('peerNotCompatible')\" translate>\n SETTINGS.ERROR.PEER_NOT_COMPATIBLE\n </mat-error>\n </mat-form-field>\n </ion-item>\n\n <!-- Offline mode (if mobile) -->\n @if (mobile) {\n <ion-item lines=\"none\">\n <mat-form-field>\n <input matInput hidden formControlName=\"accountInheritance\" type=\"text\" />\n\n <!-- slide toggle -->\n <ion-text translate>SETTINGS.OFFLINE_MODE</ion-text>\n <mat-slide-toggle\n matSuffix\n (change)=\"network.setForceOffline($event.checked)\"\n [checked]=\"network.offline\"\n ></mat-slide-toggle>\n </mat-form-field>\n </ion-item>\n }\n </ion-list>\n\n <!-- Data entry -->\n <ion-list-header>\n <h3 translate>SETTINGS.DATA_ENTRY_DIVIDER</h3>\n </ion-list-header>\n\n <ion-list [inset]=\"mobile\">\n <!-- Usage mode -->\n <ion-item lines=\"none\">\n <mat-form-field>\n <ion-icon matPrefix name=\"id-card\"></ion-icon>\n <mat-label>{{ 'SETTINGS.USAGE_MODE' | translate }}</mat-label>\n <mat-select formControlName=\"usageMode\" required>\n <mat-option *ngFor=\"let item of usageModes\" [value]=\"item\">\n {{ 'SETTINGS.USAGE_MODES.' + item | translate }}\n </mat-option>\n </mat-select>\n <mat-error *ngIf=\"form.controls.usageMode.hasError('required')\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n </mat-form-field>\n </ion-item>\n\n <!-- lat/long format-->\n <ion-item lines=\"none\">\n <mat-form-field>\n <ion-icon matPrefix name=\"locate\"></ion-icon>\n <mat-label>{{ 'SETTINGS.LAT_LONG_FORMAT' | translate }}</mat-label>\n <mat-select formControlName=\"latLongFormat\" 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=\"form.controls.latLongFormat.hasError('required')\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n </mat-form-field>\n </ion-item>\n </ion-list>\n\n <!-- fields options -->\n <app-properties-form\n #propertiesForm\n formArrayName=\"properties\"\n [definitions]=\"propertyDefinitions\"\n [options]=\"{ allowEmptyArray: true }\"\n [mobile]=\"mobile\"\n [showAddButton]=\"!mobile\"\n [showHintKey]=\"isAdmin\"\n ></app-properties-form>\n </ion-col>\n\n <!-- right margin -->\n <ion-col size=\"0\" size-lg=\"1\" size-xl=\"2\">&nbsp;</ion-col>\n </ion-row>\n </ion-grid>\n </form>\n</ion-content>\n\n<ion-footer hidden-xs hidden-sm hidden-mobile>\n <app-form-buttons-bar\n (onCancel)=\"cancel()\"\n (onSave)=\"save($event)\"\n [disabled]=\"!form.dirty || saving\"\n ></app-form-buttons-bar>\n</ion-footer>\n" }]
29243
29335
  }], ctorParameters: () => [{ type: i0.Injector }, { type: PlatformService }, { type: i2$1.NavController }, { type: LocalSettingsValidatorService }, { type: i2$1.AlertController }, { type: i1$1.TranslateService }, { type: i1$3.UntypedFormBuilder }, { type: AccountService }, { type: LocalSettingsService }, { type: i0.ChangeDetectorRef }, { type: NetworkService }, { type: undefined, decorators: [{
29244
29336
  type: Inject,
29245
29337
  args: [APP_LOCALES]
@@ -29578,7 +29670,7 @@ class EntitiesTableDataSource extends TableDataSource {
29578
29670
  .deleteAll([row.currentData], this.serviceOptions)
29579
29671
  .catch((err) => this.handleServiceError(err))
29580
29672
  .then(() => {
29581
- setTimeout$1(() => {
29673
+ setTimeout(() => {
29582
29674
  // make sure row has been deleted (because GrapQHl cache remove can failed)
29583
29675
  const present = this.getRow(id) === row;
29584
29676
  if (present)
@@ -30719,7 +30811,7 @@ class AppTable {
30719
30811
  this.emitRefresh(event);
30720
30812
  // When target wait for a complete (e.g. IonRefresher)
30721
30813
  if (event?.target && event.target.complete) {
30722
- setTimeout$1(async () => {
30814
+ setTimeout(async () => {
30723
30815
  await this.waitIdle();
30724
30816
  event.target.complete();
30725
30817
  });
@@ -31252,7 +31344,7 @@ class AppTable {
31252
31344
  if (!this.table) {
31253
31345
  // DEBUG only -- alert user that table not found in template
31254
31346
  if (this.debug) {
31255
- setTimeout$1(() => !this.table &&
31347
+ setTimeout(() => !this.table &&
31256
31348
  console.warn(`[table] Missing <mat-table> in the HTML template (after waiting 500ms)! Component: ${this.constructor.name}`), 500);
31257
31349
  }
31258
31350
  // Make sure to wait the table
@@ -33402,7 +33494,7 @@ class AppAsyncTable {
33402
33494
  this.emitRefresh(event);
33403
33495
  // When target wait for a complete (e.g. IonRefresher)
33404
33496
  if (event?.target && event.target.complete) {
33405
- setTimeout$1(async () => {
33497
+ setTimeout(async () => {
33406
33498
  await this.waitIdle();
33407
33499
  event.target.complete();
33408
33500
  });
@@ -33927,7 +34019,7 @@ class AppAsyncTable {
33927
34019
  if (!this.table) {
33928
34020
  // DEBUG only -- alert user that table not found in template
33929
34021
  if (this.debug) {
33930
- setTimeout$1(() => !this.table &&
34022
+ setTimeout(() => !this.table &&
33931
34023
  console.warn(`[table] Missing <mat-table> in the HTML template (after waiting 500ms)! Component: ${this.constructor.name}`), 500);
33932
34024
  }
33933
34025
  // Make sure to wait the table
@@ -35473,7 +35565,7 @@ class AppTabEditor extends AppEditor {
35473
35565
  }
35474
35566
  }
35475
35567
  // Realign tab, after a delay because the tab can be disabled when component is created
35476
- setTimeout$1(() => this.tabGroup.realignInkBar(), 500);
35568
+ setTimeout(() => this.tabGroup.realignInkBar(), 500);
35477
35569
  }));
35478
35570
  }
35479
35571
  }
@@ -35496,7 +35588,7 @@ class AppTabEditor extends AppEditor {
35496
35588
  this.tabGroup.selectedIndex = value;
35497
35589
  this.markForCheck();
35498
35590
  // Wait tab change in UI, before realign ink tab
35499
- setTimeout$1(() => this.tabGroup.realignInkBar(), 200);
35591
+ setTimeout(() => this.tabGroup.realignInkBar(), 200);
35500
35592
  }
35501
35593
  else if (!opts || opts.emitEvent !== false) {
35502
35594
  this.markForCheck();
@@ -35557,7 +35649,7 @@ class AppTabEditor extends AppEditor {
35557
35649
  console.error('[tab-page] Unknown swipe action: ' + event.type);
35558
35650
  return false;
35559
35651
  }
35560
- setTimeout$1(() => {
35652
+ setTimeout(() => {
35561
35653
  this.selectedTabIndex = selectTabIndex;
35562
35654
  this.markForCheck();
35563
35655
  });
@@ -35693,7 +35785,7 @@ class AppEntityEditorModal extends AppTabEditor {
35693
35785
  }
35694
35786
  else {
35695
35787
  // Use a timeout to avoid error 'NG0100: ExpressionChangedAfterItHasBeenCheckedError'
35696
- setTimeout$1(() => this.load());
35788
+ setTimeout(() => this.load());
35697
35789
  }
35698
35790
  }
35699
35791
  ngOnDestroy() {
@@ -36306,7 +36398,7 @@ class AccountPage extends AppForm {
36306
36398
  }));
36307
36399
  this.registerSubscription(this.configService.config.subscribe((config) => this.onConfigLoaded(config)));
36308
36400
  // Realign tab, after a delay because the tab can be disabled when component is created
36309
- setTimeout$1(() => this.tabGroup.realignInkBar(), 500);
36401
+ setTimeout(() => this.tabGroup.realignInkBar(), 500);
36310
36402
  }
36311
36403
  ngOnDestroy() {
36312
36404
  super.ngOnDestroy();
@@ -36446,7 +36538,7 @@ class AccountPage extends AppForm {
36446
36538
  this.disable();
36447
36539
  await this.accountService.save(newAccount);
36448
36540
  // Reload
36449
- setTimeout$1(() => this.onLogin(this.accountService.account), 100);
36541
+ setTimeout(() => this.onLogin(this.accountService.account), 100);
36450
36542
  this.markAsPristine();
36451
36543
  return true;
36452
36544
  }
@@ -37275,7 +37367,7 @@ class AppEntityEditor extends AppTabEditor {
37275
37367
  super.ngAfterViewInit();
37276
37368
  // Load data
37277
37369
  if (this._autoLoad) {
37278
- setTimeout$1(() => this.loadFromRoute(), this._autoLoadDelay);
37370
+ setTimeout(() => this.loadFromRoute(), this._autoLoadDelay);
37279
37371
  }
37280
37372
  }
37281
37373
  ngOnDestroy() {
@@ -37610,7 +37702,7 @@ class AppEntityEditor extends AppTabEditor {
37610
37702
  return false;
37611
37703
  }
37612
37704
  // Wait, then go back (wait is need in order to update back href is need)
37613
- await setTimeout$1(() => this.goBack(), 500);
37705
+ await setTimeout(() => this.goBack(), 500);
37614
37706
  return true;
37615
37707
  }
37616
37708
  async reload() {
@@ -38689,7 +38781,6 @@ class UserEventNotificationIcon {
38689
38781
  if (this.visible !== value) {
38690
38782
  this.visible = value;
38691
38783
  this.cd.markForCheck();
38692
- // FIXME: if zoneless timers, should use detectChanges() ?
38693
38784
  }
38694
38785
  }
38695
38786
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.8", ngImport: i0, type: UserEventNotificationIcon, deps: [{ token: APP_USER_EVENT_SERVICE, optional: true }, { token: AccountService }, { token: i2$1.PopoverController }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
@@ -39005,7 +39096,7 @@ class MessageModal {
39005
39096
  this.canSelectType = toBoolean(this.canSelectType, this.accountService.isAdmin());
39006
39097
  }
39007
39098
  ngAfterViewInit() {
39008
- setTimeout$1(() => {
39099
+ setTimeout(() => {
39009
39100
  this.form.markAsReady({ emitEvent: false });
39010
39101
  if (this.data) {
39011
39102
  this.data.type = this.data.type || MessageTypes.INBOX_MESSAGE;
@@ -39378,7 +39469,7 @@ class JobProgressionIcon extends RxState {
39378
39469
  // emit event
39379
39470
  this.jobFinished.emit(progression.id);
39380
39471
  if (this.autoRemove) {
39381
- setTimeout$1(() => {
39472
+ setTimeout(() => {
39382
39473
  this.stopListenJob(progression.id);
39383
39474
  }, this.autoRemoveDelay);
39384
39475
  }
@@ -40732,13 +40823,13 @@ class LatLongTestPage {
40732
40823
  this.form.get('enable').valueChanges.subscribe((value) => disableFormGroup.setValue(value));
40733
40824
  }
40734
40825
  ngOnInit() {
40735
- setTimeout$1(() => this.loadData(), 250);
40826
+ setTimeout(() => this.loadData(), 250);
40736
40827
  }
40737
40828
  toggleMode(value) {
40738
40829
  if (this.mode !== value) {
40739
40830
  this.mode = value;
40740
40831
  }
40741
- setTimeout$1(() => this.loadData(), 250);
40832
+ setTimeout(() => this.loadData(), 250);
40742
40833
  }
40743
40834
  // Load the form with data
40744
40835
  async loadData() {
@@ -40786,7 +40877,7 @@ class LatLongTestPage {
40786
40877
  }
40787
40878
  this.geoPositionMessage = logMessage;
40788
40879
  // Clean the log message, if same
40789
- setTimeout$1(() => {
40880
+ setTimeout(() => {
40790
40881
  if (this.geoPositionMessage === logMessage) {
40791
40882
  this.geoPositionMessage = null;
40792
40883
  }
@@ -41602,7 +41693,7 @@ class UploadFileTestingPage {
41602
41693
  return { type: HttpEventType.UploadProgress, total: file.size, loaded };
41603
41694
  }
41604
41695
  // Stop the timer
41605
- setTimeout$1(() => $stop.next(), 1000);
41696
+ setTimeout(() => $stop.next(), 1000);
41606
41697
  // Return final response
41607
41698
  return new HttpResponse({ body: { finalName: file.name } });
41608
41699
  }));
@@ -43141,7 +43232,7 @@ class ArrayFormTestPage extends AppForm {
43141
43232
  this.cd = cd;
43142
43233
  }
43143
43234
  ngOnInit() {
43144
- setTimeout$1(() => this.loadData(), 250);
43235
+ setTimeout(() => this.loadData(), 250);
43145
43236
  }
43146
43237
  ngOnDestroy() {
43147
43238
  this.subscription.unsubscribe();
@@ -43882,5 +43973,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.8", ngImpor
43882
43973
  * Generated bundle index. Do not edit.
43883
43974
  */
43884
43975
 
43885
- export { APP_ABOUT_DEVELOPERS, APP_ABOUT_PARTNERS, APP_CONFIG_OPTIONS, APP_DEBUG_DATA_SERVICE, APP_FORM_ERROR_I18N_KEYS, APP_GRAPHQL_FRAGMENTS, APP_GRAPHQL_TYPE_POLICIES, APP_HOME_BUTTONS, APP_JOB_PROGRESSION_SERVICE, APP_LOCALES, APP_LOCAL_SETTINGS, APP_LOCAL_SETTINGS_OPTIONS, APP_LOCAL_STORAGE_TYPE_POLICIES, APP_LOGGING_SERVICE, APP_MENU_ITEMS, APP_MENU_OPTIONS, APP_NAMED_FILTER_SERVICE, APP_PROGRESS_BAR_SERVICE, APP_SETTINGS_MENU_ITEMS, APP_STORAGE, APP_STORAGE_EXPLORER_PROTECTED_KEYS, APP_TESTING_PAGES, APP_USER_EVENT_LIST_INFINITE_SCROLL_THRESHOLD, APP_USER_EVENT_SERVICE, APP_USER_SETTINGS_OPTIONS, APP_USER_TOKEN_SCOPES, AboutModal, AbstractNamedFilterService, AbstractSelectionModelPipe, AbstractTableSelectionPipe, AbstractUserEventService, Account, AccountPage, AccountService, AccountToStringPipe, AccountUtils, ActionsColumnComponent, AdminModule, AdminRoutingModule, AdminUsersModule, Alerts, AndroidOsEnvironment, AppAboutModalModule, AppAccountModule, AppAsyncTable, AppAuthForm, AppAuthModal, AppAuthModule, AppChangePasswordModule, AppChangePasswordPage, AppEditor, AppEditorOptions, AppEntityEditor, AppEntityEditorModal, AppEntityEditorModalOptions, AppEntityFormModule, AppForm, AppFormArray, AppFormButtonsBarModule, AppFormContainer, AppFormField, AppFormModule, AppFormProvider, AppFormUtils, AppGestureConfig, AppGraphQLModule, AppHelpModal, AppHomePageModule, AppIconComponent, AppIconModule, AppImageGalleryComponent, AppInMemoryTable, AppInstallUpgradeCard, AppInstallUpgradeCardModule, AppListForm, AppListFormModule, AppLoadingSpinner, AppMenuModule, AppNullForm, AppPropertiesForm, AppPropertiesFormModule, AppPropertiesTable, AppRegisterModule, AppResetPasswordModal, AppRowField, AppSelectPeerModule, AppSettingsPageModule, AppTabEditor, AppTabEditorOptions, AppTable, AppTableModule, AppTableUtils, AppTextPopoverModule, AppUpdateOfflineModeCard, AppUpdateOfflineModeCardModule, AppValidatorService, ArrayFilterPipe, ArrayFirstPipe, ArrayFormTestPage, ArrayIncludesPipe, ArrayJoinPipe, ArrayLastPipe, ArrayLengthPipe, ArrayPluckPipe, AsAnyPipe, AsArrayPipe, AsBooleanPipe, AsFloatLabelTypePipe, AsObservablePipe, AudioProvider, AudioTestingModule, AudioTestingPage, AuthGuardService, AutoTitleDirective, AutocompleteTestPage, AutofocusDirective, BadgeDirective, BadgeNumberPipe, Base58, BaseEntityService, BaseGraphqlService, BaseGraphqlServiceOptions, BaseReferential, Beans, BooleanFormatPipe, BooleanTestPage, CORE_CONFIG_OPTIONS, CORE_TESTING_PAGES, CapitalizePipe, CellValueChangeListener, ChangePasswordForm, ChipsTestPage, Color, ColorScale, ComponentDirtyGuard, ConfigFragments, ConfigService, Configuration, CoreModule, CorePipesModule, CoreTestingModule, CryptoService, CsvUtils, DATE_ISO_PATTERN, DATE_MATCH_REGEXP, DATE_PATTERN, DATE_UNIX_MS_TIMESTAMP, DATE_UNIX_TIMESTAMP, DEFAULT_JOIN_ARRAY_VALUES_SEPARATOR, DEFAULT_JOIN_PROPERTIES_SEPARATOR, DEFAULT_MENU_SHOW_WHEN, DEFAULT_PAGE_SIZE, DEFAULT_PAGE_SIZE_OPTIONS, DEFAULT_PLACEHOLDER_CHAR, DEFAULT_REQUIRED_COLUMNS, DateDiffDurationPipe, DateFormatPipe, DateFormatService, DateFromNowPipe, DateShortTestPage, DateTestPage, DateTimeTestPage, DateUtils, DebugComponent, Department, DepartmentToStringPipe, DragAndDropDirective, DurationPipe, DurationTestPage, ED25519_SEED_LENGTH, EMPTY_PLACEHOLDER_CHAR, EMPTY_PLACEHOLDER_CHAR_REGEXP_GLOBAL, ENTITIES_STORAGE_KEY_PREFIX, ENVIRONMENT, EmptyArrayPipe, EntitiesAsyncTableDataSource, EntitiesStorage, EntitiesTableDataSource, Entity, EntityClass, EntityClasses, EntityFilter, EntityFilterUtils, EntityMetadataComponent, EntityStore, EntityUtils, Environment, EnvironmentHttpLoader, EnvironmentLoader, ErrorCodes, EvenPipe, FileResponse, FileService, FileSizePipe, FilesUtils, FormArrayHelper, FormArrayTestModule, FormButtonsBarComponent, FormButtonsBarToken, FormErrorPipe, FormErrorTranslatePipe, FormErrorTranslator, FormFieldValuesHolder, FormGetArrayPipe, FormGetControlPipe, FormGetGroupPipe, FormGetPipe, FormGetValuePipe, GalleryTestPage, GeolocationUtils, GraphqlService, HAMMER_PRESS_TIME, HAMMER_TAP_TIME, HighlightPipe, HomePage, Hotkeys, HotkeysDialogComponent, IMAGE_DEFAULTS, IPosition, ImageAttachment, ImageAttachmentFilter, ImageAttachmentService, ImageGalleryModule, ImageGalleryTestingModule, ImageModule, ImageService, ImagesUtils, InMemoryEntitiesService, IsAllSelectedPipe, IsEmptySelectionPipe, IsLoginAccountPipe, IsMultipleSelectionPipe, IsNilOrBlankPipe, IsNilOrNaNPipe, IsNilPipe, IsNotAllSelectedPipe, IsNotEmptySelectionPipe, IsNotNilOrBlankPipe, IsNotNilOrNaNPipe, IsNotNilPipe, IsOnDeskPipe, IsOnFieldPipe, IsSelectedPipe, IsSingleSelectionPipe, JobModule, JobProgression, JobProgressionComponent, JobProgressionIcon, JobProgressionList, JobProgressionService, JobProgressionTestService, JobProgressionTestingPage, JobTestingModule, JobUtils, JsonUtils, KEYBOARD_HIDE_DELAY_MS, LAT_LONG_DEFAULT_MAX_DECIMALS, LAT_LONG_PATTERNS, LatLongFormatPipe, LatLongTestPage, LatitudeFormatPipe, LocalSettingsService, LogLevel, LogUtils, Logger, LoggingService, LoggingServiceModule, LongitudeFormatPipe, MASKS, MAT_FORM_FIELD_DEFAULT_APPEARANCE, MAT_FORM_FIELD_DEFAULT_SUBSCRIPT_SIZING, MINIFY_ENTITY_FOR_LOCAL_STORAGE, MINIFY_ENTITY_FOR_POD, MOMENT_NO_TIME_PROPERTY, MapGetPipe, MapKeysPipe, MapValuesPipe, MaskitoPlaceholderPipe, MaskitoTestPage, MatAutocompleteConfigHolder, MatAutocompleteField, MatAutocompleteFieldUtils, MatBadgeTestPage, MatBooleanField, MatChipsField, MatColorPipe, MatCommonTestPage, MatDate, MatDateShort, MatDateTime, MatDuration, MatLatLongField, MatPaginatorI18n, MatStepperI18n, MatSwipeField, MaterialTestingModule, MathAbsPipe, MenuComponent, MenuItem, MenuItems, MenuOptions, MenuService, MenuTestingModule, MenuTestingPage, Message, MessageFilter, MessageForm, MessageModal, MessageModule, MessageService, MessageTypeList, MessageTypes, MimeTypes, ModalToolbarComponent, NETWORK_DEFAULT_CONNECTION_TIMEOUT, NamedFilter, NamedFilterFilter, NamedFilterSelector, NamedFilterSelectorTestingModule, NamedFilterSelectorTestingPage, NavActionsColumnComponent, NetworkService, NewTokenModal, NgInitDirective, NgVarDirective, NoHtmlPipe, NotEmptyArrayPipe, NumberFormatPipe, ObservableTestPage, OddPipe, OtherMenuTestingPage, PEER_URL_REGEXP, PLUS_PLACEHOLDER_CHAR_REGEXP_GLOBAL, PRIORITIZED_AUTHORITIES, PUBKEY_REGEXP, Peer, Person, PersonFilter, PersonFragments, PersonService, PersonToStringPipe, PersonUtils, PersonValidatorService, PlatformService, ProgressBarService, ProgressInterceptor, PropertiesFormTestPage, PropertiesFormTestingModule, PropertyEntity, PropertyEntityFilter, PropertyEntityValidator, PropertyFormatPipe, PropertyGetPipe, RESERVED_END_COLUMNS, RESERVED_START_COLUMNS, Referential, ReferentialFilter, ReferentialRef, ReferentialToStringPipe, ReferentialUtils, ReferentialValidatorService, RegisterConfirmPage, RegisterForm, RegisterModal, ResizableComponent, ResizableDirective, ResizableModule, RxStateModule, SCRYPT_PARAMS, SETTINGS_DISPLAY_COLUMNS, SETTINGS_FILTER, SETTINGS_PAGE_SIZE, SETTINGS_SORTED_COLUMN, SETTINGS_STORAGE_KEY, SETTINGS_TRANSIENT_PROPERTIES, SHARED_MATERIAL_TESTING_PAGES, SHARED_STORAGE_TESTING_PAGES, SHARED_TESTING_PAGES, SOCIAL_TESTING_PAGES, SPACE_PLACEHOLDER_CHAR, SPACE_PLACEHOLDER_CHAR_REGEXP_GLOBAL, SafeHtmlPipe, SelectPeerModal, SelectionLengthPipe, ServerErrorCodes, SettingsPage, SharedAsyncValidators, SharedBadgeModule, SharedDebugModule, SharedDirectivesModule, SharedFormArrayValidators, SharedFormGroupValidators, SharedHotkeysModule, SharedMatAutocompleteModule, SharedMatBooleanModule, SharedMatChipsModule, SharedMatDateTimeModule, SharedMatDurationModule, SharedMatLatLongModule, SharedMatSwipeModule, SharedMaterialModule, SharedModule, SharedNamedFilterModule, SharedPipesModule, SharedRoutingModule, SharedTestingModule, SharedTestsPage, SharedTextFormModule, SharedToolbarModule, SharedValidators, SocialErrorCodes, SocialModule, SocialModuleOptionsToken, SocialTestingModule, Software, StartableService, StatusById, StatusIds, StatusList, StorageDrivers, StorageExplorerComponent, StorageExplorerModule, StorageExplorerTestingModule, StorageExplorerTestingRoutingModule, StorageService, StrIncludesPipe, StrLengthPipe, SubMenuTabDirective, SwipeTestPage, Table2TestPage, TableSelectColumnsComponent, TableTestPage, TableTestingModule, TableValidatorService, TextForm, TextFormTestingPage, TextPopover, TextPopoverTestingModule, TextPopoverTestingPage, ToStringPipe, ToastTestingModule, ToastTestingPage, Toasts, TokenScope, ToolbarComponent, ToolbarToken, TranslatablePipe, TranslateContextPipe, TranslateContextService, TreeItemEntityUtils, UploadFile, UploadFileComponent, UploadFilePopover, UploadFileTestingModule, UploadFileTestingPage, UriUtils, UserEventModule, UserEventNotificationIcon, UserEventNotificationList, UserEventTestService, UserEventTestingModule, UserEventTestingPage, UserSettings, UserToken, UserTokenTable, UsersPage, ValueFormatPipe, accountToString, adaptValueToControl, addValueInArray, arrayDistinct, arrayResize, arraySize, asInputElement, booleanToString, canHaveFocus, capitalizeFirstLetter, chainPromises, changeCaseToUnderscore, clearValueInArray, collectByProperty, copyEntity2Form, createPromiseEvent, createPromiseEventEmitter, departmentToString, departmentsToString, disableControls, emitPromiseEvent, entityToString, equals, equalsOrNil, escapeRegExp, fadeInAnimation, fadeInOutAnimation, fadeInSlowAnimation, filterFalse, filterFormErrors, filterFormErrorsByPath, filterFormErrorsByPrefix, filterNotNil, filterNumberInput, filterTrue, findParentWithClass, firstArrayValue, firstFalse, firstFalsePromise, firstNotNil, firstNotNilPromise, firstTrue, firstTruePromise, focusInput, focusNextInput, focusPreviousInput, formatLatLong, formatLatitude, formatLongitude, fromDateISOString, fromScrollEndEvent, fromUnixMsTimestamp, fromUnixTimestamp, getCaretPosition, getColorContrast, getColorShade, getColorTint, getConnectionType, getControlFromPath, getFocusableInputElements, getFormErrors, getFormValueFromEntity, getInputRangeFromCaretIndex, getInputSelectionRangesFromMask, getProperty, getPropertyByPath, getPropertyByPathAsString, getRandomImage, getRandomImageWithCredit, hexToRgb, hexToRgbArray, initArrayControlsFromValues, intersectArrays, isAndroid, isBlankString, isCapacitor, isControlHasInput, isEmptyArray, isIOS, isInputElement, isInstanceOf, isInt, isMobile, isNil, isNilOrBlank, isNilOrNaN, isNotEmptyArray, isNotNil, isNotNilBoolean, isNotNilObject, isNotNilOrBlank, isNotNilOrNaN, isNotNilString, isNumber, isNumberRange, isOnFieldMode, isProgressEvent, isResponseEvent, isStartableService, isTouchUi, isWindows, joinProperties, joinPropertiesPath, lastArrayValue, logFormErrors, markAllAsTouched, markAsUntouched, markControlAsTouched, markFormGroupAsTouched, maskitoAutoSelectByMaskPattern, maskitoPrefixPlugin, matchMedia, matchUpperCase, mergeLoadResult, mixHex, moveInputCaretToSeparator, newArray, noHtml, noTrailingSlash, notNilOrDefault, nullIfNilOrBlank, nullIfUndefined, parseLatitudeOrLongitude, propertiesPathComparator, propertyComparator, propertyPathComparator, referentialToString, referentialsToString, remove, removeAll, removeDiacritics, removeDuplicatesFromArray, removeEnd, removeValueInArray, replaceAll, resetCalculatedValue, resizeArray, rgbArrayToHex, rgbToHex, round, scrollFactory, selectInputContent, selectInputRange, setCalculatedValue, setPropertyByPath, setTabIndex, sleep, slideInAnimation, slideInOutAnimation, slideUpDownAnimation, sort, splitById, splitByProperty, startsWithUpperCase, suggestFromArray, suggestFromStringArray, tabindexComparator, testUserAgent, toBoolean, toDateISOString, toDuration, toFloat, toInt, toNotNil, toNumber, trimEmptyToNull, uncapitalizeFirstLetter, undefinedIfNull, underscoreToChangeCase, updateValueAndValidity, waitFor, waitForFalse, waitForTrue, waitIdle, waitWhilePending };
43976
+ export { APP_ABOUT_DEVELOPERS, APP_ABOUT_PARTNERS, APP_CONFIG_OPTIONS, APP_DEBUG_DATA_SERVICE, APP_FORM_ERROR_I18N_KEYS, APP_GRAPHQL_FRAGMENTS, APP_GRAPHQL_TYPE_POLICIES, APP_HOME_BUTTONS, APP_HOTKEYS_CONFIG, APP_JOB_PROGRESSION_SERVICE, APP_LOCALES, APP_LOCAL_SETTINGS, APP_LOCAL_SETTINGS_OPTIONS, APP_LOCAL_STORAGE_TYPE_POLICIES, APP_LOGGING_SERVICE, APP_MENU_ITEMS, APP_MENU_OPTIONS, APP_NAMED_FILTER_SERVICE, APP_PROGRESS_BAR_SERVICE, APP_SETTINGS_MENU_ITEMS, APP_STORAGE, APP_STORAGE_EXPLORER_PROTECTED_KEYS, APP_TESTING_PAGES, APP_USER_EVENT_LIST_INFINITE_SCROLL_THRESHOLD, APP_USER_EVENT_SERVICE, APP_USER_SETTINGS_OPTIONS, APP_USER_TOKEN_SCOPES, AboutModal, AbstractNamedFilterService, AbstractSelectionModelPipe, AbstractTableSelectionPipe, AbstractUserEventService, Account, AccountPage, AccountService, AccountToStringPipe, AccountUtils, ActionsColumnComponent, AdminModule, AdminRoutingModule, AdminUsersModule, Alerts, AndroidOsEnvironment, AppAboutModalModule, AppAccountModule, AppAsyncTable, AppAuthForm, AppAuthModal, AppAuthModule, AppChangePasswordModule, AppChangePasswordPage, AppEditor, AppEditorOptions, AppEntityEditor, AppEntityEditorModal, AppEntityEditorModalOptions, AppEntityFormModule, AppForm, AppFormArray, AppFormButtonsBarModule, AppFormContainer, AppFormField, AppFormModule, AppFormProvider, AppFormUtils, AppGestureConfig, AppGraphQLModule, AppHelpModal, AppHomePageModule, AppIconComponent, AppIconModule, AppImageGalleryComponent, AppInMemoryTable, AppInstallUpgradeCard, AppInstallUpgradeCardModule, AppListForm, AppListFormModule, AppLoadingSpinner, AppMenuModule, AppNullForm, AppPropertiesForm, AppPropertiesFormModule, AppPropertiesTable, AppPropertiesUtils, AppPropertyUtils, AppRegisterModule, AppResetPasswordModal, AppRowField, AppSelectPeerModule, AppSettingsPageModule, AppTabEditor, AppTabEditorOptions, AppTable, AppTableModule, AppTableUtils, AppTextPopoverModule, AppUpdateOfflineModeCard, AppUpdateOfflineModeCardModule, AppValidatorService, ArrayFilterPipe, ArrayFirstPipe, ArrayFormTestPage, ArrayIncludesPipe, ArrayJoinPipe, ArrayLastPipe, ArrayLengthPipe, ArrayPluckPipe, AsAnyPipe, AsArrayPipe, AsBooleanPipe, AsFloatLabelTypePipe, AsObservablePipe, AudioProvider, AudioTestingModule, AudioTestingPage, AuthGuardService, AutoTitleDirective, AutocompleteTestPage, AutofocusDirective, BadgeDirective, BadgeNumberPipe, Base58, BaseEntityService, BaseGraphqlService, BaseGraphqlServiceOptions, BaseReferential, Beans, BooleanFormatPipe, BooleanTestPage, CORE_CONFIG_OPTIONS, CORE_TESTING_PAGES, CapitalizePipe, CellValueChangeListener, ChangePasswordForm, ChipsTestPage, Color, ColorScale, ComponentDirtyGuard, ConfigFragments, ConfigService, Configuration, CoreModule, CorePipesModule, CoreTestingModule, CryptoService, CsvUtils, DATE_ISO_PATTERN, DATE_MATCH_REGEXP, DATE_PATTERN, DATE_UNIX_MS_TIMESTAMP, DATE_UNIX_TIMESTAMP, DEFAULT_JOIN_ARRAY_VALUES_SEPARATOR, DEFAULT_JOIN_PROPERTIES_SEPARATOR, DEFAULT_MENU_SHOW_WHEN, DEFAULT_PAGE_SIZE, DEFAULT_PAGE_SIZE_OPTIONS, DEFAULT_PLACEHOLDER_CHAR, DEFAULT_REQUIRED_COLUMNS, DateDiffDurationPipe, DateFormatPipe, DateFormatService, DateFromNowPipe, DateShortTestPage, DateTestPage, DateTimeTestPage, DateUtils, DebugComponent, Department, DepartmentToStringPipe, DragAndDropDirective, DurationPipe, DurationTestPage, ED25519_SEED_LENGTH, EMPTY_PLACEHOLDER_CHAR, EMPTY_PLACEHOLDER_CHAR_REGEXP_GLOBAL, ENTITIES_STORAGE_KEY_PREFIX, ENVIRONMENT, EmptyArrayPipe, EntitiesAsyncTableDataSource, EntitiesStorage, EntitiesTableDataSource, Entity, EntityClass, EntityClasses, EntityFilter, EntityFilterUtils, EntityMetadataComponent, EntityStore, EntityUtils, Environment, EnvironmentHttpLoader, EnvironmentLoader, ErrorCodes, EvenPipe, FileResponse, FileService, FileSizePipe, FilesUtils, FormArrayHelper, FormArrayTestModule, FormButtonsBarComponent, FormButtonsBarToken, FormErrorPipe, FormErrorTranslatePipe, FormErrorTranslator, FormFieldValuesHolder, FormGetArrayPipe, FormGetControlPipe, FormGetGroupPipe, FormGetPipe, FormGetValuePipe, GalleryTestPage, GeolocationUtils, GraphqlService, HAMMER_PRESS_TIME, HAMMER_TAP_TIME, HighlightPipe, HomePage, Hotkeys, HotkeysDialogComponent, IMAGE_DEFAULTS, IPosition, ImageAttachment, ImageAttachmentFilter, ImageAttachmentService, ImageGalleryModule, ImageGalleryTestingModule, ImageModule, ImageService, ImagesUtils, InMemoryEntitiesService, IsAllSelectedPipe, IsEmptySelectionPipe, IsLoginAccountPipe, IsMultipleSelectionPipe, IsNilOrBlankPipe, IsNilOrNaNPipe, IsNilPipe, IsNotAllSelectedPipe, IsNotEmptySelectionPipe, IsNotNilOrBlankPipe, IsNotNilOrNaNPipe, IsNotNilPipe, IsOnDeskPipe, IsOnFieldPipe, IsSelectedPipe, IsSingleSelectionPipe, JobModule, JobProgression, JobProgressionComponent, JobProgressionIcon, JobProgressionList, JobProgressionService, JobProgressionTestService, JobProgressionTestingPage, JobTestingModule, JobUtils, JsonUtils, KEYBOARD_HIDE_DELAY_MS, LAT_LONG_DEFAULT_MAX_DECIMALS, LAT_LONG_PATTERNS, LatLongFormatPipe, LatLongTestPage, LatitudeFormatPipe, LocalSettingsService, LogLevel, LogUtils, Logger, LoggingService, LoggingServiceModule, LongitudeFormatPipe, MASKS, MAT_FORM_FIELD_DEFAULT_APPEARANCE, MAT_FORM_FIELD_DEFAULT_SUBSCRIPT_SIZING, MINIFY_ENTITY_FOR_LOCAL_STORAGE, MINIFY_ENTITY_FOR_POD, MOMENT_NO_TIME_PROPERTY, MapGetPipe, MapKeysPipe, MapValuesPipe, MaskitoPlaceholderPipe, MaskitoTestPage, MatAutocompleteConfigHolder, MatAutocompleteField, MatAutocompleteFieldUtils, MatBadgeTestPage, MatBooleanField, MatChipsField, MatColorPipe, MatCommonTestPage, MatDate, MatDateShort, MatDateTime, MatDuration, MatLatLongField, MatPaginatorI18n, MatStepperI18n, MatSwipeField, MaterialTestingModule, MathAbsPipe, MenuComponent, MenuItem, MenuItems, MenuOptions, MenuService, MenuTestingModule, MenuTestingPage, Message, MessageFilter, MessageForm, MessageModal, MessageModule, MessageService, MessageTypeList, MessageTypes, MimeTypes, ModalToolbarComponent, NETWORK_DEFAULT_CONNECTION_TIMEOUT, NamedFilter, NamedFilterFilter, NamedFilterSelector, NamedFilterSelectorTestingModule, NamedFilterSelectorTestingPage, NavActionsColumnComponent, NetworkService, NewTokenModal, NgInitDirective, NgVarDirective, NoHtmlPipe, NotEmptyArrayPipe, NumberFormatPipe, ObservableTestPage, OddPipe, OtherMenuTestingPage, PEER_URL_REGEXP, PLUS_PLACEHOLDER_CHAR_REGEXP_GLOBAL, PRIORITIZED_AUTHORITIES, PUBKEY_REGEXP, Peer, Person, PersonFilter, PersonFragments, PersonService, PersonToStringPipe, PersonUtils, PersonValidatorService, PlatformService, ProgressBarService, ProgressInterceptor, PropertiesFormTestPage, PropertiesFormTestingModule, PropertyEntity, PropertyEntityFilter, PropertyEntityValidator, PropertyFormatPipe, PropertyGetPipe, RESERVED_END_COLUMNS, RESERVED_START_COLUMNS, Referential, ReferentialFilter, ReferentialRef, ReferentialToStringPipe, ReferentialUtils, ReferentialValidatorService, RegisterConfirmPage, RegisterForm, RegisterModal, ResizableComponent, ResizableDirective, ResizableModule, RxStateModule, SCRYPT_PARAMS, SETTINGS_DISPLAY_COLUMNS, SETTINGS_FILTER, SETTINGS_PAGE_SIZE, SETTINGS_SORTED_COLUMN, SETTINGS_STORAGE_KEY, SETTINGS_TRANSIENT_PROPERTIES, SHARED_MATERIAL_TESTING_PAGES, SHARED_STORAGE_TESTING_PAGES, SHARED_TESTING_PAGES, SOCIAL_TESTING_PAGES, SPACE_PLACEHOLDER_CHAR, SPACE_PLACEHOLDER_CHAR_REGEXP_GLOBAL, SafeHtmlPipe, SelectPeerModal, SelectionLengthPipe, ServerErrorCodes, SettingsPage, SharedAsyncValidators, SharedBadgeModule, SharedDebugModule, SharedDirectivesModule, SharedFormArrayValidators, SharedFormGroupValidators, SharedHotkeysModule, SharedMatAutocompleteModule, SharedMatBooleanModule, SharedMatChipsModule, SharedMatDateTimeModule, SharedMatDurationModule, SharedMatLatLongModule, SharedMatSwipeModule, SharedMaterialModule, SharedModule, SharedNamedFilterModule, SharedPipesModule, SharedRoutingModule, SharedTestingModule, SharedTestsPage, SharedTextFormModule, SharedToolbarModule, SharedValidators, SocialErrorCodes, SocialModule, SocialModuleOptionsToken, SocialTestingModule, Software, StartableService, StatusById, StatusIds, StatusList, StorageDrivers, StorageExplorerComponent, StorageExplorerModule, StorageExplorerTestingModule, StorageExplorerTestingRoutingModule, StorageService, StrIncludesPipe, StrLengthPipe, SubMenuTabDirective, SwipeTestPage, Table2TestPage, TableSelectColumnsComponent, TableTestPage, TableTestingModule, TableValidatorService, TextForm, TextFormTestingPage, TextPopover, TextPopoverTestingModule, TextPopoverTestingPage, ToStringPipe, ToastTestingModule, ToastTestingPage, Toasts, TokenScope, ToolbarComponent, ToolbarToken, TranslatablePipe, TranslateContextPipe, TranslateContextService, TreeItemEntityUtils, UploadFile, UploadFileComponent, UploadFilePopover, UploadFileTestingModule, UploadFileTestingPage, UriUtils, UserEventModule, UserEventNotificationIcon, UserEventNotificationList, UserEventTestService, UserEventTestingModule, UserEventTestingPage, UserSettings, UserToken, UserTokenTable, UsersPage, ValueFormatPipe, accountToString, adaptValueToControl, addValueInArray, arrayDistinct, arrayResize, arraySize, asInputElement, booleanToString, canHaveFocus, capitalizeFirstLetter, chainPromises, changeCaseToUnderscore, clearValueInArray, collectByProperty, copyEntity2Form, createPromiseEvent, createPromiseEventEmitter, departmentToString, departmentsToString, disableControls, emitPromiseEvent, entityToString, equals, equalsOrNil, escapeRegExp, fadeInAnimation, fadeInOutAnimation, fadeInSlowAnimation, filterFalse, filterFormErrors, filterFormErrorsByPath, filterFormErrorsByPrefix, filterNotNil, filterNumberInput, filterTrue, findParentWithClass, firstArrayValue, firstFalse, firstFalsePromise, firstNotNil, firstNotNilPromise, firstTrue, firstTruePromise, focusInput, focusNextInput, focusPreviousInput, formatLatLong, formatLatitude, formatLongitude, fromDateISOString, fromScrollEndEvent, fromUnixMsTimestamp, fromUnixTimestamp, getCaretPosition, getColorContrast, getColorShade, getColorTint, getConnectionType, getControlFromPath, getFocusableInputElements, getFormErrors, getFormValueFromEntity, getInputRangeFromCaretIndex, getInputSelectionRangesFromMask, getProperty, getPropertyByPath, getPropertyByPathAsString, getRandomImage, getRandomImageWithCredit, hexToRgb, hexToRgbArray, initArrayControlsFromValues, intersectArrays, isAndroid, isBlankString, isCapacitor, isControlHasInput, isEmptyArray, isIOS, isInputElement, isInstanceOf, isInt, isMobile, isNil, isNilOrBlank, isNilOrNaN, isNotEmptyArray, isNotNil, isNotNilBoolean, isNotNilObject, isNotNilOrBlank, isNotNilOrNaN, isNotNilString, isNumber, isNumberRange, isOnFieldMode, isProgressEvent, isResponseEvent, isStartableService, isTouchUi, isWindows, joinProperties, joinPropertiesPath, lastArrayValue, logFormErrors, markAllAsTouched, markAsUntouched, markControlAsTouched, markFormGroupAsTouched, maskitoAutoSelectByMaskPattern, maskitoPrefixPlugin, matchMedia, matchUpperCase, mergeLoadResult, mixHex, moveInputCaretToSeparator, newArray, noHtml, noTrailingSlash, notNilOrDefault, nullIfNilOrBlank, nullIfUndefined, parseLatitudeOrLongitude, propertiesPathComparator, propertyComparator, propertyPathComparator, referentialToString, referentialsToString, remove, removeAll, removeDiacritics, removeDuplicatesFromArray, removeEnd, removeValueInArray, replaceAll, resetCalculatedValue, resizeArray, rgbArrayToHex, rgbToHex, round, scrollFactory, selectInputContent, selectInputRange, setCalculatedValue, setPropertyByPath, setTabIndex, sleep, slideInAnimation, slideInOutAnimation, slideUpDownAnimation, sort, splitById, splitByProperty, startsWithUpperCase, suggestFromArray, suggestFromStringArray, tabindexComparator, testUserAgent, toBoolean, toDateISOString, toDuration, toFloat, toInt, toNotNil, toNumber, trimEmptyToNull, uncapitalizeFirstLetter, undefinedIfNull, underscoreToChangeCase, updateValueAndValidity, waitFor, waitForFalse, waitForTrue, waitIdle, waitWhilePending };
43886
43977
  //# sourceMappingURL=sumaris-net.ngx-components.mjs.map