@sumaris-net/ngx-components 2.7.6-rc2 → 2.8.0-rc1
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.
- package/doc/changelog.md +7 -0
- package/esm2022/public_api.mjs +5 -3
- package/esm2022/src/app/admin/users/users.mjs +3 -3
- package/esm2022/src/app/core/account/new-token.modal.mjs +4 -4
- package/esm2022/src/app/core/auth/auth.form.mjs +2 -2
- package/esm2022/src/app/core/form/entity/editor.class.mjs +33 -487
- package/esm2022/src/app/core/form/entity/entity-editor-modal.class.mjs +14 -26
- package/esm2022/src/app/core/form/entity/entity-editor.class.mjs +5 -4
- package/esm2022/src/app/core/form/entity/tab-editor.class.mjs +194 -0
- package/esm2022/src/app/core/form/form-container.class.mjs +312 -0
- package/esm2022/src/app/core/form/form.class.mjs +27 -36
- package/esm2022/src/app/core/form/form.utils.mjs +1 -1
- package/esm2022/src/app/core/form/list/list.form.mjs +4 -4
- package/esm2022/src/app/core/menu/testing/menu.testing.mjs +2 -2
- package/esm2022/src/app/core/settings/settings.page.mjs +5 -9
- package/esm2022/src/app/core/table/actions-column.component.mjs +7 -7
- package/esm2022/src/app/core/table/async-table.class.mjs +8 -8
- package/esm2022/src/app/core/table/table.class.mjs +9 -9
- package/esm2022/src/app/shared/form/field.component.mjs +2 -2
- package/esm2022/src/app/shared/image/gallery/image-gallery.component.mjs +2 -2
- package/esm2022/src/app/shared/toolbar/modal-toolbar.mjs +2 -2
- package/esm2022/src/app/shared/validator/validators.mjs +3 -2
- package/fesm2022/sumaris-net.ngx-components.mjs +310 -295
- package/fesm2022/sumaris-net.ngx-components.mjs.map +1 -1
- package/package.json +1 -1
- package/public_api.d.ts +4 -2
- package/src/app/core/account/new-token.modal.d.ts +1 -1
- package/src/app/core/form/entity/editor.class.d.ts +18 -177
- package/src/app/core/form/entity/entity-editor-modal.class.d.ts +9 -12
- package/src/app/core/form/entity/entity-editor.class.d.ts +10 -6
- package/src/app/core/form/entity/tab-editor.class.d.ts +70 -0
- package/src/app/core/form/form-container.class.d.ts +123 -0
- package/src/app/core/form/form.class.d.ts +11 -21
- package/src/app/core/form/form.utils.d.ts +38 -23
- package/src/app/core/menu/testing/menu.testing.d.ts +1 -1
- package/src/app/core/settings/settings.page.d.ts +1 -2
- package/src/app/shared/inputs.d.ts +1 -1
- package/src/app/shared/validator/validators.d.ts +1 -0
- package/src/assets/manifest.json +1 -1
|
@@ -2395,12 +2395,13 @@ class SharedFormGroupValidators {
|
|
|
2395
2395
|
};
|
|
2396
2396
|
}
|
|
2397
2397
|
static requiredIf(fieldName, anotherFieldToCheck, opts) {
|
|
2398
|
+
const predicate = opts?.predicate || ((control) => isNotNilOrBlank(control.value));
|
|
2398
2399
|
return (group) => {
|
|
2399
2400
|
const control = group.get(fieldName);
|
|
2400
2401
|
const anotherControl = anotherFieldToCheck instanceof AbstractControl ? anotherFieldToCheck : group.get(anotherFieldToCheck);
|
|
2401
2402
|
if (!anotherControl)
|
|
2402
2403
|
throw new Error('Unable to find field to check!');
|
|
2403
|
-
if (isNilOrBlank(control.value) &&
|
|
2404
|
+
if (isNilOrBlank(control.value) && predicate(anotherControl)) {
|
|
2404
2405
|
const error = { required: true };
|
|
2405
2406
|
control.setErrors(error);
|
|
2406
2407
|
control.markAsTouched({ onlySelf: true });
|
|
@@ -11349,41 +11350,18 @@ class MatAutocompleteConfigHolder {
|
|
|
11349
11350
|
class AppForm {
|
|
11350
11351
|
_subscription = new Subscription();
|
|
11351
11352
|
_form;
|
|
11352
|
-
|
|
11353
|
+
_enabled = false;
|
|
11353
11354
|
errorTranslator;
|
|
11354
11355
|
i18nFieldPrefix = null;
|
|
11355
11356
|
translate;
|
|
11356
11357
|
settings;
|
|
11357
11358
|
destroySubject = new Subject();
|
|
11358
|
-
|
|
11359
|
-
autocompleteFields;
|
|
11359
|
+
// TODO use RxState instead ?
|
|
11360
11360
|
readySubject = new BehaviorSubject(false);
|
|
11361
11361
|
loadingSubject = new BehaviorSubject(true);
|
|
11362
11362
|
errorSubject = new BehaviorSubject(undefined);
|
|
11363
|
-
|
|
11364
|
-
|
|
11365
|
-
*/
|
|
11366
|
-
set _loading(value) {
|
|
11367
|
-
this.loadingSubject.next(value);
|
|
11368
|
-
}
|
|
11369
|
-
/**
|
|
11370
|
-
* @deprecated
|
|
11371
|
-
*/
|
|
11372
|
-
get _loading() {
|
|
11373
|
-
return this.loadingSubject.value;
|
|
11374
|
-
}
|
|
11375
|
-
/**
|
|
11376
|
-
* @deprecated
|
|
11377
|
-
*/
|
|
11378
|
-
get _$ready() {
|
|
11379
|
-
return this.readySubject;
|
|
11380
|
-
}
|
|
11381
|
-
/**
|
|
11382
|
-
* @deprecated
|
|
11383
|
-
*/
|
|
11384
|
-
get _$loading() {
|
|
11385
|
-
return this.loadingSubject;
|
|
11386
|
-
}
|
|
11363
|
+
autocompleteHelper;
|
|
11364
|
+
autocompleteFields;
|
|
11387
11365
|
get error() {
|
|
11388
11366
|
return this.errorSubject.value;
|
|
11389
11367
|
}
|
|
@@ -11424,23 +11402,32 @@ class AppForm {
|
|
|
11424
11402
|
return !this.form || this.form.untouched;
|
|
11425
11403
|
}
|
|
11426
11404
|
get enabled() {
|
|
11427
|
-
return this.
|
|
11405
|
+
return this._enabled;
|
|
11428
11406
|
}
|
|
11429
11407
|
get disabled() {
|
|
11430
|
-
return !this.
|
|
11408
|
+
return !this._enabled;
|
|
11409
|
+
}
|
|
11410
|
+
/**
|
|
11411
|
+
* @deprecated
|
|
11412
|
+
*/
|
|
11413
|
+
get _enable() {
|
|
11414
|
+
return this._enabled;
|
|
11415
|
+
}
|
|
11416
|
+
set _enable(value) {
|
|
11417
|
+
this._enabled = value;
|
|
11431
11418
|
}
|
|
11432
11419
|
disable(opts) {
|
|
11433
11420
|
this.form?.disable(opts);
|
|
11434
|
-
if (this.
|
|
11435
|
-
this.
|
|
11421
|
+
if (this._enabled) {
|
|
11422
|
+
this._enabled = false;
|
|
11436
11423
|
if (!opts || opts.emitEvent !== false)
|
|
11437
11424
|
this.markForCheck();
|
|
11438
11425
|
}
|
|
11439
11426
|
}
|
|
11440
11427
|
enable(opts) {
|
|
11441
11428
|
this.form?.enable(opts);
|
|
11442
|
-
if (!this.
|
|
11443
|
-
this.
|
|
11429
|
+
if (!this._enabled) {
|
|
11430
|
+
this._enabled = true;
|
|
11444
11431
|
if (!opts || opts.emitEvent !== false)
|
|
11445
11432
|
this.markForCheck();
|
|
11446
11433
|
}
|
|
@@ -11471,7 +11458,8 @@ class AppForm {
|
|
|
11471
11458
|
this.autocompleteFields = this.autocompleteHelper.fields;
|
|
11472
11459
|
}
|
|
11473
11460
|
ngOnInit() {
|
|
11474
|
-
|
|
11461
|
+
// Will enable/Disable the delegating angular form
|
|
11462
|
+
if (this._enabled)
|
|
11475
11463
|
this.enable();
|
|
11476
11464
|
else
|
|
11477
11465
|
this.disable();
|
|
@@ -11523,6 +11511,9 @@ class AppForm {
|
|
|
11523
11511
|
this._subscription.add(this._form.statusChanges.subscribe((_) => this.markForCheck()));
|
|
11524
11512
|
}
|
|
11525
11513
|
}
|
|
11514
|
+
getValue() {
|
|
11515
|
+
return this.form.value;
|
|
11516
|
+
}
|
|
11526
11517
|
setValue(data, opts) {
|
|
11527
11518
|
if (!data) {
|
|
11528
11519
|
console.warn('[form] Trying to set an empty value to form. Skipping');
|
|
@@ -11566,7 +11557,8 @@ class AppForm {
|
|
|
11566
11557
|
*/
|
|
11567
11558
|
markAsTouched(opts) {
|
|
11568
11559
|
// this.form.markAllAsTouched() // This is not working well (e.g. in TripForm)
|
|
11569
|
-
|
|
11560
|
+
if (this.debug)
|
|
11561
|
+
console.warn('TODO: Replace this call by markAllAsTouched() - because of changes in ngx-components >= 0.16.0');
|
|
11570
11562
|
AppFormUtils.markAsTouched(this.form, opts);
|
|
11571
11563
|
if (!opts || opts.emitEvent !== false)
|
|
11572
11564
|
this.markForCheck();
|
|
@@ -12324,7 +12316,7 @@ class AppFormField {
|
|
|
12324
12316
|
}
|
|
12325
12317
|
}
|
|
12326
12318
|
filterAlphanumericalInput(event) {
|
|
12327
|
-
if (event.
|
|
12319
|
+
if (event.code === 'Enter' && this.onKeyupEnter.observed) {
|
|
12328
12320
|
this.onKeyupEnter.emit(event);
|
|
12329
12321
|
return;
|
|
12330
12322
|
}
|
|
@@ -20557,7 +20549,7 @@ class ModalToolbarComponent {
|
|
|
20557
20549
|
this.hotkeys = hotkeys;
|
|
20558
20550
|
}
|
|
20559
20551
|
ngOnInit() {
|
|
20560
|
-
this.canValidate = toBoolean(this.canValidate, this.validate.
|
|
20552
|
+
this.canValidate = toBoolean(this.canValidate, this.validate.observed);
|
|
20561
20553
|
// Ctrl+S
|
|
20562
20554
|
this._subscription.add(this.hotkeys
|
|
20563
20555
|
.addShortcut({ keys: 'control.s', description: 'COMMON.BTN_VALIDATE', elementName: this.modalName })
|
|
@@ -22885,7 +22877,7 @@ class AppImageGalleryComponent {
|
|
|
22885
22877
|
}
|
|
22886
22878
|
async canDeleteRows(rows, opts) {
|
|
22887
22879
|
// Check using emitter
|
|
22888
|
-
if (this.onBeforeDeleteRows.
|
|
22880
|
+
if (this.onBeforeDeleteRows.observed) {
|
|
22889
22881
|
try {
|
|
22890
22882
|
const canDelete = await emitPromiseEvent(this.onBeforeDeleteRows, 'canDelete', {
|
|
22891
22883
|
detail: { rows },
|
|
@@ -26581,7 +26573,7 @@ class AppAuthForm extends AppForm {
|
|
|
26581
26573
|
this.environment = environment;
|
|
26582
26574
|
this.mobile = settings.mobile;
|
|
26583
26575
|
this.canWorkOffline = this.settings.hasOfflineFeature();
|
|
26584
|
-
this.
|
|
26576
|
+
this._enabled = true;
|
|
26585
26577
|
}
|
|
26586
26578
|
ngOnInit() {
|
|
26587
26579
|
super.ngOnInit();
|
|
@@ -27372,7 +27364,7 @@ class SettingsPage extends AppForm {
|
|
|
27372
27364
|
this.menuItems = menuItems || [];
|
|
27373
27365
|
this.mobile = this.platform.mobile;
|
|
27374
27366
|
// By default, disable the form
|
|
27375
|
-
this.
|
|
27367
|
+
this._enabled = false;
|
|
27376
27368
|
}
|
|
27377
27369
|
async ngOnInit() {
|
|
27378
27370
|
super.ngOnInit();
|
|
@@ -27572,9 +27564,9 @@ class SettingsPage extends AppForm {
|
|
|
27572
27564
|
console.error('[settings] Unknown item type (no path)', item);
|
|
27573
27565
|
}
|
|
27574
27566
|
}
|
|
27575
|
-
/* -- protected functions -- */
|
|
27576
27567
|
async getValue() {
|
|
27577
|
-
const json =
|
|
27568
|
+
const json = this.form.value;
|
|
27569
|
+
json.properties = EntityUtils.getPropertyArrayAsObject(json.properties);
|
|
27578
27570
|
// Override properties from account
|
|
27579
27571
|
if (json.accountInheritance && this.isLogin) {
|
|
27580
27572
|
const account = this.accountService.account;
|
|
@@ -27585,11 +27577,7 @@ class SettingsPage extends AppForm {
|
|
|
27585
27577
|
}
|
|
27586
27578
|
return json;
|
|
27587
27579
|
}
|
|
27588
|
-
|
|
27589
|
-
const json = this.form.value;
|
|
27590
|
-
json.properties = EntityUtils.getPropertyArrayAsObject(json.properties);
|
|
27591
|
-
return Promise.resolve(json);
|
|
27592
|
-
}
|
|
27580
|
+
/* -- protected functions -- */
|
|
27593
27581
|
async toggleDarkMode() {
|
|
27594
27582
|
const value = this.form.get('darkMode').value;
|
|
27595
27583
|
this.form.get('darkMode').setValue(!value);
|
|
@@ -28923,7 +28911,7 @@ class AppTable {
|
|
|
28923
28911
|
}
|
|
28924
28912
|
cancel(event, opts) {
|
|
28925
28913
|
// Check confirmation
|
|
28926
|
-
if ((!opts || opts.interactive !== false) && this.dirty && (this.confirmBeforeCancel || this.onBeforeCancelRows.
|
|
28914
|
+
if ((!opts || opts.interactive !== false) && this.dirty && (this.confirmBeforeCancel || this.onBeforeCancelRows.observed)) {
|
|
28927
28915
|
event?.stopPropagation();
|
|
28928
28916
|
this.canCancelRows().then((confirm) => {
|
|
28929
28917
|
// If confirmed, loop
|
|
@@ -28980,7 +28968,7 @@ class AppTable {
|
|
|
28980
28968
|
}
|
|
28981
28969
|
else {
|
|
28982
28970
|
const rows = this._dataSource.getRows();
|
|
28983
|
-
|
|
28971
|
+
this.selection.setSelection(...rows);
|
|
28984
28972
|
}
|
|
28985
28973
|
}
|
|
28986
28974
|
async deleteSelection(event, opts) {
|
|
@@ -29329,7 +29317,7 @@ class AppTable {
|
|
|
29329
29317
|
}
|
|
29330
29318
|
async canDeleteRows(rows, opts) {
|
|
29331
29319
|
// Check using emitter
|
|
29332
|
-
if (this.onBeforeDeleteRows.
|
|
29320
|
+
if (this.onBeforeDeleteRows.observed) {
|
|
29333
29321
|
try {
|
|
29334
29322
|
const canDelete = await emitPromiseEvent(this.onBeforeDeleteRows, 'canDelete', {
|
|
29335
29323
|
detail: { rows },
|
|
@@ -29356,7 +29344,7 @@ class AppTable {
|
|
|
29356
29344
|
if (isEmptyArray(rows))
|
|
29357
29345
|
return true; // No dirty: OK
|
|
29358
29346
|
// Check using emitter
|
|
29359
|
-
if (this.onBeforeCancelRows.
|
|
29347
|
+
if (this.onBeforeCancelRows.observed) {
|
|
29360
29348
|
try {
|
|
29361
29349
|
const isCancel = await emitPromiseEvent(this.onBeforeCancelRows, 'canCancel', {
|
|
29362
29350
|
detail: { rows },
|
|
@@ -29399,7 +29387,7 @@ class AppTable {
|
|
|
29399
29387
|
// Default behavior
|
|
29400
29388
|
let confirmed = true;
|
|
29401
29389
|
if (save) {
|
|
29402
|
-
if (this.onBeforeSave.
|
|
29390
|
+
if (this.onBeforeSave.observed) {
|
|
29403
29391
|
// Ask confirmation
|
|
29404
29392
|
try {
|
|
29405
29393
|
const res = await emitPromiseEvent(this.onBeforeSave, 'beforeSave', {
|
|
@@ -29440,7 +29428,7 @@ class AppTable {
|
|
|
29440
29428
|
if (this.debug && this.dirty) {
|
|
29441
29429
|
console.warn('[table] Opening row details, but table has unsaved changes!');
|
|
29442
29430
|
}
|
|
29443
|
-
if (this.onOpenRow.
|
|
29431
|
+
if (this.onOpenRow.observed) {
|
|
29444
29432
|
this.onOpenRow.emit(row);
|
|
29445
29433
|
return true;
|
|
29446
29434
|
}
|
|
@@ -29458,7 +29446,7 @@ class AppTable {
|
|
|
29458
29446
|
async openNewRowDetail(event) {
|
|
29459
29447
|
if (!this.allowRowDetail)
|
|
29460
29448
|
return false;
|
|
29461
|
-
if (this.onNewRow.
|
|
29449
|
+
if (this.onNewRow.observed) {
|
|
29462
29450
|
this.onNewRow.emit(event);
|
|
29463
29451
|
return true;
|
|
29464
29452
|
}
|
|
@@ -29803,7 +29791,7 @@ class AppTable {
|
|
|
29803
29791
|
throw new Error('Row cannot be canceling, but only deleting');
|
|
29804
29792
|
const confirmed = !opts || opts.interactive !== false;
|
|
29805
29793
|
// Ask user confirmation, if cancel
|
|
29806
|
-
if (!confirmed && row.dirty && (this.confirmBeforeCancel || this.onBeforeCancelRows.
|
|
29794
|
+
if (!confirmed && row.dirty && (this.confirmBeforeCancel || this.onBeforeCancelRows.observed)) {
|
|
29807
29795
|
event.stopPropagation();
|
|
29808
29796
|
this.canCancelRows([row], opts).then((confirm) => {
|
|
29809
29797
|
// If confirmed, loop
|
|
@@ -30101,12 +30089,12 @@ class ActionsColumnComponent {
|
|
|
30101
30089
|
ngOnInit() {
|
|
30102
30090
|
this.cd.detectChanges();
|
|
30103
30091
|
this.table.addColumnDef(this.columnDef);
|
|
30104
|
-
this.canCancel = toBoolean(this.canCancel, this.cancelOrDeleteClick.
|
|
30105
|
-
this.canConfirm = toBoolean(this.canConfirm, this.confirmEditCreateClick.
|
|
30106
|
-
this.canDelete = toBoolean(this.canDelete, this.cancelOrDeleteClick.
|
|
30107
|
-
this.canConfirmAndAdd = toBoolean(this.canConfirmAndAdd, this.confirmAndAddClick.
|
|
30108
|
-
this.canBackward = toBoolean(this.canBackward, this.backward.
|
|
30109
|
-
this.canForward = toBoolean(this.canForward, this.forward.
|
|
30092
|
+
this.canCancel = toBoolean(this.canCancel, this.cancelOrDeleteClick.observed);
|
|
30093
|
+
this.canConfirm = toBoolean(this.canConfirm, this.confirmEditCreateClick.observed);
|
|
30094
|
+
this.canDelete = toBoolean(this.canDelete, this.cancelOrDeleteClick.observed);
|
|
30095
|
+
this.canConfirmAndAdd = toBoolean(this.canConfirmAndAdd, this.confirmAndAddClick.observed);
|
|
30096
|
+
this.canBackward = toBoolean(this.canBackward, this.backward.observed);
|
|
30097
|
+
this.canForward = toBoolean(this.canForward, this.forward.observed);
|
|
30110
30098
|
if (isNil(this.dirtyIcon)) {
|
|
30111
30099
|
this.dirtyIcon = 'star';
|
|
30112
30100
|
}
|
|
@@ -30594,7 +30582,7 @@ class AppListForm extends AppForm {
|
|
|
30594
30582
|
}
|
|
30595
30583
|
}
|
|
30596
30584
|
async onItemClick(event, item, opts) {
|
|
30597
|
-
if (!item || event.defaultPrevented || !this.selectionChanges.
|
|
30585
|
+
if (!item || event.defaultPrevented || !this.selectionChanges.observed)
|
|
30598
30586
|
return;
|
|
30599
30587
|
// Multiple selection (if ctrl+click)
|
|
30600
30588
|
if (event.ctrlKey && this.options.allowMultipleSelection) {
|
|
@@ -30658,11 +30646,11 @@ class AppListForm extends AppForm {
|
|
|
30658
30646
|
this.cd.markForCheck();
|
|
30659
30647
|
}
|
|
30660
30648
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.2.4", ngImport: i0, type: AppListForm, deps: [{ token: i0.Injector }, { token: i1$2.UntypedFormBuilder }, { token: i2.DateAdapter }, { token: LocalSettingsService }, { token: i0.ChangeDetectorRef }, { token: i1$2.FormGroupDirective, optional: true }], target: i0.ɵɵFactoryTarget.Component });
|
|
30661
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.2.4", type: AppListForm, selector: "app-list-form", inputs: { formArrayName: "formArrayName", formArray: "formArray", options: "options", displayWithFn: ["displayWith", "displayWithFn"], equalsFn: ["equals", "equalsFn"] }, outputs: { onNewItem: "onNewItem", selectionChanges: "selectionChanges" }, usesInheritance: true, ngImport: i0, template: "<ng-container *ngIf=\"!loading; else listSkeleton\">\n <!-- List -->\n <ion-list class=\"ion-no-padding\">\n <ng-container *ngFor=\"let itemControl of itemControls; index as i; last as last\">\n <ion-item\n *ngIf=\"itemControl.value; let item\"\n [class.disabled]=\"disabled\"\n tappable\n (click)=\"onItemClick($event, item)\"\n [color]=\"selection.isSelected(item) ? 'secondary100' : undefined\"\n [button]=\"selectionChanges.observers | isNotEmptyArray\"\n >\n <ion-label>{{ displayWith(item) }}</ion-label>\n\n <!-- buttons -->\n <ion-buttons slot=\"end\" *ngIf=\"enabled\" class=\"action-buttons\">\n <ion-button fill=\"clear\" (click)=\"removeAt(i)\">\n <ion-icon slot=\"icon-only\" name=\"trash\"></ion-icon>\n </ion-button>\n\n <ion-button\n *ngFor=\"let button of options.buttons\"\n fill=\"clear\"\n [color]=\"button.color\"\n [class.cdk-visually-hidden]=\"button.disabled | async\"\n (click)=\"onItemButtonClick(button, $event, item, i)\"\n [title]=\"button.title || '' | translate\"\n >\n <ion-icon slot=\"icon-only\" [name]=\"button.icon\"></ion-icon>\n </ion-button>\n </ion-buttons>\n </ion-item>\n </ng-container>\n </ion-list>\n\n <!-- Add button -->\n <ion-button\n color=\"tertiary\"\n fill=\"clear\"\n *ngIf=\"enabled && onNewItem.
|
|
30649
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.2.4", type: AppListForm, selector: "app-list-form", inputs: { formArrayName: "formArrayName", formArray: "formArray", options: "options", displayWithFn: ["displayWith", "displayWithFn"], equalsFn: ["equals", "equalsFn"] }, outputs: { onNewItem: "onNewItem", selectionChanges: "selectionChanges" }, usesInheritance: true, ngImport: i0, template: "<ng-container *ngIf=\"!loading; else listSkeleton\">\n <!-- List -->\n <ion-list class=\"ion-no-padding\">\n <ng-container *ngFor=\"let itemControl of itemControls; index as i; last as last\">\n <ion-item\n *ngIf=\"itemControl.value; let item\"\n [class.disabled]=\"disabled\"\n tappable\n (click)=\"onItemClick($event, item)\"\n [color]=\"selection.isSelected(item) ? 'secondary100' : undefined\"\n [button]=\"selectionChanges.observers | isNotEmptyArray\"\n >\n <ion-label>{{ displayWith(item) }}</ion-label>\n\n <!-- buttons -->\n <ion-buttons slot=\"end\" *ngIf=\"enabled\" class=\"action-buttons\">\n <ion-button fill=\"clear\" (click)=\"removeAt(i)\">\n <ion-icon slot=\"icon-only\" name=\"trash\"></ion-icon>\n </ion-button>\n\n <ion-button\n *ngFor=\"let button of options.buttons\"\n fill=\"clear\"\n [color]=\"button.color\"\n [class.cdk-visually-hidden]=\"button.disabled | async\"\n (click)=\"onItemButtonClick(button, $event, item, i)\"\n [title]=\"button.title || '' | translate\"\n >\n <ion-icon slot=\"icon-only\" [name]=\"button.icon\"></ion-icon>\n </ion-button>\n </ion-buttons>\n </ion-item>\n </ng-container>\n </ion-list>\n\n <!-- Add button -->\n <ion-button\n color=\"tertiary\"\n fill=\"clear\"\n *ngIf=\"enabled && onNewItem.observed; else emptyText\"\n [title]=\"'COMMON.BTN_ADD' | translate\"\n (click)=\"onNewClick($event)\"\n >\n <ion-icon slot=\"start\" name=\"add\"></ion-icon>\n <ion-label translate>COMMON.BTN_ADD</ion-label>\n </ion-button>\n\n <!-- Empty (if readonly) -->\n <ng-template #emptyText>\n <ion-text *ngIf=\"!length\" color=\"medium\"><i translate>COMMON.EMPTY_OPTION</i></ion-text>\n </ng-template>\n</ng-container>\n\n<ng-template #listSkeleton>\n <ion-list>\n <ng-container *ngTemplateOutlet=\"itemSkeleton\"></ng-container>\n <ng-container *ngTemplateOutlet=\"itemSkeleton\"></ng-container>\n <ng-container *ngTemplateOutlet=\"itemSkeleton\"></ng-container>\n </ion-list>\n</ng-template>\n\n<ng-template #itemSkeleton>\n <ion-item>\n <ion-label>\n <ion-skeleton-text animated style=\"width: 60%\"></ion-skeleton-text>\n </ion-label>\n </ion-item>\n</ng-template>\n", styles: [":host{--ion-item-background-selected: var(--ion-color-secondary100);--ion-item-color-selected: var(--ion-color-secondary100-contrast)}ion-item.disabled ion-label{color:var(--ion-color-medium-shade, grey)}ion-item{--min-height: 48px;background-color:var(--ion-item-background)}ion-item ion-text,ion-item ion-label{color:var(--ion-item-color)}ion-item .action-buttons{visibility:hidden;display:none}ion-item:hover{height:var(--min-height);--ion-item-background-color: var(--ion-color-light);--ion-item-color: var(--ion-color-light-contrast)}ion-item:hover .action-buttons{margin-top:-1px;visibility:visible;display:block}ion-item.selected{--ion-item-background-color-hover: var(--ion-item-background-selected) !important;--ion-item-color-hover: var(--ion-item-color-selected) !important}\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: "directive", type: i3.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { 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.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", "counter", "counterFormatter", "detail", "detailIcon", "disabled", "download", "fill", "href", "lines", "mode", "rel", "routerAnimation", "routerDirection", "shape", "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.IonSkeletonText, selector: "ion-skeleton-text", inputs: ["animated"] }, { 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: "pipe", type: i3.AsyncPipe, name: "async" }, { kind: "pipe", type: i1$1.TranslatePipe, name: "translate" }, { kind: "pipe", type: NotEmptyArrayPipe, name: "isNotEmptyArray" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
30662
30650
|
}
|
|
30663
30651
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.2.4", ngImport: i0, type: AppListForm, decorators: [{
|
|
30664
30652
|
type: Component,
|
|
30665
|
-
args: [{ selector: 'app-list-form', changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-container *ngIf=\"!loading; else listSkeleton\">\n <!-- List -->\n <ion-list class=\"ion-no-padding\">\n <ng-container *ngFor=\"let itemControl of itemControls; index as i; last as last\">\n <ion-item\n *ngIf=\"itemControl.value; let item\"\n [class.disabled]=\"disabled\"\n tappable\n (click)=\"onItemClick($event, item)\"\n [color]=\"selection.isSelected(item) ? 'secondary100' : undefined\"\n [button]=\"selectionChanges.observers | isNotEmptyArray\"\n >\n <ion-label>{{ displayWith(item) }}</ion-label>\n\n <!-- buttons -->\n <ion-buttons slot=\"end\" *ngIf=\"enabled\" class=\"action-buttons\">\n <ion-button fill=\"clear\" (click)=\"removeAt(i)\">\n <ion-icon slot=\"icon-only\" name=\"trash\"></ion-icon>\n </ion-button>\n\n <ion-button\n *ngFor=\"let button of options.buttons\"\n fill=\"clear\"\n [color]=\"button.color\"\n [class.cdk-visually-hidden]=\"button.disabled | async\"\n (click)=\"onItemButtonClick(button, $event, item, i)\"\n [title]=\"button.title || '' | translate\"\n >\n <ion-icon slot=\"icon-only\" [name]=\"button.icon\"></ion-icon>\n </ion-button>\n </ion-buttons>\n </ion-item>\n </ng-container>\n </ion-list>\n\n <!-- Add button -->\n <ion-button\n color=\"tertiary\"\n fill=\"clear\"\n *ngIf=\"enabled && onNewItem.
|
|
30653
|
+
args: [{ selector: 'app-list-form', changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-container *ngIf=\"!loading; else listSkeleton\">\n <!-- List -->\n <ion-list class=\"ion-no-padding\">\n <ng-container *ngFor=\"let itemControl of itemControls; index as i; last as last\">\n <ion-item\n *ngIf=\"itemControl.value; let item\"\n [class.disabled]=\"disabled\"\n tappable\n (click)=\"onItemClick($event, item)\"\n [color]=\"selection.isSelected(item) ? 'secondary100' : undefined\"\n [button]=\"selectionChanges.observers | isNotEmptyArray\"\n >\n <ion-label>{{ displayWith(item) }}</ion-label>\n\n <!-- buttons -->\n <ion-buttons slot=\"end\" *ngIf=\"enabled\" class=\"action-buttons\">\n <ion-button fill=\"clear\" (click)=\"removeAt(i)\">\n <ion-icon slot=\"icon-only\" name=\"trash\"></ion-icon>\n </ion-button>\n\n <ion-button\n *ngFor=\"let button of options.buttons\"\n fill=\"clear\"\n [color]=\"button.color\"\n [class.cdk-visually-hidden]=\"button.disabled | async\"\n (click)=\"onItemButtonClick(button, $event, item, i)\"\n [title]=\"button.title || '' | translate\"\n >\n <ion-icon slot=\"icon-only\" [name]=\"button.icon\"></ion-icon>\n </ion-button>\n </ion-buttons>\n </ion-item>\n </ng-container>\n </ion-list>\n\n <!-- Add button -->\n <ion-button\n color=\"tertiary\"\n fill=\"clear\"\n *ngIf=\"enabled && onNewItem.observed; else emptyText\"\n [title]=\"'COMMON.BTN_ADD' | translate\"\n (click)=\"onNewClick($event)\"\n >\n <ion-icon slot=\"start\" name=\"add\"></ion-icon>\n <ion-label translate>COMMON.BTN_ADD</ion-label>\n </ion-button>\n\n <!-- Empty (if readonly) -->\n <ng-template #emptyText>\n <ion-text *ngIf=\"!length\" color=\"medium\"><i translate>COMMON.EMPTY_OPTION</i></ion-text>\n </ng-template>\n</ng-container>\n\n<ng-template #listSkeleton>\n <ion-list>\n <ng-container *ngTemplateOutlet=\"itemSkeleton\"></ng-container>\n <ng-container *ngTemplateOutlet=\"itemSkeleton\"></ng-container>\n <ng-container *ngTemplateOutlet=\"itemSkeleton\"></ng-container>\n </ion-list>\n</ng-template>\n\n<ng-template #itemSkeleton>\n <ion-item>\n <ion-label>\n <ion-skeleton-text animated style=\"width: 60%\"></ion-skeleton-text>\n </ion-label>\n </ion-item>\n</ng-template>\n", styles: [":host{--ion-item-background-selected: var(--ion-color-secondary100);--ion-item-color-selected: var(--ion-color-secondary100-contrast)}ion-item.disabled ion-label{color:var(--ion-color-medium-shade, grey)}ion-item{--min-height: 48px;background-color:var(--ion-item-background)}ion-item ion-text,ion-item ion-label{color:var(--ion-item-color)}ion-item .action-buttons{visibility:hidden;display:none}ion-item:hover{height:var(--min-height);--ion-item-background-color: var(--ion-color-light);--ion-item-color: var(--ion-color-light-contrast)}ion-item:hover .action-buttons{margin-top:-1px;visibility:visible;display:block}ion-item.selected{--ion-item-background-color-hover: var(--ion-item-background-selected) !important;--ion-item-color-hover: var(--ion-item-color-selected) !important}\n"] }]
|
|
30666
30654
|
}], ctorParameters: () => [{ type: i0.Injector }, { type: i1$2.UntypedFormBuilder }, { type: i2.DateAdapter }, { type: LocalSettingsService }, { type: i0.ChangeDetectorRef }, { type: i1$2.FormGroupDirective, decorators: [{
|
|
30667
30655
|
type: Optional
|
|
30668
30656
|
}] }], propDecorators: { formArrayName: [{
|
|
@@ -30900,67 +30888,31 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.2.4", ngImpor
|
|
|
30900
30888
|
args: [{ providedIn: 'root' }]
|
|
30901
30889
|
}], ctorParameters: () => [{ type: i1$2.UntypedFormBuilder }] });
|
|
30902
30890
|
|
|
30903
|
-
class AppTabEditorOptions {
|
|
30904
|
-
/**
|
|
30905
|
-
* Number of tab. 1 by default
|
|
30906
|
-
*/
|
|
30907
|
-
tabCount;
|
|
30908
|
-
/**
|
|
30909
|
-
* '200ms' by default
|
|
30910
|
-
*/
|
|
30911
|
-
tabGroupAnimationDuration;
|
|
30912
|
-
/**
|
|
30913
|
-
* Should enable swipe between tab, on touch screen
|
|
30914
|
-
*/
|
|
30915
|
-
enableSwipe; // true by default
|
|
30916
|
-
}
|
|
30917
30891
|
// eslint-disable-next-line @angular-eslint/directive-class-suffix
|
|
30918
|
-
class
|
|
30919
|
-
route;
|
|
30920
|
-
router;
|
|
30921
|
-
navController;
|
|
30922
|
-
alertCtrl;
|
|
30923
|
-
translate;
|
|
30892
|
+
class AppFormContainer {
|
|
30924
30893
|
_children;
|
|
30894
|
+
_childrenPath;
|
|
30925
30895
|
_subscription = new Subscription();
|
|
30896
|
+
_logPrefix = '[form-container] ';
|
|
30926
30897
|
_enabled = false;
|
|
30927
|
-
toastController;
|
|
30928
30898
|
destroySubject = new Subject();
|
|
30929
|
-
// TODO use RxState instead
|
|
30899
|
+
// TODO use RxState instead ?
|
|
30930
30900
|
readySubject = new BehaviorSubject(false);
|
|
30931
|
-
dirtySubject = new BehaviorSubject(false);
|
|
30932
30901
|
loadingSubject = new BehaviorSubject(true);
|
|
30933
|
-
|
|
30934
|
-
savingSubject = new BehaviorSubject(false);
|
|
30902
|
+
dirtySubject = new BehaviorSubject(false);
|
|
30935
30903
|
touchedSubject = new BehaviorSubject(false);
|
|
30936
|
-
|
|
30937
|
-
|
|
30938
|
-
|
|
30939
|
-
queryParams;
|
|
30940
|
-
i18nContext;
|
|
30941
|
-
/**
|
|
30942
|
-
* @deprecated
|
|
30943
|
-
*/
|
|
30944
|
-
set _loading(value) {
|
|
30945
|
-
this.loadingSubject.next(value);
|
|
30904
|
+
errorSubject = new BehaviorSubject(undefined);
|
|
30905
|
+
get children() {
|
|
30906
|
+
return this._children;
|
|
30946
30907
|
}
|
|
30947
|
-
|
|
30948
|
-
|
|
30949
|
-
*/
|
|
30950
|
-
get _loading() {
|
|
30951
|
-
return this.loadingSubject.value;
|
|
30908
|
+
get tables() {
|
|
30909
|
+
return this._children && this._children.filter((c) => c instanceof AppTable);
|
|
30952
30910
|
}
|
|
30953
|
-
|
|
30954
|
-
|
|
30955
|
-
*/
|
|
30956
|
-
get _$ready() {
|
|
30957
|
-
return this.readySubject;
|
|
30911
|
+
get forms() {
|
|
30912
|
+
return this._children && this._children.filter((c) => c instanceof AppForm);
|
|
30958
30913
|
}
|
|
30959
|
-
|
|
30960
|
-
|
|
30961
|
-
*/
|
|
30962
|
-
get _$loading() {
|
|
30963
|
-
return this.loadingSubject;
|
|
30914
|
+
get editors() {
|
|
30915
|
+
return this._children && this._children.filter((c) => c instanceof AppEditor);
|
|
30964
30916
|
}
|
|
30965
30917
|
get error() {
|
|
30966
30918
|
return this.errorSubject.value;
|
|
@@ -30968,30 +30920,15 @@ class AppEditor {
|
|
|
30968
30920
|
set error(error) {
|
|
30969
30921
|
this.setError(error);
|
|
30970
30922
|
}
|
|
30971
|
-
get
|
|
30972
|
-
return this.
|
|
30973
|
-
}
|
|
30974
|
-
get destroyed() {
|
|
30975
|
-
return this.destroySubject?.closed !== false;
|
|
30976
|
-
}
|
|
30977
|
-
toolbar = null;
|
|
30978
|
-
formButtonsBar = null;
|
|
30979
|
-
content;
|
|
30980
|
-
get tables() {
|
|
30981
|
-
return this._children && this._children.filter((c) => c instanceof AppTable);
|
|
30982
|
-
}
|
|
30983
|
-
get forms() {
|
|
30984
|
-
return this._children && this._children.filter((c) => c instanceof AppForm);
|
|
30923
|
+
get loading() {
|
|
30924
|
+
return this.loadingSubject.value || (this._children && this._children.findIndex((c) => c.enabled && c.loading) !== -1) || false;
|
|
30985
30925
|
}
|
|
30986
|
-
get
|
|
30987
|
-
return this.
|
|
30926
|
+
get loaded() {
|
|
30927
|
+
return (!this.loadingSubject.value && (!this._children || this._children.findIndex((c) => c.enabled && c.loading) === -1)) || false;
|
|
30988
30928
|
}
|
|
30989
30929
|
get dirty() {
|
|
30990
30930
|
return this.dirtySubject.value || (this._children && this._children.findIndex((c) => c.enabled && c.dirty) !== -1) || false;
|
|
30991
30931
|
}
|
|
30992
|
-
/**
|
|
30993
|
-
* Is valid (tables and forms)
|
|
30994
|
-
*/
|
|
30995
30932
|
get valid() {
|
|
30996
30933
|
// Important: Should be not invalid AND not pending, so use '!valid' (DO NOT use 'invalid')
|
|
30997
30934
|
return !this._children || this._children.findIndex((c) => c.enabled && !c.valid) === -1;
|
|
@@ -31002,11 +30939,8 @@ class AppEditor {
|
|
|
31002
30939
|
get pending() {
|
|
31003
30940
|
return (this._children && this._children.findIndex((c) => c.enabled && c.pending) !== -1) || false;
|
|
31004
30941
|
}
|
|
31005
|
-
get
|
|
31006
|
-
return this.
|
|
31007
|
-
}
|
|
31008
|
-
get loaded() {
|
|
31009
|
-
return (!this.loadingSubject.value && (!this._children || this._children.findIndex((c) => c.enabled && c.loading) === -1)) || false;
|
|
30942
|
+
get empty() {
|
|
30943
|
+
return !this._enabled;
|
|
31010
30944
|
}
|
|
31011
30945
|
get touched() {
|
|
31012
30946
|
return this.touchedSubject.value || (this._children && this._children.findIndex((c) => c.enabled && c.touched) !== -1) || false;
|
|
@@ -31020,39 +30954,24 @@ class AppEditor {
|
|
|
31020
30954
|
get disabled() {
|
|
31021
30955
|
return !this._enabled;
|
|
31022
30956
|
}
|
|
31023
|
-
get
|
|
31024
|
-
return this.
|
|
31025
|
-
}
|
|
31026
|
-
get empty() {
|
|
31027
|
-
return !this._enabled;
|
|
31028
|
-
}
|
|
31029
|
-
constructor(route, router, navController, alertCtrl, translate) {
|
|
31030
|
-
this.route = route;
|
|
31031
|
-
this.router = router;
|
|
31032
|
-
this.navController = navController;
|
|
31033
|
-
this.alertCtrl = alertCtrl;
|
|
31034
|
-
this.translate = translate;
|
|
30957
|
+
get destroyed() {
|
|
30958
|
+
return this.destroySubject?.closed !== false;
|
|
31035
30959
|
}
|
|
30960
|
+
debug = false;
|
|
30961
|
+
constructor() { }
|
|
31036
30962
|
ngOnInit() {
|
|
31037
|
-
|
|
31038
|
-
this.registerSubscription(this.formButtonsBar.onBack
|
|
31039
|
-
.pipe(throttleTime(200)) // Avoid to be called twice
|
|
31040
|
-
.subscribe((event) => this.goBack(event)));
|
|
31041
|
-
}
|
|
31042
|
-
}
|
|
31043
|
-
// eslint-disable-next-line @angular-eslint/no-empty-lifecycle-method
|
|
31044
|
-
ngAfterViewInit() {
|
|
31045
|
-
// Can be overridden by subclasses
|
|
30963
|
+
// Can be override by sub classes
|
|
31046
30964
|
}
|
|
31047
30965
|
ngOnDestroy() {
|
|
31048
30966
|
this._subscription.unsubscribe();
|
|
31049
30967
|
this.readySubject.unsubscribe();
|
|
31050
30968
|
this.loadingSubject.unsubscribe();
|
|
30969
|
+
this.touchedSubject.unsubscribe();
|
|
31051
30970
|
this.errorSubject.unsubscribe();
|
|
31052
30971
|
this.destroySubject.next();
|
|
31053
30972
|
this.destroySubject.unsubscribe();
|
|
31054
30973
|
}
|
|
31055
|
-
|
|
30974
|
+
addForm(path, form) {
|
|
31056
30975
|
if (!form)
|
|
31057
30976
|
throw new Error('Trying to register an undefined child form');
|
|
31058
30977
|
this._children = this._children || [];
|
|
@@ -31062,17 +30981,19 @@ class AppEditor {
|
|
|
31062
30981
|
else {
|
|
31063
30982
|
this._children.push(form);
|
|
31064
30983
|
}
|
|
31065
|
-
|
|
30984
|
+
this._childrenPath = this._childrenPath || [];
|
|
30985
|
+
this._childrenPath.push(path || null);
|
|
31066
30986
|
}
|
|
31067
|
-
|
|
31068
|
-
(forms || []).forEach((form) => this.
|
|
30987
|
+
addForms(forms) {
|
|
30988
|
+
(forms || []).forEach((form) => this.addForm(null, form));
|
|
31069
30989
|
}
|
|
31070
|
-
|
|
30990
|
+
removeForm(form) {
|
|
31071
30991
|
if (!form)
|
|
31072
30992
|
throw new Error('Trying to remove an undefined child form');
|
|
31073
|
-
const index = (this._children || []).findIndex((c) => c === form);
|
|
30993
|
+
const index = typeof form == 'string' ? (this._childrenPath || []).findIndex((c) => c === form) : (this._children || []).findIndex((c) => c === form);
|
|
31074
30994
|
if (index !== -1) {
|
|
31075
|
-
|
|
30995
|
+
this._childrenPath.splice(index, 1);
|
|
30996
|
+
return this._children.splice(index, 1)?.[0];
|
|
31076
30997
|
}
|
|
31077
30998
|
return undefined;
|
|
31078
30999
|
}
|
|
@@ -31090,7 +31011,6 @@ class AppEditor {
|
|
|
31090
31011
|
}
|
|
31091
31012
|
markAsPristine(opts) {
|
|
31092
31013
|
this.error = null;
|
|
31093
|
-
this.submitted = false;
|
|
31094
31014
|
if (this.dirtySubject.value !== false) {
|
|
31095
31015
|
this.dirtySubject.next(false);
|
|
31096
31016
|
}
|
|
@@ -31127,21 +31047,22 @@ class AppEditor {
|
|
|
31127
31047
|
this.markForCheck();
|
|
31128
31048
|
}
|
|
31129
31049
|
markAsDirty(opts) {
|
|
31130
|
-
if (
|
|
31050
|
+
if (this.dirtySubject.value !== true) {
|
|
31131
31051
|
this.dirtySubject.next(true);
|
|
31132
31052
|
if (!this.loading && (!opts || opts.emitEvent !== false))
|
|
31133
31053
|
this.markForCheck();
|
|
31134
31054
|
}
|
|
31135
31055
|
}
|
|
31136
31056
|
markAsLoading(opts) {
|
|
31137
|
-
if (!this.loadingSubject.value) {
|
|
31057
|
+
if (!this.loadingSubject.closed && this.loadingSubject.value !== true) {
|
|
31138
31058
|
this.loadingSubject.next(true);
|
|
31139
|
-
if (!opts || opts.emitEvent !== false)
|
|
31059
|
+
if (!opts || opts.emitEvent !== false) {
|
|
31140
31060
|
this.markForCheck();
|
|
31061
|
+
}
|
|
31141
31062
|
}
|
|
31142
31063
|
}
|
|
31143
31064
|
markAsLoaded(opts) {
|
|
31144
|
-
if (!this.loadingSubject.closed && this.loadingSubject.value) {
|
|
31065
|
+
if (!this.loadingSubject.closed && this.loadingSubject.value !== false) {
|
|
31145
31066
|
this.loadingSubject.next(false);
|
|
31146
31067
|
if (!opts || opts.onlySelf !== true) {
|
|
31147
31068
|
// Emit to children forms and editors
|
|
@@ -31156,19 +31077,184 @@ class AppEditor {
|
|
|
31156
31077
|
}
|
|
31157
31078
|
markAsReady(opts) {
|
|
31158
31079
|
this._children?.forEach((c) => c.markAsReady(opts));
|
|
31159
|
-
if (!this.readySubject.closed &&
|
|
31080
|
+
if (!this.readySubject.closed && this.readySubject.value !== true) {
|
|
31160
31081
|
this.readySubject.next(true);
|
|
31082
|
+
// If subclasses implements OnReady
|
|
31083
|
+
if (typeof this['ngOnReady'] === 'function') {
|
|
31084
|
+
this.ngOnReady();
|
|
31085
|
+
}
|
|
31086
|
+
}
|
|
31161
31087
|
}
|
|
31088
|
+
/**
|
|
31089
|
+
* Wait form is ready
|
|
31090
|
+
*
|
|
31091
|
+
* @param opts
|
|
31092
|
+
*/
|
|
31162
31093
|
ready(opts) {
|
|
31163
31094
|
if (this.readySubject.value)
|
|
31164
31095
|
return Promise.resolve();
|
|
31165
31096
|
return waitForTrue(this.readySubject, { stop: this.destroySubject, ...opts });
|
|
31166
31097
|
}
|
|
31098
|
+
/**
|
|
31099
|
+
* Wait form is not busy (=loaded)
|
|
31100
|
+
*
|
|
31101
|
+
* @param opts
|
|
31102
|
+
*/
|
|
31167
31103
|
waitIdle(opts) {
|
|
31168
31104
|
if (!this.loadingSubject.value)
|
|
31169
31105
|
return Promise.resolve();
|
|
31170
31106
|
return waitForFalse(this.loadingSubject, { stop: this.destroySubject, ...opts });
|
|
31171
31107
|
}
|
|
31108
|
+
logFormErrors(prefix) {
|
|
31109
|
+
if (this.debug)
|
|
31110
|
+
console.debug('[editor] Editor not valid. Checking where (forms, tables)...');
|
|
31111
|
+
this._children?.forEach((c) => this.logChildrenErrors(c, prefix));
|
|
31112
|
+
}
|
|
31113
|
+
/* -- protected methods -- */
|
|
31114
|
+
registerSubscription(sub) {
|
|
31115
|
+
this._subscription.add(sub);
|
|
31116
|
+
}
|
|
31117
|
+
unregisterSubscription(sub) {
|
|
31118
|
+
this._subscription.remove(sub);
|
|
31119
|
+
}
|
|
31120
|
+
setError(value, opts) {
|
|
31121
|
+
// Compare using '!=' to detect null and undefined as same value
|
|
31122
|
+
if (this.errorSubject.value != value) {
|
|
31123
|
+
this.errorSubject.next(value);
|
|
31124
|
+
if (!opts || opts.emitEvent !== false)
|
|
31125
|
+
this.markForCheck();
|
|
31126
|
+
}
|
|
31127
|
+
}
|
|
31128
|
+
resetError(opts) {
|
|
31129
|
+
this.setError(undefined, opts);
|
|
31130
|
+
}
|
|
31131
|
+
markForCheck() {
|
|
31132
|
+
// Should be overwritten by subclasses
|
|
31133
|
+
if (this.debug)
|
|
31134
|
+
console.warn('markForCheck() has been called, but is not overwritten by component ' + this.constructor.name);
|
|
31135
|
+
}
|
|
31136
|
+
logChildrenErrors(c, prefix, path) {
|
|
31137
|
+
prefix = prefix || this._logPrefix;
|
|
31138
|
+
// If editor
|
|
31139
|
+
if (c instanceof AppEditor) {
|
|
31140
|
+
if (!c.empty && !c.valid) {
|
|
31141
|
+
if (c.pending) {
|
|
31142
|
+
const path = c.constructor.name.toLowerCase();
|
|
31143
|
+
console.warn(`${prefix} -> ${path}: waiting while pending...`);
|
|
31144
|
+
AppFormUtils.waitWhilePending(c, { timeout: 1000 }).then(() => c.logFormErrors(prefix));
|
|
31145
|
+
}
|
|
31146
|
+
else {
|
|
31147
|
+
c.logFormErrors(prefix);
|
|
31148
|
+
}
|
|
31149
|
+
}
|
|
31150
|
+
}
|
|
31151
|
+
// Angular form control
|
|
31152
|
+
else if (c instanceof AbstractControl) {
|
|
31153
|
+
AppFormUtils.logFormErrors(c, prefix, path);
|
|
31154
|
+
}
|
|
31155
|
+
// If form provider: get delegate
|
|
31156
|
+
else if (c instanceof AppFormProvider) {
|
|
31157
|
+
if (!c.empty && !c.valid) {
|
|
31158
|
+
c.waitDelegate({ timeout: 1000 }).then((delegate) => this.logChildrenErrors(delegate, prefix, 'provider'));
|
|
31159
|
+
}
|
|
31160
|
+
}
|
|
31161
|
+
// If table
|
|
31162
|
+
else if (c instanceof AppTable) {
|
|
31163
|
+
if (c.invalid && c.editedRow && c.editedRow.validator) {
|
|
31164
|
+
const path = c.constructor.name.toLowerCase();
|
|
31165
|
+
AppFormUtils.logFormErrors(c.editedRow.validator, prefix, path);
|
|
31166
|
+
}
|
|
31167
|
+
}
|
|
31168
|
+
// If form
|
|
31169
|
+
else if (c instanceof AppForm) {
|
|
31170
|
+
if (!c.empty && !c.valid) {
|
|
31171
|
+
if (c.pending) {
|
|
31172
|
+
const path = c.constructor.name.toLowerCase();
|
|
31173
|
+
console.warn(`${prefix} -> ${path}: waiting while pending...`);
|
|
31174
|
+
AppFormUtils.waitWhilePending(c, { timeout: 1000 }).then(() => this.logChildrenErrors(c.form, prefix, path));
|
|
31175
|
+
}
|
|
31176
|
+
else {
|
|
31177
|
+
AppFormUtils.logFormErrors(c.form, prefix);
|
|
31178
|
+
}
|
|
31179
|
+
}
|
|
31180
|
+
}
|
|
31181
|
+
else {
|
|
31182
|
+
console.warn(`${prefix} Unknown children sub-form: `, c);
|
|
31183
|
+
}
|
|
31184
|
+
}
|
|
31185
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.2.4", ngImport: i0, type: AppFormContainer, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
31186
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.2.4", type: AppFormContainer, inputs: { debug: "debug" }, ngImport: i0 });
|
|
31187
|
+
}
|
|
31188
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.2.4", ngImport: i0, type: AppFormContainer, decorators: [{
|
|
31189
|
+
type: Directive
|
|
31190
|
+
}], ctorParameters: () => [], propDecorators: { debug: [{
|
|
31191
|
+
type: Input
|
|
31192
|
+
}] } });
|
|
31193
|
+
|
|
31194
|
+
// eslint-disable-next-line @angular-eslint/directive-class-suffix
|
|
31195
|
+
class AppEditor extends AppFormContainer {
|
|
31196
|
+
route;
|
|
31197
|
+
router;
|
|
31198
|
+
navController;
|
|
31199
|
+
alertCtrl;
|
|
31200
|
+
translate;
|
|
31201
|
+
toastController;
|
|
31202
|
+
savingSubject = new BehaviorSubject(false);
|
|
31203
|
+
submitted = false;
|
|
31204
|
+
queryParams;
|
|
31205
|
+
i18nContext;
|
|
31206
|
+
get saving() {
|
|
31207
|
+
return this.savingSubject.value || this.editors?.some((e) => e.saving);
|
|
31208
|
+
}
|
|
31209
|
+
toolbar = null;
|
|
31210
|
+
formButtonsBar = null;
|
|
31211
|
+
content;
|
|
31212
|
+
constructor(route, router, navController, alertCtrl, translate) {
|
|
31213
|
+
super();
|
|
31214
|
+
this.route = route;
|
|
31215
|
+
this.router = router;
|
|
31216
|
+
this.navController = navController;
|
|
31217
|
+
this.alertCtrl = alertCtrl;
|
|
31218
|
+
this.translate = translate;
|
|
31219
|
+
this._logPrefix = '[editor] ';
|
|
31220
|
+
}
|
|
31221
|
+
ngOnInit() {
|
|
31222
|
+
super.ngOnInit();
|
|
31223
|
+
if (this.formButtonsBar) {
|
|
31224
|
+
this.registerSubscription(this.formButtonsBar.onBack
|
|
31225
|
+
.pipe(throttleTime(200)) // Avoid to be called twice
|
|
31226
|
+
.subscribe((event) => this.goBack(event)));
|
|
31227
|
+
}
|
|
31228
|
+
}
|
|
31229
|
+
// eslint-disable-next-line @angular-eslint/no-empty-lifecycle-method
|
|
31230
|
+
ngAfterViewInit() {
|
|
31231
|
+
// Can be overridden by subclasses
|
|
31232
|
+
}
|
|
31233
|
+
ngOnDestroy() {
|
|
31234
|
+
super.ngOnDestroy();
|
|
31235
|
+
this.savingSubject.unsubscribe();
|
|
31236
|
+
}
|
|
31237
|
+
/**
|
|
31238
|
+
* @deprecated Use addForm(path, form)
|
|
31239
|
+
* @param form
|
|
31240
|
+
*/
|
|
31241
|
+
addChildForm(form) {
|
|
31242
|
+
this.addForm(null, form);
|
|
31243
|
+
}
|
|
31244
|
+
/**
|
|
31245
|
+
* @deprecated Use addForms()
|
|
31246
|
+
* @param forms
|
|
31247
|
+
*/
|
|
31248
|
+
addChildForms(forms) {
|
|
31249
|
+
this.addForms(forms);
|
|
31250
|
+
}
|
|
31251
|
+
/**
|
|
31252
|
+
* @deprecated Use removeForm()
|
|
31253
|
+
* @param form
|
|
31254
|
+
*/
|
|
31255
|
+
removeChildForm(form) {
|
|
31256
|
+
return this.removeForm(form);
|
|
31257
|
+
}
|
|
31172
31258
|
markAsSaving(opts) {
|
|
31173
31259
|
if (this.savingSubject.value !== true) {
|
|
31174
31260
|
this.savingSubject.next(true);
|
|
@@ -31197,9 +31283,9 @@ class AppEditor {
|
|
|
31197
31283
|
* @param opts
|
|
31198
31284
|
*/
|
|
31199
31285
|
async unload(opts) {
|
|
31200
|
-
console.debug('
|
|
31286
|
+
console.debug(this._logPrefix + 'Unloading data...');
|
|
31201
31287
|
this.markAsLoading();
|
|
31202
|
-
this.
|
|
31288
|
+
this.children?.forEach((f) => {
|
|
31203
31289
|
if (f instanceof AppForm) {
|
|
31204
31290
|
// Fix error when 'null' is pass (default value = {} was not applied)
|
|
31205
31291
|
f.reset(undefined, opts);
|
|
@@ -31262,11 +31348,6 @@ class AppEditor {
|
|
|
31262
31348
|
return this.navController.navigateBack('/');
|
|
31263
31349
|
}
|
|
31264
31350
|
}
|
|
31265
|
-
logFormErrors(prefix) {
|
|
31266
|
-
if (this.debug)
|
|
31267
|
-
console.debug('[editor] Editor not valid. Checking where (forms, tables)...');
|
|
31268
|
-
this._children?.forEach((c) => this.logChildrenErrors(c, prefix));
|
|
31269
|
-
}
|
|
31270
31351
|
/* -- protected methods -- */
|
|
31271
31352
|
async scrollToTop(duration) {
|
|
31272
31353
|
duration = toNumber(duration, 500);
|
|
@@ -31286,12 +31367,6 @@ class AppEditor {
|
|
|
31286
31367
|
}
|
|
31287
31368
|
return this.content.scrollToTop(duration);
|
|
31288
31369
|
}
|
|
31289
|
-
registerSubscription(sub) {
|
|
31290
|
-
this._subscription.add(sub);
|
|
31291
|
-
}
|
|
31292
|
-
unregisterSubscription(sub) {
|
|
31293
|
-
this._subscription.remove(sub);
|
|
31294
|
-
}
|
|
31295
31370
|
async saveIfDirtyAndConfirm(event, opts) {
|
|
31296
31371
|
if (!this.dirty)
|
|
31297
31372
|
return true;
|
|
@@ -31338,76 +31413,18 @@ class AppEditor {
|
|
|
31338
31413
|
}
|
|
31339
31414
|
return await this.save(event, opts);
|
|
31340
31415
|
}
|
|
31416
|
+
async saveDirtyChildren() {
|
|
31417
|
+
// Save all dirty tables
|
|
31418
|
+
const results = await Promise.all([...this.tables, ...this.editors].filter((c) => c.dirty).map((c) => c.save()));
|
|
31419
|
+
return !results.some((saved) => saved !== true);
|
|
31420
|
+
}
|
|
31341
31421
|
async showToast(opts) {
|
|
31342
31422
|
if (!this.toastController)
|
|
31343
31423
|
throw new Error("Missing toastController in component's constructor");
|
|
31344
31424
|
await Toasts.show(this.toastController, this.translate, opts);
|
|
31345
31425
|
}
|
|
31346
|
-
logChildrenErrors(c, prefix, path) {
|
|
31347
|
-
prefix = prefix || '[app-tab-editor] ';
|
|
31348
|
-
// If editor
|
|
31349
|
-
if (c instanceof AppEditor) {
|
|
31350
|
-
if (!c.empty && !c.valid) {
|
|
31351
|
-
if (c.pending) {
|
|
31352
|
-
const path = c.constructor.name.toLowerCase();
|
|
31353
|
-
console.warn(`${prefix} -> ${path}: waiting while pending...`);
|
|
31354
|
-
AppFormUtils.waitWhilePending(c, { timeout: 1000 }).then(() => c.logFormErrors(prefix));
|
|
31355
|
-
}
|
|
31356
|
-
else {
|
|
31357
|
-
c.logFormErrors(prefix);
|
|
31358
|
-
}
|
|
31359
|
-
}
|
|
31360
|
-
}
|
|
31361
|
-
// Angular form control
|
|
31362
|
-
else if (c instanceof AbstractControl) {
|
|
31363
|
-
AppFormUtils.logFormErrors(c, prefix, path);
|
|
31364
|
-
}
|
|
31365
|
-
// If form provider: get delegate
|
|
31366
|
-
else if (c instanceof AppFormProvider) {
|
|
31367
|
-
if (!c.empty && !c.valid) {
|
|
31368
|
-
c.waitDelegate({ timeout: 1000 }).then((delegate) => this.logChildrenErrors(delegate, prefix, 'provider'));
|
|
31369
|
-
}
|
|
31370
|
-
}
|
|
31371
|
-
// If table
|
|
31372
|
-
else if (c instanceof AppTable) {
|
|
31373
|
-
if (c.invalid && c.editedRow && c.editedRow.validator) {
|
|
31374
|
-
const path = c.constructor.name.toLowerCase();
|
|
31375
|
-
AppFormUtils.logFormErrors(c.editedRow.validator, prefix, path);
|
|
31376
|
-
}
|
|
31377
|
-
}
|
|
31378
|
-
// If form
|
|
31379
|
-
else if (c instanceof AppForm) {
|
|
31380
|
-
if (!c.empty && !c.valid) {
|
|
31381
|
-
if (c.pending) {
|
|
31382
|
-
const path = c.constructor.name.toLowerCase();
|
|
31383
|
-
console.warn(`${prefix} -> ${path}: waiting while pending...`);
|
|
31384
|
-
AppFormUtils.waitWhilePending(c, { timeout: 1000 }).then(() => this.logChildrenErrors(c.form, prefix, path));
|
|
31385
|
-
}
|
|
31386
|
-
else {
|
|
31387
|
-
AppFormUtils.logFormErrors(c.form, prefix);
|
|
31388
|
-
}
|
|
31389
|
-
}
|
|
31390
|
-
}
|
|
31391
|
-
else {
|
|
31392
|
-
console.warn(`${prefix} Unknown children sub-form: `, c);
|
|
31393
|
-
}
|
|
31394
|
-
}
|
|
31395
|
-
setError(value, opts) {
|
|
31396
|
-
// Compare using '!=' to detect null and undefined as same value
|
|
31397
|
-
if (this.errorSubject.value != value) {
|
|
31398
|
-
this.errorSubject.next(value);
|
|
31399
|
-
if (!opts || opts.emitEvent !== false)
|
|
31400
|
-
this.markForCheck();
|
|
31401
|
-
}
|
|
31402
|
-
}
|
|
31403
|
-
resetError(opts) {
|
|
31404
|
-
this.setError(undefined, opts);
|
|
31405
|
-
}
|
|
31406
|
-
markForCheck() {
|
|
31407
|
-
// Should be override by subclasses, if change detection is Push
|
|
31408
|
-
}
|
|
31409
31426
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.2.4", ngImport: i0, type: AppEditor, deps: [{ token: i1$5.ActivatedRoute }, { token: i1$5.Router }, { token: i2$1.NavController }, { token: i2$1.AlertController }, { token: i1$1.TranslateService }], target: i0.ɵɵFactoryTarget.Directive });
|
|
31410
|
-
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.2.4", type: AppEditor, viewQueries: [{ propertyName: "toolbar", first: true, predicate: ToolbarToken, descendants: true }, { propertyName: "formButtonsBar", first: true, predicate: FormButtonsBarToken, descendants: true, static: true }, { propertyName: "content", first: true, predicate: IonContent, descendants: true, static: true }], ngImport: i0 });
|
|
31427
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.2.4", type: AppEditor, viewQueries: [{ propertyName: "toolbar", first: true, predicate: ToolbarToken, descendants: true }, { propertyName: "formButtonsBar", first: true, predicate: FormButtonsBarToken, descendants: true, static: true }, { propertyName: "content", first: true, predicate: IonContent, descendants: true, static: true }], usesInheritance: true, ngImport: i0 });
|
|
31411
31428
|
}
|
|
31412
31429
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.2.4", ngImport: i0, type: AppEditor, decorators: [{
|
|
31413
31430
|
type: Directive
|
|
@@ -31421,6 +31438,21 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.2.4", ngImpor
|
|
|
31421
31438
|
type: ViewChild,
|
|
31422
31439
|
args: [IonContent, { static: true }]
|
|
31423
31440
|
}] } });
|
|
31441
|
+
|
|
31442
|
+
class AppTabEditorOptions {
|
|
31443
|
+
/**
|
|
31444
|
+
* Number of tab. 1 by default
|
|
31445
|
+
*/
|
|
31446
|
+
tabCount;
|
|
31447
|
+
/**
|
|
31448
|
+
* '200ms' by default
|
|
31449
|
+
*/
|
|
31450
|
+
tabGroupAnimationDuration;
|
|
31451
|
+
/**
|
|
31452
|
+
* Should enable swipe between tab, on touch screen
|
|
31453
|
+
*/
|
|
31454
|
+
enableSwipe; // true by default
|
|
31455
|
+
}
|
|
31424
31456
|
// eslint-disable-next-line @angular-eslint/directive-class-suffix
|
|
31425
31457
|
class AppTabEditor extends AppEditor {
|
|
31426
31458
|
route;
|
|
@@ -31460,6 +31492,7 @@ class AppTabEditor extends AppEditor {
|
|
|
31460
31492
|
this.enableSwipe = options.enableSwipe;
|
|
31461
31493
|
this.tabGroupAnimationDuration = options.tabGroupAnimationDuration;
|
|
31462
31494
|
this.queryTabIndexParamName = 'tab';
|
|
31495
|
+
this._logPrefix = '[tab-editor] ';
|
|
31463
31496
|
}
|
|
31464
31497
|
ngOnInit() {
|
|
31465
31498
|
super.ngOnInit();
|
|
@@ -31483,8 +31516,6 @@ class AppTabEditor extends AppEditor {
|
|
|
31483
31516
|
ngOnDestroy() {
|
|
31484
31517
|
super.ngOnDestroy();
|
|
31485
31518
|
this.selectedTabIndexChange.complete();
|
|
31486
|
-
this.loadingSubject.unsubscribe();
|
|
31487
|
-
this.errorSubject.unsubscribe();
|
|
31488
31519
|
}
|
|
31489
31520
|
setSelectedTabIndex(value, opts) {
|
|
31490
31521
|
// Fix value
|
|
@@ -31575,11 +31606,6 @@ class AppTabEditor extends AppEditor {
|
|
|
31575
31606
|
this.selectedTabIndex = 0;
|
|
31576
31607
|
await super.unload(opts);
|
|
31577
31608
|
}
|
|
31578
|
-
async saveDirtyChildren() {
|
|
31579
|
-
// Save all dirty tables
|
|
31580
|
-
const results = await Promise.all([...this.tables, ...this.editors].filter((c) => c.dirty).map((c) => c.save()));
|
|
31581
|
-
return !results.some((saved) => saved !== true);
|
|
31582
|
-
}
|
|
31583
31609
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.2.4", ngImport: i0, type: AppTabEditor, deps: [{ token: i1$5.ActivatedRoute, optional: true }, { token: i1$5.Router }, { token: i2$1.NavController }, { token: i2$1.AlertController }, { token: i1$1.TranslateService }, { token: AppTabEditorOptions, optional: true }], target: i0.ɵɵFactoryTarget.Directive });
|
|
31584
31610
|
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.2.4", type: AppTabEditor, inputs: { queryTabIndexParamName: "queryTabIndexParamName", selectedTabIndex: "selectedTabIndex" }, outputs: { selectedTabIndexChange: "selectedTabIndexChange" }, viewQueries: [{ propertyName: "tabGroup", first: true, predicate: ["tabGroup"], descendants: true, static: true }], usesInheritance: true, ngImport: i0 });
|
|
31585
31611
|
}
|
|
@@ -31607,7 +31633,7 @@ class AppEntityEditorModalOptions extends AppTabEditorOptions {
|
|
|
31607
31633
|
// eslint-disable-next-line @angular-eslint/directive-class-suffix
|
|
31608
31634
|
class AppEntityEditorModal extends AppTabEditor {
|
|
31609
31635
|
dataType;
|
|
31610
|
-
_logPrefix;
|
|
31636
|
+
_logPrefix = '';
|
|
31611
31637
|
_isNew;
|
|
31612
31638
|
dateFormat;
|
|
31613
31639
|
cd;
|
|
@@ -31615,13 +31641,19 @@ class AppEntityEditorModal extends AppTabEditor {
|
|
|
31615
31641
|
modalCtrl;
|
|
31616
31642
|
errorTranslator;
|
|
31617
31643
|
savingSubject = new BehaviorSubject(false);
|
|
31618
|
-
|
|
31644
|
+
titleSubject = new BehaviorSubject(undefined);
|
|
31619
31645
|
data;
|
|
31620
31646
|
mobile;
|
|
31621
31647
|
usageMode;
|
|
31622
31648
|
onAfterModalInit;
|
|
31623
31649
|
onDelete;
|
|
31624
31650
|
i18nSuffix = null;
|
|
31651
|
+
/**
|
|
31652
|
+
* @deprecated
|
|
31653
|
+
*/
|
|
31654
|
+
get $title() {
|
|
31655
|
+
return this.titleSubject;
|
|
31656
|
+
}
|
|
31625
31657
|
set isNew(value) {
|
|
31626
31658
|
this._isNew = value;
|
|
31627
31659
|
}
|
|
@@ -31649,23 +31681,6 @@ class AppEntityEditorModal extends AppTabEditor {
|
|
|
31649
31681
|
get isOnFieldMode() {
|
|
31650
31682
|
return this.settings.isOnFieldMode(this.usageMode);
|
|
31651
31683
|
}
|
|
31652
|
-
get saving() {
|
|
31653
|
-
return this.savingSubject.value;
|
|
31654
|
-
}
|
|
31655
|
-
markAsSaving(opts) {
|
|
31656
|
-
if (this.savingSubject.value !== true) {
|
|
31657
|
-
this.savingSubject.next(true);
|
|
31658
|
-
if (!opts || opts.emitEvent !== false)
|
|
31659
|
-
this.markForCheck();
|
|
31660
|
-
}
|
|
31661
|
-
}
|
|
31662
|
-
markAsSaved(opts) {
|
|
31663
|
-
if (this.savingSubject.value !== false) {
|
|
31664
|
-
this.savingSubject.next(false);
|
|
31665
|
-
if (!opts || opts.emitEvent !== false)
|
|
31666
|
-
this.markForCheck();
|
|
31667
|
-
}
|
|
31668
|
-
}
|
|
31669
31684
|
constructor(injector, dataType, options) {
|
|
31670
31685
|
super(null, injector.get(Router), injector.get(NavController), injector.get(AlertController), injector.get(TranslateService), options);
|
|
31671
31686
|
this.dataType = dataType;
|
|
@@ -31719,9 +31734,8 @@ class AppEntityEditorModal extends AppTabEditor {
|
|
|
31719
31734
|
}
|
|
31720
31735
|
ngOnDestroy() {
|
|
31721
31736
|
super.ngOnDestroy();
|
|
31722
|
-
this
|
|
31723
|
-
this
|
|
31724
|
-
this.savingSubject.unsubscribe();
|
|
31737
|
+
this.titleSubject.complete();
|
|
31738
|
+
this.titleSubject.unsubscribe();
|
|
31725
31739
|
}
|
|
31726
31740
|
waitIdle(opts) {
|
|
31727
31741
|
// Wait end of saving
|
|
@@ -31967,7 +31981,7 @@ class AppEntityEditorModal extends AppTabEditor {
|
|
|
31967
31981
|
async updateTitle(data) {
|
|
31968
31982
|
data = data || this.data;
|
|
31969
31983
|
const title = await this.computeTitle(data);
|
|
31970
|
-
this
|
|
31984
|
+
this.titleSubject.next(title);
|
|
31971
31985
|
}
|
|
31972
31986
|
async scrollToTop(duration) {
|
|
31973
31987
|
if (this.content) {
|
|
@@ -32063,7 +32077,7 @@ class NewTokenModal extends AppEntityEditorModal {
|
|
|
32063
32077
|
return 0;
|
|
32064
32078
|
}
|
|
32065
32079
|
registerForms() {
|
|
32066
|
-
this.
|
|
32080
|
+
this.addForm(null, this.tokenAppForm);
|
|
32067
32081
|
}
|
|
32068
32082
|
setValue(data) {
|
|
32069
32083
|
// Affect pubkey from current account
|
|
@@ -32106,11 +32120,11 @@ class NewTokenModal extends AppEntityEditorModal {
|
|
|
32106
32120
|
return flags;
|
|
32107
32121
|
}
|
|
32108
32122
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.2.4", ngImport: i0, type: NewTokenModal, deps: [{ token: i0.Injector }, { token: UserTokenValidatorService }, { token: AccountService }], target: i0.ɵɵFactoryTarget.Component });
|
|
32109
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.2.4", type: NewTokenModal, selector: "app-new-token-modal", inputs: { tokenScopes: "tokenScopes", existingNames: "existingNames" }, usesInheritance: true, ngImport: i0, template: "<app-modal-toolbar\n modalName=\"NewTokenModal\"\n [title]=\"$title | async\"\n [color]=\"'secondary'\"\n [showSpinner]=\"loading\"\n [canValidate]=\"!loading && valid\"\n (cancel)=\"close($event)\"\n (validate)=\"saveAndClose($event)\"\n></app-modal-toolbar>\n\n<ion-content 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 <p><b translate>ACCOUNT.TOKENS.CREATE.DESCRIPTION</b></p>\n\n <form class=\"form-container\" [formGroup]=\"tokenForm\">\n <ion-grid class=\"ion-no-padding\">\n <ion-row>\n <ion-col>\n <mat-form-field>\n <mat-label>{{ 'ACCOUNT.TOKENS.CREATE.NAME' | translate }}</mat-label>\n <input\n matInput\n [appAutofocus]=\"true\"\n [autofocusDelay]=\"500\"\n formControlName=\"name\"\n autocomplete=\"off\"\n required\n [readonly]=\"tokenForm | formGetValue: 'token' | isNotNilOrBlank\"\n />\n <mat-error *ngIf=\"form.controls.name.hasError('required') && form.controls.name.touched\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n <mat-error *ngIf=\"form.controls.name.hasError('notAlreadyExists') && form.controls.name.touched\" translate>\n ACCOUNT.TOKENS.CREATE.NAME_ALREADY_EXISTS\n </mat-error>\n </mat-form-field>\n </ion-col>\n </ion-row>\n <ion-row>\n <ion-col>\n <mat-chips-field\n formControlName=\"scopes\"\n appearance=\"fill\"\n chipColor=\"primary\"\n [placeholder]=\"'ACCOUNT.TOKENS.CREATE.SCOPES' | translate\"\n [config]=\"tokenConfig\"\n [mobile]=\"mobile\"\n [debug]=\"false\"\n [required]=\"true\"\n [readonly]=\"tokenForm | formGetValue: 'token' | isNotNilOrBlank\"\n >\n <mat-error *ngIf=\"form.controls.name.hasError('notEmptyArray') && form.controls.name.touched\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n </mat-chips-field>\n </ion-col>\n </ion-row>\n <ion-row>\n <ion-col>\n <mat-date-field\n formControlName=\"expirationDate\"\n [placeholder]=\"'ACCOUNT.TOKENS.CREATE.EXPIRATION_DATE' | translate\"\n [mobile]=\"mobile\"\n [required]=\"true\"\n [readonly]=\"tokenForm | formGetValue: 'token' | isNotNilOrBlank\"\n ></mat-date-field>\n </ion-col>\n </ion-row>\n <ion-row>\n <ion-col>\n <ion-button\n *ngIf=\"tokenForm | formGetValue: 'token' | isNilOrBlank; else showToken\"\n [title]=\"'ACCOUNT.TOKENS.CREATE.BTN_GENERATE_TITLE' | translate\"\n (click)=\"generate($event)\"\n [disabled]=\"tokenForm.invalid\"\n >\n {{ 'ACCOUNT.TOKENS.CREATE.BTN_GENERATE' | translate }}\n </ion-button>\n <ng-template #showToken>\n <p><b translate>ACCOUNT.TOKENS.CREATE.COPY_HELP</b></p>\n <mat-form-field subscriptSizing=\"dynamic\">\n <textarea\n matInput\n formControlName=\"token\"\n readonly\n style=\"height: auto; background-color: lightgray\"\n rows=\"8\"\n ></textarea>\n <button\n matSuffix\n mat-icon-button\n [title]=\"'ACCOUNT.TOKENS.CREATE.BTN_COPY_TITLE' | translate\"\n (click)=\"copy($event)\"\n >\n <mat-icon>content_copy</mat-icon>\n </button>\n </mat-form-field>\n </ng-template>\n </ion-col>\n </ion-row>\n </ion-grid>\n </form>\n</ion-content>\n\n<ion-footer hidden-xs hidden-sm hidden-mobile>\n <ion-toolbar>\n <ion-row class=\"ion-no-padding\" nowrap>\n <ion-col>\n <ng-content></ng-content>\n </ion-col>\n\n <ion-col size=\"auto\">\n <ion-button fill=\"clear\" color=\"dark\" (click)=\"close($event)\">\n <ion-label translate>COMMON.BTN_CANCEL</ion-label>\n </ion-button>\n\n <ion-button\n [fill]=\"invalid ? 'clear' : 'solid'\"\n [disabled]=\"disabled || loading || invalid\"\n (click)=\"saveAndClose($event)\"\n (keyup.enter)=\"saveAndClose($event)\"\n color=\"tertiary\"\n >\n <ion-label translate>COMMON.BTN_VALIDATE</ion-label>\n </ion-button>\n </ion-col>\n </ion-row>\n </ion-toolbar>\n</ion-footer>\n", dependencies: [{ 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.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", "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", "counter", "counterFormatter", "detail", "detailIcon", "disabled", "download", "fill", "href", "lines", "mode", "rel", "routerAnimation", "routerDirection", "shape", "target", "type"] }, { kind: "component", type: i2$1.IonLabel, selector: "ion-label", inputs: ["color", "mode", "position"] }, { kind: "component", type: i2$1.IonRow, selector: "ion-row" }, { kind: "component", type: i2$1.IonToolbar, selector: "ion-toolbar", inputs: ["color", "mode"] }, { kind: "directive", type: i1$1.TranslateDirective, selector: "[translate],[ngx-translate]", inputs: ["translate", "translateParams"] }, { kind: "directive", type: i1$2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$2.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$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$2.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1$2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { 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.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: i4$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i9$1.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "component", type: MatDate, selector: "mat-date-field", inputs: ["mobile", "formControl", "formControlName", "placeholder", "floatLabel", "appearance", "required", "compact", "autofocus", "startDate", "clearable", "timezone", "datePickerFilter", "readonly", "tabindex"] }, { kind: "component", type: MatChipsField, selector: "mat-chips-field", inputs: ["equals", "logPrefix", "formControl", "formControlName", "floatLabel", "appearance", "subscriptSizing", "placeholder", "suggestFn", "required", "mobile", "readonly", "clearable", "debounceTime", "displayWith", "displayAttributes", "displayColumnSizes", "displayColumnNames", "highlightAccent", "showAllOnFocus", "showPanelOnFocus", "autofocus", "config", "i18nPrefix", "noResultMessage", "class", "panelWidth", "matAutocompletePosition", "itemSize", "fetchMoreThreshold", "suggestLengthThreshold", "showLoadingSpinner", "chipColor", "debug", "filter", "tabindex", "items"], outputs: ["click", "blur", "focus", "dropButtonClick", "keydown.escape", "keyup.enter"] }, { kind: "directive", type: AutofocusDirective, selector: "[autofocus], input[appAutofocus]", inputs: ["appAutofocus", "autofocusDelay"] }, { kind: "component", type: ModalToolbarComponent, selector: "app-modal-toolbar", inputs: ["modalName", "title", "color", "showSpinner", "canValidate", "validateIcon"], outputs: ["cancel", "validate"] }, { kind: "pipe", type: i3.AsyncPipe, name: "async" }, { kind: "pipe", type: i1$1.TranslatePipe, name: "translate" }, { kind: "pipe", type: IsNilOrBlankPipe, name: "isNilOrBlank" }, { kind: "pipe", type: IsNotNilOrBlankPipe, name: "isNotNilOrBlank" }, { kind: "pipe", type: FormGetValuePipe, name: "formGetValue" }] });
|
|
32123
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.2.4", type: NewTokenModal, selector: "app-new-token-modal", inputs: { tokenScopes: "tokenScopes", existingNames: "existingNames" }, usesInheritance: true, ngImport: i0, template: "<app-modal-toolbar\n modalName=\"NewTokenModal\"\n [title]=\"titleSubject | async\"\n [color]=\"'secondary'\"\n [showSpinner]=\"loading\"\n [canValidate]=\"!loading && valid\"\n (cancel)=\"close($event)\"\n (validate)=\"saveAndClose($event)\"\n></app-modal-toolbar>\n\n<ion-content 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 <p><b translate>ACCOUNT.TOKENS.CREATE.DESCRIPTION</b></p>\n\n <form class=\"form-container\" [formGroup]=\"tokenForm\">\n <ion-grid class=\"ion-no-padding\">\n <ion-row>\n <ion-col>\n <mat-form-field>\n <mat-label>{{ 'ACCOUNT.TOKENS.CREATE.NAME' | translate }}</mat-label>\n <input\n matInput\n [appAutofocus]=\"true\"\n [autofocusDelay]=\"500\"\n formControlName=\"name\"\n autocomplete=\"off\"\n required\n [readonly]=\"tokenForm | formGetValue: 'token' | isNotNilOrBlank\"\n />\n <mat-error *ngIf=\"form.controls.name.hasError('required') && form.controls.name.touched\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n <mat-error *ngIf=\"form.controls.name.hasError('notAlreadyExists') && form.controls.name.touched\" translate>\n ACCOUNT.TOKENS.CREATE.NAME_ALREADY_EXISTS\n </mat-error>\n </mat-form-field>\n </ion-col>\n </ion-row>\n <ion-row>\n <ion-col>\n <mat-chips-field\n formControlName=\"scopes\"\n appearance=\"fill\"\n chipColor=\"primary\"\n [placeholder]=\"'ACCOUNT.TOKENS.CREATE.SCOPES' | translate\"\n [config]=\"tokenConfig\"\n [mobile]=\"mobile\"\n [debug]=\"false\"\n [required]=\"true\"\n [readonly]=\"tokenForm | formGetValue: 'token' | isNotNilOrBlank\"\n >\n <mat-error *ngIf=\"form.controls.name.hasError('notEmptyArray') && form.controls.name.touched\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n </mat-chips-field>\n </ion-col>\n </ion-row>\n <ion-row>\n <ion-col>\n <mat-date-field\n formControlName=\"expirationDate\"\n [placeholder]=\"'ACCOUNT.TOKENS.CREATE.EXPIRATION_DATE' | translate\"\n [mobile]=\"mobile\"\n [required]=\"true\"\n [readonly]=\"tokenForm | formGetValue: 'token' | isNotNilOrBlank\"\n ></mat-date-field>\n </ion-col>\n </ion-row>\n <ion-row>\n <ion-col>\n <ion-button\n *ngIf=\"tokenForm | formGetValue: 'token' | isNilOrBlank; else showToken\"\n [title]=\"'ACCOUNT.TOKENS.CREATE.BTN_GENERATE_TITLE' | translate\"\n (click)=\"generate($event)\"\n [disabled]=\"tokenForm.invalid\"\n >\n {{ 'ACCOUNT.TOKENS.CREATE.BTN_GENERATE' | translate }}\n </ion-button>\n <ng-template #showToken>\n <p><b translate>ACCOUNT.TOKENS.CREATE.COPY_HELP</b></p>\n <mat-form-field subscriptSizing=\"dynamic\">\n <textarea\n matInput\n formControlName=\"token\"\n readonly\n style=\"height: auto; background-color: lightgray\"\n rows=\"8\"\n ></textarea>\n <button\n matSuffix\n mat-icon-button\n [title]=\"'ACCOUNT.TOKENS.CREATE.BTN_COPY_TITLE' | translate\"\n (click)=\"copy($event)\"\n >\n <mat-icon>content_copy</mat-icon>\n </button>\n </mat-form-field>\n </ng-template>\n </ion-col>\n </ion-row>\n </ion-grid>\n </form>\n</ion-content>\n\n<ion-footer hidden-xs hidden-sm hidden-mobile>\n <ion-toolbar>\n <ion-row class=\"ion-no-padding\" nowrap>\n <ion-col>\n <ng-content></ng-content>\n </ion-col>\n\n <ion-col size=\"auto\">\n <ion-button fill=\"clear\" color=\"dark\" (click)=\"close($event)\">\n <ion-label translate>COMMON.BTN_CANCEL</ion-label>\n </ion-button>\n\n <ion-button\n [fill]=\"invalid ? 'clear' : 'solid'\"\n [disabled]=\"disabled || loading || invalid\"\n (click)=\"saveAndClose($event)\"\n (keyup.enter)=\"saveAndClose($event)\"\n color=\"tertiary\"\n >\n <ion-label translate>COMMON.BTN_VALIDATE</ion-label>\n </ion-button>\n </ion-col>\n </ion-row>\n </ion-toolbar>\n</ion-footer>\n", dependencies: [{ 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.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", "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", "counter", "counterFormatter", "detail", "detailIcon", "disabled", "download", "fill", "href", "lines", "mode", "rel", "routerAnimation", "routerDirection", "shape", "target", "type"] }, { kind: "component", type: i2$1.IonLabel, selector: "ion-label", inputs: ["color", "mode", "position"] }, { kind: "component", type: i2$1.IonRow, selector: "ion-row" }, { kind: "component", type: i2$1.IonToolbar, selector: "ion-toolbar", inputs: ["color", "mode"] }, { kind: "directive", type: i1$1.TranslateDirective, selector: "[translate],[ngx-translate]", inputs: ["translate", "translateParams"] }, { kind: "directive", type: i1$2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$2.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$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$2.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1$2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { 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.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: i4$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i9$1.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "component", type: MatDate, selector: "mat-date-field", inputs: ["mobile", "formControl", "formControlName", "placeholder", "floatLabel", "appearance", "required", "compact", "autofocus", "startDate", "clearable", "timezone", "datePickerFilter", "readonly", "tabindex"] }, { kind: "component", type: MatChipsField, selector: "mat-chips-field", inputs: ["equals", "logPrefix", "formControl", "formControlName", "floatLabel", "appearance", "subscriptSizing", "placeholder", "suggestFn", "required", "mobile", "readonly", "clearable", "debounceTime", "displayWith", "displayAttributes", "displayColumnSizes", "displayColumnNames", "highlightAccent", "showAllOnFocus", "showPanelOnFocus", "autofocus", "config", "i18nPrefix", "noResultMessage", "class", "panelWidth", "matAutocompletePosition", "itemSize", "fetchMoreThreshold", "suggestLengthThreshold", "showLoadingSpinner", "chipColor", "debug", "filter", "tabindex", "items"], outputs: ["click", "blur", "focus", "dropButtonClick", "keydown.escape", "keyup.enter"] }, { kind: "directive", type: AutofocusDirective, selector: "[autofocus], input[appAutofocus]", inputs: ["appAutofocus", "autofocusDelay"] }, { kind: "component", type: ModalToolbarComponent, selector: "app-modal-toolbar", inputs: ["modalName", "title", "color", "showSpinner", "canValidate", "validateIcon"], outputs: ["cancel", "validate"] }, { kind: "pipe", type: i3.AsyncPipe, name: "async" }, { kind: "pipe", type: i1$1.TranslatePipe, name: "translate" }, { kind: "pipe", type: IsNilOrBlankPipe, name: "isNilOrBlank" }, { kind: "pipe", type: IsNotNilOrBlankPipe, name: "isNotNilOrBlank" }, { kind: "pipe", type: FormGetValuePipe, name: "formGetValue" }] });
|
|
32110
32124
|
}
|
|
32111
32125
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.2.4", ngImport: i0, type: NewTokenModal, decorators: [{
|
|
32112
32126
|
type: Component,
|
|
32113
|
-
args: [{ selector: 'app-new-token-modal', template: "<app-modal-toolbar\n modalName=\"NewTokenModal\"\n [title]=\"
|
|
32127
|
+
args: [{ selector: 'app-new-token-modal', template: "<app-modal-toolbar\n modalName=\"NewTokenModal\"\n [title]=\"titleSubject | async\"\n [color]=\"'secondary'\"\n [showSpinner]=\"loading\"\n [canValidate]=\"!loading && valid\"\n (cancel)=\"close($event)\"\n (validate)=\"saveAndClose($event)\"\n></app-modal-toolbar>\n\n<ion-content 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 <p><b translate>ACCOUNT.TOKENS.CREATE.DESCRIPTION</b></p>\n\n <form class=\"form-container\" [formGroup]=\"tokenForm\">\n <ion-grid class=\"ion-no-padding\">\n <ion-row>\n <ion-col>\n <mat-form-field>\n <mat-label>{{ 'ACCOUNT.TOKENS.CREATE.NAME' | translate }}</mat-label>\n <input\n matInput\n [appAutofocus]=\"true\"\n [autofocusDelay]=\"500\"\n formControlName=\"name\"\n autocomplete=\"off\"\n required\n [readonly]=\"tokenForm | formGetValue: 'token' | isNotNilOrBlank\"\n />\n <mat-error *ngIf=\"form.controls.name.hasError('required') && form.controls.name.touched\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n <mat-error *ngIf=\"form.controls.name.hasError('notAlreadyExists') && form.controls.name.touched\" translate>\n ACCOUNT.TOKENS.CREATE.NAME_ALREADY_EXISTS\n </mat-error>\n </mat-form-field>\n </ion-col>\n </ion-row>\n <ion-row>\n <ion-col>\n <mat-chips-field\n formControlName=\"scopes\"\n appearance=\"fill\"\n chipColor=\"primary\"\n [placeholder]=\"'ACCOUNT.TOKENS.CREATE.SCOPES' | translate\"\n [config]=\"tokenConfig\"\n [mobile]=\"mobile\"\n [debug]=\"false\"\n [required]=\"true\"\n [readonly]=\"tokenForm | formGetValue: 'token' | isNotNilOrBlank\"\n >\n <mat-error *ngIf=\"form.controls.name.hasError('notEmptyArray') && form.controls.name.touched\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n </mat-chips-field>\n </ion-col>\n </ion-row>\n <ion-row>\n <ion-col>\n <mat-date-field\n formControlName=\"expirationDate\"\n [placeholder]=\"'ACCOUNT.TOKENS.CREATE.EXPIRATION_DATE' | translate\"\n [mobile]=\"mobile\"\n [required]=\"true\"\n [readonly]=\"tokenForm | formGetValue: 'token' | isNotNilOrBlank\"\n ></mat-date-field>\n </ion-col>\n </ion-row>\n <ion-row>\n <ion-col>\n <ion-button\n *ngIf=\"tokenForm | formGetValue: 'token' | isNilOrBlank; else showToken\"\n [title]=\"'ACCOUNT.TOKENS.CREATE.BTN_GENERATE_TITLE' | translate\"\n (click)=\"generate($event)\"\n [disabled]=\"tokenForm.invalid\"\n >\n {{ 'ACCOUNT.TOKENS.CREATE.BTN_GENERATE' | translate }}\n </ion-button>\n <ng-template #showToken>\n <p><b translate>ACCOUNT.TOKENS.CREATE.COPY_HELP</b></p>\n <mat-form-field subscriptSizing=\"dynamic\">\n <textarea\n matInput\n formControlName=\"token\"\n readonly\n style=\"height: auto; background-color: lightgray\"\n rows=\"8\"\n ></textarea>\n <button\n matSuffix\n mat-icon-button\n [title]=\"'ACCOUNT.TOKENS.CREATE.BTN_COPY_TITLE' | translate\"\n (click)=\"copy($event)\"\n >\n <mat-icon>content_copy</mat-icon>\n </button>\n </mat-form-field>\n </ng-template>\n </ion-col>\n </ion-row>\n </ion-grid>\n </form>\n</ion-content>\n\n<ion-footer hidden-xs hidden-sm hidden-mobile>\n <ion-toolbar>\n <ion-row class=\"ion-no-padding\" nowrap>\n <ion-col>\n <ng-content></ng-content>\n </ion-col>\n\n <ion-col size=\"auto\">\n <ion-button fill=\"clear\" color=\"dark\" (click)=\"close($event)\">\n <ion-label translate>COMMON.BTN_CANCEL</ion-label>\n </ion-button>\n\n <ion-button\n [fill]=\"invalid ? 'clear' : 'solid'\"\n [disabled]=\"disabled || loading || invalid\"\n (click)=\"saveAndClose($event)\"\n (keyup.enter)=\"saveAndClose($event)\"\n color=\"tertiary\"\n >\n <ion-label translate>COMMON.BTN_VALIDATE</ion-label>\n </ion-button>\n </ion-col>\n </ion-row>\n </ion-toolbar>\n</ion-footer>\n" }]
|
|
32114
32128
|
}], ctorParameters: () => [{ type: i0.Injector }, { type: UserTokenValidatorService }, { type: AccountService }], propDecorators: { tokenScopes: [{
|
|
32115
32129
|
type: Input
|
|
32116
32130
|
}], existingNames: [{
|
|
@@ -32974,6 +32988,7 @@ class AppEntityEditor extends AppTabEditor {
|
|
|
32974
32988
|
dataType;
|
|
32975
32989
|
dataService;
|
|
32976
32990
|
data;
|
|
32991
|
+
previousDataId;
|
|
32977
32992
|
defaultBackHref;
|
|
32978
32993
|
historyIcon;
|
|
32979
32994
|
titleSubject = new BehaviorSubject(undefined);
|
|
@@ -33063,6 +33078,7 @@ class AppEntityEditor extends AppTabEditor {
|
|
|
33063
33078
|
};
|
|
33064
33079
|
// FOR DEV ONLY ----
|
|
33065
33080
|
//this.debug = !environment.production;
|
|
33081
|
+
this._logPrefix = '[entity-editor] ';
|
|
33066
33082
|
}
|
|
33067
33083
|
ngOnInit() {
|
|
33068
33084
|
super.ngOnInit();
|
|
@@ -33087,12 +33103,11 @@ class AppEntityEditor extends AppTabEditor {
|
|
|
33087
33103
|
this.titleSubject.unsubscribe();
|
|
33088
33104
|
this.onUpdateView.complete();
|
|
33089
33105
|
this.onUpdateView.unsubscribe();
|
|
33090
|
-
this.savingSubject.unsubscribe();
|
|
33091
33106
|
}
|
|
33092
33107
|
waitIdle(opts) {
|
|
33093
33108
|
// Wait end of saving
|
|
33094
33109
|
if (this.saving)
|
|
33095
|
-
return waitForFalse(this.savingSubject);
|
|
33110
|
+
return waitForFalse(this.savingSubject, { stop: this.destroySubject });
|
|
33096
33111
|
return super.waitIdle(opts);
|
|
33097
33112
|
}
|
|
33098
33113
|
/**
|
|
@@ -34670,7 +34685,7 @@ class AppAsyncTable {
|
|
|
34670
34685
|
}
|
|
34671
34686
|
async cancel(event, opts) {
|
|
34672
34687
|
// Check confirmation
|
|
34673
|
-
if ((!opts || opts.interactive !== false) && this.dirty && (this.confirmBeforeCancel || this.onBeforeCancelRows.
|
|
34688
|
+
if ((!opts || opts.interactive !== false) && this.dirty && (this.confirmBeforeCancel || this.onBeforeCancelRows.observed)) {
|
|
34674
34689
|
event?.stopPropagation();
|
|
34675
34690
|
if (!(await this.canCancelRows())) {
|
|
34676
34691
|
return;
|
|
@@ -35056,7 +35071,7 @@ class AppAsyncTable {
|
|
|
35056
35071
|
}
|
|
35057
35072
|
async canDeleteRows(rows, opts) {
|
|
35058
35073
|
// Check using emitter
|
|
35059
|
-
if (this.onBeforeDeleteRows.
|
|
35074
|
+
if (this.onBeforeDeleteRows.observed) {
|
|
35060
35075
|
try {
|
|
35061
35076
|
const canDelete = await emitPromiseEvent(this.onBeforeDeleteRows, 'canDelete', {
|
|
35062
35077
|
detail: { rows },
|
|
@@ -35083,7 +35098,7 @@ class AppAsyncTable {
|
|
|
35083
35098
|
if (isEmptyArray(rows))
|
|
35084
35099
|
return true; // No dirty: OK
|
|
35085
35100
|
// Check using emitter
|
|
35086
|
-
if (this.onBeforeCancelRows.
|
|
35101
|
+
if (this.onBeforeCancelRows.observed) {
|
|
35087
35102
|
try {
|
|
35088
35103
|
const isCancel = await emitPromiseEvent(this.onBeforeCancelRows, 'canCancel', {
|
|
35089
35104
|
detail: { rows },
|
|
@@ -35126,7 +35141,7 @@ class AppAsyncTable {
|
|
|
35126
35141
|
// Default behavior
|
|
35127
35142
|
let confirmed = true;
|
|
35128
35143
|
if (save) {
|
|
35129
|
-
if (this.onBeforeSave.
|
|
35144
|
+
if (this.onBeforeSave.observed) {
|
|
35130
35145
|
// Ask confirmation
|
|
35131
35146
|
try {
|
|
35132
35147
|
const res = await emitPromiseEvent(this.onBeforeSave, 'beforeSave', {
|
|
@@ -35167,7 +35182,7 @@ class AppAsyncTable {
|
|
|
35167
35182
|
if (this.debug && this.dirty) {
|
|
35168
35183
|
console.warn('[table] Opening row details, but table has unsaved changes!');
|
|
35169
35184
|
}
|
|
35170
|
-
if (this.onOpenRow.
|
|
35185
|
+
if (this.onOpenRow.observed) {
|
|
35171
35186
|
this.onOpenRow.emit(row);
|
|
35172
35187
|
return true;
|
|
35173
35188
|
}
|
|
@@ -35186,7 +35201,7 @@ class AppAsyncTable {
|
|
|
35186
35201
|
async openNewRowDetail(event) {
|
|
35187
35202
|
if (!this.allowRowDetail)
|
|
35188
35203
|
return false;
|
|
35189
|
-
if (this.onNewRow.
|
|
35204
|
+
if (this.onNewRow.observed) {
|
|
35190
35205
|
this.onNewRow.emit(event);
|
|
35191
35206
|
return true;
|
|
35192
35207
|
}
|
|
@@ -35489,7 +35504,7 @@ class AppAsyncTable {
|
|
|
35489
35504
|
throw new Error('Row cannot be canceling, but only deleting');
|
|
35490
35505
|
const confirmed = !opts || opts.interactive !== false;
|
|
35491
35506
|
// Ask user confirmation, if cancel
|
|
35492
|
-
if (!confirmed && row.dirty && (this.confirmBeforeCancel || this.onBeforeCancelRows.
|
|
35507
|
+
if (!confirmed && row.dirty && (this.confirmBeforeCancel || this.onBeforeCancelRows.observed)) {
|
|
35493
35508
|
event?.stopPropagation();
|
|
35494
35509
|
if (!(await this.canCancelRows([row], opts))) {
|
|
35495
35510
|
return;
|
|
@@ -37850,11 +37865,11 @@ class UsersPage extends AppTable {
|
|
|
37850
37865
|
this.cd.markForCheck();
|
|
37851
37866
|
}
|
|
37852
37867
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.2.4", ngImport: i0, type: UsersPage, deps: [{ token: i0.Injector }, { token: i1$2.UntypedFormBuilder }, { token: AccountService }, { token: i2$8.ValidatorService }, { token: ConfigService }, { token: PersonService }, { token: MessageService }, { token: MenuService }, { token: i0.ChangeDetectorRef }, { token: ENVIRONMENT }], target: i0.ɵɵFactoryTarget.Component });
|
|
37853
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.2.4", type: UsersPage, selector: "app-users-table", inputs: { sticky: "sticky", stickyEnd: "stickyEnd" }, providers: [{ provide: ValidatorService, useExisting: PersonValidatorService }], viewQueries: [{ propertyName: "filterExpansionPanel", first: true, predicate: MatExpansionPanel, descendants: true, static: true }], usesInheritance: true, ngImport: i0, template: "<app-toolbar\n [title]=\"'USER.LIST.TITLE' | translate\"\n color=\"primary\"\n [canGoBack]=\"false\"\n [hasValidate]=\"(loadingSubject | async) !== true && (dirtySubject | async) === true\"\n (onValidate)=\"save()\"\n>\n <ion-buttons slot=\"end\">\n <!-- Compose message -->\n <button\n mat-icon-button\n *ngIf=\"canSendMessage\"\n [title]=\"'USER.LIST.BTN_SEND_MESSAGE' | translate\"\n (click)=\"openComposeMessageModal($event)\"\n >\n <ion-icon name=\"mail\" slot=\"icon-only\"></ion-icon>\n </button>\n\n <ng-container *ngIf=\"!selection.hasValue(); else hasSelection\">\n <!-- Add -->\n <button mat-icon-button *ngIf=\"canEdit && !mobile\" [title]=\"'COMMON.BTN_ADD' | translate\" (click)=\"addRow()\">\n <mat-icon>add</mat-icon>\n </button>\n\n <!-- Refresh -->\n <button mat-icon-button *ngIf=\"!mobile\" [title]=\"'COMMON.BTN_REFRESH' | translate\" (click)=\"onRefresh.emit()\">\n <mat-icon>refresh</mat-icon>\n </button>\n\n <!-- reset filter -->\n <button mat-icon-button (click)=\"resetFilter()\" *ngIf=\"filterCriteriaCount\">\n <mat-icon color=\"accent\">filter_list_alt</mat-icon>\n <mat-icon class=\"icon-secondary\" style=\"left: 16px; top: 5px; font-weight: bold\">close</mat-icon>\n </button>\n\n <!-- show filter -->\n <button mat-icon-button (click)=\"filterExpansionPanel.toggle()\">\n <mat-icon\n *ngIf=\"filterCriteriaCount; else emptyFilter\"\n [matBadge]=\"filterCriteriaCount\"\n matBadgeColor=\"accent\"\n matBadgeSize=\"small\"\n matBadgePosition=\"above after\"\n aria-hidden=\"false\"\n >\n filter_list_alt\n </mat-icon>\n <ng-template #emptyFilter>\n <mat-icon>filter_list_alt</mat-icon>\n </ng-template>\n </button>\n </ng-container>\n\n <ng-template #hasSelection>\n <!-- delete -->\n <button\n mat-icon-button\n class=\"hidden-xs hidden-sm\"\n [title]=\"'COMMON.BTN_DELETE' | translate\"\n (click)=\"deleteSelection($event)\"\n >\n <mat-icon>delete</mat-icon>\n </button>\n </ng-template>\n </ion-buttons>\n</app-toolbar>\n\n<ion-content class=\"ion-no-padding\">\n <!-- error -->\n <ion-item\n *ngIf=\"errorSubject | async; let error\"\n lines=\"none\"\n class=\"hidden-sm hidden-xs hidden-mobile\"\n @slideUpDownAnimation\n >\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 <!-- debug -->\n <app-debug *ngIf=\"debug\">\n <ion-grid class=\"ion-no-padding\">\n <ion-row>\n <ion-col>\n focusColumn: {{ focusColumn }}\n <br />\n loadingSubject: {{ loading }}\n <br />\n </ion-col>\n </ion-row>\n </ion-grid>\n </app-debug>\n\n <!-- search -->\n <mat-expansion-panel #filterExpansionPanel class=\"ion-no-padding filter-panel filter-panel-floating\">\n <form class=\"form-container ion-padding\" [formGroup]=\"filterForm\" (ngSubmit)=\"onRefresh.emit()\">\n <ion-grid>\n <ion-row>\n <ion-col>\n <!-- search -->\n <mat-form-field>\n <mat-label>{{ 'USER.LIST.FILTER.SEARCH' | translate }}</mat-label>\n <input matInput formControlName=\"searchText\" />\n <button\n mat-icon-button\n matSuffix\n tabindex=\"-1\"\n type=\"button\"\n (click)=\"clearControlValue($event, filterForm.controls.searchText)\"\n [hidden]=\"filterForm.controls.searchText.disabled || !filterForm.controls.searchText.value\"\n >\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n </ion-col>\n\n <ion-col>\n <!-- status -->\n <mat-form-field>\n <mat-label>{{ 'USER.STATUS' | translate }}</mat-label>\n <mat-select formControlName=\"statusId\">\n <mat-option [value]=\"null\">\n <i><span translate>COMMON.EMPTY_OPTION</span></i>\n </mat-option>\n <mat-option *ngFor=\"let item of statusList\" [value]=\"item.id\">\n <ion-icon [name]=\"item.icon\"></ion-icon>\n {{ item.label | translate }}\n </mat-option>\n </mat-select>\n\n <button\n mat-icon-button\n matSuffix\n tabindex=\"-1\"\n type=\"button\"\n (click)=\"clearControlValue($event, filterForm.controls.statusId)\"\n [hidden]=\"filterForm.controls.statusId.disabled || !filterForm.controls.statusId.value\"\n >\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n </ion-col>\n </ion-row>\n </ion-grid>\n </form>\n\n <mat-action-row>\n <!-- Counter -->\n <ion-label\n [hidden]=\"(loadingSubject | async) === true || filterForm.dirty\"\n [color]=\"empty && 'danger'\"\n class=\"ion-padding\"\n >\n {{\n (totalRowCount ? 'COMMON.RESULT_COUNT' : 'COMMON.NO_RESULT')\n | translate\n : {\n count: (totalRowCount | numberFormat)\n }\n }}\n </ion-label>\n\n <div class=\"toolbar-spacer\"></div>\n\n <!-- Close panel -->\n <ion-button\n mat-button\n fill=\"clear\"\n color=\"dark\"\n (click)=\"filterExpansionPanel.close()\"\n [disabled]=\"loadingSubject | async\"\n >\n <ion-text translate>COMMON.BTN_CLOSE</ion-text>\n </ion-button>\n\n <!-- Search button -->\n <ion-button\n mat-button\n [color]=\"filterForm.dirty ? 'tertiary' : 'dark'\"\n [fill]=\"filterForm.dirty ? 'solid' : 'clear'\"\n (click)=\"applyFilterAndClosePanel($event)\"\n [disabled]=\"loadingSubject | async\"\n >\n <ion-text translate>COMMON.BTN_APPLY</ion-text>\n </ion-button>\n </mat-action-row>\n </mat-expansion-panel>\n\n <!-- error -->\n <ion-item *ngIf=\"mobile && (errorSubject | async); let 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 <div class=\"table-container\">\n <table\n #table\n mat-table\n matSort\n [dataSource]=\"dataSource\"\n [matSortActive]=\"defaultSortBy\"\n [matSortDirection]=\"defaultSortDirection\"\n matSortDisableClear\n [trackBy]=\"trackByFn\"\n >\n <ng-container matColumnDef=\"select\" [sticky]=\"sticky\">\n <th mat-header-cell *matHeaderCellDef [class.cdk-visually-hidden]=\"!inlineEdition\">\n <mat-checkbox\n (change)=\"$event ? masterToggle() : null\"\n [checked]=\"selection.hasValue() && isAllSelected()\"\n [indeterminate]=\"selection.hasValue() && !isAllSelected()\"\n ></mat-checkbox>\n </th>\n <td mat-cell *matCellDef=\"let row\" [class.cdk-visually-hidden]=\"!inlineEdition\">\n <mat-checkbox (click)=\"toggleSelectRow($event, row)\" [checked]=\"selection.isSelected(row)\"></mat-checkbox>\n </td>\n </ng-container>\n\n <!-- Id Column -->\n <ng-container matColumnDef=\"id\" [sticky]=\"sticky\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header>\n <ion-label>#</ion-label>\n </th>\n <td mat-cell *matCellDef=\"let row\">{{ row.currentData.id }}</td>\n </ng-container>\n\n <!-- avatar Column -->\n <ng-container matColumnDef=\"avatar\" [sticky]=\"sticky\">\n <th mat-header-cell *matHeaderCellDef></th>\n <td mat-cell *matCellDef=\"let row\">\n <ion-avatar [style.background-color]=\"'white'\">\n <ion-img *ngIf=\"row.currentData.avatar; let avatarUrl; else: generateIcon\" [src]=\"avatarUrl\"></ion-img>\n <ng-template #generateIcon>\n <svg width=\"39\" height=\"39\" [data-jdenticon-value]=\"row.currentData.id\"></svg>\n </ng-template>\n </ion-avatar>\n </td>\n </ng-container>\n\n <!-- lastName -->\n <ng-container matColumnDef=\"lastName\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header>\n <span translate>USER.LAST_NAME</span>\n </th>\n <td mat-cell *matCellDef=\"let row\" (click)=\"focusColumn = 'lastName'\">\n <mat-form-field *ngIf=\"row.editing; else readonlyCell\">\n <input\n matInput\n [formControl]=\"row.validator.controls['lastName']\"\n [placeholder]=\"'USER.LAST_NAME' | translate\"\n [readonly]=\"!row.editing\"\n [appAutofocus]=\"row.editing && focusColumn === 'lastName'\"\n />\n <mat-error *ngIf=\"row.validator.controls['lastName'].hasError('required')\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n <mat-error *ngIf=\"row.validator.controls['lastName'].hasError('minlength')\">\n <span>{{ 'ERROR.FIELD_MIN_LENGTH' | translate: { minLength: 2 } }}</span>\n </mat-error>\n </mat-form-field>\n <ng-template #readonlyCell>\n <ion-label appAutoTitle>\n {{ row.validator | formGetValue: 'lastName' }}\n </ion-label>\n </ng-template>\n </td>\n </ng-container>\n\n <!-- firstname -->\n <ng-container matColumnDef=\"firstName\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header>\n <span translate>USER.FIRST_NAME</span>\n </th>\n <td mat-cell *matCellDef=\"let row\" (click)=\"focusColumn = 'firstName'\">\n <mat-form-field *ngIf=\"row.editing; else readonlyCell\">\n <input\n matInput\n [formControl]=\"row.validator.controls['firstName']\"\n [placeholder]=\"'USER.FIRST_NAME' | translate\"\n [readonly]=\"!row.editing\"\n [appAutofocus]=\"row.editing && focusColumn === 'firstName'\"\n />\n <mat-error *ngIf=\"row.validator.controls['firstName'].hasError('required')\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n <mat-error *ngIf=\"row.validator.controls['firstName'].hasError('minlength')\">\n <span>{{ 'ERROR.FIELD_MIN_LENGTH' | translate: { minLength: 2 } }}</span>\n </mat-error>\n </mat-form-field>\n <ng-template #readonlyCell>\n <ion-label appAutoTitle>\n {{ row.validator | formGetValue: 'firstName' }}\n </ion-label>\n </ng-template>\n </td>\n </ng-container>\n\n <!-- email -->\n <ng-container matColumnDef=\"email\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header>\n <span translate>USER.EMAIL</span>\n </th>\n <td mat-cell *matCellDef=\"let row\" (click)=\"focusColumn = 'email'\">\n <mat-form-field *ngIf=\"row.editing; else readonlyCell\">\n <input\n matInput\n [formControl]=\"row.validator.controls['email']\"\n [placeholder]=\"'USER.EMAIL' | translate\"\n [readonly]=\"!row.editing\"\n [appAutofocus]=\"row.editing && focusColumn === 'email'\"\n />\n <mat-error *ngIf=\"row.validator.controls['email'].hasError('required')\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n <mat-error *ngIf=\"row.validator.controls['email'].hasError('email')\">\n <span translate>ERROR.FIELD_NOT_VALID_EMAIL</span>\n </mat-error>\n </mat-form-field>\n <ng-template #readonlyCell>\n <ion-label appAutoTitle>\n {{ row.validator | formGetValue: 'email' }}\n </ion-label>\n </ng-template>\n </td>\n </ng-container>\n\n <!-- additional fields -->\n <ng-container *ngFor=\"let definition of additionalFields\" [matColumnDef]=\"definition.key\">\n <th mat-header-cell *matHeaderCellDef>\n <span>{{ definition.label | translate }}</span>\n </th>\n <td mat-cell *matCellDef=\"let row\" (click)=\"focusColumn = definition.key\">\n <app-form-field\n floatLabel=\"never\"\n [definition]=\"definition\"\n [formControl]=\"row.validator.controls[definition.key]\"\n [required]=\"definition.extra?.account?.required\"\n [autofocus]=\"row.editing && focusColumn === definition.key\"\n ></app-form-field>\n </td>\n </ng-container>\n\n <!-- profile column -->\n <ng-container matColumnDef=\"profile\">\n <th mat-header-cell *matHeaderCellDef>\n <span translate>USER.PROFILE</span>\n </th>\n <td mat-cell *matCellDef=\"let row\" (click)=\"focusColumn = 'profile'\">\n <mat-form-field>\n <mat-select\n [formControl]=\"row.validator.controls['mainProfile']\"\n [placeholder]=\"'USER.PROFILE' | translate\"\n >\n <mat-option *ngFor=\"let item of profiles\" [value]=\"item\">\n {{ 'USER.PROFILE_ENUM.' + item | uppercase | translate }}\n </mat-option>\n </mat-select>\n <mat-error *ngIf=\"row.validator.controls['mainProfile'].hasError('required')\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n </mat-form-field>\n </td>\n </ng-container>\n\n <!-- Status column -->\n <ng-container matColumnDef=\"status\">\n <th mat-header-cell *matHeaderCellDef>\n <span translate>USER.STATUS</span>\n </th>\n <td mat-cell *matCellDef=\"let row\" (click)=\"focusColumn = 'status'\">\n <mat-form-field>\n <!-- <ion-icon matPrefix *ngIf=\"row.validator.controls['statusId'].value >=0\" [name]=\"statusById[row.validator.controls['statusId'].value]?.icon\"></ion-icon>-->\n\n <mat-select\n [formControl]=\"row.validator.controls['statusId']\"\n [placeholder]=\"'REFERENTIAL.STATUS' | translate\"\n >\n <mat-select-trigger>\n <span *ngIf=\"row.validator.controls['statusId'].value >=0\">\n {{ statusById[row.validator.controls['statusId'].value]?.label | translate }}\n </span>\n </mat-select-trigger>\n <mat-option *ngFor=\"let item of statusList\" [value]=\"item.id\">\n <mat-icon><ion-icon [name]=\"item.icon\"></ion-icon></mat-icon>\n {{ item.label | translate }}\n </mat-option>\n </mat-select>\n <mat-error *ngIf=\"row.validator.controls['statusId'].hasError('required')\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n </mat-form-field>\n </td>\n </ng-container>\n\n <!-- username -->\n <ng-container matColumnDef=\"username\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header>\n <span translate>USER.USERNAME</span>\n </th>\n <td mat-cell *matCellDef=\"let row\" (click)=\"focusColumn = 'username'\">\n <mat-form-field *ngIf=\"row.editing; else readonlyCell\">\n <input\n matInput\n [formControl]=\"row.validator.controls.username\"\n [placeholder]=\"'USER.USERNAME' | translate\"\n [readonly]=\"!row.editing\"\n [appAutofocus]=\"row.editing && focusColumn === 'username'\"\n />\n <mat-error *ngIf=\"row.validator.controls.username.hasError('required')\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n </mat-form-field>\n <ng-template #readonlyCell>\n <ion-label appAutoTitle>\n {{ row.validator | formGetValue: 'username' }}\n </ion-label>\n </ng-template>\n </td>\n </ng-container>\n\n <!-- username extranet -->\n <ng-container matColumnDef=\"usernameExtranet\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header>\n <span translate>USER.USERNAME_EXTRANET</span>\n </th>\n <td mat-cell *matCellDef=\"let row\" (click)=\"focusColumn = 'usernameExtranet'\">\n <mat-form-field *ngIf=\"row.editing; else readonlyCell\">\n <input\n matInput\n [formControl]=\"row.validator.controls.usernameExtranet\"\n [placeholder]=\"'USER.USERNAME_EXTRANET' | translate\"\n [readonly]=\"!row.editing\"\n [appAutofocus]=\"row.editing && focusColumn === 'usernameExtranet'\"\n />\n <mat-error *ngIf=\"row.validator.controls.usernameExtranet.hasError('required')\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n </mat-form-field>\n <ng-template #readonlyCell>\n <ion-label appAutoTitle>\n {{ row.validator | formGetValue: 'usernameExtranet' }}\n </ion-label>\n </ng-template>\n </td>\n </ng-container>\n\n <!-- pubkey -->\n <ng-container matColumnDef=\"pubkey\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header>\n <span translate>USER.PUBKEY</span>\n </th>\n <td\n mat-cell\n *matCellDef=\"let row\"\n [title]=\"row.validator.controls.pubkey.valueChanges | async\"\n (click)=\"focusColumn = 'pubkey'\"\n >\n <mat-form-field *ngIf=\"row.editing; else readonlyCell\">\n <input\n matInput\n [formControl]=\"row.validator.controls['pubkey']\"\n [placeholder]=\"'USER.PUBKEY' | translate\"\n [readonly]=\"!row.editing\"\n autocomplete=\"off\"\n />\n <mat-error *ngIf=\"row.validator.controls.pubkey.hasError('required')\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n <mat-error *ngIf=\"row.validator.controls.pubkey.hasError('pubkey')\">\n <span translate>ERROR.FIELD_NOT_VALID_PUBKEY</span>\n </mat-error>\n </mat-form-field>\n <ng-template #readonlyCell>\n <ion-label appAutoTitle>\n {{ row.validator | formGetValue: 'pubkey' }}\n </ion-label>\n </ng-template>\n </td>\n </ng-container>\n\n <!-- Actions buttons column -->\n <app-actions-column\n [stickyEnd]=\"stickyEnd\"\n (optionsClick)=\"openSelectColumnsModal($event)\"\n (cancelOrDeleteClick)=\"cancelOrDelete($event.event, $event.row)\"\n (confirmEditCreateClick)=\"confirmEditCreate($event.event, $event.row)\"\n (confirmAndAddClick)=\"confirmAndAdd($event.event, $event.row)\"\n (backward)=\"confirmAndBackward($event.event, $event.row)\"\n (forward)=\"confirmAndForward($event.event, $event.row)\"\n [canCancel]=\"false\"\n ></app-actions-column>\n\n <tr mat-header-row *matHeaderRowDef=\"displayedColumns; sticky: true\"></tr>\n <tr\n mat-row\n *matRowDef=\"let row; columns: displayedColumns\"\n [class.mat-row-selected]=\"row.editing\"\n [class.mat-row-error]=\"row.validator.invalid\"\n [class.mat-row-dirty]=\"row.currentData.dirty\"\n [class.mat-row-disabled]=\"!row.editing\"\n (click)=\"clickRow($event, row)\"\n (keydown.escape)=\"escapeEditingRow($event)\"\n [cdkTrapFocus]=\"!row.validator?.valid\"\n ></tr>\n </table>\n\n <ng-container *ngIf=\"loadingSubject | async; else noResult\">\n <ion-item>\n <ion-skeleton-text animated></ion-skeleton-text>\n </ion-item>\n </ng-container>\n\n <ng-template #noResult>\n <ion-item *ngIf=\"totalRowCount === 0\">\n <ion-text color=\"danger\" class=\"text-italic\" translate>COMMON.NO_RESULT</ion-text>\n </ion-item>\n </ng-template>\n </div>\n</ion-content>\n\n<ion-footer>\n <mat-paginator\n [length]=\"totalRowCount\"\n [pageSize]=\"defaultPageSize\"\n [pageSizeOptions]=\"defaultPageSizeOptions\"\n showFirstLastButtons\n ></mat-paginator>\n\n <app-form-buttons-bar\n *ngIf=\"!mobile && canEdit\"\n (onCancel)=\"onRefresh.emit()\"\n (onSave)=\"save()\"\n [disabled]=\"(loadingSubject | async) === true || (dirtySubject | async) !== true\"\n >\n <!-- error -->\n <ion-item *ngIf=\"errorSubject | async; let error\" lines=\"none\">\n <ion-icon color=\"danger\" slot=\"start\" name=\"alert-circle\"></ion-icon>\n <ion-label color=\"danger\" [innerHTML]=\"error | translate\"></ion-label>\n </ion-item>\n </app-form-buttons-bar>\n</ion-footer>\n\n<ion-fab slot=\"fixed\" vertical=\"bottom\" horizontal=\"end\" *ngIf=\"mobile\">\n <ion-fab-button color=\"tertiary\" (click)=\"addRow()\">\n <ion-icon name=\"add\"></ion-icon>\n </ion-fab-button>\n</ion-fab>\n", styles: [".mat-expansion-panel{margin-bottom:5px}.mat-expansion-panel .form-container mat-form-field{width:100%}.mat-expansion-panel mat-action-row ion-label{line-height:36px}.table-container{height:100%}.mat-mdc-table .mat-column-avatar{width:50px}.mat-mdc-table .mat-column-avatar ion-avatar{--border-radius: 5px !important;--border-width: 1px !important;--border-color: rgba(var(--ion-color-secondary-rgb), .5) !important;height:40px;width:40px;max-width:40px;max-height:40px;border:solid var(--border-width) var(--border-color);margin:0 2px}.mat-mdc-table .mat-column-id{width:30px;align-content:end}.mat-mdc-table .mat-column-lastName,.mat-mdc-table .mat-column-firstName{min-width:80px}.mat-mdc-table .mat-column-email,.mat-mdc-table .mat-column-pubkey,.mat-mdc-table .mat-column-department{min-width:180px}.mat-mdc-table .mat-column-profile{min-width:110px}.mat-mdc-table .mat-column-status{min-width:130px}\n"], dependencies: [{ kind: "directive", type: i4$3.SvgJdenticonDirective, selector: "svg[data-jdenticon-hash],svg[data-jdenticon-value]", inputs: ["data-jdenticon-hash", "data-jdenticon-value", "width", "height"] }, { kind: "directive", type: i1$1.TranslateDirective, selector: "[translate],[ngx-translate]", inputs: ["translate", "translateParams"] }, { 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.IonAvatar, selector: "ion-avatar" }, { 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", "forceOverscroll", "fullscreen", "scrollEvents", "scrollX", "scrollY"] }, { kind: "component", type: i2$1.IonFab, selector: "ion-fab", inputs: ["activated", "edge", "horizontal", "vertical"] }, { kind: "component", type: i2$1.IonFabButton, selector: "ion-fab-button", inputs: ["activated", "closeIcon", "color", "disabled", "download", "href", "mode", "rel", "routerAnimation", "routerDirection", "show", "size", "target", "translucent", "type"] }, { 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.IonImg, selector: "ion-img", inputs: ["alt", "src"] }, { kind: "component", type: i2$1.IonItem, selector: "ion-item", inputs: ["button", "color", "counter", "counterFormatter", "detail", "detailIcon", "disabled", "download", "fill", "href", "lines", "mode", "rel", "routerAnimation", "routerDirection", "shape", "target", "type"] }, { kind: "component", type: i2$1.IonLabel, selector: "ion-label", inputs: ["color", "mode", "position"] }, { kind: "component", type: i2$1.IonRow, selector: "ion-row" }, { kind: "component", type: i2$1.IonSkeletonText, selector: "ion-skeleton-text", inputs: ["animated"] }, { kind: "component", type: i2$1.IonText, selector: "ion-text", inputs: ["color", "mode"] }, { kind: "directive", type: i1$2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$2.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$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$2.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1$2.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: i7$1.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: i7$1.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i7$1.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: i7$1.MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: i7$1.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i7$1.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: i7$1.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i7$1.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "component", type: i7$1.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: i7$1.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { kind: "directive", type: i8$1.MatSort, selector: "[matSort]", inputs: ["matSortActive", "matSortStart", "matSortDirection", "matSortDisableClear", "matSortDisabled"], outputs: ["matSortChange"], exportAs: ["matSort"] }, { kind: "component", type: i8$1.MatSortHeader, selector: "[mat-sort-header]", inputs: ["mat-sort-header", "arrowPosition", "start", "disabled", "sortActionDescription", "disableClear"], exportAs: ["matSortHeader"] }, { kind: "component", type: i9$2.MatPaginator, selector: "mat-paginator", inputs: ["color", "pageIndex", "length", "pageSize", "pageSizeOptions", "hidePageSize", "showFirstLastButtons", "selectConfig", "disabled"], outputs: ["page"], exportAs: ["matPaginator"] }, { 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.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", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }, { kind: "component", type: i13$2.MatExpansionPanel, selector: "mat-expansion-panel", inputs: ["hideToggle", "togglePosition"], outputs: ["afterExpand", "afterCollapse"], exportAs: ["matExpansionPanel"] }, { kind: "directive", type: i13$2.MatExpansionPanelActionRow, selector: "mat-action-row" }, { kind: "component", type: i4$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i9$1.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "component", type: i13.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: "directive", type: i13.MatSelectTrigger, selector: "mat-select-trigger" }, { kind: "component", type: i2.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "directive", type: i7$2.MatBadge, selector: "[matBadge]", inputs: ["matBadgeColor", "matBadgeOverlap", "matBadgeDisabled", "matBadgePosition", "matBadge", "matBadgeDescription", "matBadgeSize", "matBadgeHidden"] }, { kind: "directive", type: i1$3.CdkTrapFocus, selector: "[cdkTrapFocus]", inputs: ["cdkTrapFocus", "cdkTrapFocusAutoCapture"], exportAs: ["cdkTrapFocus"] }, { kind: "directive", type: AutofocusDirective, selector: "[autofocus], input[appAutofocus]", inputs: ["appAutofocus", "autofocusDelay"] }, { kind: "directive", type: AutoTitleDirective, selector: "[appAutoTitle]" }, { kind: "component", type: ToolbarComponent, selector: "app-toolbar", inputs: ["progressBarMode", "title", "color", "class", "backHref", "defaultBackHref", "hasValidate", "hasClose", "hasSearch", "canGoBack", "canShowMenu"], outputs: ["onValidate", "onClose", "onValidateAndClose", "onBackClick", "onSearch"] }, { kind: "component", type: AppFormField, selector: "app-form-field", inputs: ["definition", "required", "readonly", "disabled", "formControl", "formControlName", "placeholder", "compact", "floatLabel", "appearance", "tabindex", "autofocus", "clearable", "chipColor", "class", "debug"], outputs: ["keyup.enter"] }, { kind: "component", type: FormButtonsBarComponent, selector: "app-form-buttons-bar", inputs: ["disabled", "disabledCancel", "classList", "saveButtonColor", "backText", "cancelText", "nextText", "showBack", "showCancel", "showNext", "showSave", "showSaveAndClose", "showSaveAndNext"], outputs: ["onCancel", "onSave", "onNext", "onBack", "onSaveAndClose", "onSaveAndNext"] }, { kind: "component", type: ActionsColumnComponent, selector: "app-actions-column", inputs: ["matColumnDef", "style", "stickyEnd", "canCancel", "canConfirm", "canDelete", "canBackward", "canForward", "canConfirmAndAdd", "dirtyIcon", "optionsTitle", "class", "cellTemplate"], outputs: ["optionsClick", "cancelOrDeleteClick", "confirmEditCreateClick", "confirmAndAddClick", "backward", "forward"] }, { kind: "component", type: DebugComponent, selector: "app-debug", inputs: ["title", "enable", "expanded"] }, { kind: "pipe", type: i1$1.TranslatePipe, name: "translate" }, { kind: "pipe", type: i3.AsyncPipe, name: "async" }, { kind: "pipe", type: i3.UpperCasePipe, name: "uppercase" }, { kind: "pipe", type: NumberFormatPipe, name: "numberFormat" }, { kind: "pipe", type: FormGetValuePipe, name: "formGetValue" }], animations: [slideUpDownAnimation], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
37868
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.2.4", type: UsersPage, selector: "app-users-table", inputs: { sticky: "sticky", stickyEnd: "stickyEnd" }, providers: [{ provide: ValidatorService, useExisting: PersonValidatorService }], viewQueries: [{ propertyName: "filterExpansionPanel", first: true, predicate: MatExpansionPanel, descendants: true, static: true }], usesInheritance: true, ngImport: i0, template: "<app-toolbar\n [title]=\"'USER.LIST.TITLE' | translate\"\n color=\"primary\"\n [canGoBack]=\"false\"\n [hasValidate]=\"(loadingSubject | async) !== true && (dirtySubject | async) === true\"\n (onValidate)=\"save()\"\n>\n <ion-buttons slot=\"end\">\n <!-- Compose message -->\n <button\n mat-icon-button\n *ngIf=\"canSendMessage\"\n [title]=\"'USER.LIST.BTN_SEND_MESSAGE' | translate\"\n (click)=\"openComposeMessageModal($event)\"\n >\n <ion-icon name=\"mail\" slot=\"icon-only\"></ion-icon>\n </button>\n\n <ng-container *ngIf=\"!selection.hasValue(); else hasSelection\">\n <!-- Add -->\n <button mat-icon-button *ngIf=\"canEdit && !mobile\" [title]=\"'COMMON.BTN_ADD' | translate\" (click)=\"addRow()\">\n <mat-icon>add</mat-icon>\n </button>\n\n <!-- Refresh -->\n <button mat-icon-button *ngIf=\"!mobile\" [title]=\"'COMMON.BTN_REFRESH' | translate\" (click)=\"onRefresh.emit()\">\n <mat-icon>refresh</mat-icon>\n </button>\n\n <!-- reset filter -->\n <button mat-icon-button (click)=\"resetFilter()\" *ngIf=\"filterCriteriaCount\">\n <mat-icon color=\"accent\">filter_list_alt</mat-icon>\n <mat-icon class=\"icon-secondary\" style=\"left: 16px; top: 5px; font-weight: bold\">close</mat-icon>\n </button>\n\n <!-- show filter -->\n <button mat-icon-button (click)=\"filterExpansionPanel.toggle()\">\n <mat-icon\n *ngIf=\"filterCriteriaCount; else emptyFilter\"\n [matBadge]=\"filterCriteriaCount\"\n matBadgeColor=\"accent\"\n matBadgeSize=\"small\"\n matBadgePosition=\"above after\"\n aria-hidden=\"false\"\n >\n filter_list_alt\n </mat-icon>\n <ng-template #emptyFilter>\n <mat-icon>filter_list_alt</mat-icon>\n </ng-template>\n </button>\n </ng-container>\n\n <ng-template #hasSelection>\n <!-- delete -->\n <button\n mat-icon-button\n class=\"hidden-xs hidden-sm\"\n [title]=\"'COMMON.BTN_DELETE' | translate\"\n (click)=\"deleteSelection($event)\"\n >\n <mat-icon>delete</mat-icon>\n </button>\n </ng-template>\n </ion-buttons>\n</app-toolbar>\n\n<ion-content class=\"ion-no-padding\">\n <!-- error -->\n <ion-item\n *ngIf=\"errorSubject | async; let error\"\n lines=\"none\"\n class=\"hidden-sm hidden-xs hidden-mobile\"\n @slideUpDownAnimation\n >\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 <!-- debug -->\n <app-debug *ngIf=\"debug\">\n <ion-grid class=\"ion-no-padding\">\n <ion-row>\n <ion-col>\n focusColumn: {{ focusColumn }}\n <br />\n loadingSubject: {{ loading }}\n <br />\n </ion-col>\n </ion-row>\n </ion-grid>\n </app-debug>\n\n <!-- search -->\n <mat-expansion-panel #filterExpansionPanel class=\"ion-no-padding filter-panel filter-panel-floating\">\n <form class=\"form-container ion-padding\" [formGroup]=\"filterForm\" (ngSubmit)=\"onRefresh.emit()\">\n <ion-grid>\n <ion-row>\n <ion-col>\n <!-- search -->\n <mat-form-field>\n <mat-label>{{ 'USER.LIST.FILTER.SEARCH' | translate }}</mat-label>\n <input matInput formControlName=\"searchText\" />\n <button\n mat-icon-button\n matSuffix\n tabindex=\"-1\"\n type=\"button\"\n (click)=\"clearControlValue($event, filterForm.controls.searchText)\"\n [hidden]=\"filterForm.controls.searchText.disabled || !filterForm.controls.searchText.value\"\n >\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n </ion-col>\n\n <ion-col>\n <!-- status -->\n <mat-form-field>\n <mat-label>{{ 'USER.STATUS' | translate }}</mat-label>\n <mat-select formControlName=\"statusId\">\n <mat-option [value]=\"null\">\n <i><span translate>COMMON.EMPTY_OPTION</span></i>\n </mat-option>\n <mat-option *ngFor=\"let item of statusList\" [value]=\"item.id\">\n <ion-icon [name]=\"item.icon\"></ion-icon>\n {{ item.label | translate }}\n </mat-option>\n </mat-select>\n\n <button\n mat-icon-button\n matSuffix\n tabindex=\"-1\"\n type=\"button\"\n (click)=\"clearControlValue($event, filterForm.controls.statusId)\"\n [hidden]=\"filterForm.controls.statusId.disabled || !filterForm.controls.statusId.value\"\n >\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n </ion-col>\n </ion-row>\n </ion-grid>\n </form>\n\n <mat-action-row>\n <!-- Counter -->\n <ion-label\n [hidden]=\"(loadingSubject | async) === true || filterForm.dirty\"\n [color]=\"empty && 'danger'\"\n class=\"ion-padding\"\n >\n {{\n (totalRowCount ? 'COMMON.RESULT_COUNT' : 'COMMON.NO_RESULT')\n | translate\n : {\n count: (totalRowCount | numberFormat)\n }\n }}\n </ion-label>\n\n <div class=\"toolbar-spacer\"></div>\n\n <!-- Close panel -->\n <ion-button\n mat-button\n fill=\"clear\"\n color=\"dark\"\n (click)=\"filterExpansionPanel.close()\"\n [disabled]=\"loadingSubject | async\"\n >\n <ion-text translate>COMMON.BTN_CLOSE</ion-text>\n </ion-button>\n\n <!-- Search button -->\n <ion-button\n mat-button\n [color]=\"filterForm.dirty ? 'tertiary' : 'dark'\"\n [fill]=\"filterForm.dirty ? 'solid' : 'clear'\"\n (click)=\"applyFilterAndClosePanel($event)\"\n [disabled]=\"loadingSubject | async\"\n >\n <ion-text translate>COMMON.BTN_APPLY</ion-text>\n </ion-button>\n </mat-action-row>\n </mat-expansion-panel>\n\n <!-- error -->\n <ion-item *ngIf=\"mobile && (errorSubject | async); let 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 <div class=\"table-container\">\n <table\n #table\n mat-table\n matSort\n [dataSource]=\"dataSource\"\n [matSortActive]=\"defaultSortBy\"\n [matSortDirection]=\"defaultSortDirection\"\n matSortDisableClear\n [trackBy]=\"trackByFn\"\n >\n <ng-container matColumnDef=\"select\" [sticky]=\"sticky\">\n <th mat-header-cell *matHeaderCellDef [class.cdk-visually-hidden]=\"!inlineEdition\">\n <mat-checkbox\n (change)=\"$event ? masterToggle() : null\"\n [checked]=\"selection.hasValue() && isAllSelected()\"\n [indeterminate]=\"selection.hasValue() && !isAllSelected()\"\n ></mat-checkbox>\n </th>\n <td mat-cell *matCellDef=\"let row\" [class.cdk-visually-hidden]=\"!inlineEdition\">\n <mat-checkbox (click)=\"toggleSelectRow($event, row)\" [checked]=\"selection.isSelected(row)\"></mat-checkbox>\n </td>\n </ng-container>\n\n <!-- Id Column -->\n <ng-container matColumnDef=\"id\" [sticky]=\"sticky\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header>\n <ion-label>#</ion-label>\n </th>\n <td mat-cell *matCellDef=\"let row\">\n <ion-label>{{ row.currentData.id }}</ion-label>\n </td>\n </ng-container>\n\n <!-- avatar Column -->\n <ng-container matColumnDef=\"avatar\" [sticky]=\"sticky\">\n <th mat-header-cell *matHeaderCellDef></th>\n <td mat-cell *matCellDef=\"let row\">\n <ion-avatar [style.background-color]=\"'white'\">\n <ion-img *ngIf=\"row.currentData.avatar; let avatarUrl; else: generateIcon\" [src]=\"avatarUrl\"></ion-img>\n <ng-template #generateIcon>\n <svg width=\"39\" height=\"39\" [data-jdenticon-value]=\"row.currentData.id\"></svg>\n </ng-template>\n </ion-avatar>\n </td>\n </ng-container>\n\n <!-- lastName -->\n <ng-container matColumnDef=\"lastName\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header>\n <span translate>USER.LAST_NAME</span>\n </th>\n <td mat-cell *matCellDef=\"let row\" (click)=\"focusColumn = 'lastName'\">\n <mat-form-field *ngIf=\"row.editing; else readonlyCell\">\n <input\n matInput\n [formControl]=\"row.validator.controls['lastName']\"\n [placeholder]=\"'USER.LAST_NAME' | translate\"\n [readonly]=\"!row.editing\"\n [appAutofocus]=\"row.editing && focusColumn === 'lastName'\"\n />\n <mat-error *ngIf=\"row.validator.controls['lastName'].hasError('required')\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n <mat-error *ngIf=\"row.validator.controls['lastName'].hasError('minlength')\">\n <span>{{ 'ERROR.FIELD_MIN_LENGTH' | translate: { minLength: 2 } }}</span>\n </mat-error>\n </mat-form-field>\n <ng-template #readonlyCell>\n <ion-label appAutoTitle>\n {{ row.validator | formGetValue: 'lastName' }}\n </ion-label>\n </ng-template>\n </td>\n </ng-container>\n\n <!-- firstname -->\n <ng-container matColumnDef=\"firstName\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header>\n <span translate>USER.FIRST_NAME</span>\n </th>\n <td mat-cell *matCellDef=\"let row\" (click)=\"focusColumn = 'firstName'\">\n <mat-form-field *ngIf=\"row.editing; else readonlyCell\">\n <input\n matInput\n [formControl]=\"row.validator.controls['firstName']\"\n [placeholder]=\"'USER.FIRST_NAME' | translate\"\n [readonly]=\"!row.editing\"\n [appAutofocus]=\"row.editing && focusColumn === 'firstName'\"\n />\n <mat-error *ngIf=\"row.validator.controls['firstName'].hasError('required')\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n <mat-error *ngIf=\"row.validator.controls['firstName'].hasError('minlength')\">\n <span>{{ 'ERROR.FIELD_MIN_LENGTH' | translate: { minLength: 2 } }}</span>\n </mat-error>\n </mat-form-field>\n <ng-template #readonlyCell>\n <ion-label appAutoTitle>\n {{ row.validator | formGetValue: 'firstName' }}\n </ion-label>\n </ng-template>\n </td>\n </ng-container>\n\n <!-- email -->\n <ng-container matColumnDef=\"email\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header>\n <span translate>USER.EMAIL</span>\n </th>\n <td mat-cell *matCellDef=\"let row\" (click)=\"focusColumn = 'email'\">\n <mat-form-field *ngIf=\"row.editing; else readonlyCell\">\n <input\n matInput\n [formControl]=\"row.validator.controls['email']\"\n [placeholder]=\"'USER.EMAIL' | translate\"\n [readonly]=\"!row.editing\"\n [appAutofocus]=\"row.editing && focusColumn === 'email'\"\n />\n <mat-error *ngIf=\"row.validator.controls['email'].hasError('required')\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n <mat-error *ngIf=\"row.validator.controls['email'].hasError('email')\">\n <span translate>ERROR.FIELD_NOT_VALID_EMAIL</span>\n </mat-error>\n </mat-form-field>\n <ng-template #readonlyCell>\n <ion-label appAutoTitle>\n {{ row.validator | formGetValue: 'email' }}\n </ion-label>\n </ng-template>\n </td>\n </ng-container>\n\n <!-- additional fields -->\n <ng-container *ngFor=\"let definition of additionalFields\" [matColumnDef]=\"definition.key\">\n <th mat-header-cell *matHeaderCellDef>\n <span>{{ definition.label | translate }}</span>\n </th>\n <td mat-cell *matCellDef=\"let row\" (click)=\"focusColumn = definition.key\">\n <app-form-field\n floatLabel=\"never\"\n [definition]=\"definition\"\n [formControl]=\"row.validator.controls[definition.key]\"\n [required]=\"definition.extra?.account?.required\"\n [autofocus]=\"row.editing && focusColumn === definition.key\"\n ></app-form-field>\n </td>\n </ng-container>\n\n <!-- profile column -->\n <ng-container matColumnDef=\"profile\">\n <th mat-header-cell *matHeaderCellDef>\n <span translate>USER.PROFILE</span>\n </th>\n <td mat-cell *matCellDef=\"let row\" (click)=\"focusColumn = 'profile'\">\n <mat-form-field>\n <mat-select\n [formControl]=\"row.validator.controls['mainProfile']\"\n [placeholder]=\"'USER.PROFILE' | translate\"\n >\n <mat-option *ngFor=\"let item of profiles\" [value]=\"item\">\n {{ 'USER.PROFILE_ENUM.' + item | uppercase | translate }}\n </mat-option>\n </mat-select>\n <mat-error *ngIf=\"row.validator.controls['mainProfile'].hasError('required')\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n </mat-form-field>\n </td>\n </ng-container>\n\n <!-- Status column -->\n <ng-container matColumnDef=\"status\">\n <th mat-header-cell *matHeaderCellDef>\n <span translate>USER.STATUS</span>\n </th>\n <td mat-cell *matCellDef=\"let row\" (click)=\"focusColumn = 'status'\">\n <mat-form-field>\n <!-- <ion-icon matPrefix *ngIf=\"row.validator.controls['statusId'].value >=0\" [name]=\"statusById[row.validator.controls['statusId'].value]?.icon\"></ion-icon>-->\n\n <mat-select\n [formControl]=\"row.validator.controls['statusId']\"\n [placeholder]=\"'REFERENTIAL.STATUS' | translate\"\n >\n <mat-select-trigger>\n <span *ngIf=\"row.validator.controls['statusId'].value >=0\">\n {{ statusById[row.validator.controls['statusId'].value]?.label | translate }}\n </span>\n </mat-select-trigger>\n <mat-option *ngFor=\"let item of statusList\" [value]=\"item.id\">\n <mat-icon><ion-icon [name]=\"item.icon\"></ion-icon></mat-icon>\n {{ item.label | translate }}\n </mat-option>\n </mat-select>\n <mat-error *ngIf=\"row.validator.controls['statusId'].hasError('required')\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n </mat-form-field>\n </td>\n </ng-container>\n\n <!-- username -->\n <ng-container matColumnDef=\"username\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header>\n <span translate>USER.USERNAME</span>\n </th>\n <td mat-cell *matCellDef=\"let row\" (click)=\"focusColumn = 'username'\">\n <mat-form-field *ngIf=\"row.editing; else readonlyCell\">\n <input\n matInput\n [formControl]=\"row.validator.controls.username\"\n [placeholder]=\"'USER.USERNAME' | translate\"\n [readonly]=\"!row.editing\"\n [appAutofocus]=\"row.editing && focusColumn === 'username'\"\n />\n <mat-error *ngIf=\"row.validator.controls.username.hasError('required')\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n </mat-form-field>\n <ng-template #readonlyCell>\n <ion-label appAutoTitle>\n {{ row.validator | formGetValue: 'username' }}\n </ion-label>\n </ng-template>\n </td>\n </ng-container>\n\n <!-- username extranet -->\n <ng-container matColumnDef=\"usernameExtranet\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header>\n <span translate>USER.USERNAME_EXTRANET</span>\n </th>\n <td mat-cell *matCellDef=\"let row\" (click)=\"focusColumn = 'usernameExtranet'\">\n <mat-form-field *ngIf=\"row.editing; else readonlyCell\">\n <input\n matInput\n [formControl]=\"row.validator.controls.usernameExtranet\"\n [placeholder]=\"'USER.USERNAME_EXTRANET' | translate\"\n [readonly]=\"!row.editing\"\n [appAutofocus]=\"row.editing && focusColumn === 'usernameExtranet'\"\n />\n <mat-error *ngIf=\"row.validator.controls.usernameExtranet.hasError('required')\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n </mat-form-field>\n <ng-template #readonlyCell>\n <ion-label appAutoTitle>\n {{ row.validator | formGetValue: 'usernameExtranet' }}\n </ion-label>\n </ng-template>\n </td>\n </ng-container>\n\n <!-- pubkey -->\n <ng-container matColumnDef=\"pubkey\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header>\n <span translate>USER.PUBKEY</span>\n </th>\n <td\n mat-cell\n *matCellDef=\"let row\"\n [title]=\"row.validator.controls.pubkey.valueChanges | async\"\n (click)=\"focusColumn = 'pubkey'\"\n >\n <mat-form-field *ngIf=\"row.editing; else readonlyCell\">\n <input\n matInput\n [formControl]=\"row.validator.controls['pubkey']\"\n [placeholder]=\"'USER.PUBKEY' | translate\"\n [readonly]=\"!row.editing\"\n autocomplete=\"off\"\n />\n <mat-error *ngIf=\"row.validator.controls.pubkey.hasError('required')\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n <mat-error *ngIf=\"row.validator.controls.pubkey.hasError('pubkey')\">\n <span translate>ERROR.FIELD_NOT_VALID_PUBKEY</span>\n </mat-error>\n </mat-form-field>\n <ng-template #readonlyCell>\n <ion-label appAutoTitle>\n {{ row.validator | formGetValue: 'pubkey' }}\n </ion-label>\n </ng-template>\n </td>\n </ng-container>\n\n <!-- Actions buttons column -->\n <app-actions-column\n [stickyEnd]=\"stickyEnd\"\n (optionsClick)=\"openSelectColumnsModal($event)\"\n (cancelOrDeleteClick)=\"cancelOrDelete($event.event, $event.row)\"\n (confirmEditCreateClick)=\"confirmEditCreate($event.event, $event.row)\"\n (confirmAndAddClick)=\"confirmAndAdd($event.event, $event.row)\"\n (backward)=\"confirmAndBackward($event.event, $event.row)\"\n (forward)=\"confirmAndForward($event.event, $event.row)\"\n [canCancel]=\"false\"\n ></app-actions-column>\n\n <tr mat-header-row *matHeaderRowDef=\"displayedColumns; sticky: true\"></tr>\n <tr\n mat-row\n *matRowDef=\"let row; columns: displayedColumns\"\n [class.mat-row-selected]=\"row.editing\"\n [class.mat-row-error]=\"row.validator.invalid\"\n [class.mat-row-dirty]=\"row.currentData.dirty\"\n [class.mat-row-disabled]=\"!row.editing\"\n (click)=\"clickRow($event, row)\"\n (keydown.escape)=\"escapeEditingRow($event)\"\n [cdkTrapFocus]=\"!row.validator?.valid\"\n ></tr>\n </table>\n\n <ng-container *ngIf=\"loadingSubject | async; else noResult\">\n <ion-item>\n <ion-skeleton-text animated></ion-skeleton-text>\n </ion-item>\n </ng-container>\n\n <ng-template #noResult>\n <ion-item *ngIf=\"totalRowCount === 0\">\n <ion-text color=\"danger\" class=\"text-italic\" translate>COMMON.NO_RESULT</ion-text>\n </ion-item>\n </ng-template>\n </div>\n</ion-content>\n\n<ion-footer>\n <mat-paginator\n [length]=\"totalRowCount\"\n [pageSize]=\"defaultPageSize\"\n [pageSizeOptions]=\"defaultPageSizeOptions\"\n showFirstLastButtons\n ></mat-paginator>\n\n <app-form-buttons-bar\n *ngIf=\"!mobile && canEdit\"\n (onCancel)=\"onRefresh.emit()\"\n (onSave)=\"save()\"\n [disabled]=\"(loadingSubject | async) === true || (dirtySubject | async) !== true\"\n >\n <!-- error -->\n <ion-item *ngIf=\"errorSubject | async; let error\" lines=\"none\">\n <ion-icon color=\"danger\" slot=\"start\" name=\"alert-circle\"></ion-icon>\n <ion-label color=\"danger\" [innerHTML]=\"error | translate\"></ion-label>\n </ion-item>\n </app-form-buttons-bar>\n</ion-footer>\n\n<ion-fab slot=\"fixed\" vertical=\"bottom\" horizontal=\"end\" *ngIf=\"mobile\">\n <ion-fab-button color=\"tertiary\" (click)=\"addRow()\">\n <ion-icon name=\"add\"></ion-icon>\n </ion-fab-button>\n</ion-fab>\n", styles: [".mat-expansion-panel{margin-bottom:5px}.mat-expansion-panel .form-container mat-form-field{width:100%}.mat-expansion-panel mat-action-row ion-label{line-height:36px}.table-container{height:100%}.mat-mdc-table .mat-column-avatar{width:50px}.mat-mdc-table .mat-column-avatar ion-avatar{--border-radius: 5px !important;--border-width: 1px !important;--border-color: rgba(var(--ion-color-secondary-rgb), .5) !important;height:40px;width:40px;max-width:40px;max-height:40px;border:solid var(--border-width) var(--border-color);margin:0 2px}.mat-mdc-table .mat-column-id{min-width:50px;max-width:120px;padding-right:var(--mat-cell-horizontal-padding, 4px)}.mat-mdc-table .mat-column-lastName,.mat-mdc-table .mat-column-firstName{min-width:80px}.mat-mdc-table .mat-column-email,.mat-mdc-table .mat-column-pubkey,.mat-mdc-table .mat-column-department{min-width:180px}.mat-mdc-table .mat-column-profile{min-width:110px}.mat-mdc-table .mat-column-status{min-width:130px}\n"], dependencies: [{ kind: "directive", type: i4$3.SvgJdenticonDirective, selector: "svg[data-jdenticon-hash],svg[data-jdenticon-value]", inputs: ["data-jdenticon-hash", "data-jdenticon-value", "width", "height"] }, { kind: "directive", type: i1$1.TranslateDirective, selector: "[translate],[ngx-translate]", inputs: ["translate", "translateParams"] }, { 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.IonAvatar, selector: "ion-avatar" }, { 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", "forceOverscroll", "fullscreen", "scrollEvents", "scrollX", "scrollY"] }, { kind: "component", type: i2$1.IonFab, selector: "ion-fab", inputs: ["activated", "edge", "horizontal", "vertical"] }, { kind: "component", type: i2$1.IonFabButton, selector: "ion-fab-button", inputs: ["activated", "closeIcon", "color", "disabled", "download", "href", "mode", "rel", "routerAnimation", "routerDirection", "show", "size", "target", "translucent", "type"] }, { 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.IonImg, selector: "ion-img", inputs: ["alt", "src"] }, { kind: "component", type: i2$1.IonItem, selector: "ion-item", inputs: ["button", "color", "counter", "counterFormatter", "detail", "detailIcon", "disabled", "download", "fill", "href", "lines", "mode", "rel", "routerAnimation", "routerDirection", "shape", "target", "type"] }, { kind: "component", type: i2$1.IonLabel, selector: "ion-label", inputs: ["color", "mode", "position"] }, { kind: "component", type: i2$1.IonRow, selector: "ion-row" }, { kind: "component", type: i2$1.IonSkeletonText, selector: "ion-skeleton-text", inputs: ["animated"] }, { kind: "component", type: i2$1.IonText, selector: "ion-text", inputs: ["color", "mode"] }, { kind: "directive", type: i1$2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$2.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$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$2.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1$2.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: i7$1.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: i7$1.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i7$1.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: i7$1.MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: i7$1.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i7$1.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: i7$1.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i7$1.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "component", type: i7$1.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: i7$1.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { kind: "directive", type: i8$1.MatSort, selector: "[matSort]", inputs: ["matSortActive", "matSortStart", "matSortDirection", "matSortDisableClear", "matSortDisabled"], outputs: ["matSortChange"], exportAs: ["matSort"] }, { kind: "component", type: i8$1.MatSortHeader, selector: "[mat-sort-header]", inputs: ["mat-sort-header", "arrowPosition", "start", "disabled", "sortActionDescription", "disableClear"], exportAs: ["matSortHeader"] }, { kind: "component", type: i9$2.MatPaginator, selector: "mat-paginator", inputs: ["color", "pageIndex", "length", "pageSize", "pageSizeOptions", "hidePageSize", "showFirstLastButtons", "selectConfig", "disabled"], outputs: ["page"], exportAs: ["matPaginator"] }, { 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.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", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }, { kind: "component", type: i13$2.MatExpansionPanel, selector: "mat-expansion-panel", inputs: ["hideToggle", "togglePosition"], outputs: ["afterExpand", "afterCollapse"], exportAs: ["matExpansionPanel"] }, { kind: "directive", type: i13$2.MatExpansionPanelActionRow, selector: "mat-action-row" }, { kind: "component", type: i4$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i9$1.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "component", type: i13.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: "directive", type: i13.MatSelectTrigger, selector: "mat-select-trigger" }, { kind: "component", type: i2.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "directive", type: i7$2.MatBadge, selector: "[matBadge]", inputs: ["matBadgeColor", "matBadgeOverlap", "matBadgeDisabled", "matBadgePosition", "matBadge", "matBadgeDescription", "matBadgeSize", "matBadgeHidden"] }, { kind: "directive", type: i1$3.CdkTrapFocus, selector: "[cdkTrapFocus]", inputs: ["cdkTrapFocus", "cdkTrapFocusAutoCapture"], exportAs: ["cdkTrapFocus"] }, { kind: "directive", type: AutofocusDirective, selector: "[autofocus], input[appAutofocus]", inputs: ["appAutofocus", "autofocusDelay"] }, { kind: "directive", type: AutoTitleDirective, selector: "[appAutoTitle]" }, { kind: "component", type: ToolbarComponent, selector: "app-toolbar", inputs: ["progressBarMode", "title", "color", "class", "backHref", "defaultBackHref", "hasValidate", "hasClose", "hasSearch", "canGoBack", "canShowMenu"], outputs: ["onValidate", "onClose", "onValidateAndClose", "onBackClick", "onSearch"] }, { kind: "component", type: AppFormField, selector: "app-form-field", inputs: ["definition", "required", "readonly", "disabled", "formControl", "formControlName", "placeholder", "compact", "floatLabel", "appearance", "tabindex", "autofocus", "clearable", "chipColor", "class", "debug"], outputs: ["keyup.enter"] }, { kind: "component", type: FormButtonsBarComponent, selector: "app-form-buttons-bar", inputs: ["disabled", "disabledCancel", "classList", "saveButtonColor", "backText", "cancelText", "nextText", "showBack", "showCancel", "showNext", "showSave", "showSaveAndClose", "showSaveAndNext"], outputs: ["onCancel", "onSave", "onNext", "onBack", "onSaveAndClose", "onSaveAndNext"] }, { kind: "component", type: ActionsColumnComponent, selector: "app-actions-column", inputs: ["matColumnDef", "style", "stickyEnd", "canCancel", "canConfirm", "canDelete", "canBackward", "canForward", "canConfirmAndAdd", "dirtyIcon", "optionsTitle", "class", "cellTemplate"], outputs: ["optionsClick", "cancelOrDeleteClick", "confirmEditCreateClick", "confirmAndAddClick", "backward", "forward"] }, { kind: "component", type: DebugComponent, selector: "app-debug", inputs: ["title", "enable", "expanded"] }, { kind: "pipe", type: i1$1.TranslatePipe, name: "translate" }, { kind: "pipe", type: i3.AsyncPipe, name: "async" }, { kind: "pipe", type: i3.UpperCasePipe, name: "uppercase" }, { kind: "pipe", type: NumberFormatPipe, name: "numberFormat" }, { kind: "pipe", type: FormGetValuePipe, name: "formGetValue" }], animations: [slideUpDownAnimation], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
37854
37869
|
}
|
|
37855
37870
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.2.4", ngImport: i0, type: UsersPage, decorators: [{
|
|
37856
37871
|
type: Component,
|
|
37857
|
-
args: [{ selector: 'app-users-table', providers: [{ provide: ValidatorService, useExisting: PersonValidatorService }], animations: [slideUpDownAnimation], changeDetection: ChangeDetectionStrategy.OnPush, template: "<app-toolbar\n [title]=\"'USER.LIST.TITLE' | translate\"\n color=\"primary\"\n [canGoBack]=\"false\"\n [hasValidate]=\"(loadingSubject | async) !== true && (dirtySubject | async) === true\"\n (onValidate)=\"save()\"\n>\n <ion-buttons slot=\"end\">\n <!-- Compose message -->\n <button\n mat-icon-button\n *ngIf=\"canSendMessage\"\n [title]=\"'USER.LIST.BTN_SEND_MESSAGE' | translate\"\n (click)=\"openComposeMessageModal($event)\"\n >\n <ion-icon name=\"mail\" slot=\"icon-only\"></ion-icon>\n </button>\n\n <ng-container *ngIf=\"!selection.hasValue(); else hasSelection\">\n <!-- Add -->\n <button mat-icon-button *ngIf=\"canEdit && !mobile\" [title]=\"'COMMON.BTN_ADD' | translate\" (click)=\"addRow()\">\n <mat-icon>add</mat-icon>\n </button>\n\n <!-- Refresh -->\n <button mat-icon-button *ngIf=\"!mobile\" [title]=\"'COMMON.BTN_REFRESH' | translate\" (click)=\"onRefresh.emit()\">\n <mat-icon>refresh</mat-icon>\n </button>\n\n <!-- reset filter -->\n <button mat-icon-button (click)=\"resetFilter()\" *ngIf=\"filterCriteriaCount\">\n <mat-icon color=\"accent\">filter_list_alt</mat-icon>\n <mat-icon class=\"icon-secondary\" style=\"left: 16px; top: 5px; font-weight: bold\">close</mat-icon>\n </button>\n\n <!-- show filter -->\n <button mat-icon-button (click)=\"filterExpansionPanel.toggle()\">\n <mat-icon\n *ngIf=\"filterCriteriaCount; else emptyFilter\"\n [matBadge]=\"filterCriteriaCount\"\n matBadgeColor=\"accent\"\n matBadgeSize=\"small\"\n matBadgePosition=\"above after\"\n aria-hidden=\"false\"\n >\n filter_list_alt\n </mat-icon>\n <ng-template #emptyFilter>\n <mat-icon>filter_list_alt</mat-icon>\n </ng-template>\n </button>\n </ng-container>\n\n <ng-template #hasSelection>\n <!-- delete -->\n <button\n mat-icon-button\n class=\"hidden-xs hidden-sm\"\n [title]=\"'COMMON.BTN_DELETE' | translate\"\n (click)=\"deleteSelection($event)\"\n >\n <mat-icon>delete</mat-icon>\n </button>\n </ng-template>\n </ion-buttons>\n</app-toolbar>\n\n<ion-content class=\"ion-no-padding\">\n <!-- error -->\n <ion-item\n *ngIf=\"errorSubject | async; let error\"\n lines=\"none\"\n class=\"hidden-sm hidden-xs hidden-mobile\"\n @slideUpDownAnimation\n >\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 <!-- debug -->\n <app-debug *ngIf=\"debug\">\n <ion-grid class=\"ion-no-padding\">\n <ion-row>\n <ion-col>\n focusColumn: {{ focusColumn }}\n <br />\n loadingSubject: {{ loading }}\n <br />\n </ion-col>\n </ion-row>\n </ion-grid>\n </app-debug>\n\n <!-- search -->\n <mat-expansion-panel #filterExpansionPanel class=\"ion-no-padding filter-panel filter-panel-floating\">\n <form class=\"form-container ion-padding\" [formGroup]=\"filterForm\" (ngSubmit)=\"onRefresh.emit()\">\n <ion-grid>\n <ion-row>\n <ion-col>\n <!-- search -->\n <mat-form-field>\n <mat-label>{{ 'USER.LIST.FILTER.SEARCH' | translate }}</mat-label>\n <input matInput formControlName=\"searchText\" />\n <button\n mat-icon-button\n matSuffix\n tabindex=\"-1\"\n type=\"button\"\n (click)=\"clearControlValue($event, filterForm.controls.searchText)\"\n [hidden]=\"filterForm.controls.searchText.disabled || !filterForm.controls.searchText.value\"\n >\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n </ion-col>\n\n <ion-col>\n <!-- status -->\n <mat-form-field>\n <mat-label>{{ 'USER.STATUS' | translate }}</mat-label>\n <mat-select formControlName=\"statusId\">\n <mat-option [value]=\"null\">\n <i><span translate>COMMON.EMPTY_OPTION</span></i>\n </mat-option>\n <mat-option *ngFor=\"let item of statusList\" [value]=\"item.id\">\n <ion-icon [name]=\"item.icon\"></ion-icon>\n {{ item.label | translate }}\n </mat-option>\n </mat-select>\n\n <button\n mat-icon-button\n matSuffix\n tabindex=\"-1\"\n type=\"button\"\n (click)=\"clearControlValue($event, filterForm.controls.statusId)\"\n [hidden]=\"filterForm.controls.statusId.disabled || !filterForm.controls.statusId.value\"\n >\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n </ion-col>\n </ion-row>\n </ion-grid>\n </form>\n\n <mat-action-row>\n <!-- Counter -->\n <ion-label\n [hidden]=\"(loadingSubject | async) === true || filterForm.dirty\"\n [color]=\"empty && 'danger'\"\n class=\"ion-padding\"\n >\n {{\n (totalRowCount ? 'COMMON.RESULT_COUNT' : 'COMMON.NO_RESULT')\n | translate\n : {\n count: (totalRowCount | numberFormat)\n }\n }}\n </ion-label>\n\n <div class=\"toolbar-spacer\"></div>\n\n <!-- Close panel -->\n <ion-button\n mat-button\n fill=\"clear\"\n color=\"dark\"\n (click)=\"filterExpansionPanel.close()\"\n [disabled]=\"loadingSubject | async\"\n >\n <ion-text translate>COMMON.BTN_CLOSE</ion-text>\n </ion-button>\n\n <!-- Search button -->\n <ion-button\n mat-button\n [color]=\"filterForm.dirty ? 'tertiary' : 'dark'\"\n [fill]=\"filterForm.dirty ? 'solid' : 'clear'\"\n (click)=\"applyFilterAndClosePanel($event)\"\n [disabled]=\"loadingSubject | async\"\n >\n <ion-text translate>COMMON.BTN_APPLY</ion-text>\n </ion-button>\n </mat-action-row>\n </mat-expansion-panel>\n\n <!-- error -->\n <ion-item *ngIf=\"mobile && (errorSubject | async); let 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 <div class=\"table-container\">\n <table\n #table\n mat-table\n matSort\n [dataSource]=\"dataSource\"\n [matSortActive]=\"defaultSortBy\"\n [matSortDirection]=\"defaultSortDirection\"\n matSortDisableClear\n [trackBy]=\"trackByFn\"\n >\n <ng-container matColumnDef=\"select\" [sticky]=\"sticky\">\n <th mat-header-cell *matHeaderCellDef [class.cdk-visually-hidden]=\"!inlineEdition\">\n <mat-checkbox\n (change)=\"$event ? masterToggle() : null\"\n [checked]=\"selection.hasValue() && isAllSelected()\"\n [indeterminate]=\"selection.hasValue() && !isAllSelected()\"\n ></mat-checkbox>\n </th>\n <td mat-cell *matCellDef=\"let row\" [class.cdk-visually-hidden]=\"!inlineEdition\">\n <mat-checkbox (click)=\"toggleSelectRow($event, row)\" [checked]=\"selection.isSelected(row)\"></mat-checkbox>\n </td>\n </ng-container>\n\n <!-- Id Column -->\n <ng-container matColumnDef=\"id\" [sticky]=\"sticky\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header>\n <ion-label>#</ion-label>\n </th>\n <td mat-cell *matCellDef=\"let row\">{{ row.currentData.id }}</td>\n </ng-container>\n\n <!-- avatar Column -->\n <ng-container matColumnDef=\"avatar\" [sticky]=\"sticky\">\n <th mat-header-cell *matHeaderCellDef></th>\n <td mat-cell *matCellDef=\"let row\">\n <ion-avatar [style.background-color]=\"'white'\">\n <ion-img *ngIf=\"row.currentData.avatar; let avatarUrl; else: generateIcon\" [src]=\"avatarUrl\"></ion-img>\n <ng-template #generateIcon>\n <svg width=\"39\" height=\"39\" [data-jdenticon-value]=\"row.currentData.id\"></svg>\n </ng-template>\n </ion-avatar>\n </td>\n </ng-container>\n\n <!-- lastName -->\n <ng-container matColumnDef=\"lastName\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header>\n <span translate>USER.LAST_NAME</span>\n </th>\n <td mat-cell *matCellDef=\"let row\" (click)=\"focusColumn = 'lastName'\">\n <mat-form-field *ngIf=\"row.editing; else readonlyCell\">\n <input\n matInput\n [formControl]=\"row.validator.controls['lastName']\"\n [placeholder]=\"'USER.LAST_NAME' | translate\"\n [readonly]=\"!row.editing\"\n [appAutofocus]=\"row.editing && focusColumn === 'lastName'\"\n />\n <mat-error *ngIf=\"row.validator.controls['lastName'].hasError('required')\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n <mat-error *ngIf=\"row.validator.controls['lastName'].hasError('minlength')\">\n <span>{{ 'ERROR.FIELD_MIN_LENGTH' | translate: { minLength: 2 } }}</span>\n </mat-error>\n </mat-form-field>\n <ng-template #readonlyCell>\n <ion-label appAutoTitle>\n {{ row.validator | formGetValue: 'lastName' }}\n </ion-label>\n </ng-template>\n </td>\n </ng-container>\n\n <!-- firstname -->\n <ng-container matColumnDef=\"firstName\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header>\n <span translate>USER.FIRST_NAME</span>\n </th>\n <td mat-cell *matCellDef=\"let row\" (click)=\"focusColumn = 'firstName'\">\n <mat-form-field *ngIf=\"row.editing; else readonlyCell\">\n <input\n matInput\n [formControl]=\"row.validator.controls['firstName']\"\n [placeholder]=\"'USER.FIRST_NAME' | translate\"\n [readonly]=\"!row.editing\"\n [appAutofocus]=\"row.editing && focusColumn === 'firstName'\"\n />\n <mat-error *ngIf=\"row.validator.controls['firstName'].hasError('required')\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n <mat-error *ngIf=\"row.validator.controls['firstName'].hasError('minlength')\">\n <span>{{ 'ERROR.FIELD_MIN_LENGTH' | translate: { minLength: 2 } }}</span>\n </mat-error>\n </mat-form-field>\n <ng-template #readonlyCell>\n <ion-label appAutoTitle>\n {{ row.validator | formGetValue: 'firstName' }}\n </ion-label>\n </ng-template>\n </td>\n </ng-container>\n\n <!-- email -->\n <ng-container matColumnDef=\"email\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header>\n <span translate>USER.EMAIL</span>\n </th>\n <td mat-cell *matCellDef=\"let row\" (click)=\"focusColumn = 'email'\">\n <mat-form-field *ngIf=\"row.editing; else readonlyCell\">\n <input\n matInput\n [formControl]=\"row.validator.controls['email']\"\n [placeholder]=\"'USER.EMAIL' | translate\"\n [readonly]=\"!row.editing\"\n [appAutofocus]=\"row.editing && focusColumn === 'email'\"\n />\n <mat-error *ngIf=\"row.validator.controls['email'].hasError('required')\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n <mat-error *ngIf=\"row.validator.controls['email'].hasError('email')\">\n <span translate>ERROR.FIELD_NOT_VALID_EMAIL</span>\n </mat-error>\n </mat-form-field>\n <ng-template #readonlyCell>\n <ion-label appAutoTitle>\n {{ row.validator | formGetValue: 'email' }}\n </ion-label>\n </ng-template>\n </td>\n </ng-container>\n\n <!-- additional fields -->\n <ng-container *ngFor=\"let definition of additionalFields\" [matColumnDef]=\"definition.key\">\n <th mat-header-cell *matHeaderCellDef>\n <span>{{ definition.label | translate }}</span>\n </th>\n <td mat-cell *matCellDef=\"let row\" (click)=\"focusColumn = definition.key\">\n <app-form-field\n floatLabel=\"never\"\n [definition]=\"definition\"\n [formControl]=\"row.validator.controls[definition.key]\"\n [required]=\"definition.extra?.account?.required\"\n [autofocus]=\"row.editing && focusColumn === definition.key\"\n ></app-form-field>\n </td>\n </ng-container>\n\n <!-- profile column -->\n <ng-container matColumnDef=\"profile\">\n <th mat-header-cell *matHeaderCellDef>\n <span translate>USER.PROFILE</span>\n </th>\n <td mat-cell *matCellDef=\"let row\" (click)=\"focusColumn = 'profile'\">\n <mat-form-field>\n <mat-select\n [formControl]=\"row.validator.controls['mainProfile']\"\n [placeholder]=\"'USER.PROFILE' | translate\"\n >\n <mat-option *ngFor=\"let item of profiles\" [value]=\"item\">\n {{ 'USER.PROFILE_ENUM.' + item | uppercase | translate }}\n </mat-option>\n </mat-select>\n <mat-error *ngIf=\"row.validator.controls['mainProfile'].hasError('required')\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n </mat-form-field>\n </td>\n </ng-container>\n\n <!-- Status column -->\n <ng-container matColumnDef=\"status\">\n <th mat-header-cell *matHeaderCellDef>\n <span translate>USER.STATUS</span>\n </th>\n <td mat-cell *matCellDef=\"let row\" (click)=\"focusColumn = 'status'\">\n <mat-form-field>\n <!-- <ion-icon matPrefix *ngIf=\"row.validator.controls['statusId'].value >=0\" [name]=\"statusById[row.validator.controls['statusId'].value]?.icon\"></ion-icon>-->\n\n <mat-select\n [formControl]=\"row.validator.controls['statusId']\"\n [placeholder]=\"'REFERENTIAL.STATUS' | translate\"\n >\n <mat-select-trigger>\n <span *ngIf=\"row.validator.controls['statusId'].value >=0\">\n {{ statusById[row.validator.controls['statusId'].value]?.label | translate }}\n </span>\n </mat-select-trigger>\n <mat-option *ngFor=\"let item of statusList\" [value]=\"item.id\">\n <mat-icon><ion-icon [name]=\"item.icon\"></ion-icon></mat-icon>\n {{ item.label | translate }}\n </mat-option>\n </mat-select>\n <mat-error *ngIf=\"row.validator.controls['statusId'].hasError('required')\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n </mat-form-field>\n </td>\n </ng-container>\n\n <!-- username -->\n <ng-container matColumnDef=\"username\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header>\n <span translate>USER.USERNAME</span>\n </th>\n <td mat-cell *matCellDef=\"let row\" (click)=\"focusColumn = 'username'\">\n <mat-form-field *ngIf=\"row.editing; else readonlyCell\">\n <input\n matInput\n [formControl]=\"row.validator.controls.username\"\n [placeholder]=\"'USER.USERNAME' | translate\"\n [readonly]=\"!row.editing\"\n [appAutofocus]=\"row.editing && focusColumn === 'username'\"\n />\n <mat-error *ngIf=\"row.validator.controls.username.hasError('required')\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n </mat-form-field>\n <ng-template #readonlyCell>\n <ion-label appAutoTitle>\n {{ row.validator | formGetValue: 'username' }}\n </ion-label>\n </ng-template>\n </td>\n </ng-container>\n\n <!-- username extranet -->\n <ng-container matColumnDef=\"usernameExtranet\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header>\n <span translate>USER.USERNAME_EXTRANET</span>\n </th>\n <td mat-cell *matCellDef=\"let row\" (click)=\"focusColumn = 'usernameExtranet'\">\n <mat-form-field *ngIf=\"row.editing; else readonlyCell\">\n <input\n matInput\n [formControl]=\"row.validator.controls.usernameExtranet\"\n [placeholder]=\"'USER.USERNAME_EXTRANET' | translate\"\n [readonly]=\"!row.editing\"\n [appAutofocus]=\"row.editing && focusColumn === 'usernameExtranet'\"\n />\n <mat-error *ngIf=\"row.validator.controls.usernameExtranet.hasError('required')\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n </mat-form-field>\n <ng-template #readonlyCell>\n <ion-label appAutoTitle>\n {{ row.validator | formGetValue: 'usernameExtranet' }}\n </ion-label>\n </ng-template>\n </td>\n </ng-container>\n\n <!-- pubkey -->\n <ng-container matColumnDef=\"pubkey\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header>\n <span translate>USER.PUBKEY</span>\n </th>\n <td\n mat-cell\n *matCellDef=\"let row\"\n [title]=\"row.validator.controls.pubkey.valueChanges | async\"\n (click)=\"focusColumn = 'pubkey'\"\n >\n <mat-form-field *ngIf=\"row.editing; else readonlyCell\">\n <input\n matInput\n [formControl]=\"row.validator.controls['pubkey']\"\n [placeholder]=\"'USER.PUBKEY' | translate\"\n [readonly]=\"!row.editing\"\n autocomplete=\"off\"\n />\n <mat-error *ngIf=\"row.validator.controls.pubkey.hasError('required')\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n <mat-error *ngIf=\"row.validator.controls.pubkey.hasError('pubkey')\">\n <span translate>ERROR.FIELD_NOT_VALID_PUBKEY</span>\n </mat-error>\n </mat-form-field>\n <ng-template #readonlyCell>\n <ion-label appAutoTitle>\n {{ row.validator | formGetValue: 'pubkey' }}\n </ion-label>\n </ng-template>\n </td>\n </ng-container>\n\n <!-- Actions buttons column -->\n <app-actions-column\n [stickyEnd]=\"stickyEnd\"\n (optionsClick)=\"openSelectColumnsModal($event)\"\n (cancelOrDeleteClick)=\"cancelOrDelete($event.event, $event.row)\"\n (confirmEditCreateClick)=\"confirmEditCreate($event.event, $event.row)\"\n (confirmAndAddClick)=\"confirmAndAdd($event.event, $event.row)\"\n (backward)=\"confirmAndBackward($event.event, $event.row)\"\n (forward)=\"confirmAndForward($event.event, $event.row)\"\n [canCancel]=\"false\"\n ></app-actions-column>\n\n <tr mat-header-row *matHeaderRowDef=\"displayedColumns; sticky: true\"></tr>\n <tr\n mat-row\n *matRowDef=\"let row; columns: displayedColumns\"\n [class.mat-row-selected]=\"row.editing\"\n [class.mat-row-error]=\"row.validator.invalid\"\n [class.mat-row-dirty]=\"row.currentData.dirty\"\n [class.mat-row-disabled]=\"!row.editing\"\n (click)=\"clickRow($event, row)\"\n (keydown.escape)=\"escapeEditingRow($event)\"\n [cdkTrapFocus]=\"!row.validator?.valid\"\n ></tr>\n </table>\n\n <ng-container *ngIf=\"loadingSubject | async; else noResult\">\n <ion-item>\n <ion-skeleton-text animated></ion-skeleton-text>\n </ion-item>\n </ng-container>\n\n <ng-template #noResult>\n <ion-item *ngIf=\"totalRowCount === 0\">\n <ion-text color=\"danger\" class=\"text-italic\" translate>COMMON.NO_RESULT</ion-text>\n </ion-item>\n </ng-template>\n </div>\n</ion-content>\n\n<ion-footer>\n <mat-paginator\n [length]=\"totalRowCount\"\n [pageSize]=\"defaultPageSize\"\n [pageSizeOptions]=\"defaultPageSizeOptions\"\n showFirstLastButtons\n ></mat-paginator>\n\n <app-form-buttons-bar\n *ngIf=\"!mobile && canEdit\"\n (onCancel)=\"onRefresh.emit()\"\n (onSave)=\"save()\"\n [disabled]=\"(loadingSubject | async) === true || (dirtySubject | async) !== true\"\n >\n <!-- error -->\n <ion-item *ngIf=\"errorSubject | async; let error\" lines=\"none\">\n <ion-icon color=\"danger\" slot=\"start\" name=\"alert-circle\"></ion-icon>\n <ion-label color=\"danger\" [innerHTML]=\"error | translate\"></ion-label>\n </ion-item>\n </app-form-buttons-bar>\n</ion-footer>\n\n<ion-fab slot=\"fixed\" vertical=\"bottom\" horizontal=\"end\" *ngIf=\"mobile\">\n <ion-fab-button color=\"tertiary\" (click)=\"addRow()\">\n <ion-icon name=\"add\"></ion-icon>\n </ion-fab-button>\n</ion-fab>\n", styles: [".mat-expansion-panel{margin-bottom:5px}.mat-expansion-panel .form-container mat-form-field{width:100%}.mat-expansion-panel mat-action-row ion-label{line-height:36px}.table-container{height:100%}.mat-mdc-table .mat-column-avatar{width:50px}.mat-mdc-table .mat-column-avatar ion-avatar{--border-radius: 5px !important;--border-width: 1px !important;--border-color: rgba(var(--ion-color-secondary-rgb), .5) !important;height:40px;width:40px;max-width:40px;max-height:40px;border:solid var(--border-width) var(--border-color);margin:0 2px}.mat-mdc-table .mat-column-id{width:30px;align-content:end}.mat-mdc-table .mat-column-lastName,.mat-mdc-table .mat-column-firstName{min-width:80px}.mat-mdc-table .mat-column-email,.mat-mdc-table .mat-column-pubkey,.mat-mdc-table .mat-column-department{min-width:180px}.mat-mdc-table .mat-column-profile{min-width:110px}.mat-mdc-table .mat-column-status{min-width:130px}\n"] }]
|
|
37872
|
+
args: [{ selector: 'app-users-table', providers: [{ provide: ValidatorService, useExisting: PersonValidatorService }], animations: [slideUpDownAnimation], changeDetection: ChangeDetectionStrategy.OnPush, template: "<app-toolbar\n [title]=\"'USER.LIST.TITLE' | translate\"\n color=\"primary\"\n [canGoBack]=\"false\"\n [hasValidate]=\"(loadingSubject | async) !== true && (dirtySubject | async) === true\"\n (onValidate)=\"save()\"\n>\n <ion-buttons slot=\"end\">\n <!-- Compose message -->\n <button\n mat-icon-button\n *ngIf=\"canSendMessage\"\n [title]=\"'USER.LIST.BTN_SEND_MESSAGE' | translate\"\n (click)=\"openComposeMessageModal($event)\"\n >\n <ion-icon name=\"mail\" slot=\"icon-only\"></ion-icon>\n </button>\n\n <ng-container *ngIf=\"!selection.hasValue(); else hasSelection\">\n <!-- Add -->\n <button mat-icon-button *ngIf=\"canEdit && !mobile\" [title]=\"'COMMON.BTN_ADD' | translate\" (click)=\"addRow()\">\n <mat-icon>add</mat-icon>\n </button>\n\n <!-- Refresh -->\n <button mat-icon-button *ngIf=\"!mobile\" [title]=\"'COMMON.BTN_REFRESH' | translate\" (click)=\"onRefresh.emit()\">\n <mat-icon>refresh</mat-icon>\n </button>\n\n <!-- reset filter -->\n <button mat-icon-button (click)=\"resetFilter()\" *ngIf=\"filterCriteriaCount\">\n <mat-icon color=\"accent\">filter_list_alt</mat-icon>\n <mat-icon class=\"icon-secondary\" style=\"left: 16px; top: 5px; font-weight: bold\">close</mat-icon>\n </button>\n\n <!-- show filter -->\n <button mat-icon-button (click)=\"filterExpansionPanel.toggle()\">\n <mat-icon\n *ngIf=\"filterCriteriaCount; else emptyFilter\"\n [matBadge]=\"filterCriteriaCount\"\n matBadgeColor=\"accent\"\n matBadgeSize=\"small\"\n matBadgePosition=\"above after\"\n aria-hidden=\"false\"\n >\n filter_list_alt\n </mat-icon>\n <ng-template #emptyFilter>\n <mat-icon>filter_list_alt</mat-icon>\n </ng-template>\n </button>\n </ng-container>\n\n <ng-template #hasSelection>\n <!-- delete -->\n <button\n mat-icon-button\n class=\"hidden-xs hidden-sm\"\n [title]=\"'COMMON.BTN_DELETE' | translate\"\n (click)=\"deleteSelection($event)\"\n >\n <mat-icon>delete</mat-icon>\n </button>\n </ng-template>\n </ion-buttons>\n</app-toolbar>\n\n<ion-content class=\"ion-no-padding\">\n <!-- error -->\n <ion-item\n *ngIf=\"errorSubject | async; let error\"\n lines=\"none\"\n class=\"hidden-sm hidden-xs hidden-mobile\"\n @slideUpDownAnimation\n >\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 <!-- debug -->\n <app-debug *ngIf=\"debug\">\n <ion-grid class=\"ion-no-padding\">\n <ion-row>\n <ion-col>\n focusColumn: {{ focusColumn }}\n <br />\n loadingSubject: {{ loading }}\n <br />\n </ion-col>\n </ion-row>\n </ion-grid>\n </app-debug>\n\n <!-- search -->\n <mat-expansion-panel #filterExpansionPanel class=\"ion-no-padding filter-panel filter-panel-floating\">\n <form class=\"form-container ion-padding\" [formGroup]=\"filterForm\" (ngSubmit)=\"onRefresh.emit()\">\n <ion-grid>\n <ion-row>\n <ion-col>\n <!-- search -->\n <mat-form-field>\n <mat-label>{{ 'USER.LIST.FILTER.SEARCH' | translate }}</mat-label>\n <input matInput formControlName=\"searchText\" />\n <button\n mat-icon-button\n matSuffix\n tabindex=\"-1\"\n type=\"button\"\n (click)=\"clearControlValue($event, filterForm.controls.searchText)\"\n [hidden]=\"filterForm.controls.searchText.disabled || !filterForm.controls.searchText.value\"\n >\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n </ion-col>\n\n <ion-col>\n <!-- status -->\n <mat-form-field>\n <mat-label>{{ 'USER.STATUS' | translate }}</mat-label>\n <mat-select formControlName=\"statusId\">\n <mat-option [value]=\"null\">\n <i><span translate>COMMON.EMPTY_OPTION</span></i>\n </mat-option>\n <mat-option *ngFor=\"let item of statusList\" [value]=\"item.id\">\n <ion-icon [name]=\"item.icon\"></ion-icon>\n {{ item.label | translate }}\n </mat-option>\n </mat-select>\n\n <button\n mat-icon-button\n matSuffix\n tabindex=\"-1\"\n type=\"button\"\n (click)=\"clearControlValue($event, filterForm.controls.statusId)\"\n [hidden]=\"filterForm.controls.statusId.disabled || !filterForm.controls.statusId.value\"\n >\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n </ion-col>\n </ion-row>\n </ion-grid>\n </form>\n\n <mat-action-row>\n <!-- Counter -->\n <ion-label\n [hidden]=\"(loadingSubject | async) === true || filterForm.dirty\"\n [color]=\"empty && 'danger'\"\n class=\"ion-padding\"\n >\n {{\n (totalRowCount ? 'COMMON.RESULT_COUNT' : 'COMMON.NO_RESULT')\n | translate\n : {\n count: (totalRowCount | numberFormat)\n }\n }}\n </ion-label>\n\n <div class=\"toolbar-spacer\"></div>\n\n <!-- Close panel -->\n <ion-button\n mat-button\n fill=\"clear\"\n color=\"dark\"\n (click)=\"filterExpansionPanel.close()\"\n [disabled]=\"loadingSubject | async\"\n >\n <ion-text translate>COMMON.BTN_CLOSE</ion-text>\n </ion-button>\n\n <!-- Search button -->\n <ion-button\n mat-button\n [color]=\"filterForm.dirty ? 'tertiary' : 'dark'\"\n [fill]=\"filterForm.dirty ? 'solid' : 'clear'\"\n (click)=\"applyFilterAndClosePanel($event)\"\n [disabled]=\"loadingSubject | async\"\n >\n <ion-text translate>COMMON.BTN_APPLY</ion-text>\n </ion-button>\n </mat-action-row>\n </mat-expansion-panel>\n\n <!-- error -->\n <ion-item *ngIf=\"mobile && (errorSubject | async); let 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 <div class=\"table-container\">\n <table\n #table\n mat-table\n matSort\n [dataSource]=\"dataSource\"\n [matSortActive]=\"defaultSortBy\"\n [matSortDirection]=\"defaultSortDirection\"\n matSortDisableClear\n [trackBy]=\"trackByFn\"\n >\n <ng-container matColumnDef=\"select\" [sticky]=\"sticky\">\n <th mat-header-cell *matHeaderCellDef [class.cdk-visually-hidden]=\"!inlineEdition\">\n <mat-checkbox\n (change)=\"$event ? masterToggle() : null\"\n [checked]=\"selection.hasValue() && isAllSelected()\"\n [indeterminate]=\"selection.hasValue() && !isAllSelected()\"\n ></mat-checkbox>\n </th>\n <td mat-cell *matCellDef=\"let row\" [class.cdk-visually-hidden]=\"!inlineEdition\">\n <mat-checkbox (click)=\"toggleSelectRow($event, row)\" [checked]=\"selection.isSelected(row)\"></mat-checkbox>\n </td>\n </ng-container>\n\n <!-- Id Column -->\n <ng-container matColumnDef=\"id\" [sticky]=\"sticky\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header>\n <ion-label>#</ion-label>\n </th>\n <td mat-cell *matCellDef=\"let row\">\n <ion-label>{{ row.currentData.id }}</ion-label>\n </td>\n </ng-container>\n\n <!-- avatar Column -->\n <ng-container matColumnDef=\"avatar\" [sticky]=\"sticky\">\n <th mat-header-cell *matHeaderCellDef></th>\n <td mat-cell *matCellDef=\"let row\">\n <ion-avatar [style.background-color]=\"'white'\">\n <ion-img *ngIf=\"row.currentData.avatar; let avatarUrl; else: generateIcon\" [src]=\"avatarUrl\"></ion-img>\n <ng-template #generateIcon>\n <svg width=\"39\" height=\"39\" [data-jdenticon-value]=\"row.currentData.id\"></svg>\n </ng-template>\n </ion-avatar>\n </td>\n </ng-container>\n\n <!-- lastName -->\n <ng-container matColumnDef=\"lastName\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header>\n <span translate>USER.LAST_NAME</span>\n </th>\n <td mat-cell *matCellDef=\"let row\" (click)=\"focusColumn = 'lastName'\">\n <mat-form-field *ngIf=\"row.editing; else readonlyCell\">\n <input\n matInput\n [formControl]=\"row.validator.controls['lastName']\"\n [placeholder]=\"'USER.LAST_NAME' | translate\"\n [readonly]=\"!row.editing\"\n [appAutofocus]=\"row.editing && focusColumn === 'lastName'\"\n />\n <mat-error *ngIf=\"row.validator.controls['lastName'].hasError('required')\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n <mat-error *ngIf=\"row.validator.controls['lastName'].hasError('minlength')\">\n <span>{{ 'ERROR.FIELD_MIN_LENGTH' | translate: { minLength: 2 } }}</span>\n </mat-error>\n </mat-form-field>\n <ng-template #readonlyCell>\n <ion-label appAutoTitle>\n {{ row.validator | formGetValue: 'lastName' }}\n </ion-label>\n </ng-template>\n </td>\n </ng-container>\n\n <!-- firstname -->\n <ng-container matColumnDef=\"firstName\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header>\n <span translate>USER.FIRST_NAME</span>\n </th>\n <td mat-cell *matCellDef=\"let row\" (click)=\"focusColumn = 'firstName'\">\n <mat-form-field *ngIf=\"row.editing; else readonlyCell\">\n <input\n matInput\n [formControl]=\"row.validator.controls['firstName']\"\n [placeholder]=\"'USER.FIRST_NAME' | translate\"\n [readonly]=\"!row.editing\"\n [appAutofocus]=\"row.editing && focusColumn === 'firstName'\"\n />\n <mat-error *ngIf=\"row.validator.controls['firstName'].hasError('required')\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n <mat-error *ngIf=\"row.validator.controls['firstName'].hasError('minlength')\">\n <span>{{ 'ERROR.FIELD_MIN_LENGTH' | translate: { minLength: 2 } }}</span>\n </mat-error>\n </mat-form-field>\n <ng-template #readonlyCell>\n <ion-label appAutoTitle>\n {{ row.validator | formGetValue: 'firstName' }}\n </ion-label>\n </ng-template>\n </td>\n </ng-container>\n\n <!-- email -->\n <ng-container matColumnDef=\"email\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header>\n <span translate>USER.EMAIL</span>\n </th>\n <td mat-cell *matCellDef=\"let row\" (click)=\"focusColumn = 'email'\">\n <mat-form-field *ngIf=\"row.editing; else readonlyCell\">\n <input\n matInput\n [formControl]=\"row.validator.controls['email']\"\n [placeholder]=\"'USER.EMAIL' | translate\"\n [readonly]=\"!row.editing\"\n [appAutofocus]=\"row.editing && focusColumn === 'email'\"\n />\n <mat-error *ngIf=\"row.validator.controls['email'].hasError('required')\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n <mat-error *ngIf=\"row.validator.controls['email'].hasError('email')\">\n <span translate>ERROR.FIELD_NOT_VALID_EMAIL</span>\n </mat-error>\n </mat-form-field>\n <ng-template #readonlyCell>\n <ion-label appAutoTitle>\n {{ row.validator | formGetValue: 'email' }}\n </ion-label>\n </ng-template>\n </td>\n </ng-container>\n\n <!-- additional fields -->\n <ng-container *ngFor=\"let definition of additionalFields\" [matColumnDef]=\"definition.key\">\n <th mat-header-cell *matHeaderCellDef>\n <span>{{ definition.label | translate }}</span>\n </th>\n <td mat-cell *matCellDef=\"let row\" (click)=\"focusColumn = definition.key\">\n <app-form-field\n floatLabel=\"never\"\n [definition]=\"definition\"\n [formControl]=\"row.validator.controls[definition.key]\"\n [required]=\"definition.extra?.account?.required\"\n [autofocus]=\"row.editing && focusColumn === definition.key\"\n ></app-form-field>\n </td>\n </ng-container>\n\n <!-- profile column -->\n <ng-container matColumnDef=\"profile\">\n <th mat-header-cell *matHeaderCellDef>\n <span translate>USER.PROFILE</span>\n </th>\n <td mat-cell *matCellDef=\"let row\" (click)=\"focusColumn = 'profile'\">\n <mat-form-field>\n <mat-select\n [formControl]=\"row.validator.controls['mainProfile']\"\n [placeholder]=\"'USER.PROFILE' | translate\"\n >\n <mat-option *ngFor=\"let item of profiles\" [value]=\"item\">\n {{ 'USER.PROFILE_ENUM.' + item | uppercase | translate }}\n </mat-option>\n </mat-select>\n <mat-error *ngIf=\"row.validator.controls['mainProfile'].hasError('required')\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n </mat-form-field>\n </td>\n </ng-container>\n\n <!-- Status column -->\n <ng-container matColumnDef=\"status\">\n <th mat-header-cell *matHeaderCellDef>\n <span translate>USER.STATUS</span>\n </th>\n <td mat-cell *matCellDef=\"let row\" (click)=\"focusColumn = 'status'\">\n <mat-form-field>\n <!-- <ion-icon matPrefix *ngIf=\"row.validator.controls['statusId'].value >=0\" [name]=\"statusById[row.validator.controls['statusId'].value]?.icon\"></ion-icon>-->\n\n <mat-select\n [formControl]=\"row.validator.controls['statusId']\"\n [placeholder]=\"'REFERENTIAL.STATUS' | translate\"\n >\n <mat-select-trigger>\n <span *ngIf=\"row.validator.controls['statusId'].value >=0\">\n {{ statusById[row.validator.controls['statusId'].value]?.label | translate }}\n </span>\n </mat-select-trigger>\n <mat-option *ngFor=\"let item of statusList\" [value]=\"item.id\">\n <mat-icon><ion-icon [name]=\"item.icon\"></ion-icon></mat-icon>\n {{ item.label | translate }}\n </mat-option>\n </mat-select>\n <mat-error *ngIf=\"row.validator.controls['statusId'].hasError('required')\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n </mat-form-field>\n </td>\n </ng-container>\n\n <!-- username -->\n <ng-container matColumnDef=\"username\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header>\n <span translate>USER.USERNAME</span>\n </th>\n <td mat-cell *matCellDef=\"let row\" (click)=\"focusColumn = 'username'\">\n <mat-form-field *ngIf=\"row.editing; else readonlyCell\">\n <input\n matInput\n [formControl]=\"row.validator.controls.username\"\n [placeholder]=\"'USER.USERNAME' | translate\"\n [readonly]=\"!row.editing\"\n [appAutofocus]=\"row.editing && focusColumn === 'username'\"\n />\n <mat-error *ngIf=\"row.validator.controls.username.hasError('required')\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n </mat-form-field>\n <ng-template #readonlyCell>\n <ion-label appAutoTitle>\n {{ row.validator | formGetValue: 'username' }}\n </ion-label>\n </ng-template>\n </td>\n </ng-container>\n\n <!-- username extranet -->\n <ng-container matColumnDef=\"usernameExtranet\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header>\n <span translate>USER.USERNAME_EXTRANET</span>\n </th>\n <td mat-cell *matCellDef=\"let row\" (click)=\"focusColumn = 'usernameExtranet'\">\n <mat-form-field *ngIf=\"row.editing; else readonlyCell\">\n <input\n matInput\n [formControl]=\"row.validator.controls.usernameExtranet\"\n [placeholder]=\"'USER.USERNAME_EXTRANET' | translate\"\n [readonly]=\"!row.editing\"\n [appAutofocus]=\"row.editing && focusColumn === 'usernameExtranet'\"\n />\n <mat-error *ngIf=\"row.validator.controls.usernameExtranet.hasError('required')\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n </mat-form-field>\n <ng-template #readonlyCell>\n <ion-label appAutoTitle>\n {{ row.validator | formGetValue: 'usernameExtranet' }}\n </ion-label>\n </ng-template>\n </td>\n </ng-container>\n\n <!-- pubkey -->\n <ng-container matColumnDef=\"pubkey\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header>\n <span translate>USER.PUBKEY</span>\n </th>\n <td\n mat-cell\n *matCellDef=\"let row\"\n [title]=\"row.validator.controls.pubkey.valueChanges | async\"\n (click)=\"focusColumn = 'pubkey'\"\n >\n <mat-form-field *ngIf=\"row.editing; else readonlyCell\">\n <input\n matInput\n [formControl]=\"row.validator.controls['pubkey']\"\n [placeholder]=\"'USER.PUBKEY' | translate\"\n [readonly]=\"!row.editing\"\n autocomplete=\"off\"\n />\n <mat-error *ngIf=\"row.validator.controls.pubkey.hasError('required')\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n <mat-error *ngIf=\"row.validator.controls.pubkey.hasError('pubkey')\">\n <span translate>ERROR.FIELD_NOT_VALID_PUBKEY</span>\n </mat-error>\n </mat-form-field>\n <ng-template #readonlyCell>\n <ion-label appAutoTitle>\n {{ row.validator | formGetValue: 'pubkey' }}\n </ion-label>\n </ng-template>\n </td>\n </ng-container>\n\n <!-- Actions buttons column -->\n <app-actions-column\n [stickyEnd]=\"stickyEnd\"\n (optionsClick)=\"openSelectColumnsModal($event)\"\n (cancelOrDeleteClick)=\"cancelOrDelete($event.event, $event.row)\"\n (confirmEditCreateClick)=\"confirmEditCreate($event.event, $event.row)\"\n (confirmAndAddClick)=\"confirmAndAdd($event.event, $event.row)\"\n (backward)=\"confirmAndBackward($event.event, $event.row)\"\n (forward)=\"confirmAndForward($event.event, $event.row)\"\n [canCancel]=\"false\"\n ></app-actions-column>\n\n <tr mat-header-row *matHeaderRowDef=\"displayedColumns; sticky: true\"></tr>\n <tr\n mat-row\n *matRowDef=\"let row; columns: displayedColumns\"\n [class.mat-row-selected]=\"row.editing\"\n [class.mat-row-error]=\"row.validator.invalid\"\n [class.mat-row-dirty]=\"row.currentData.dirty\"\n [class.mat-row-disabled]=\"!row.editing\"\n (click)=\"clickRow($event, row)\"\n (keydown.escape)=\"escapeEditingRow($event)\"\n [cdkTrapFocus]=\"!row.validator?.valid\"\n ></tr>\n </table>\n\n <ng-container *ngIf=\"loadingSubject | async; else noResult\">\n <ion-item>\n <ion-skeleton-text animated></ion-skeleton-text>\n </ion-item>\n </ng-container>\n\n <ng-template #noResult>\n <ion-item *ngIf=\"totalRowCount === 0\">\n <ion-text color=\"danger\" class=\"text-italic\" translate>COMMON.NO_RESULT</ion-text>\n </ion-item>\n </ng-template>\n </div>\n</ion-content>\n\n<ion-footer>\n <mat-paginator\n [length]=\"totalRowCount\"\n [pageSize]=\"defaultPageSize\"\n [pageSizeOptions]=\"defaultPageSizeOptions\"\n showFirstLastButtons\n ></mat-paginator>\n\n <app-form-buttons-bar\n *ngIf=\"!mobile && canEdit\"\n (onCancel)=\"onRefresh.emit()\"\n (onSave)=\"save()\"\n [disabled]=\"(loadingSubject | async) === true || (dirtySubject | async) !== true\"\n >\n <!-- error -->\n <ion-item *ngIf=\"errorSubject | async; let error\" lines=\"none\">\n <ion-icon color=\"danger\" slot=\"start\" name=\"alert-circle\"></ion-icon>\n <ion-label color=\"danger\" [innerHTML]=\"error | translate\"></ion-label>\n </ion-item>\n </app-form-buttons-bar>\n</ion-footer>\n\n<ion-fab slot=\"fixed\" vertical=\"bottom\" horizontal=\"end\" *ngIf=\"mobile\">\n <ion-fab-button color=\"tertiary\" (click)=\"addRow()\">\n <ion-icon name=\"add\"></ion-icon>\n </ion-fab-button>\n</ion-fab>\n", styles: [".mat-expansion-panel{margin-bottom:5px}.mat-expansion-panel .form-container mat-form-field{width:100%}.mat-expansion-panel mat-action-row ion-label{line-height:36px}.table-container{height:100%}.mat-mdc-table .mat-column-avatar{width:50px}.mat-mdc-table .mat-column-avatar ion-avatar{--border-radius: 5px !important;--border-width: 1px !important;--border-color: rgba(var(--ion-color-secondary-rgb), .5) !important;height:40px;width:40px;max-width:40px;max-height:40px;border:solid var(--border-width) var(--border-color);margin:0 2px}.mat-mdc-table .mat-column-id{min-width:50px;max-width:120px;padding-right:var(--mat-cell-horizontal-padding, 4px)}.mat-mdc-table .mat-column-lastName,.mat-mdc-table .mat-column-firstName{min-width:80px}.mat-mdc-table .mat-column-email,.mat-mdc-table .mat-column-pubkey,.mat-mdc-table .mat-column-department{min-width:180px}.mat-mdc-table .mat-column-profile{min-width:110px}.mat-mdc-table .mat-column-status{min-width:130px}\n"] }]
|
|
37858
37873
|
}], ctorParameters: () => [{ type: i0.Injector }, { type: i1$2.UntypedFormBuilder }, { type: AccountService }, { type: i2$8.ValidatorService }, { type: ConfigService }, { type: PersonService }, { type: MessageService }, { type: MenuService }, { type: i0.ChangeDetectorRef }, { type: undefined, decorators: [{
|
|
37859
37874
|
type: Inject,
|
|
37860
37875
|
args: [ENVIRONMENT]
|
|
@@ -41479,5 +41494,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.2.4", ngImpor
|
|
|
41479
41494
|
* Generated bundle index. Do not edit.
|
|
41480
41495
|
*/
|
|
41481
41496
|
|
|
41482
|
-
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, AbstractDateFormat, AbstractNamedFilterService, AbstractUserEventService, Account, AccountPage, AccountService, AccountToStringPipe, AccountUtils, ActionsColumnComponent, AdminModule, AdminRoutingModule, AdminUsersModule, Alerts, AndroidOsEnvironment, AppAboutModalModule, AppAccountModule, AppAsyncTable, AppAuthForm, AppAuthModal, AppAuthModule, AppEditor, AppEditorOptions, AppEntityEditor, AppEntityEditorModal, AppEntityEditorModalOptions, AppEntityFormModule, AppForm, AppFormArray, AppFormButtonsBarModule, AppFormField, AppFormModule, AppFormProvider, AppFormUtils, AppGestureConfig, AppGraphQLModule, AppHelpModal, AppHomePageModule, AppIconComponent, AppIconModule, AppImageGalleryComponent, AppInMemoryTable, AppInstallUpgradeCard, AppInstallUpgradeCardModule, AppListForm, AppListFormModule, AppLoadingSpinner, AppMenuModule, AppNullForm, AppPropertiesForm, AppPropertiesFormModule, AppPropertiesTable, AppRegisterModule, AppSelectPeerModule, AppSettingsPageModule, AppTabEditor, AppTabEditorOptions, AppTable, AppTableModule, AppTableUtils, AppTextPopoverModule, AppUpdateOfflineModeCard, AppUpdateOfflineModeCardModule, AppValidatorService, ArrayFilterPipe, ArrayFirstPipe, ArrayIncludesPipe, ArrayJoinPipe, ArrayLengthPipe, ArrayPluckPipe, AsAnyPipe, AsArrayPipe, AsFloatLabelTypePipe, AsObservablePipe, AudioProvider, AudioTestingModule, AudioTestingPage, AuthGuardService, AutoTitleDirective, AutocompleteTestPage, AutofocusDirective, BadgeDirective, Base58, BaseEntityService, BaseGraphqlService, BaseGraphqlServiceOptions, BaseReferential, Beans, BooleanTestPage, CORE_CONFIG_OPTIONS, CORE_TESTING_PAGES, CapitalizePipe, CellValueChangeListener, 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_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, 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, FormButtonsBarComponent, FormButtonsBarToken, 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, IsLoginAccountPipe, IsNilOrBlankPipe, IsNilOrNaNPipe, IsNilPipe, IsNotNilOrBlankPipe, IsNotNilOrNaNPipe, IsNotNilPipe, IsOnDeskPipe, IsOnFieldPipe, 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, 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, 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, NetworkService, NewTokenModal, NgInitDirective, NgVarDirective, NotEmptyArrayPipe, NumberFormatPipe, ObservableTestPage, OddPipe, OtherMenuTestingPage, PEER_URL_REGEXP, 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, SelectPeerModal, 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, accountToString, adaptValueToControl, addValueInArray, arrayDistinct, arraySize, asInputElement, canHaveFocus, capitalizeFirstLetter, chainPromises, changeCaseToUnderscore, clearValueInArray, collectByProperty, copyEntity2Form, createPromiseEvent, createPromiseEventEmitter, departmentToString, departmentsToString, disableControls, emitPromiseEvent, entityToString, equals, equalsOrNil, escapeRegExp, fadeInAnimation, fadeInOutAnimation, fadeInSlowAnimation, filterFalse, filterNotNil, filterNumberInput, filterTrue, findParentWithClass, firstArrayValue, firstFalse, firstFalsePromise, firstNotNil, firstNotNilPromise, firstTrue, firstTruePromise, focusInput, focusNextInput, focusPreviousInput, formatLatitude, formatLongitude, fromDateISOString, fromScrollEndEvent, fromUnixMsTimestamp, fromUnixTimestamp, getCaretPosition, getColorContrast, getColorShade, getColorTint, getConnectionType, getControlFromPath, getFocusableInputElements, getFormErrors, getFormValueFromEntity, getProperty, getPropertyByPath, getPropertyByPathAsString, getRandomImage, hexToRgb, hexToRgbArray, initArrayControlsFromValues, isAndroid, isBlankString, isCapacitor, isControlHasInput, isEmptyArray, isIOS, isInputElement, isInstanceOf, isInt, isMobile, isNil, isNilOrBlank, isNilOrNaN, isNotEmptyArray, isNotNil, isNotNilBoolean, isNotNilOrBlank, isNotNilOrNaN, isNotNilString, isNumber, isNumberRange, isProgressEvent, isResponseEvent, isStartableService, isTouchUi, isWindows, joinProperties, joinPropertiesPath, logFormErrors, markAllAsTouched, markAsUntouched, markControlAsTouched, markFormGroupAsTouched, maskitoPrefixPlugin, matchMedia, matchUpperCase, mergeLoadResult, mixHex, moveInputCaretToSeparator, noTrailingSlash, notNilOrDefault, 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 };
|
|
41497
|
+
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, AbstractDateFormat, AbstractNamedFilterService, AbstractUserEventService, Account, AccountPage, AccountService, AccountToStringPipe, AccountUtils, ActionsColumnComponent, AdminModule, AdminRoutingModule, AdminUsersModule, Alerts, AndroidOsEnvironment, AppAboutModalModule, AppAccountModule, AppAsyncTable, AppAuthForm, AppAuthModal, AppAuthModule, 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, AppSelectPeerModule, AppSettingsPageModule, AppTabEditor, AppTabEditorOptions, AppTable, AppTableModule, AppTableUtils, AppTextPopoverModule, AppUpdateOfflineModeCard, AppUpdateOfflineModeCardModule, AppValidatorService, ArrayFilterPipe, ArrayFirstPipe, ArrayIncludesPipe, ArrayJoinPipe, ArrayLengthPipe, ArrayPluckPipe, AsAnyPipe, AsArrayPipe, AsFloatLabelTypePipe, AsObservablePipe, AudioProvider, AudioTestingModule, AudioTestingPage, AuthGuardService, AutoTitleDirective, AutocompleteTestPage, AutofocusDirective, BadgeDirective, Base58, BaseEntityService, BaseGraphqlService, BaseGraphqlServiceOptions, BaseReferential, Beans, BooleanTestPage, CORE_CONFIG_OPTIONS, CORE_TESTING_PAGES, CapitalizePipe, CellValueChangeListener, 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_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, 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, FormButtonsBarComponent, FormButtonsBarToken, 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, IsLoginAccountPipe, IsNilOrBlankPipe, IsNilOrNaNPipe, IsNilPipe, IsNotNilOrBlankPipe, IsNotNilOrNaNPipe, IsNotNilPipe, IsOnDeskPipe, IsOnFieldPipe, 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, 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, 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, NetworkService, NewTokenModal, NgInitDirective, NgVarDirective, NotEmptyArrayPipe, NumberFormatPipe, ObservableTestPage, OddPipe, OtherMenuTestingPage, PEER_URL_REGEXP, 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, SelectPeerModal, 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, accountToString, adaptValueToControl, addValueInArray, arrayDistinct, arraySize, asInputElement, canHaveFocus, capitalizeFirstLetter, chainPromises, changeCaseToUnderscore, clearValueInArray, collectByProperty, copyEntity2Form, createPromiseEvent, createPromiseEventEmitter, departmentToString, departmentsToString, disableControls, emitPromiseEvent, entityToString, equals, equalsOrNil, escapeRegExp, fadeInAnimation, fadeInOutAnimation, fadeInSlowAnimation, filterFalse, filterNotNil, filterNumberInput, filterTrue, findParentWithClass, firstArrayValue, firstFalse, firstFalsePromise, firstNotNil, firstNotNilPromise, firstTrue, firstTruePromise, focusInput, focusNextInput, focusPreviousInput, formatLatitude, formatLongitude, fromDateISOString, fromScrollEndEvent, fromUnixMsTimestamp, fromUnixTimestamp, getCaretPosition, getColorContrast, getColorShade, getColorTint, getConnectionType, getControlFromPath, getFocusableInputElements, getFormErrors, getFormValueFromEntity, getProperty, getPropertyByPath, getPropertyByPathAsString, getRandomImage, hexToRgb, hexToRgbArray, initArrayControlsFromValues, isAndroid, isBlankString, isCapacitor, isControlHasInput, isEmptyArray, isIOS, isInputElement, isInstanceOf, isInt, isMobile, isNil, isNilOrBlank, isNilOrNaN, isNotEmptyArray, isNotNil, isNotNilBoolean, isNotNilOrBlank, isNotNilOrNaN, isNotNilString, isNumber, isNumberRange, isProgressEvent, isResponseEvent, isStartableService, isTouchUi, isWindows, joinProperties, joinPropertiesPath, logFormErrors, markAllAsTouched, markAsUntouched, markControlAsTouched, markFormGroupAsTouched, maskitoPrefixPlugin, matchMedia, matchUpperCase, mergeLoadResult, mixHex, moveInputCaretToSeparator, noTrailingSlash, notNilOrDefault, 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 };
|
|
41483
41498
|
//# sourceMappingURL=sumaris-net.ngx-components.mjs.map
|