@sumaris-net/ngx-components 2.3.5 → 2.4.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.
@@ -140,7 +140,7 @@ import { isDataSource, SelectionModel } from '@angular/cdk/collections';
140
140
  import { Camera, CameraResultType } from '@capacitor/camera';
141
141
  import { Geolocation } from '@capacitor/geolocation';
142
142
  import * as i3$2 from '@e-is/ngx-material-table';
143
- import { ValidatorService, TableDataSource } from '@e-is/ngx-material-table';
143
+ import { ValidatorService, TableDataSource, AsyncTableDataSource } from '@e-is/ngx-material-table';
144
144
 
145
145
  const ENVIRONMENT = new InjectionToken('ENV');
146
146
  class Environment {
@@ -6424,7 +6424,7 @@ class MatDateTime {
6424
6424
  }
6425
6425
  else {
6426
6426
  // Reset hour
6427
- const day = date.startOf('day');
6427
+ const day = date.clone().startOf('day');
6428
6428
  const dayStr = this.dateAdapter.format(day, this.dayPattern);
6429
6429
  // Format time
6430
6430
  let timeStr;
@@ -25546,6 +25546,18 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImpo
25546
25546
  type: Directive
25547
25547
  }], ctorParameters: function () { return [{ type: GraphqlService }, { type: PlatformService }, { type: undefined }, { type: undefined }, { type: undefined }]; } });
25548
25548
 
25549
+ const SETTINGS_DISPLAY_COLUMNS = 'displayColumns';
25550
+ const SETTINGS_SORTED_COLUMN = 'sortedColumn';
25551
+ const SETTINGS_FILTER = 'filter';
25552
+ const SETTINGS_PAGE_SIZE = 'pageSize';
25553
+ const DEFAULT_PAGE_SIZE = 20;
25554
+ const DEFAULT_PAGE_SIZE_OPTIONS = [20, 50, 100, 200, 500];
25555
+ const RESERVED_START_COLUMNS = ['select', 'id'];
25556
+ const RESERVED_END_COLUMNS = ['actions'];
25557
+ const DEFAULT_REQUIRED_COLUMNS = ['id'];
25558
+ class CellValueChangeListener {
25559
+ }
25560
+
25549
25561
  class AppTableUtils {
25550
25562
  static waitIdle(table) {
25551
25563
  if (!table || !table.dataSource) {
@@ -25960,17 +25972,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImpo
25960
25972
  type: Directive
25961
25973
  }], ctorParameters: function () { return [{ type: undefined }, { type: undefined }, { type: undefined }, { type: undefined }]; } });
25962
25974
 
25963
- const SETTINGS_DISPLAY_COLUMNS = 'displayColumns';
25964
- const SETTINGS_SORTED_COLUMN = 'sortedColumn';
25965
- const SETTINGS_FILTER = 'filter';
25966
- const SETTINGS_PAGE_SIZE = 'pageSize';
25967
- const DEFAULT_PAGE_SIZE = 20;
25968
- const DEFAULT_PAGE_SIZE_OPTIONS = [20, 50, 100, 200, 500];
25969
- const RESERVED_START_COLUMNS = ['select', 'id'];
25970
- const RESERVED_END_COLUMNS = ['actions'];
25971
- const DEFAULT_REQUIRED_COLUMNS = ['id'];
25972
- class CellValueChangeListener {
25973
- }
25974
25975
  // @dynamic
25975
25976
  // eslint-disable-next-line @angular-eslint/directive-class-suffix
25976
25977
  class AppTable {
@@ -28526,9 +28527,10 @@ class AppEntityEditor extends AppTabEditor {
28526
28527
  this._listenChangesSubscription = this.listenChanges(this.data.id, {
28527
28528
  interval: this._listenIntervalInSeconds
28528
28529
  })
28529
- .pipe(filter(isNotNil),
28530
- // If saving, wait end, to avoid to detect self changes
28531
- mergeMap((data) => this.saving ? of(data) : firstFalse(this.savingSubject).pipe(mapTo(data))))
28530
+ .pipe(filter(isNotNil), mergeMap((data) => this.saving
28531
+ // If saving, wait end, to avoid to detect self changes
28532
+ ? firstFalse(this.savingSubject).pipe(mapTo(data), debounceTime(500))
28533
+ : of(data)))
28532
28534
  .subscribe((data) => {
28533
28535
  const isNewer = isMoment(data.updateDate) && data.updateDate.isAfter(this.data.updateDate);
28534
28536
  if (!isNewer)
@@ -29439,6 +29441,2082 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImpo
29439
29441
  type: Input
29440
29442
  }] } });
29441
29443
 
29444
+ // @dynamic
29445
+ // eslint-disable-next-line @angular-eslint/directive-class-suffix
29446
+ class EntitiesAsyncTableDataSource extends AsyncTableDataSource {
29447
+ /**
29448
+ * Creates a new TableDataSource instance, that can be used as datasource of `@angular/cdk` data-table.
29449
+ *
29450
+ * @param dataService A service to load and save data
29451
+ * @param dataType Type of data contained by the Table. If not specified, then `data` with at least one element must be specified.
29452
+ * @param environment
29453
+ * @param validatorService Service that create instances of the FormGroup used to validate row fields.
29454
+ * @param config Additional configuration for table.
29455
+ */
29456
+ constructor(dataType, dataService, validatorService, options) {
29457
+ super([], dataType, validatorService, Object.assign({ keepOriginalDataAfterConfirm: false, readOnly: false, saveOnlyDirtyRows: false }, options));
29458
+ this.dataService = dataService;
29459
+ this._debug = false;
29460
+ this._creating = false;
29461
+ this._saving = false;
29462
+ this._fetchMoreFn = null;
29463
+ this._stopWatchSubject = new Subject();
29464
+ this.loadingSubject = new BehaviorSubject(undefined);
29465
+ this._entityName = removeEnd((new dataType()).__typename || 'UnknownVO', 'VO');
29466
+ this._debug = (options === null || options === void 0 ? void 0 : options.suppressErrors) === false && !environment.production;
29467
+ }
29468
+ get watchAllOptions() {
29469
+ return this.config.watchAllOptions;
29470
+ }
29471
+ set watchAllOptions(value) {
29472
+ this.config.watchAllOptions = value;
29473
+ }
29474
+ get saveAllOptions() {
29475
+ return this.config.saveAllOptions;
29476
+ }
29477
+ set saveAllOptions(value) {
29478
+ this.config.saveAllOptions = value;
29479
+ }
29480
+ get loaded() {
29481
+ return this.loadingSubject.value === false; // Should be false when undefined (initial state)
29482
+ }
29483
+ get loading() {
29484
+ return this.loadingSubject.value !== false; // Should be true when undefined (initial state)
29485
+ }
29486
+ ngOnDestroy() {
29487
+ this.disconnect();
29488
+ }
29489
+ watchAll(offset, size, sortBy, sortDirection, filter) {
29490
+ this._stopWatchSubject.next();
29491
+ this._fetchMoreFn = null;
29492
+ this.markAsLoading();
29493
+ return this.dataService.watchAll(offset, size, sortBy, sortDirection, filter, this.watchAllOptions)
29494
+ .pipe(catchError(err => this.handleError(err, 'ERROR.LOAD_DATA_ERROR')), map((res) => {
29495
+ if (this._saving) {
29496
+ console.info(`[entities-table-datasource] Received ${this._entityName} data (from service), but still saving: skip`);
29497
+ }
29498
+ else if (this.hasSomeEditingRow()) {
29499
+ console.warn(`[entities-table-datasource] Received ${this._entityName} data, while some row still editing: skip; Please check save() implementation in the table!`);
29500
+ }
29501
+ else {
29502
+ this.updateDatasource((res.data || []));
29503
+ this._fetchMoreFn = res.fetchMore;
29504
+ }
29505
+ return res;
29506
+ }),
29507
+ // Stop this pipe next time we call watchAll()
29508
+ takeUntil(this._stopWatchSubject)
29509
+ // ⚠ Notice: Don't put any operator after takeUntil to avoid potential subscription leaks
29510
+ );
29511
+ }
29512
+ updateDatasourceFromRows(rows) {
29513
+ var _a;
29514
+ // Avoid to update dataSourceSubject, when not need
29515
+ if ((_a = this.datasourceSubject.observers) === null || _a === void 0 ? void 0 : _a.length) {
29516
+ if (!this.config.suppressErrors)
29517
+ console.warn('[entities-table-datasource] Update datasource subject. Please prefer using \'rowsSubject\' instead of \'datasourceSubject\'');
29518
+ super.updateDatasourceFromRows(rows);
29519
+ }
29520
+ else {
29521
+ console.debug('[entities-table-datasource] Skipping datasourceSubject update (not used yet).');
29522
+ }
29523
+ }
29524
+ save() {
29525
+ return __awaiter(this, void 0, void 0, function* () {
29526
+ if (this.config.readOnly) {
29527
+ console.error('[entities-table-datasource] Enable to save, because config.readOnly=true');
29528
+ return false;
29529
+ }
29530
+ // Saving twice (should never occur)
29531
+ if (this._saving) {
29532
+ console.warn(`[entities-table-datasource] Trying to save ${this._entityName} rows twice. Skip`);
29533
+ return false;
29534
+ }
29535
+ this._saving = true;
29536
+ this.markAsLoading();
29537
+ const onlyDirtyRows = this.config.saveOnlyDirtyRows;
29538
+ try {
29539
+ if (this._debug)
29540
+ console.debug(`[entities-table-datasource] Saving ${this._entityName} rows... {onlyDirtyRows: ${onlyDirtyRows}}`);
29541
+ // Get all rows
29542
+ const rows = this.getRows();
29543
+ // Finish editing all rows
29544
+ const invalidRows = (yield Promise.all(this.getEditingRows()
29545
+ .map(row => row.confirmEditCreate().then(confirmed => confirmed === false ? row : null))))
29546
+ .filter(isNotNil);
29547
+ // Cannot finish some rows: error
29548
+ if (invalidRows.length) {
29549
+ // log errors
29550
+ if (this._debug)
29551
+ invalidRows.forEach(row => AppTableUtils.logRowErrors(row, `[entities-table-datasource] ${this._entityName} row #${row.id}`));
29552
+ // Stop with an error
29553
+ throw { code: ErrorCodes.TABLE_INVALID_ROW_ERROR, message: 'ERROR.TABLE_INVALID_ROW_ERROR' };
29554
+ }
29555
+ let data;
29556
+ let dataToSave;
29557
+ if (this.validatorService) {
29558
+ dataToSave = [];
29559
+ data = rows.map(row => {
29560
+ const currentData = new this.dataConstructor();
29561
+ currentData.fromObject(row.currentData);
29562
+ // Filter to keep only dirty row
29563
+ if (onlyDirtyRows && row.validator.dirty)
29564
+ dataToSave.push(currentData);
29565
+ return currentData;
29566
+ });
29567
+ if (!onlyDirtyRows)
29568
+ dataToSave = data;
29569
+ }
29570
+ // Or use the current data without conversion (when no validator service used)
29571
+ else {
29572
+ data = rows.map(row => row.currentData);
29573
+ // save all data, as we don't have any dirty marker
29574
+ dataToSave = data;
29575
+ }
29576
+ // If no data to save: exit
29577
+ if (onlyDirtyRows && !dataToSave.length) {
29578
+ if (this._debug)
29579
+ console.debug(`[entities-table-datasource] No ${this._entityName} data to save. Skip`);
29580
+ return false;
29581
+ }
29582
+ if (this._debug)
29583
+ console.debug(`[entities-table-datasource] Asking service to save this ${this._entityName} data:`, dataToSave);
29584
+ yield this.dataService.saveAll(dataToSave, this.saveAllOptions);
29585
+ if (this._debug)
29586
+ console.debug(`[entities-table-datasource] Saving ${this._entityName} data [OK]`);
29587
+ // LP 23/03/2021: update datasource is necessary but can be changed to a refetch() on QueryRef (must be created and registered in GraphqlService.watchQuery)
29588
+ this.updateDatasource(data, { emitEvent: false });
29589
+ return true;
29590
+ }
29591
+ catch (error) {
29592
+ if (this._debug)
29593
+ console.error('[entities-table-datasource] Error while saving: ' + error && error.message || error);
29594
+ throw error;
29595
+ }
29596
+ finally {
29597
+ this._saving = false;
29598
+ this.markAsLoaded();
29599
+ }
29600
+ });
29601
+ }
29602
+ updateDatasource(data, opts) {
29603
+ if (this._debug)
29604
+ console.debug(`[entities-table-datasource] Updating datasource with data:`, data);
29605
+ super.updateDatasource(data, opts);
29606
+ if (!opts || opts.emitEvent !== false) {
29607
+ this.markAsLoaded();
29608
+ }
29609
+ }
29610
+ connect(collectionViewer) {
29611
+ // DEBUG
29612
+ //console.debug("[entities-datasource] connect");
29613
+ return super.connect(collectionViewer);
29614
+ }
29615
+ disconnect(collectionViewer) {
29616
+ if (this._debug)
29617
+ console.debug('[entities-table-datasource] Disconnecting...');
29618
+ super.disconnect(collectionViewer);
29619
+ if (!this._stopWatchSubject.closed) {
29620
+ if (this._debug)
29621
+ console.debug('[entities-table-datasource] Closing...');
29622
+ this._stopWatchSubject.next();
29623
+ this._stopWatchSubject.complete();
29624
+ this._stopWatchSubject.unsubscribe();
29625
+ this.loadingSubject.complete();
29626
+ this.loadingSubject.unsubscribe();
29627
+ }
29628
+ }
29629
+ waitIdle(debounceTimeMs) {
29630
+ return firstFalsePromise(this.loadingSubject
29631
+ .asObservable()
29632
+ .pipe(debounceTime(debounceTimeMs || 100) // if not started yet, wait
29633
+ ));
29634
+ }
29635
+ confirmCreate(row) {
29636
+ const _super = Object.create(null, {
29637
+ confirmCreate: { get: () => super.confirmCreate }
29638
+ });
29639
+ return __awaiter(this, void 0, void 0, function* () {
29640
+ const confirmed = yield _super.confirmCreate.call(this, row);
29641
+ if (!confirmed)
29642
+ return false;
29643
+ if (row.editing && row.validator) {
29644
+ console.warn('[entities-table-datasource] Row still has {editing: true} after confirmCreate()! Force editing to false');
29645
+ row.validator.disable({ onlySelf: true, emitEvent: false });
29646
+ }
29647
+ return confirmed;
29648
+ });
29649
+ }
29650
+ confirmEdit(row) {
29651
+ const _super = Object.create(null, {
29652
+ confirmEdit: { get: () => super.confirmEdit }
29653
+ });
29654
+ return __awaiter(this, void 0, void 0, function* () {
29655
+ const confirmed = yield _super.confirmEdit.call(this, row);
29656
+ if (!confirmed)
29657
+ return false;
29658
+ if (row.editing && row.validator) {
29659
+ console.warn('[entities-table-datasource] Row still has {editing: true} after confirmEdit()! Force editing to false');
29660
+ row.validator.disable({ onlySelf: true, emitEvent: false });
29661
+ }
29662
+ return true;
29663
+ });
29664
+ }
29665
+ startEdit(row) {
29666
+ const _super = Object.create(null, {
29667
+ startEdit: { get: () => super.startEdit }
29668
+ });
29669
+ return __awaiter(this, void 0, void 0, function* () {
29670
+ const editing = yield _super.startEdit.call(this, row);
29671
+ if (!editing)
29672
+ return false;
29673
+ if (!row.editing && row.validator) {
29674
+ console.warn('[entities-table-datasource] Row still has {editing: false} after startEdit()! Force editing');
29675
+ row.validator.enable({ onlySelf: true, emitEvent: false });
29676
+ }
29677
+ return true;
29678
+ });
29679
+ }
29680
+ handleError(error, message) {
29681
+ const errorMsg = error && error.message || error;
29682
+ console.error(`[entities-table-datasource] Service ${this._entityName} sent error: ${errorMsg}`, error);
29683
+ this.markAsLoaded();
29684
+ throw new Error(message || errorMsg);
29685
+ }
29686
+ handleServiceError(error) {
29687
+ const errorMsg = error && error.message || error;
29688
+ console.error(`[entities-table-datasource] Service ${this._entityName} sent error: ${errorMsg}`, error);
29689
+ this.markAsLoaded();
29690
+ throw error;
29691
+ }
29692
+ delete(id) {
29693
+ const _super = Object.create(null, {
29694
+ delete: { get: () => super.delete }
29695
+ });
29696
+ return __awaiter(this, void 0, void 0, function* () {
29697
+ // If new row: not need to propagate to the dataService
29698
+ if (id === -1) {
29699
+ return _super.delete.call(this, id);
29700
+ }
29701
+ const row = this.getRow(id);
29702
+ if (!row) {
29703
+ console.error(`[entities-table-datasource] Row to delete with id=${id} not found`);
29704
+ return;
29705
+ }
29706
+ this.markAsLoading();
29707
+ try {
29708
+ yield this.dataService.deleteAll([row.currentData], this.saveAllOptions);
29709
+ // Wait cache update, then table update
29710
+ yield sleep(300);
29711
+ // make sure row has been deleted (because GraphQl cache remove can fail)
29712
+ const present = this.getRow(id) === row;
29713
+ if (present)
29714
+ yield _super.delete.call(this, id);
29715
+ this.markAsLoaded();
29716
+ }
29717
+ catch (err) {
29718
+ this.handleServiceError(err);
29719
+ }
29720
+ });
29721
+ }
29722
+ deleteAll(rows) {
29723
+ const _super = Object.create(null, {
29724
+ delete: { get: () => super.delete }
29725
+ });
29726
+ return __awaiter(this, void 0, void 0, function* () {
29727
+ this.markAsLoading();
29728
+ const data = this.getDataFromRows(rows);
29729
+ try {
29730
+ // Call service deletion
29731
+ yield this.dataService.deleteAll(data, this.saveAllOptions);
29732
+ // Workaround, to be sure all rows have been deleted
29733
+ // Sometime, the service miss deletion, or GraphQl cache remove failed.
29734
+ // In this case, apply missing deletion using the parent delete() function
29735
+ const rowNotDeleted = this.getRows().filter(row => rows.includes(row));
29736
+ const deleteFn = _super.delete;
29737
+ if (isNotEmptyArray(rowNotDeleted)) {
29738
+ console.warn(`[entities-table-datasource] Force deletion of ${rowNotDeleted.length} rows! Please check that data service update the cache, after deletion`);
29739
+ rowNotDeleted
29740
+ // Start at the end
29741
+ .sort((a, b) => a.id > b.id ? -1 : 1)
29742
+ .forEach(r => deleteFn(r.id));
29743
+ }
29744
+ }
29745
+ catch (err) {
29746
+ // Handle service error
29747
+ this.handleServiceError(err);
29748
+ }
29749
+ finally {
29750
+ this.markAsLoaded();
29751
+ }
29752
+ });
29753
+ }
29754
+ getRow(id) {
29755
+ return super.getRow(id);
29756
+ }
29757
+ getRows() {
29758
+ return this.rowsSubject.value || [];
29759
+ }
29760
+ getEditingRows() {
29761
+ return this.getRows().filter(row => row.editing);
29762
+ }
29763
+ getSingleEditingRow() {
29764
+ const rows = this.getRows();
29765
+ return rows.length === 1 ? rows[0] : undefined;
29766
+ }
29767
+ hasSomeEditingRow() {
29768
+ return this.getRows().some(row => row.editing);
29769
+ }
29770
+ createNew(insertAt, opts = { editing: true }) {
29771
+ const _super = Object.create(null, {
29772
+ createNew: { get: () => super.createNew }
29773
+ });
29774
+ var _a;
29775
+ return __awaiter(this, void 0, void 0, function* () {
29776
+ // Avoid multiple call (only one editing row is allowed)
29777
+ if (this._creating && opts.editing)
29778
+ return;
29779
+ this._creating = true;
29780
+ try {
29781
+ const row = yield _super.createNew.call(this, insertAt, opts);
29782
+ if (!row)
29783
+ return undefined; // Stop here
29784
+ // Call observers
29785
+ if ((_a = this.config) === null || _a === void 0 ? void 0 : _a.onRowCreated) {
29786
+ try {
29787
+ yield this.config.onRowCreated(row);
29788
+ }
29789
+ catch (err) {
29790
+ // Log, then continue
29791
+ console.error(err && err.message || err, err);
29792
+ }
29793
+ }
29794
+ return row;
29795
+ }
29796
+ finally {
29797
+ this._creating = false;
29798
+ }
29799
+ });
29800
+ }
29801
+ getData() {
29802
+ const rows = this.getRows();
29803
+ return this.getDataFromRows(rows);
29804
+ }
29805
+ fetchMore(opts) {
29806
+ const _super = Object.create(null, {
29807
+ updateDatasource: { get: () => super.updateDatasource }
29808
+ });
29809
+ return __awaiter(this, void 0, void 0, function* () {
29810
+ if (!this._fetchMoreFn)
29811
+ return false; // Avoid multiple call
29812
+ if (this.hasSomeEditingRow()) {
29813
+ console.warn(`Cannot fetch more ${this._entityName} because some row) still editing`);
29814
+ return;
29815
+ }
29816
+ console.debug(`Will fetching more row(s) still...`);
29817
+ // Forget the fetchMore function, to avoid multiple call
29818
+ const fetchMoreFn = this._fetchMoreFn;
29819
+ this._fetchMoreFn = null;
29820
+ // Fetch next page
29821
+ const res = yield fetchMoreFn();
29822
+ // Skip if empty (no more data)
29823
+ if (isEmptyArray(res === null || res === void 0 ? void 0 : res.data))
29824
+ return false;
29825
+ // Update the data source
29826
+ _super.updateDatasource.call(this, (this.currentData || []).concat(...res.data), opts);
29827
+ // Remember fetchMore
29828
+ this._fetchMoreFn = res.fetchMore;
29829
+ return true;
29830
+ });
29831
+ }
29832
+ /* -- protected method -- */
29833
+ markAsLoading() {
29834
+ if (this.loadingSubject.value !== true) {
29835
+ this.loadingSubject.next(true);
29836
+ }
29837
+ }
29838
+ markAsLoaded() {
29839
+ if (this.loadingSubject.value !== false) {
29840
+ this.loadingSubject.next(false);
29841
+ }
29842
+ }
29843
+ }
29844
+ EntitiesAsyncTableDataSource.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: EntitiesAsyncTableDataSource, deps: "invalid", target: i0.ɵɵFactoryTarget.Directive });
29845
+ EntitiesAsyncTableDataSource.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "14.2.12", type: EntitiesAsyncTableDataSource, usesInheritance: true, ngImport: i0 });
29846
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: EntitiesAsyncTableDataSource, decorators: [{
29847
+ type: Directive
29848
+ }], ctorParameters: function () { return [{ type: undefined }, { type: undefined }, { type: undefined }, { type: undefined }]; } });
29849
+
29850
+ // @dynamic
29851
+ // noinspection DuplicatedCode
29852
+ // eslint-disable-next-line @angular-eslint/directive-class-suffix
29853
+ class AppAsyncTable {
29854
+ constructor(injector, columns, _dataSource, _filter) {
29855
+ this.columns = columns;
29856
+ this._dataSource = _dataSource;
29857
+ this._filter = _filter;
29858
+ this._initialized = false;
29859
+ this._subscription = new Subscription();
29860
+ this._cellValueChangesDefs = {};
29861
+ this._enabled = true;
29862
+ this.allowRowDetail = true;
29863
+ this.destroySubject = new Subject();
29864
+ this.excludesColumns = [];
29865
+ this.totalRowCount = null;
29866
+ this.readySubject = new BehaviorSubject(false);
29867
+ this.loadingSubject = new BehaviorSubject(true);
29868
+ this.savingSubject = new BehaviorSubject(false);
29869
+ this.touchedSubject = new BehaviorSubject(false);
29870
+ this.dirtySubject = new BehaviorSubject(false);
29871
+ this.errorSubject = new BehaviorSubject(undefined);
29872
+ this.selection = new SelectionModel(true, []);
29873
+ this.i18nColumnPrefix = 'COMMON.';
29874
+ this.autoLoad = true;
29875
+ this.focusFirstColumn = false;
29876
+ this.confirmBeforeDelete = false;
29877
+ this.confirmBeforeCancel = false;
29878
+ this.undoableDeletion = false;
29879
+ this.propagateRowError = false;
29880
+ this.defaultPageSize = DEFAULT_PAGE_SIZE;
29881
+ this.defaultPageSizeOptions = DEFAULT_PAGE_SIZE_OPTIONS;
29882
+ this.onRefresh = new EventEmitter();
29883
+ this.onOpenRow = new EventEmitter();
29884
+ this.onNewRow = new EventEmitter();
29885
+ this.onStartEditingRow = new EventEmitter();
29886
+ this.onConfirmEditCreateRow = new EventEmitter();
29887
+ this.onCancelOrDeleteRow = new EventEmitter();
29888
+ this.onBeforeDeleteRows = createPromiseEventEmitter();
29889
+ this.onBeforeCancelRows = createPromiseEventEmitter();
29890
+ this.onBeforeSave = createPromiseEventEmitter();
29891
+ this.onAfterDeletedRows = new EventEmitter();
29892
+ this.onSort = new EventEmitter();
29893
+ this.onDirty = new EventEmitter();
29894
+ this.onError = new EventEmitter();
29895
+ this._paginator = null;
29896
+ this.route = injector.get(ActivatedRoute);
29897
+ this.router = injector.get(Router);
29898
+ this.location = injector.get(Location);
29899
+ this.settings = injector.get(LocalSettingsService);
29900
+ this.translate = injector.get(TranslateService);
29901
+ this.modalCtrl = injector.get(ModalController);
29902
+ this.alertCtrl = injector.get(AlertController);
29903
+ this.toastController = injector.get(ToastController);
29904
+ this.formErrorAdapter = injector.get(FormErrorTranslator);
29905
+ this.mobile = this.settings.mobile;
29906
+ // Autocomplete fields
29907
+ this._autocompleteConfigHolder = new MatAutocompleteConfigHolder({
29908
+ getUserAttributes: (a, b) => this.settings.getFieldDisplayAttributes(a, b)
29909
+ });
29910
+ this.autocompleteFields = this._autocompleteConfigHolder.fields;
29911
+ }
29912
+ get error() {
29913
+ return this.errorSubject.value;
29914
+ }
29915
+ set error(error) {
29916
+ this.setError(error);
29917
+ }
29918
+ get firstUserColumn() {
29919
+ return this.displayedColumns[RESERVED_START_COLUMNS.length];
29920
+ }
29921
+ get lastUserColumn() {
29922
+ return this.displayedColumns[this.displayedColumns.length - RESERVED_END_COLUMNS.length - 1];
29923
+ }
29924
+ set dataSource(value) {
29925
+ this.setDatasource(value);
29926
+ }
29927
+ get dataSource() {
29928
+ return this._dataSource;
29929
+ }
29930
+ set filter(value) {
29931
+ this.setFilter(value);
29932
+ }
29933
+ get filter() {
29934
+ return this._filter;
29935
+ }
29936
+ get empty() {
29937
+ return this.loading || this.totalRowCount === 0;
29938
+ }
29939
+ get dirty() {
29940
+ return this.dirtySubject.value;
29941
+ }
29942
+ get valid() {
29943
+ return this.dataSource.getRows().every(row => row.editing ? row.valid : true);
29944
+ }
29945
+ get invalid() {
29946
+ return this.dataSource.getRows().some(row => row.editing ? row.invalid : false);
29947
+ }
29948
+ get pending() {
29949
+ return this.dataSource.getRows().some(row => row.editing ? row.pending : false);
29950
+ }
29951
+ get touched() {
29952
+ return this.touchedSubject.value;
29953
+ }
29954
+ get untouched() {
29955
+ return !this.touchedSubject.value;
29956
+ }
29957
+ disable(opts) {
29958
+ if (this.sort)
29959
+ this.sort.disabled = true;
29960
+ this._enabled = false;
29961
+ if (!opts || opts.emitEvent != false)
29962
+ this.markForCheck();
29963
+ }
29964
+ enable(opts) {
29965
+ if (this.sort)
29966
+ this.sort.disabled = false;
29967
+ this._enabled = true;
29968
+ if (!opts || opts.emitEvent != false)
29969
+ this.markForCheck();
29970
+ }
29971
+ get enabled() {
29972
+ return this._enabled;
29973
+ }
29974
+ // FIXME: need to hidden buttons (in HTML), etc. when disabled
29975
+ set disabled(value) {
29976
+ if (value !== !this._enabled) {
29977
+ if (value)
29978
+ this.disable({ emitEvent: false });
29979
+ else
29980
+ this.enable({ emitEvent: false });
29981
+ }
29982
+ }
29983
+ get disabled() {
29984
+ return !this._enabled;
29985
+ }
29986
+ markAsDirty(opts) {
29987
+ if (this.dirtySubject.value !== true) {
29988
+ this.dirtySubject.next(true);
29989
+ if (!opts || opts.emitEvent !== false) {
29990
+ this.markForCheck();
29991
+ }
29992
+ }
29993
+ }
29994
+ markAsPristine(opts) {
29995
+ if (this.dirtySubject.value !== false) {
29996
+ this.dirtySubject.next(false);
29997
+ if (!opts || opts.emitEvent !== false) {
29998
+ this.markForCheck();
29999
+ }
30000
+ }
30001
+ }
30002
+ markAsUntouched(opts) {
30003
+ return __awaiter(this, void 0, void 0, function* () {
30004
+ let needEmitEvent = false;
30005
+ if (this.touchedSubject.value) {
30006
+ this.touchedSubject.next(false);
30007
+ needEmitEvent = true;
30008
+ }
30009
+ if (this.dirty || this.dataSource.hasSomeEditingRow()) {
30010
+ for (const row of this.dataSource.getEditingRows()) {
30011
+ // Cancel the current editing row only if editing and if it was not previously saved
30012
+ yield this.dataSource.cancelOrDelete(row);
30013
+ // Mark row as pristine
30014
+ yield this.checkIfRowPristine(row, { emitEvent: false });
30015
+ }
30016
+ needEmitEvent = true;
30017
+ }
30018
+ this.previouslyEditedRowId = undefined;
30019
+ if (needEmitEvent && (!opts || opts.emitEvent !== false))
30020
+ this.markForCheck();
30021
+ });
30022
+ }
30023
+ /**
30024
+ * @deprecated prefer to use markAllAsTouched()
30025
+ * @param opts
30026
+ */
30027
+ markAsTouched(opts) {
30028
+ console.warn('TODO: Replace this call by markAllAsTouched() - because of changes in ngx-components >= 0.16.0');
30029
+ if (this.dataSource.hasSomeEditingRow()) {
30030
+ this.dataSource.getEditingRows().forEach(row => { var _a; return (_a = row.validator) === null || _a === void 0 ? void 0 : _a.markAllAsTouched(); });
30031
+ if (!opts || opts.emitEvent !== false) {
30032
+ this.markForCheck();
30033
+ }
30034
+ }
30035
+ }
30036
+ markAllAsTouched(opts) {
30037
+ if (this.touchedSubject.value !== true) {
30038
+ this.touchedSubject.next(true);
30039
+ if (!opts || opts.emitEvent !== false)
30040
+ this.markForCheck();
30041
+ }
30042
+ if (this.dataSource.hasSomeEditingRow()) {
30043
+ this.dataSource.getEditingRows().forEach(row => { var _a; return (_a = row.validator) === null || _a === void 0 ? void 0 : _a.markAllAsTouched(); });
30044
+ }
30045
+ }
30046
+ markAsSaving(opts) {
30047
+ if (this.savingSubject.value !== true) {
30048
+ this.focusColumn = undefined; // unselect focus column
30049
+ this.savingSubject.next(true);
30050
+ if (!opts || opts.emitEvent !== false)
30051
+ this.markForCheck();
30052
+ }
30053
+ }
30054
+ markAsSaved(opts) {
30055
+ if (this.savingSubject.value !== false) {
30056
+ this.savingSubject.next(false);
30057
+ if (!opts || opts.emitEvent !== false)
30058
+ this.markForCheck();
30059
+ }
30060
+ }
30061
+ markAsLoading(opts) {
30062
+ this.setLoading(true, opts);
30063
+ }
30064
+ markAsLoaded(opts) {
30065
+ this.setLoading(false, opts);
30066
+ }
30067
+ markAsReady(opts) {
30068
+ if (this.readySubject.value !== true) {
30069
+ this.readySubject.next(true);
30070
+ // If subclasses implements OnReady
30071
+ if (typeof this['ngOnReady'] === 'function') {
30072
+ this.ngOnReady();
30073
+ }
30074
+ }
30075
+ }
30076
+ get loading() {
30077
+ return this.loadingSubject.value;
30078
+ }
30079
+ get loaded() {
30080
+ return !this.loadingSubject.value;
30081
+ }
30082
+ enableSort() {
30083
+ if (this.sort)
30084
+ this.sort.disabled = false;
30085
+ }
30086
+ disableSort() {
30087
+ if (this.sort)
30088
+ this.sort.disabled = true;
30089
+ }
30090
+ set pageSize(value) {
30091
+ this.defaultPageSize = value;
30092
+ if (this.paginator) {
30093
+ this.paginator.pageSize = value;
30094
+ }
30095
+ }
30096
+ get pageSize() {
30097
+ return this.paginator && this.paginator.pageSize || this.defaultPageSize || DEFAULT_PAGE_SIZE;
30098
+ }
30099
+ get pageOffset() {
30100
+ return this.paginator && this.paginator.pageIndex * this.paginator.pageSize || 0;
30101
+ }
30102
+ get sortActive() {
30103
+ return this.sort && this.sort.active;
30104
+ }
30105
+ get sortDirection() {
30106
+ return this.sort && this.sort.direction && (this.sort.direction === 'desc' ? 'desc' : 'asc') || undefined;
30107
+ }
30108
+ set paginator(value) {
30109
+ this._paginator = value;
30110
+ }
30111
+ get paginator() {
30112
+ return this._paginator || this.childPaginator;
30113
+ }
30114
+ get destroyed() {
30115
+ var _a;
30116
+ return ((_a = this.destroySubject) === null || _a === void 0 ? void 0 : _a.closed) !== false;
30117
+ }
30118
+ ngOnInit() {
30119
+ var _a;
30120
+ if (this._initialized)
30121
+ return; // Init only once
30122
+ this._initialized = true;
30123
+ // Set defaults
30124
+ this.readOnly = toBoolean(this.readOnly, ((_a = this.dataSource) === null || _a === void 0 ? void 0 : _a.config.readOnly) || false); // read/write by default
30125
+ this.inlineEdition = !this.readOnly && toBoolean(this.inlineEdition, false); // force to false when readonly
30126
+ this.saveBeforeDelete = toBoolean(this.saveBeforeDelete, !this.readOnly); // force to false when readonly
30127
+ this.saveBeforeSort = toBoolean(this.saveBeforeSort, !this.readOnly); // force to false when readonly
30128
+ this.saveBeforeFilter = toBoolean(this.saveBeforeFilter, !this.readOnly); // force to false when readonly
30129
+ this.keepEditedRowOnSave = toBoolean(this.keepEditedRowOnSave, this.inlineEdition);
30130
+ this.errorTranslatorOptions = this.errorTranslatorOptions || { separator: ', ', controlPathTranslator: this }; // Can be override in subclasses constructors
30131
+ // Check ask user confirmation is possible
30132
+ if (this.confirmBeforeDelete && !this.alertCtrl)
30133
+ throw Error('Missing \'alertCtrl\' or \'injector\' in component\'s constructor.');
30134
+ // Defined unique id for settings for the page
30135
+ this.settingsId = this.settingsId || this.generateTableId();
30136
+ this.displayedColumns = this.getDisplayColumns();
30137
+ // Load the sorted columns, from settings
30138
+ {
30139
+ const sortedColumn = this.getSortedColumn();
30140
+ this.defaultSortBy = sortedColumn.id;
30141
+ this.defaultSortDirection = sortedColumn.start;
30142
+ }
30143
+ this.defaultPageSize = this.getPageSize();
30144
+ // Propagate error to event emitter
30145
+ this.registerSubscription(this.errorSubject
30146
+ .subscribe(value => this.onError.emit(value)));
30147
+ // Propagate dirty to event emitter
30148
+ this.registerSubscription(this.dirtySubject
30149
+ .subscribe(value => this.onDirty.emit(value)));
30150
+ // Propagate row dirty state to table
30151
+ this.registerSubscription(this.onStartEditingRow
30152
+ .pipe(filter(row => (row === null || row === void 0 ? void 0 : row.validator) && true), mergeMap(row => row.validator.valueChanges
30153
+ .pipe(filter(row => row.dirty), first(),
30154
+ // DEBUG
30155
+ //tap(() => console.debug("Propagate row's dirty to table..."))
30156
+ // Stop if next another row, or destroying
30157
+ takeUntil(this.onStartEditingRow), takeUntil(this.destroySubject))))
30158
+ .subscribe(() => this.markAsDirty()));
30159
+ // Call datasource refresh, on each refresh events
30160
+ this.registerSubscription(this.onRefresh
30161
+ .pipe(startWith((this.autoLoad ? {} : 'skip')), switchMap((event) => {
30162
+ this.dirtySubject.next(false);
30163
+ this.selection.clear();
30164
+ if (event === 'skip') {
30165
+ return of(undefined);
30166
+ }
30167
+ if (!this._dataSource) {
30168
+ if (this.debug)
30169
+ console.debug('[table] Skipping data load: no dataSource defined');
30170
+ return of(undefined);
30171
+ }
30172
+ if (this.debug)
30173
+ console.debug('[table] Calling dataSource.watchAll()...');
30174
+ return this._dataSource.watchAll(this.pageOffset, this.pageSize, this.sortActive, this.sortDirection, this._filter);
30175
+ }), catchError(err => {
30176
+ if (this.debug)
30177
+ console.error(err);
30178
+ this.setError(err && err.message || err);
30179
+ return of(undefined); // Continue
30180
+ }))
30181
+ .subscribe(res => this.updateView(res)));
30182
+ // Listen dataSource loading events
30183
+ if (this._dataSource)
30184
+ this.listenDatasourceLoading(this._dataSource);
30185
+ }
30186
+ ngAfterViewInit() {
30187
+ // Detect when parent ngOnInit() not call
30188
+ if (this.debug && !this.displayedColumns)
30189
+ console.warn(`[table] Missing 'displayedColumns'. Did you call parent ngOnInit() in component ${this.constructor.name} ?`);
30190
+ // Start listening sort and paginator events
30191
+ // noinspection JSIgnoredPromiseFromCall
30192
+ this.listenSortAndPaginationEvents();
30193
+ }
30194
+ ngOnDestroy() {
30195
+ this._subscription.unsubscribe();
30196
+ // Unsubscribe column value changes
30197
+ Object.keys(this._cellValueChangesDefs).forEach(col => this.stopCellValueChanges(col, true));
30198
+ this._cellValueChangesDefs = {};
30199
+ this.readySubject.unsubscribe();
30200
+ this.loadingSubject.unsubscribe();
30201
+ this.savingSubject.unsubscribe();
30202
+ this.errorSubject.unsubscribe();
30203
+ this.dirtySubject.unsubscribe();
30204
+ this.onRefresh.unsubscribe();
30205
+ this.onOpenRow.unsubscribe();
30206
+ this.onNewRow.unsubscribe();
30207
+ this.onStartEditingRow.unsubscribe();
30208
+ this.onConfirmEditCreateRow.unsubscribe();
30209
+ this.onCancelOrDeleteRow.unsubscribe();
30210
+ this.onBeforeDeleteRows.unsubscribe();
30211
+ this.onBeforeCancelRows.unsubscribe();
30212
+ this.onBeforeSave.unsubscribe();
30213
+ this.onAfterDeletedRows.unsubscribe();
30214
+ this.onSort.unsubscribe();
30215
+ this.onDirty.unsubscribe();
30216
+ this.onError.unsubscribe();
30217
+ this.destroySubject.next();
30218
+ this.destroySubject.unsubscribe();
30219
+ }
30220
+ updateView(res, opts) {
30221
+ return __awaiter(this, void 0, void 0, function* () {
30222
+ if (!res)
30223
+ return; // Skip (e.g error)
30224
+ if (res && res.data) {
30225
+ this.visibleRowCount = res.data.length;
30226
+ this.totalRowCount = isNotNil(res.total) ? res.total : ((this.paginator && this.paginator.pageIndex * (this.paginator.pageSize || DEFAULT_PAGE_SIZE) || 0) + this.visibleRowCount);
30227
+ if (this.debug)
30228
+ console.debug(`[table] ${res.data.length} rows loaded`);
30229
+ }
30230
+ else {
30231
+ //if (this.debug) console.debug('[table] NO rows loaded');
30232
+ this.totalRowCount = 0;
30233
+ this.visibleRowCount = 0;
30234
+ }
30235
+ if (!opts || opts.emitEvent !== false) {
30236
+ yield this.markAsUntouched({ emitEvent: false });
30237
+ this.markAsPristine({ emitEvent: false });
30238
+ this.markAsLoaded({ emitEvent: false });
30239
+ }
30240
+ this.markForCheck();
30241
+ });
30242
+ }
30243
+ setDatasource(datasource) {
30244
+ if (this._dataSource)
30245
+ throw new Error('[table] dataSource already set !');
30246
+ if (datasource && this._dataSource !== datasource) {
30247
+ this._dataSource = datasource;
30248
+ if (this._initialized)
30249
+ this.listenDatasourceLoading(datasource);
30250
+ }
30251
+ }
30252
+ resetDataSource() {
30253
+ if (this._dataSourceLoadingSubscription) {
30254
+ this._dataSourceLoadingSubscription.unsubscribe();
30255
+ this._subscription.remove(this._dataSourceLoadingSubscription);
30256
+ }
30257
+ //this._dataSource?.close();
30258
+ this._dataSource = null;
30259
+ }
30260
+ addColumnDef(column) {
30261
+ this.table.addColumnDef(column);
30262
+ }
30263
+ removeColumnDef(column) {
30264
+ this.table.removeColumnDef(column);
30265
+ }
30266
+ setFilter(filter, opts) {
30267
+ opts = opts || { emitEvent: true };
30268
+ if (this.saveBeforeFilter) {
30269
+ // if a dirty table is to be saved before filter
30270
+ if (this.dirty) {
30271
+ // Save
30272
+ this.saveBeforeAction('filter').then(saved => {
30273
+ // Apply filter only if user didn't cancel the save or the save is ok
30274
+ if (saved) {
30275
+ this.applyFilter(filter, opts);
30276
+ }
30277
+ });
30278
+ }
30279
+ else {
30280
+ // apply filter on non-dirty table
30281
+ this.applyFilter(filter, opts);
30282
+ }
30283
+ }
30284
+ else {
30285
+ // apply filter directly
30286
+ this.applyFilter(filter, opts);
30287
+ }
30288
+ }
30289
+ confirmAndAdd(event, row) {
30290
+ return __awaiter(this, void 0, void 0, function* () {
30291
+ if (!(yield this.confirmEditCreate(event, row))) {
30292
+ return false;
30293
+ }
30294
+ // Add row
30295
+ return yield this.addRow(event);
30296
+ });
30297
+ }
30298
+ confirmAndBackward(event, row) {
30299
+ return __awaiter(this, void 0, void 0, function* () {
30300
+ // Deleting edited row, if empty and not dirty
30301
+ if (this.dataSource.hasSomeEditingRow()) {
30302
+ for (const editingRow of this.dataSource.getEditingRows().filter(row => row.id === -1 && row.invalid && !row.dirty)) {
30303
+ yield this.deleteNewRow(event, editingRow);
30304
+ }
30305
+ // Wait deletion is done, then edit previous row (by id, because of reloading)
30306
+ yield this.waitIdle();
30307
+ yield this.editRowById(event, row.id, { focusColumn: this.lastUserColumn });
30308
+ return true;
30309
+ }
30310
+ // Edit previous row
30311
+ yield this.editRow(event, row, { focusColumn: this.lastUserColumn });
30312
+ return true;
30313
+ });
30314
+ }
30315
+ confirmAndForward(event, row) {
30316
+ return __awaiter(this, void 0, void 0, function* () {
30317
+ if (!this.inlineEdition)
30318
+ return false;
30319
+ yield this.confirmEditCreate(event, row);
30320
+ // Edit next row
30321
+ yield this.editRowById(event, row.id + 1, { focusColumn: this.firstUserColumn });
30322
+ return true;
30323
+ });
30324
+ }
30325
+ /**
30326
+ * Confirm the creation of the given row, or if not specified the currently edited row
30327
+ *
30328
+ * @param event
30329
+ * @param row
30330
+ */
30331
+ confirmEditCreate(event, row) {
30332
+ return __awaiter(this, void 0, void 0, function* () {
30333
+ row = row || this.dataSource.getSingleEditingRow();
30334
+ if (!row || !row.editing)
30335
+ return true; // no row to confirm
30336
+ // Stop event
30337
+ event === null || event === void 0 ? void 0 : event.stopPropagation();
30338
+ // Confirmation edition or creation
30339
+ const confirmed = yield row.confirmEditCreate();
30340
+ if (confirmed) {
30341
+ // Mark table as dirty (if row is dirty)
30342
+ if (row.dirty) {
30343
+ this.markAsDirty({ emitEvent: false /* because of resetError() */ });
30344
+ }
30345
+ // Clear error
30346
+ this.resetError();
30347
+ // Emit the confirm event
30348
+ this.onConfirmEditCreateRow.next(row);
30349
+ return true; // Continue
30350
+ }
30351
+ if (row.validator) {
30352
+ // If pending: Wait end of validation
30353
+ // TODO: remove when using async isValid() function
30354
+ if (row.pending) {
30355
+ yield AppFormUtils.waitWhilePending(row.validator);
30356
+ }
30357
+ // NOT confirmed = row has error
30358
+ if (this.debug) {
30359
+ console.warn('[table] Cannot confirm row, because invalid');
30360
+ AppFormUtils.logFormErrors(row.validator, '[table] ');
30361
+ }
30362
+ // fix: mark all controls as touched to show errors
30363
+ row.validator.markAllAsTouched();
30364
+ // Compute row error, and propagate to table's error
30365
+ if (this.propagateRowError) {
30366
+ const error = this.getRowError(row);
30367
+ this.setError(error);
30368
+ }
30369
+ }
30370
+ // Not confirmed
30371
+ return false;
30372
+ });
30373
+ }
30374
+ cancelOrDelete(event, row, opts) {
30375
+ return __awaiter(this, void 0, void 0, function* () {
30376
+ // Delete new row
30377
+ if (row.id === -1) {
30378
+ yield this.deleteNewRow(event, row);
30379
+ }
30380
+ // Delete existing (but not editing) row
30381
+ else if (!row.editing) {
30382
+ yield this.deleteExistingRow(event, row, opts);
30383
+ }
30384
+ // Cancel existing (and editing) row
30385
+ else {
30386
+ yield this.cancelExistingRow(event, row, opts);
30387
+ }
30388
+ });
30389
+ }
30390
+ addRow(event, insertAt, opts) {
30391
+ return __awaiter(this, void 0, void 0, function* () {
30392
+ if (this.debug)
30393
+ console.debug('[table] Asking for new row...');
30394
+ if (!this._enabled)
30395
+ return false;
30396
+ // Use modal if inline edition is disabled
30397
+ if (!this.inlineEdition) {
30398
+ yield this.openNewRowDetail(event);
30399
+ return false;
30400
+ }
30401
+ // Try to finish edited row first
30402
+ if (!(yield this.confirmEditCreate())) {
30403
+ return false;
30404
+ }
30405
+ // Add new row
30406
+ const row = yield this.addRowToTable(insertAt, opts);
30407
+ return !!row;
30408
+ });
30409
+ }
30410
+ save(opts) {
30411
+ var _a, _b;
30412
+ return __awaiter(this, void 0, void 0, function* () {
30413
+ opts = Object.assign({ keepEditing: this.keepEditedRowOnSave }, opts);
30414
+ if (this.readOnly) {
30415
+ throw { code: ErrorCodes.TABLE_READ_ONLY, message: 'ERROR.TABLE_READ_ONLY' };
30416
+ }
30417
+ this.resetError();
30418
+ // Keep edited row id (should be done BEFORE confirmEditCreate() )
30419
+ const editedRow = this.dataSource.getSingleEditingRow();
30420
+ this.previouslyEditedRowId = opts.keepEditing ? (((editedRow === null || editedRow === void 0 ? void 0 : editedRow.editing) ? editedRow.id : undefined) || ((_a = this.singleSelectedRow) === null || _a === void 0 ? void 0 : _a.id)) : undefined;
30421
+ const previouslyEditedData = opts.keepEditing ? (isNotNil(this.previouslyEditedRowId) && (editedRow === null || editedRow === void 0 ? void 0 : editedRow.currentData) || ((_b = this.singleSelectedRow) === null || _b === void 0 ? void 0 : _b.currentData)) : undefined;
30422
+ if (!(yield this.confirmEditCreate())) {
30423
+ throw { code: ErrorCodes.TABLE_INVALID_ROW_ERROR, message: 'ERROR.TABLE_INVALID_ROW_ERROR' };
30424
+ }
30425
+ // Mark as saving
30426
+ this.markAsSaving();
30427
+ try {
30428
+ // Calling service save()
30429
+ if (this.debug)
30430
+ console.debug('[table] Calling dataSource.save()...');
30431
+ const isOK = yield this._dataSource.save();
30432
+ if (isOK)
30433
+ this.markAsPristine();
30434
+ return isOK;
30435
+ }
30436
+ catch (err) {
30437
+ this.setError(err && err.message || err);
30438
+ throw err;
30439
+ }
30440
+ finally {
30441
+ this.markAsSaved();
30442
+ // Restore previous row
30443
+ if (isNotNil(this.previouslyEditedRowId)) {
30444
+ yield this.selectRowByIdOrData(this.previouslyEditedRowId, previouslyEditedData);
30445
+ }
30446
+ }
30447
+ });
30448
+ }
30449
+ cancel(event, opts) {
30450
+ return __awaiter(this, void 0, void 0, function* () {
30451
+ // Check confirmation
30452
+ if ((!opts || opts.interactive !== false) && this.dirty && (this.confirmBeforeCancel || this.onBeforeCancelRows.observers.length > 0)) {
30453
+ event === null || event === void 0 ? void 0 : event.stopPropagation();
30454
+ if (!(yield this.canCancelRows())) {
30455
+ return;
30456
+ }
30457
+ }
30458
+ this.onRefresh.emit();
30459
+ });
30460
+ }
30461
+ duplicateRow(event, row, opts) {
30462
+ var _a;
30463
+ return __awaiter(this, void 0, void 0, function* () {
30464
+ event === null || event === void 0 ? void 0 : event.stopPropagation();
30465
+ row = row || this.singleSelectedRow;
30466
+ if (!row || !(yield this.confirmEditCreate(event, row))) {
30467
+ return false;
30468
+ }
30469
+ const newRow = yield this.addRowToTable(row.id + 1);
30470
+ if (!newRow)
30471
+ throw new Error('Cannot add new row to table');
30472
+ const json = Object.assign(Object.assign({}, row.currentData), { id: null });
30473
+ // Reset some properties (e.g. rankOrder, etc)
30474
+ if (opts && opts.skipProperties) {
30475
+ const newData = newRow.currentData;
30476
+ opts.skipProperties.forEach(key => json[key] = newData[key]);
30477
+ }
30478
+ if (newRow.validator) {
30479
+ newRow.validator.patchValue(json);
30480
+ newRow.validator.markAsDirty();
30481
+ }
30482
+ else {
30483
+ if ((_a = newRow.currentData) === null || _a === void 0 ? void 0 : _a.fromObject) {
30484
+ newRow.currentData.fromObject(json);
30485
+ }
30486
+ else {
30487
+ newRow.currentData = json;
30488
+ }
30489
+ this.markAsDirty();
30490
+ }
30491
+ // select
30492
+ yield this.clickRow(undefined, newRow);
30493
+ });
30494
+ }
30495
+ /** Whether the number of selected elements matches the total number of rows. */
30496
+ isAllSelected() {
30497
+ // DEBUG
30498
+ //console.debug('isAllSelected. lengths', this.selection.selected.length, this.totalRowCount);
30499
+ return this.selection.selected.length === this.totalRowCount ||
30500
+ this.selection.selected.length === this.visibleRowCount;
30501
+ }
30502
+ /** Selects all rows if they are not all selected; otherwise clear selection. */
30503
+ masterToggle() {
30504
+ return __awaiter(this, void 0, void 0, function* () {
30505
+ if (this.loading)
30506
+ return;
30507
+ if (this.isAllSelected()) {
30508
+ this.selection.clear();
30509
+ }
30510
+ else {
30511
+ const rows = this._dataSource.getRows();
30512
+ rows.forEach(row => this.selection.select(row));
30513
+ }
30514
+ });
30515
+ }
30516
+ deleteSelection(event, opts) {
30517
+ return this.deleteRows(event, this.selection.selected, opts);
30518
+ }
30519
+ /**
30520
+ *
30521
+ * @param event
30522
+ * @param row
30523
+ * @param opts Use interactive=false to avoid user interaction (e.g. user confirmation)
30524
+ * And to force deletion even if table is busy
30525
+ */
30526
+ deleteRow(event, row, opts) {
30527
+ return __awaiter(this, void 0, void 0, function* () {
30528
+ const deleteCount = yield this.deleteRows(event, [row], opts);
30529
+ return deleteCount === 1;
30530
+ });
30531
+ }
30532
+ /**
30533
+ *
30534
+ * @param event
30535
+ * @param rows
30536
+ * @param opts Use interactive=false to avoid user interaction (e.g. user confirmation)
30537
+ * And to force deletion even if table is busy
30538
+ */
30539
+ deleteRows(event, rows, opts) {
30540
+ return __awaiter(this, void 0, void 0, function* () {
30541
+ if (this.readOnly) {
30542
+ throw { code: ErrorCodes.TABLE_READ_ONLY, message: 'ERROR.TABLE_READ_ONLY' };
30543
+ }
30544
+ if (event === null || event === void 0 ? void 0 : event.defaultPrevented)
30545
+ return 0; // SKip
30546
+ event === null || event === void 0 ? void 0 : event.preventDefault();
30547
+ if (!this._enabled || isEmptyArray(rows))
30548
+ return 0; // Skip is disabled, or no rows to delete
30549
+ if (this.loading && (!opts || opts.interactive !== false)) {
30550
+ console.warn('[app-table] Skip deleteRows() because table is busy (loading). Use opts.interactive = false to force deletion');
30551
+ return 0; // Skip if loading
30552
+ }
30553
+ // Make sure to keep newly created row
30554
+ const editedRow = this.dataSource.getSingleEditingRow();
30555
+ if ((editedRow === null || editedRow === void 0 ? void 0 : editedRow.id) === -1 && editedRow.editing && !rows.includes(editedRow)) {
30556
+ const confirmed = yield this.confirmEditCreate();
30557
+ if (!confirmed)
30558
+ return 0; // Cannot delete (e.g. edited row is invalid)
30559
+ }
30560
+ // Check if it can delete
30561
+ const canDelete = yield this.canDeleteRows(rows, opts);
30562
+ if (!canDelete)
30563
+ return 0; // Cannot delete
30564
+ // Reverse row order (on a copy)
30565
+ // This is a workaround, need because row.delete() has async execution
30566
+ // and index cache is updated with a delay
30567
+ let tempRows = rows.slice()
30568
+ .sort((a, b) => a.id > b.id ? -1 : 1);
30569
+ let deletedRows = [];
30570
+ // If data need to be saved first
30571
+ if (this.saveBeforeDelete) {
30572
+ // Exclude invalid rows (because of save() will fail, when exists some invalid rows)
30573
+ tempRows = tempRows.filter(row => {
30574
+ // Delete the row :
30575
+ // - if newly created row (id = -1),
30576
+ // - or if invalid and not editing (= not cancellable)
30577
+ if (row.id === -1 || (!row.editing && row.invalid /*do not use !valid because if row is disabled, it will be always !valid */)) {
30578
+ if (this.debug)
30579
+ console.debug(`[table] Delete row #${row.id}`);
30580
+ row.delete();
30581
+ this.visibleRowCount--;
30582
+ this.totalRowCount--;
30583
+ deletedRows.push(row);
30584
+ return false; // Exclude from the list to delete using the service
30585
+ }
30586
+ // Cancel the row (and mark as pristine), when not valid but in edition
30587
+ else if (row.editing && !row.valid) {
30588
+ row.cancel();
30589
+ // Mark row as pristine (if possible)
30590
+ this.checkIfRowPristine(row, { emitEvent: false, onlySelf: true /*avoid propagation to table*/ });
30591
+ return true; // Keep the row. the row will be deleted after the save
30592
+ }
30593
+ return true;
30594
+ });
30595
+ // Apply save, only if there is still some rows to delete
30596
+ // WARN: If no more rows (e.g. because all has been cancelled) then continue anyway to clear editedRow and selection (issue IMAGINE-669)
30597
+ if (deletedRows.length || tempRows.length) {
30598
+ // Save data (e.g. when using memory service)
30599
+ const saved = yield this.saveBeforeAction('delete');
30600
+ if (!saved) {
30601
+ // Stop if save cancelled or save failed
30602
+ return;
30603
+ }
30604
+ }
30605
+ }
30606
+ try {
30607
+ // Apply deletion on datasource
30608
+ // If no more rows to delete, continue anyway to clear editedRow and selection (issue IMAGINE-669)
30609
+ if (tempRows.length) {
30610
+ if (this.debug)
30611
+ console.debug(`[table] Delete ${tempRows.length} rows...`);
30612
+ yield this._dataSource.deleteAll(tempRows);
30613
+ }
30614
+ // DO not update manually, because watchALl().subscribe() will update this count
30615
+ //this.totalRowCount -= deleteCount;
30616
+ //this.visibleRowCount -= deleteCount;
30617
+ this.selection.clear();
30618
+ this.markAsDirty({ emitEvent: false /*markForCheck() is called just after*/ });
30619
+ this.markForCheck();
30620
+ this.onAfterDeletedRows.next(rows);
30621
+ return rows.length;
30622
+ }
30623
+ catch (err) {
30624
+ this.setError(err && err.message || err);
30625
+ throw err;
30626
+ }
30627
+ });
30628
+ }
30629
+ selectRowById(id) {
30630
+ return __awaiter(this, void 0, void 0, function* () {
30631
+ if (id === undefined)
30632
+ return false;
30633
+ yield this.waitIdle();
30634
+ const row = this.dataSource.getRow(id);
30635
+ if (!row)
30636
+ return false;
30637
+ return this.clickRow(null, row);
30638
+ });
30639
+ }
30640
+ /**
30641
+ * Try to select row by data. Will use dataEquals() (that call EntityUtils.equals()) to find same row's data
30642
+ * @param data
30643
+ */
30644
+ selectRowByData(data) {
30645
+ return __awaiter(this, void 0, void 0, function* () {
30646
+ if (data === undefined)
30647
+ return Promise.resolve(false);
30648
+ yield this.waitIdle();
30649
+ const row = this.dataSource.getRows()
30650
+ .find(row => this.equals(row.currentData, data));
30651
+ if (!row)
30652
+ return false;
30653
+ return this.clickRow(null, row);
30654
+ });
30655
+ }
30656
+ clickRow(event, row) {
30657
+ return __awaiter(this, void 0, void 0, function* () {
30658
+ if (this.loading) {
30659
+ // Wait while loading, and loop
30660
+ if (this.debug)
30661
+ console.debug('[table] Waiting before apply clickRow() (datasource is busy)...');
30662
+ yield this.waitIdle({ timeout: 2000 });
30663
+ }
30664
+ // DEBUG
30665
+ //console.debug("[table] Detect click on row");
30666
+ if (row.id === -1 || row.editing)
30667
+ return true; // Already in edition
30668
+ if (event === null || event === void 0 ? void 0 : event.defaultPrevented)
30669
+ return false; // Cancelled by event
30670
+ // Open the detail page (if not inline editing)
30671
+ if (!this.inlineEdition) {
30672
+ if (event) {
30673
+ event.stopPropagation();
30674
+ event.preventDefault();
30675
+ }
30676
+ this.markAsLoading();
30677
+ this.selection.clear();
30678
+ this.openRow(row.currentData.id, row)
30679
+ .then(() => this.markAsLoaded())
30680
+ .catch(() => this.markAsLoaded());
30681
+ return true;
30682
+ }
30683
+ // Start editing row
30684
+ return this.editRow(event, row, { focusColumn: undefined /*force to use the click target*/ });
30685
+ });
30686
+ }
30687
+ moveRow(id, direction) {
30688
+ return __awaiter(this, void 0, void 0, function* () {
30689
+ yield this.dataSource.move(id, direction);
30690
+ });
30691
+ }
30692
+ ready(opts) {
30693
+ return waitForTrue(this.readySubject, opts);
30694
+ }
30695
+ waitIdle(opts) {
30696
+ return waitForFalse(this.loadingSubject, opts);
30697
+ }
30698
+ openSelectColumnsModal(event) {
30699
+ return __awaiter(this, void 0, void 0, function* () {
30700
+ event === null || event === void 0 ? void 0 : event.preventDefault();
30701
+ // Copy current columns (deep copy)
30702
+ const columns = this.getCurrentColumns();
30703
+ const hasTopModal = !!(yield this.modalCtrl.getTop());
30704
+ const modal = yield this.modalCtrl.create({
30705
+ component: TableSelectColumnsComponent,
30706
+ componentProps: { columns },
30707
+ cssClass: hasTopModal && 'stack-modal'
30708
+ });
30709
+ // Open the modal
30710
+ yield modal.present();
30711
+ // On dismiss
30712
+ const { data } = yield modal.onDidDismiss();
30713
+ if (!data)
30714
+ return; // CANCELLED
30715
+ // Apply columns
30716
+ const userColumns = (data || []).filter(c => c.canHide === false || c.visible).map(c => c.name) || [];
30717
+ this.displayedColumns = RESERVED_START_COLUMNS.concat(userColumns).concat(RESERVED_END_COLUMNS);
30718
+ this.markForCheck();
30719
+ // Update user settings
30720
+ yield this.settings.savePageSetting(this.settingsId, userColumns, SETTINGS_DISPLAY_COLUMNS);
30721
+ });
30722
+ }
30723
+ trackByFn(index, row) {
30724
+ return row.id;
30725
+ }
30726
+ doRefresh(event) {
30727
+ this.onRefresh.emit(event);
30728
+ // When target wait for a complete (e.g. IonRefresher)
30729
+ if ((event === null || event === void 0 ? void 0 : event.target) && event.target.complete) {
30730
+ setTimeout(() => __awaiter(this, void 0, void 0, function* () {
30731
+ yield this.waitIdle();
30732
+ event.target.complete();
30733
+ }));
30734
+ }
30735
+ }
30736
+ getCurrentColumns() {
30737
+ const hiddenColumns = this.columns.slice(RESERVED_START_COLUMNS.length)
30738
+ .filter(name => this.displayedColumns.indexOf(name) === -1);
30739
+ return this.displayedColumns
30740
+ .concat(hiddenColumns)
30741
+ .filter(name => !RESERVED_START_COLUMNS.includes(name) && !RESERVED_END_COLUMNS.includes(name)
30742
+ && !this.excludesColumns.includes(name))
30743
+ .map(name => ({
30744
+ name,
30745
+ label: this.getI18nColumnName(name),
30746
+ visible: this.displayedColumns.indexOf(name) !== -1,
30747
+ canHide: this.getRequiredColumns().indexOf(name) === -1
30748
+ }));
30749
+ }
30750
+ escapeEditingRow(event, row) {
30751
+ return __awaiter(this, void 0, void 0, function* () {
30752
+ row = row || this.dataSource.getSingleEditingRow();
30753
+ if (!row || !row.editing)
30754
+ return;
30755
+ // DEBUG
30756
+ //console.debug('[app-table] Cancel the row (keydown.escape)');
30757
+ if (event) {
30758
+ // Avoid to cancel the editor
30759
+ event.preventDefault();
30760
+ event.stopPropagation();
30761
+ }
30762
+ // If new row (no id)
30763
+ if (row.id === -1) {
30764
+ if (row.validator) {
30765
+ // If pending: Wait end of validation, then loop
30766
+ if (row.pending) {
30767
+ yield AppFormUtils.waitWhilePending(row.validator);
30768
+ }
30769
+ // Row is invalid: delete the row
30770
+ if (row.invalid) {
30771
+ yield this.deleteNewRow(event, row);
30772
+ return;
30773
+ }
30774
+ }
30775
+ }
30776
+ // If the row exists (has an id)
30777
+ else {
30778
+ // need to call cancel function (if confirmation will be called before)
30779
+ if (this.confirmBeforeCancel) {
30780
+ yield this.cancelExistingRow(event, row, { keepEditing: false });
30781
+ return;
30782
+ }
30783
+ }
30784
+ // By default, try to confirm the row
30785
+ yield this.confirmEditCreate(event, row);
30786
+ });
30787
+ }
30788
+ translateControlPath(path) {
30789
+ var _a;
30790
+ // Can be overridden by subclasses, to resolve all field name
30791
+ // Use columns key, has default name
30792
+ const i18nColumnKey = this.getI18nColumnName(path);
30793
+ return ((_a = this.translate) === null || _a === void 0 ? void 0 : _a.instant(i18nColumnKey)) || i18nColumnKey;
30794
+ }
30795
+ /* -- protected method -- */
30796
+ editRow(event, row, opts) {
30797
+ return __awaiter(this, void 0, void 0, function* () {
30798
+ if (!this._enabled || !this.inlineEdition)
30799
+ return false;
30800
+ if (this.dataSource.getEditingRows().includes(row))
30801
+ return true; // Already the edited row
30802
+ if (event === null || event === void 0 ? void 0 : event.defaultPrevented)
30803
+ return false;
30804
+ if (!(yield this.confirmEditCreate())) {
30805
+ return false;
30806
+ }
30807
+ if (!row.editing && !this.loading) {
30808
+ this.focusColumn = opts && opts.focusColumn || this.focusColumn;
30809
+ yield this._dataSource.startEdit(row);
30810
+ }
30811
+ this.onStartEditingRow.emit(row);
30812
+ return true;
30813
+ });
30814
+ }
30815
+ /**
30816
+ * Try to select row, by row.id, or by data. WIll use EntityUtils.equals()
30817
+ * @param id
30818
+ * @param data
30819
+ * @protected
30820
+ */
30821
+ selectRowByIdOrData(id, data) {
30822
+ return __awaiter(this, void 0, void 0, function* () {
30823
+ let done = false;
30824
+ try {
30825
+ // Select by row id (if NOT a new row)
30826
+ if (isNotNil(id) || id !== -1) {
30827
+ done = yield this.selectRowById(id);
30828
+ if (done)
30829
+ return true;
30830
+ console.warn('[app-table] Save: Cannot reselect row by row.id: ', id);
30831
+ }
30832
+ // Try by data
30833
+ if (data) {
30834
+ done = yield this.selectRowByData(data);
30835
+ if (done)
30836
+ return true;
30837
+ console.warn('[app-table] Save: Cannot reselect row by data: ', data);
30838
+ }
30839
+ return false;
30840
+ }
30841
+ catch (err) {
30842
+ // Log, but continue
30843
+ console.error(err && err.message || err);
30844
+ return false;
30845
+ }
30846
+ });
30847
+ }
30848
+ /**
30849
+ * return the selected row if unique in selection
30850
+ */
30851
+ get singleSelectedRow() {
30852
+ var _a;
30853
+ return ((_a = this.selection.selected) === null || _a === void 0 ? void 0 : _a.length) === 1 ? this.selection.selected[0] : undefined;
30854
+ }
30855
+ canDeleteRows(rows, opts) {
30856
+ return __awaiter(this, void 0, void 0, function* () {
30857
+ // Check using emitter
30858
+ if (this.onBeforeDeleteRows.observers.length > 0) {
30859
+ try {
30860
+ const canDelete = yield emitPromiseEvent(this.onBeforeDeleteRows, 'canDelete', {
30861
+ detail: { rows }
30862
+ });
30863
+ if (!canDelete)
30864
+ return false;
30865
+ }
30866
+ catch (err) {
30867
+ if (err === 'CANCELLED')
30868
+ return false; // User cancel
30869
+ console.error('Error while checking if can delete rows', err);
30870
+ throw err;
30871
+ }
30872
+ }
30873
+ // Ask user confirmation
30874
+ if (this.confirmBeforeDelete && (!opts || opts.interactive !== false)) {
30875
+ return this.askDeleteConfirmation(null, rows);
30876
+ }
30877
+ return true;
30878
+ });
30879
+ }
30880
+ canCancelRows(rows, opts) {
30881
+ return __awaiter(this, void 0, void 0, function* () {
30882
+ // Get dirty rows
30883
+ rows = rows || this.dataSource.getRows().filter(row => { var _a; return (_a = row.validator) === null || _a === void 0 ? void 0 : _a.dirty; });
30884
+ if (isEmptyArray(rows))
30885
+ return true; // No dirty: OK
30886
+ // Check using emitter
30887
+ if (this.onBeforeCancelRows.observers.length > 0) {
30888
+ try {
30889
+ const isCancel = yield emitPromiseEvent(this.onBeforeCancelRows, 'canCancel', {
30890
+ detail: { rows }
30891
+ });
30892
+ if (!isCancel)
30893
+ return false;
30894
+ }
30895
+ catch (err) {
30896
+ if (err === 'CANCELLED')
30897
+ return false; // User cancel
30898
+ console.error('Error while checking if can cancel rows', err);
30899
+ throw err;
30900
+ }
30901
+ }
30902
+ // Ask user confirmation
30903
+ if (this.confirmBeforeCancel && (!opts || opts.interactive !== false)) {
30904
+ return this.askCancelConfirmation(null, rows);
30905
+ }
30906
+ return true;
30907
+ });
30908
+ }
30909
+ saveBeforeAction(saveAction) {
30910
+ return __awaiter(this, void 0, void 0, function* () {
30911
+ if (!this.dirty) {
30912
+ // Continue without save
30913
+ return true;
30914
+ }
30915
+ let save;
30916
+ switch (saveAction) {
30917
+ case 'delete':
30918
+ save = this.saveBeforeDelete;
30919
+ break;
30920
+ case 'filter':
30921
+ save = this.saveBeforeFilter;
30922
+ break;
30923
+ case 'sort':
30924
+ save = this.saveBeforeSort;
30925
+ break;
30926
+ default:
30927
+ save = true;
30928
+ }
30929
+ // Default behavior
30930
+ let confirmed = true;
30931
+ if (save) {
30932
+ if (this.onBeforeSave.observers.length > 0) {
30933
+ // Ask confirmation
30934
+ try {
30935
+ const res = yield emitPromiseEvent(this.onBeforeSave, 'beforeSave', {
30936
+ detail: { action: saveAction, valid: this.valid }
30937
+ });
30938
+ confirmed = res.confirmed;
30939
+ save = res.save;
30940
+ }
30941
+ catch (err) {
30942
+ if (err === 'CANCELLED')
30943
+ return false; // User cancel
30944
+ console.error('Error while checking if can delete rows', err);
30945
+ throw err;
30946
+ }
30947
+ }
30948
+ }
30949
+ if (confirmed) {
30950
+ if (save) {
30951
+ // User confirmed save
30952
+ const saved = yield this.save();
30953
+ this.markAsDirty(); // Restore dirty flag
30954
+ return saved;
30955
+ }
30956
+ return true; // No save but continue action
30957
+ }
30958
+ return false; // User cancel the action
30959
+ });
30960
+ }
30961
+ /**
30962
+ * Open a row detail view. By default, will to open row detail page.
30963
+ * Can be overridden by subclasses, BUT prefer to subscribe on onOpenRow
30964
+ * @param id
30965
+ * @param row
30966
+ * @protected
30967
+ */
30968
+ openRow(id, row) {
30969
+ return __awaiter(this, void 0, void 0, function* () {
30970
+ if (this.allowRowDetail) {
30971
+ if (this.debug && this.dirty) {
30972
+ console.warn('[table] Opening row details, but table has unsaved changes!');
30973
+ }
30974
+ if (this.onOpenRow.observers.length) {
30975
+ this.onOpenRow.emit(row);
30976
+ return true;
30977
+ }
30978
+ // No ID defined: unable to open details
30979
+ if (isNil(id)) {
30980
+ console.warn('[table] Opening row details, but data has no id!');
30981
+ return false;
30982
+ }
30983
+ return this.router.navigate(['.', id.toString()], {
30984
+ relativeTo: this.route,
30985
+ queryParams: {}
30986
+ });
30987
+ }
30988
+ return false;
30989
+ });
30990
+ }
30991
+ openNewRowDetail(event) {
30992
+ return __awaiter(this, void 0, void 0, function* () {
30993
+ if (!this.allowRowDetail)
30994
+ return false;
30995
+ if (this.onNewRow.observers.length > 0) {
30996
+ this.onNewRow.emit(event);
30997
+ return true;
30998
+ }
30999
+ return yield this.router.navigate(['new'], {
31000
+ relativeTo: this.route
31001
+ });
31002
+ });
31003
+ }
31004
+ // can be overridden to add more required columns
31005
+ getRequiredColumns() {
31006
+ return DEFAULT_REQUIRED_COLUMNS;
31007
+ }
31008
+ getUserColumns() {
31009
+ return this.settings.getPageSettings(this.settingsId, SETTINGS_DISPLAY_COLUMNS);
31010
+ }
31011
+ getSortedColumn() {
31012
+ const data = this.settings.getPageSettings(this.settingsId, SETTINGS_SORTED_COLUMN);
31013
+ const parts = data && data.split(':');
31014
+ if (parts && parts.length === 2 && this.columns.includes(parts[0])) {
31015
+ return { id: parts[0], start: parts[1] === 'desc' ? 'desc' : 'asc', disableClear: false };
31016
+ }
31017
+ if (this.defaultSortBy) {
31018
+ return { id: this.defaultSortBy, start: this.defaultSortDirection || 'asc', disableClear: false };
31019
+ }
31020
+ return { id: 'id', start: 'asc', disableClear: false };
31021
+ }
31022
+ getPageSize() {
31023
+ const pageSize = this.settings.getPageSettings(this.settingsId, SETTINGS_PAGE_SIZE);
31024
+ return pageSize || this.defaultPageSize;
31025
+ }
31026
+ getDisplayColumns() {
31027
+ let userColumns = this.getUserColumns();
31028
+ // No user override
31029
+ if (!userColumns) {
31030
+ // Return default, without columns to hide
31031
+ return this.columns.filter(column => !this.excludesColumns.includes(column));
31032
+ }
31033
+ // Get fixed start columns
31034
+ const fixedStartColumns = this.columns.filter(c => RESERVED_START_COLUMNS.includes(c));
31035
+ // Remove end columns
31036
+ const fixedEndColumns = this.columns.filter(c => RESERVED_END_COLUMNS.includes(c));
31037
+ // Remove fixed columns from user columns
31038
+ userColumns = userColumns.filter(c => !fixedStartColumns.includes(c) && !fixedEndColumns.includes(c) && this.columns.includes(c));
31039
+ // Add required columns if missing
31040
+ userColumns.push(...this.getRequiredColumns().filter(c => !fixedStartColumns.includes(c) && !fixedEndColumns.includes(c) && !userColumns.includes(c)));
31041
+ return fixedStartColumns
31042
+ .concat(userColumns)
31043
+ .concat(fixedEndColumns)
31044
+ // Remove columns to hide
31045
+ .filter(column => !this.excludesColumns.includes(column));
31046
+ }
31047
+ /**
31048
+ * Recompute display columns
31049
+ *
31050
+ * @protected
31051
+ */
31052
+ updateColumns() {
31053
+ this.displayedColumns = this.getDisplayColumns();
31054
+ if (!this.loading)
31055
+ this.markForCheck();
31056
+ }
31057
+ registerSubscription(sub) {
31058
+ this._subscription.add(sub);
31059
+ }
31060
+ unregisterSubscription(sub) {
31061
+ this._subscription.remove(sub);
31062
+ }
31063
+ registerAutocompleteField(fieldName, options) {
31064
+ return this._autocompleteConfigHolder.add(fieldName, options);
31065
+ }
31066
+ getI18nColumnName(columnName) {
31067
+ return (this.i18nColumnPrefix || '') + changeCaseToUnderscore(columnName).toUpperCase();
31068
+ }
31069
+ generateTableId() {
31070
+ var _a;
31071
+ // noinspection JSNonASCIINames
31072
+ const id = this.location.path(true)
31073
+ .replace(/[?].*$/g, '')
31074
+ .replace(/\/\d+/g, '_id')
31075
+ + '_'
31076
+ // Get a component unique name - See https://stackoverflow.com/questions/60114682/how-to-access-components-unique-encapsulation-id-in-angular-9
31077
+ + (((_a = this.constructor['ɵcmp']) === null || _a === void 0 ? void 0 : _a.id) || this.constructor.name);
31078
+ //if (this.debug) console.debug("[table] id = " + id);
31079
+ return id;
31080
+ }
31081
+ addRowToTable(insertAt, opts) {
31082
+ return __awaiter(this, void 0, void 0, function* () {
31083
+ // Try to finish edited row first
31084
+ if (!(yield this.confirmEditCreate())) {
31085
+ console.warn('[table] Cannot add new row, because the previous edited row cannot be confirmed');
31086
+ return undefined;
31087
+ }
31088
+ const editing = this.inlineEdition && (!opts || opts.editing !== false); // true by default, if inlineEdition
31089
+ const row = yield this._dataSource.createNew(insertAt, { editing });
31090
+ if (!row)
31091
+ return undefined;
31092
+ if (row.editing) {
31093
+ // Update focused column
31094
+ this.focusFirstColumn = true;
31095
+ this.focusColumn = (opts === null || opts === void 0 ? void 0 : opts.focusColumn) || this.firstUserColumn;
31096
+ // Emit start editing event
31097
+ this.onStartEditingRow.emit(row);
31098
+ }
31099
+ this.totalRowCount++;
31100
+ this.visibleRowCount++;
31101
+ this.markAsDirty({ emitEvent: false /*markForCheck() is called just after*/ });
31102
+ // Emit event
31103
+ if (!opts || opts.emitEvent !== false)
31104
+ this.markForCheck();
31105
+ return row;
31106
+ });
31107
+ }
31108
+ registerCellValueChanges(name, formPath, emitInitialValue) {
31109
+ formPath = formPath || name;
31110
+ emitInitialValue = emitInitialValue || false;
31111
+ let def = this._cellValueChangesDefs[name];
31112
+ if (def && (def.formPath !== formPath || def.emitInitialValue !== emitInitialValue)) {
31113
+ throw Error('Already register a cell value change for this name, with different \'formPath\' or \'emitInitialValue\'. Please use same arguments.');
31114
+ }
31115
+ // Not exists: register new definition
31116
+ if (!def) {
31117
+ if (this.debug)
31118
+ console.debug(`[table] New listener {${name}} for value changes on path ${formPath}`);
31119
+ def = {
31120
+ subject: new Subject(),
31121
+ subscription: null,
31122
+ formPath,
31123
+ emitInitialValue
31124
+ };
31125
+ this._cellValueChangesDefs[name] = def;
31126
+ // Start the listener, when editing starts
31127
+ this.registerSubscription(this.onStartEditingRow.subscribe(row => this.startCellValueChanges(name, row)));
31128
+ }
31129
+ return def.subject;
31130
+ }
31131
+ setShowColumn(columnName, show, opts) {
31132
+ if (!this.excludesColumns.includes(columnName) !== show) {
31133
+ if (!show) {
31134
+ this.excludesColumns.push(columnName);
31135
+ }
31136
+ else {
31137
+ const index = this.excludesColumns.findIndex(value => value === columnName);
31138
+ if (index >= 0)
31139
+ this.excludesColumns.splice(index, 1);
31140
+ }
31141
+ // Recompute display columns
31142
+ if (this.displayedColumns && (!opts || opts.emitEvent !== false)) {
31143
+ this.updateColumns();
31144
+ }
31145
+ }
31146
+ }
31147
+ getShowColumn(columnName) {
31148
+ return !this.excludesColumns.includes(columnName);
31149
+ }
31150
+ startsWithUpperCase(input, search) {
31151
+ return input && input.toUpperCase().startsWith(search);
31152
+ }
31153
+ markForCheck() {
31154
+ // Should be overridden by subclasses, depending on ChangeDetectionStrategy
31155
+ }
31156
+ askDeleteConfirmation(event, rows) {
31157
+ return __awaiter(this, void 0, void 0, function* () {
31158
+ if (this.undoableDeletion) {
31159
+ // Special message, for undoable deletion
31160
+ return Alerts.askConfirmation((rows === null || rows === void 0 ? void 0 : rows.length) === 1 ? 'CONFIRM.DELETE_ROW' : 'CONFIRM.DELETE_ROWS', this.alertCtrl, this.translate, event);
31161
+ }
31162
+ // Immediate deletion action
31163
+ return Alerts.askActionConfirmation(this.alertCtrl, this.translate, true, event);
31164
+ });
31165
+ }
31166
+ askCancelConfirmation(event, rows) {
31167
+ return __awaiter(this, void 0, void 0, function* () {
31168
+ return Alerts.askConfirmation((rows === null || rows === void 0 ? void 0 : rows.length) === 1 ? 'CONFIRM.CANCEL_ROW' : 'CONFIRM.CANCEL_ROWS', this.alertCtrl, this.translate, event);
31169
+ });
31170
+ }
31171
+ askRestoreConfirmation(event) {
31172
+ return __awaiter(this, void 0, void 0, function* () {
31173
+ return Alerts.askActionConfirmation(this.alertCtrl, this.translate, false, event);
31174
+ });
31175
+ }
31176
+ showToast(opts) {
31177
+ return __awaiter(this, void 0, void 0, function* () {
31178
+ if (!this.toastController)
31179
+ throw new Error('Missing toastController in component\'s constructor');
31180
+ return Toasts.show(this.toastController, this.translate, opts);
31181
+ });
31182
+ }
31183
+ resetError(opts) {
31184
+ this.setError(undefined, opts);
31185
+ }
31186
+ getRowError(row, opts) {
31187
+ row = row || this.dataSource.getSingleEditingRow();
31188
+ if (!row || !this.formErrorAdapter)
31189
+ return undefined;
31190
+ return this.formErrorAdapter.translateFormErrors(row.validator, Object.assign(Object.assign({}, this.errorTranslatorOptions), opts));
31191
+ }
31192
+ setError(value, opts) {
31193
+ if (this.errorSubject.value !== value) {
31194
+ this.errorSubject.next(value);
31195
+ if (!opts || opts.emitEvent !== false) {
31196
+ this.markForCheck();
31197
+ }
31198
+ }
31199
+ }
31200
+ /**
31201
+ * Compare data equality (default by id)
31202
+ * Can be overridden to add additional properties to compare
31203
+ *
31204
+ * @param d1
31205
+ * @param d2
31206
+ * @protected
31207
+ */
31208
+ equals(d1, d2) {
31209
+ return EntityUtils.equals(d1, d2, 'id');
31210
+ }
31211
+ markRowAsDirty(row, opts) {
31212
+ var _a;
31213
+ row = row || this.dataSource.getSingleEditingRow();
31214
+ if (row)
31215
+ (_a = row.validator) === null || _a === void 0 ? void 0 : _a.markAsDirty(opts);
31216
+ this.markAsDirty(opts);
31217
+ }
31218
+ /* -- private method -- */
31219
+ listenSortAndPaginationEvents() {
31220
+ return __awaiter(this, void 0, void 0, function* () {
31221
+ if (!this.table) {
31222
+ // DEBUG only -- alert user that table not found in template
31223
+ if (this.debug) {
31224
+ setTimeout(() => !this.table && console.warn(`[table] Missing <mat-table> in the HTML template (after waiting 500ms)! Component: ${this.constructor.name}`), 500);
31225
+ }
31226
+ // Make sure to wait the table
31227
+ yield waitFor(() => !!this.table, { stop: this.destroySubject, stopError: false /*avoid error when destorying the table*/ });
31228
+ }
31229
+ this.registerSubscription(merge(
31230
+ // Listen sort events
31231
+ this.sort && this.sort.sortChange
31232
+ .pipe(filter(() => !this.sort.disabled), mergeMap(() => __awaiter(this, void 0, void 0, function* () { return this.saveBeforeAction('sort'); })), filter(res => res === true),
31233
+ // Save sort in settings
31234
+ tap(() => {
31235
+ const value = [this.sort.active, this.sort.direction || 'asc'].join(':');
31236
+ this.settings.savePageSetting(this.settingsId, value, SETTINGS_SORTED_COLUMN);
31237
+ }))
31238
+ || EMPTY,
31239
+ // Listen paginator events
31240
+ this.paginator && this.paginator.page
31241
+ .pipe(mergeMap((_) => this.saveBeforeAction('sort')), filter(saved => saved === true),
31242
+ // Save page size in settings
31243
+ tap(() => this.settings.savePageSetting(this.settingsId, this.paginator.pageSize, SETTINGS_PAGE_SIZE))) || EMPTY)
31244
+ // Refresh on any sort or paginator events
31245
+ .subscribe(value => {
31246
+ this.onSort.emit(value);
31247
+ this.onRefresh.emit(value);
31248
+ }));
31249
+ // If the user changes the sort order, reset back to the first page.
31250
+ if (this.sort && this.paginator) {
31251
+ this.registerSubscription(this.sort.sortChange
31252
+ .pipe(filter(() => !this.sort.disabled))
31253
+ .subscribe(() => this.paginator.pageIndex = 0));
31254
+ }
31255
+ });
31256
+ }
31257
+ editRowById(event, id, opts) {
31258
+ return __awaiter(this, void 0, void 0, function* () {
31259
+ if (id < 0)
31260
+ return;
31261
+ if (id >= this.visibleRowCount) {
31262
+ yield this.addRow(event, undefined, Object.assign(Object.assign({}, opts), { editing: true }));
31263
+ }
31264
+ else {
31265
+ const row = yield this.dataSource.getRow(id);
31266
+ yield this.editRow(event, row, opts);
31267
+ }
31268
+ });
31269
+ }
31270
+ setLoading(value, opts) {
31271
+ if (this.loadingSubject.value !== value) {
31272
+ this.loadingSubject.next(value);
31273
+ if (!opts || opts.emitEvent !== false) {
31274
+ this.markForCheck();
31275
+ }
31276
+ }
31277
+ }
31278
+ deleteNewRow(event, row) {
31279
+ return __awaiter(this, void 0, void 0, function* () {
31280
+ if (row.id !== -1)
31281
+ throw new Error('Row must have id = -1');
31282
+ event === null || event === void 0 ? void 0 : event.stopPropagation();
31283
+ this.selection.clear();
31284
+ yield this._dataSource.cancelOrDelete(row);
31285
+ this.onCancelOrDeleteRow.next(row);
31286
+ this.resetError();
31287
+ this.totalRowCount--;
31288
+ this.visibleRowCount--;
31289
+ });
31290
+ }
31291
+ deleteExistingRow(event, row, opts) {
31292
+ return __awaiter(this, void 0, void 0, function* () {
31293
+ // Make sure row will be cancelled, and NOT deleted
31294
+ if (row.id === -1)
31295
+ throw new Error('Row must have an id');
31296
+ if (event === null || event === void 0 ? void 0 : event.defaultPrevented)
31297
+ return 0; // SKip
31298
+ event === null || event === void 0 ? void 0 : event.preventDefault();
31299
+ yield this.deleteRow(null, row, opts);
31300
+ });
31301
+ }
31302
+ cancelExistingRow(event, row, opts) {
31303
+ return __awaiter(this, void 0, void 0, function* () {
31304
+ // Make sure row will be cancelled, and NOT deleted
31305
+ if (row.id === -1 || !row.editing)
31306
+ throw new Error('Row cannot be canceling, but only deleting');
31307
+ const confirmed = (!opts || opts.interactive !== false);
31308
+ // Ask user confirmation, if cancel
31309
+ if (!confirmed && row.dirty && (this.confirmBeforeCancel || this.onBeforeCancelRows.observers.length > 0)) {
31310
+ event.stopPropagation();
31311
+ if (!(yield this.canCancelRows([row], opts))) {
31312
+ return;
31313
+ }
31314
+ }
31315
+ const keepEditing = row.editing && (!opts || opts.keepEditing !== false);
31316
+ yield this._dataSource.cancelOrDelete(row);
31317
+ this.onCancelOrDeleteRow.next(row);
31318
+ // Mark row as pristine
31319
+ yield this.checkIfRowPristine(row);
31320
+ // Restore editing state
31321
+ if (keepEditing) {
31322
+ yield this.editRow(undefined, row);
31323
+ }
31324
+ });
31325
+ }
31326
+ checkIfRowPristine(row, opts) {
31327
+ var _a, _b;
31328
+ return __awaiter(this, void 0, void 0, function* () {
31329
+ // Mark row as pristine
31330
+ const markRowAsPristine = ((_a = this.dataSource) === null || _a === void 0 ? void 0 : _a.config.restoreOriginalDataOnCancel) === true;
31331
+ if (markRowAsPristine) {
31332
+ (_b = row.validator) === null || _b === void 0 ? void 0 : _b.markAsPristine();
31333
+ // Check if table is now pristine
31334
+ if (!opts || opts.onlySelf !== true) {
31335
+ yield this.checkIfPristine(opts);
31336
+ }
31337
+ }
31338
+ });
31339
+ }
31340
+ checkIfPristine(opts) {
31341
+ return __awaiter(this, void 0, void 0, function* () {
31342
+ if (!this.dirty)
31343
+ return; // Already pristine
31344
+ const rows = this._dataSource.getRows();
31345
+ const pristine = (rows || []).findIndex(row => row.dirty) === -1;
31346
+ if (pristine)
31347
+ this.markAsPristine(opts);
31348
+ });
31349
+ }
31350
+ applyFilter(filter, opts) {
31351
+ if (this.debug)
31352
+ console.debug('[table] Applying filter', filter);
31353
+ this._filter = filter;
31354
+ if (opts && opts.emitEvent) {
31355
+ if (this.paginator && this.paginator.pageIndex > 0) {
31356
+ this.paginator.pageIndex = 0;
31357
+ }
31358
+ this.onRefresh.emit();
31359
+ }
31360
+ }
31361
+ listenDatasourceLoading(dataSource) {
31362
+ if (!dataSource)
31363
+ throw new Error('[table] dataSource not set !');
31364
+ // Cleaning previous subscription on datasource
31365
+ if (isNotNil(this._dataSourceLoadingSubscription)) {
31366
+ if (this.debug)
31367
+ console.debug('[table] Many call to listenDatasource(): Cleaning previous subscriptions...');
31368
+ this._dataSourceLoadingSubscription.unsubscribe();
31369
+ this.unregisterSubscription(this._dataSourceLoadingSubscription);
31370
+ }
31371
+ // Propage loading to table
31372
+ this._dataSourceLoadingSubscription = this._dataSource.loadingSubject
31373
+ .pipe(distinctUntilChanged(),
31374
+ // If changed to True: propagate as soon as possible
31375
+ tap((loading) => loading && this.setLoading(true)),
31376
+ // If changed to False: wait 250ms before propagate (to make sure the spinner has been displayed)
31377
+ debounceTime(250), tap(loading => !loading && this.setLoading(false)))
31378
+ .subscribe();
31379
+ this.registerSubscription(this._dataSourceLoadingSubscription);
31380
+ }
31381
+ startCellValueChanges(name, row) {
31382
+ const def = this._cellValueChangesDefs[name];
31383
+ if (!def) {
31384
+ console.warn('[table] Listener with name {' + name + '} not registered! Please call registerCellValueChanges() before;');
31385
+ return;
31386
+ }
31387
+ // Stop previous subscription
31388
+ if (def.subscription) {
31389
+ def.subscription.unsubscribe();
31390
+ def.subscription = null;
31391
+ }
31392
+ else {
31393
+ if (this.debug)
31394
+ console.debug(`[table] Start values changes on row path {${def.formPath}}`);
31395
+ }
31396
+ // Listen value changes, and redirect to event emitter
31397
+ const control = row.validator && AppFormUtils.getControlFromPath(row.validator, def.formPath);
31398
+ if (!control) {
31399
+ console.warn(`[table] Could not listen cell changes: no validator or invalid form path {${def.formPath}}`);
31400
+ }
31401
+ else {
31402
+ def.subscription = control.valueChanges
31403
+ .pipe(
31404
+ // don't emit if control is disabled
31405
+ filter(() => control.enabled))
31406
+ .subscribe((value) => def.subject.next(value));
31407
+ // Emit the actual value
31408
+ if (def.emitInitialValue !== false) {
31409
+ def.subject.next(control.value);
31410
+ }
31411
+ }
31412
+ }
31413
+ stopCellValueChanges(name, destroy) {
31414
+ const def = this._cellValueChangesDefs[name];
31415
+ if (!def)
31416
+ return;
31417
+ if (def.subscription) {
31418
+ if (this.debug)
31419
+ console.debug('[table] Stop value changes on row path {' + def.formPath + '}');
31420
+ def.subscription.unsubscribe();
31421
+ def.subscription = null;
31422
+ }
31423
+ if (destroy && def.subject) {
31424
+ def.subject.complete();
31425
+ def.subject.unsubscribe();
31426
+ }
31427
+ }
31428
+ }
31429
+ AppAsyncTable.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: AppAsyncTable, deps: "invalid", target: i0.ɵɵFactoryTarget.Directive });
31430
+ AppAsyncTable.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "14.2.12", type: AppAsyncTable, inputs: { settingsId: "settingsId", debug: "debug", i18nColumnPrefix: "i18nColumnPrefix", i18nColumnSuffix: "i18nColumnSuffix", autoLoad: "autoLoad", readOnly: "readOnly", inlineEdition: "inlineEdition", focusFirstColumn: "focusFirstColumn", confirmBeforeDelete: "confirmBeforeDelete", confirmBeforeCancel: "confirmBeforeCancel", undoableDeletion: "undoableDeletion", saveBeforeDelete: "saveBeforeDelete", keepEditedRowOnSave: "keepEditedRowOnSave", saveBeforeSort: "saveBeforeSort", saveBeforeFilter: "saveBeforeFilter", propagateRowError: "propagateRowError", defaultSortBy: "defaultSortBy", defaultSortDirection: "defaultSortDirection", defaultPageSize: "defaultPageSize", defaultPageSizeOptions: "defaultPageSizeOptions", focusColumn: "focusColumn", dataSource: "dataSource", filter: "filter", disabled: "disabled", paginator: "paginator" }, outputs: { onRefresh: "onRefresh", onOpenRow: "onOpenRow", onNewRow: "onNewRow", onStartEditingRow: "onStartEditingRow", onConfirmEditCreateRow: "onConfirmEditCreateRow", onCancelOrDeleteRow: "onCancelOrDeleteRow", onBeforeDeleteRows: "onBeforeDeleteRows", onBeforeCancelRows: "onBeforeCancelRows", onBeforeSave: "onBeforeSave", onAfterDeletedRows: "onAfterDeletedRows", onSort: "onSort", onDirty: "onDirty", onError: "onError" }, viewQueries: [{ propertyName: "table", first: true, predicate: MatTable, descendants: true }, { propertyName: "childPaginator", first: true, predicate: MatPaginator, descendants: true }, { propertyName: "sort", first: true, predicate: MatSort, descendants: true }], ngImport: i0 });
31431
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: AppAsyncTable, decorators: [{
31432
+ type: Directive
31433
+ }], ctorParameters: function () { return [{ type: i0.Injector }, { type: undefined }, { type: EntitiesAsyncTableDataSource }, { type: undefined }]; }, propDecorators: { settingsId: [{
31434
+ type: Input
31435
+ }], debug: [{
31436
+ type: Input
31437
+ }], i18nColumnPrefix: [{
31438
+ type: Input
31439
+ }], i18nColumnSuffix: [{
31440
+ type: Input
31441
+ }], autoLoad: [{
31442
+ type: Input
31443
+ }], readOnly: [{
31444
+ type: Input
31445
+ }], inlineEdition: [{
31446
+ type: Input
31447
+ }], focusFirstColumn: [{
31448
+ type: Input
31449
+ }], confirmBeforeDelete: [{
31450
+ type: Input
31451
+ }], confirmBeforeCancel: [{
31452
+ type: Input
31453
+ }], undoableDeletion: [{
31454
+ type: Input
31455
+ }], saveBeforeDelete: [{
31456
+ type: Input
31457
+ }], keepEditedRowOnSave: [{
31458
+ type: Input
31459
+ }], saveBeforeSort: [{
31460
+ type: Input
31461
+ }], saveBeforeFilter: [{
31462
+ type: Input
31463
+ }], propagateRowError: [{
31464
+ type: Input
31465
+ }], defaultSortBy: [{
31466
+ type: Input
31467
+ }], defaultSortDirection: [{
31468
+ type: Input
31469
+ }], defaultPageSize: [{
31470
+ type: Input
31471
+ }], defaultPageSizeOptions: [{
31472
+ type: Input
31473
+ }], focusColumn: [{
31474
+ type: Input
31475
+ }], dataSource: [{
31476
+ type: Input
31477
+ }], filter: [{
31478
+ type: Input
31479
+ }], onRefresh: [{
31480
+ type: Output
31481
+ }], onOpenRow: [{
31482
+ type: Output
31483
+ }], onNewRow: [{
31484
+ type: Output
31485
+ }], onStartEditingRow: [{
31486
+ type: Output
31487
+ }], onConfirmEditCreateRow: [{
31488
+ type: Output
31489
+ }], onCancelOrDeleteRow: [{
31490
+ type: Output
31491
+ }], onBeforeDeleteRows: [{
31492
+ type: Output
31493
+ }], onBeforeCancelRows: [{
31494
+ type: Output
31495
+ }], onBeforeSave: [{
31496
+ type: Output
31497
+ }], onAfterDeletedRows: [{
31498
+ type: Output
31499
+ }], onSort: [{
31500
+ type: Output
31501
+ }], onDirty: [{
31502
+ type: Output
31503
+ }], onError: [{
31504
+ type: Output
31505
+ }], disabled: [{
31506
+ type: Input
31507
+ }], paginator: [{
31508
+ type: Input
31509
+ }], table: [{
31510
+ type: ViewChild,
31511
+ args: [MatTable, { static: false }]
31512
+ }], childPaginator: [{
31513
+ type: ViewChild,
31514
+ args: [MatPaginator, { static: false }]
31515
+ }], sort: [{
31516
+ type: ViewChild,
31517
+ args: [MatSort, { static: false }]
31518
+ }] } });
31519
+
29442
31520
  // @dynamic
29443
31521
  // eslint-disable-next-line @angular-eslint/directive-class-suffix
29444
31522
  class AppInMemoryTable extends AppTable {
@@ -34097,5 +36175,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImpo
34097
36175
  * Generated bundle index. Do not edit.
34098
36176
  */
34099
36177
 
34100
- export { APP_ABOUT_DEVELOPERS, APP_ABOUT_PARTNERS, APP_CONFIG_OPTIONS, APP_FORM_ERROR_I18N_KEYS, 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_MENU_ITEMS, APP_MENU_OPTIONS, APP_STORAGE, APP_TESTING_PAGES, APP_USER_EVENT_SERVICE, AboutModal, AbstractDateFormat, AbstractUserEventService, Account, AccountPage, AccountService, AccountToStringPipe, ActionsColumnComponent, AdminModule, AdminRoutingModule, AdminUsersModule, Alerts, AndroidOsEnvironment, AnimationState, AppAboutModalModule, AppAccountModule, 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, AppRegisterModule, AppSelectPeerModule, AppSettingsPageModule, AppTabEditor, AppTabEditorOptions, AppTable, AppTableModule, AppTableUtils, AppTextPopoverModule, AppUpdateOfflineModeCard, AppUpdateOfflineModeCardModule, AppValidatorService, AppendToInputDirective, ArrayFilterPipe, ArrayFirstPipe, ArrayIncludesPipe, ArrayJoinPipe, ArrayLengthPipe, ArrayPluckPipe, AudioProvider, AudioTestingModule, AudioTestingPage, AuthGuardService, AutoTitleDirective, AutocompleteTestPage, AutofocusDirective, BadgeDirective, Base58, BaseEntityService, BaseGraphqlService, BaseGraphqlServiceOptions, BaseReferential, Beans, CORE_CONFIG_OPTIONS, CORE_TESTING_PAGES, CellValueChangeListener, ChipsTestPage, Color, ColorScale, ComponentDirtyGuard, ConfigService, Configuration, CoreModule, CoreTestingModule, CryptoService, CsvUtils, DATE_ISO_PATTERN, 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, DateTestPage, DateTimeTestPage, DateUtils, DebugComponent, Department, DepartmentToStringPipe, DragAndDropDirective, DurationPipe, ED25519_SEED_LENGTH, EMPTY_PLACEHOLDER_CHAR, ENTITIES_STORAGE_KEY_PREFIX, ENVIRONMENT, EmptyArrayPipe, EntitiesStorage, EntitiesTableDataSource, Entity, EntityClass, EntityClasses, EntityFilter, EntityFilterUtils, EntityMetadataComponent, EntityStore, EntityUtils, Environment, ErrorCodes, EvenPipe, FileResponse, FileService, FileSizePipe, FilesUtils, FormArrayHelper, FormButtonsBarComponent, FormButtonsBarToken, FormErrorTranslatePipe, FormErrorTranslator, FormFieldValuesHolder, FormGetArrayPipe, FormGetControlPipe, FormGetGroupPipe, FormGetPipe, FormGetValuePipe, Fragments, 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, IsNotNilOrBlankPipe, IsNotNilOrNaNPipe, IsNotNilPipe, IsNotOnFieldModePipe, IsOnFieldModePipe, JobModule, JobProgression, JobProgressionIcon, JobProgressionList, JobProgressionService, JobProgressionTestService, JobProgressionTestingPage, JobTestingModule, JobUtils, JsonUtils, KEYBOARD_HIDE_DELAY_MS, LAT_LONG_DEFAULT_MAX_DECIMALS, LAT_LONG_PATTERNS, LatLongFormatPipe, LatLongTestPage, LatitudeFormatPipe, LocalSettingsService, LongitudeFormatPipe, MINIFY_ENTITY_FOR_LOCAL_STORAGE, MINIFY_ENTITY_FOR_POD, MOMENT_NO_TIME_PROPERTY, MapGetPipe, MapKeysPipe, MapValuesPipe, MatAutocompleteConfigHolder, MatAutocompleteField, MatAutocompleteFieldUtils, MatBooleanField, MatChipsField, MatColorPipe, MatDate, MatDateShort, MatDateTime, MatDuration, MatLatLongField, MatNumpadComponent, MatNumpadContainerComponent, MatNumpadContent, MatPaginatorI18n, MatStepperI18n, MatSwipeField, MaterialTestingModule, MathAbsPipe, MenuComponent, MenuItems, MenuOptions, MenuService, Message, MessageFilter, MessageForm, MessageModal, MessageModule, MessageService, MessageTypeList, MessageTypes, MimeTypes, ModalToolbarComponent, NetworkService, NgInitDirective, NgVarDirective, NotEmptyArrayPipe, NumberFormatPipe, NumpadDirective, NumpadTestPage, ObservableTestPage, OddPipe, PEER_URL_REGEXP, PRIORITIZED_AUTHORITIES, PUBKEY_REGEXP, Peer, Person, PersonFilter, PersonFragments, PersonService, PersonToStringPipe, PersonUtils, PersonValidatorService, PlatformService, ProgressBarService, ProgressInterceptor, PropertiesFormTestPage, PropertiesFormTestingModule, PropertyFormatPipe, PropertyGetPipe, RESERVED_END_COLUMNS, RESERVED_START_COLUMNS, Referential, ReferentialFilter, ReferentialRef, ReferentialUtils, ReferentialValidatorService, RegisterConfirmPage, RegisterForm, RegisterModal, ResizableComponent, ResizableDirective, ResizableModule, SCRYPT_PARAMS, SETTINGS_DISPLAY_COLUMNS, SETTINGS_FILTER, SETTINGS_PAGE_SIZE, SETTINGS_SORTED_COLUMN, SETTINGS_STORAGE_KEY, SETTINGS_TRANSIENT_PROPERTIES, SHARED_MATERIAL_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, SharedMatNumpadModule, SharedMatSwipeModule, SharedMaterialModule, SharedModule, SharedPipesModule, SharedRoutingModule, SharedTestingModule, SharedTestsPage, SharedToolbarModule, SharedValidators, SocialErrorCodes, SocialModule, SocialModuleOptionsToken, SocialTestingModule, Software, StartableService, StatusById, StatusIds, StatusList, StorageDrivers, StorageService, StrIncludesPipe, StrLengthPipe, SwipeTestPage, TableSelectColumnsComponent, TableTestPage, TableTestingModule, TextForm, TextPopover, TextPopoverTestingModule, TextPopoverTestingPage, ToStringPipe, ToastTestingModule, ToastTestingPage, Toasts, ToolbarComponent, ToolbarToken, TranslatablePipe, TranslateContextPipe, TranslateContextService, UploadFile, UploadFileComponent, UploadFilePopover, UploadFileTestingModule, UploadFileTestingPage, UriUtils, UserEventModule, UserEventNotificationIcon, UserEventTestService, UserEventTestingModule, UserEventTestingPage, UserSettings, UsersPage, accountToString, adaptValueToControl, addValueInArray, arrayDistinct, arrayGroupBy, arraySize, asInputElement, canHaveFocus, capitalizeFirstLetter, chainPromises, changeCaseToUnderscore, clearValueInArray, copyEntity2Form, createPromiseEvent, createPromiseEventEmitter, departmentToString, departmentsToString, disableControls, emitPromiseEvent, entityToString, equals, equalsOrNil, escapeRegExp, fadeInAnimation, fadeInOutAnimation, filterFalse, filterNotNil, filterNumberInput, filterTrue, 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, isCordova, isEmptyArray, isIOS, isInputElement, isInstanceOf, isInt, isMobile, isNil, isNilOrBlank, isNilOrNaN, isNotEmptyArray, isNotNil, isNotNilBoolean, isNotNilOrBlank, isNotNilOrNaN, isNotNilString, isNumber, isNumberRange, isProgressEvent, isResponseEvent, isTouchUi, isWindows, joinProperties, joinPropertiesPath, logFormErrors, markAllAsTouched, markAsUntouched, markControlAsTouched, markFormGroupAsTouched, 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, setTabIndex, sleep, slideInOutAnimation, slideUpDownAnimation, sort, splitById, splitByProperty, startsWithUpperCase, suggestFromArray, suggestFromStringArray, tabindexComparator, testUserAgent, toBoolean, toDateISOString, toDuration, toFloat, toInt, toNotNil, toNumber, trimEmptyToNull, uncapitalizeFirstLetter, updateValueAndValidity, waitFor, waitForFalse, waitForTrue, waitIdle, waitWhilePending };
36178
+ export { APP_ABOUT_DEVELOPERS, APP_ABOUT_PARTNERS, APP_CONFIG_OPTIONS, APP_FORM_ERROR_I18N_KEYS, 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_MENU_ITEMS, APP_MENU_OPTIONS, APP_STORAGE, APP_TESTING_PAGES, APP_USER_EVENT_SERVICE, AboutModal, AbstractDateFormat, AbstractUserEventService, Account, AccountPage, AccountService, AccountToStringPipe, ActionsColumnComponent, AdminModule, AdminRoutingModule, AdminUsersModule, Alerts, AndroidOsEnvironment, AnimationState, 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, AppRegisterModule, AppSelectPeerModule, AppSettingsPageModule, AppTabEditor, AppTabEditorOptions, AppTable, AppTableModule, AppTableUtils, AppTextPopoverModule, AppUpdateOfflineModeCard, AppUpdateOfflineModeCardModule, AppValidatorService, AppendToInputDirective, ArrayFilterPipe, ArrayFirstPipe, ArrayIncludesPipe, ArrayJoinPipe, ArrayLengthPipe, ArrayPluckPipe, AudioProvider, AudioTestingModule, AudioTestingPage, AuthGuardService, AutoTitleDirective, AutocompleteTestPage, AutofocusDirective, BadgeDirective, Base58, BaseEntityService, BaseGraphqlService, BaseGraphqlServiceOptions, BaseReferential, Beans, CORE_CONFIG_OPTIONS, CORE_TESTING_PAGES, CellValueChangeListener, ChipsTestPage, Color, ColorScale, ComponentDirtyGuard, ConfigService, Configuration, CoreModule, CoreTestingModule, CryptoService, CsvUtils, DATE_ISO_PATTERN, 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, DateTestPage, DateTimeTestPage, DateUtils, DebugComponent, Department, DepartmentToStringPipe, DragAndDropDirective, DurationPipe, ED25519_SEED_LENGTH, EMPTY_PLACEHOLDER_CHAR, ENTITIES_STORAGE_KEY_PREFIX, ENVIRONMENT, EmptyArrayPipe, EntitiesAsyncTableDataSource, EntitiesStorage, EntitiesTableDataSource, Entity, EntityClass, EntityClasses, EntityFilter, EntityFilterUtils, EntityMetadataComponent, EntityStore, EntityUtils, Environment, ErrorCodes, EvenPipe, FileResponse, FileService, FileSizePipe, FilesUtils, FormArrayHelper, FormButtonsBarComponent, FormButtonsBarToken, FormErrorTranslatePipe, FormErrorTranslator, FormFieldValuesHolder, FormGetArrayPipe, FormGetControlPipe, FormGetGroupPipe, FormGetPipe, FormGetValuePipe, Fragments, 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, IsNotNilOrBlankPipe, IsNotNilOrNaNPipe, IsNotNilPipe, IsNotOnFieldModePipe, IsOnFieldModePipe, JobModule, JobProgression, JobProgressionIcon, JobProgressionList, JobProgressionService, JobProgressionTestService, JobProgressionTestingPage, JobTestingModule, JobUtils, JsonUtils, KEYBOARD_HIDE_DELAY_MS, LAT_LONG_DEFAULT_MAX_DECIMALS, LAT_LONG_PATTERNS, LatLongFormatPipe, LatLongTestPage, LatitudeFormatPipe, LocalSettingsService, LongitudeFormatPipe, MINIFY_ENTITY_FOR_LOCAL_STORAGE, MINIFY_ENTITY_FOR_POD, MOMENT_NO_TIME_PROPERTY, MapGetPipe, MapKeysPipe, MapValuesPipe, MatAutocompleteConfigHolder, MatAutocompleteField, MatAutocompleteFieldUtils, MatBooleanField, MatChipsField, MatColorPipe, MatDate, MatDateShort, MatDateTime, MatDuration, MatLatLongField, MatNumpadComponent, MatNumpadContainerComponent, MatNumpadContent, MatPaginatorI18n, MatStepperI18n, MatSwipeField, MaterialTestingModule, MathAbsPipe, MenuComponent, MenuItems, MenuOptions, MenuService, Message, MessageFilter, MessageForm, MessageModal, MessageModule, MessageService, MessageTypeList, MessageTypes, MimeTypes, ModalToolbarComponent, NetworkService, NgInitDirective, NgVarDirective, NotEmptyArrayPipe, NumberFormatPipe, NumpadDirective, NumpadTestPage, ObservableTestPage, OddPipe, PEER_URL_REGEXP, PRIORITIZED_AUTHORITIES, PUBKEY_REGEXP, Peer, Person, PersonFilter, PersonFragments, PersonService, PersonToStringPipe, PersonUtils, PersonValidatorService, PlatformService, ProgressBarService, ProgressInterceptor, PropertiesFormTestPage, PropertiesFormTestingModule, PropertyFormatPipe, PropertyGetPipe, RESERVED_END_COLUMNS, RESERVED_START_COLUMNS, Referential, ReferentialFilter, ReferentialRef, ReferentialUtils, ReferentialValidatorService, RegisterConfirmPage, RegisterForm, RegisterModal, ResizableComponent, ResizableDirective, ResizableModule, SCRYPT_PARAMS, SETTINGS_DISPLAY_COLUMNS, SETTINGS_FILTER, SETTINGS_PAGE_SIZE, SETTINGS_SORTED_COLUMN, SETTINGS_STORAGE_KEY, SETTINGS_TRANSIENT_PROPERTIES, SHARED_MATERIAL_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, SharedMatNumpadModule, SharedMatSwipeModule, SharedMaterialModule, SharedModule, SharedPipesModule, SharedRoutingModule, SharedTestingModule, SharedTestsPage, SharedToolbarModule, SharedValidators, SocialErrorCodes, SocialModule, SocialModuleOptionsToken, SocialTestingModule, Software, StartableService, StatusById, StatusIds, StatusList, StorageDrivers, StorageService, StrIncludesPipe, StrLengthPipe, SwipeTestPage, TableSelectColumnsComponent, TableTestPage, TableTestingModule, TextForm, TextPopover, TextPopoverTestingModule, TextPopoverTestingPage, ToStringPipe, ToastTestingModule, ToastTestingPage, Toasts, ToolbarComponent, ToolbarToken, TranslatablePipe, TranslateContextPipe, TranslateContextService, UploadFile, UploadFileComponent, UploadFilePopover, UploadFileTestingModule, UploadFileTestingPage, UriUtils, UserEventModule, UserEventNotificationIcon, UserEventTestService, UserEventTestingModule, UserEventTestingPage, UserSettings, UsersPage, accountToString, adaptValueToControl, addValueInArray, arrayDistinct, arrayGroupBy, arraySize, asInputElement, canHaveFocus, capitalizeFirstLetter, chainPromises, changeCaseToUnderscore, clearValueInArray, copyEntity2Form, createPromiseEvent, createPromiseEventEmitter, departmentToString, departmentsToString, disableControls, emitPromiseEvent, entityToString, equals, equalsOrNil, escapeRegExp, fadeInAnimation, fadeInOutAnimation, filterFalse, filterNotNil, filterNumberInput, filterTrue, 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, isCordova, isEmptyArray, isIOS, isInputElement, isInstanceOf, isInt, isMobile, isNil, isNilOrBlank, isNilOrNaN, isNotEmptyArray, isNotNil, isNotNilBoolean, isNotNilOrBlank, isNotNilOrNaN, isNotNilString, isNumber, isNumberRange, isProgressEvent, isResponseEvent, isTouchUi, isWindows, joinProperties, joinPropertiesPath, logFormErrors, markAllAsTouched, markAsUntouched, markControlAsTouched, markFormGroupAsTouched, 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, setTabIndex, sleep, slideInOutAnimation, slideUpDownAnimation, sort, splitById, splitByProperty, startsWithUpperCase, suggestFromArray, suggestFromStringArray, tabindexComparator, testUserAgent, toBoolean, toDateISOString, toDuration, toFloat, toInt, toNotNil, toNumber, trimEmptyToNull, uncapitalizeFirstLetter, updateValueAndValidity, waitFor, waitForFalse, waitForTrue, waitIdle, waitWhilePending };
34101
36179
  //# sourceMappingURL=sumaris-net.ngx-components.mjs.map