@acorex/platform 20.8.8 → 20.8.9

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.
@@ -349,65 +349,78 @@ class AXPEntityMiddleware {
349
349
  this.providedModifiers = inject(AXP_ENTITY_MODIFIER, { optional: true }) || [];
350
350
  this.providedActionPlugins = inject(AXP_ENTITY_ACTION_PLUGIN, { optional: true }) || [];
351
351
  this.injector = inject(Injector);
352
- for (const { entityName, modifier } of this.providedModifiers) {
353
- this.register(entityName, modifier);
352
+ for (const { entityName, modifier, order } of this.providedModifiers) {
353
+ this.register(entityName, modifier, order);
354
354
  }
355
355
  }
356
356
  //#endregion
357
357
  //#region ---- Registration Methods ----
358
- register(entityName, modifier) {
358
+ register(entityName, modifier, order) {
359
+ const resolvedOrder = order ?? 0;
359
360
  if (entityName instanceof RegExp) {
360
- this.patternModifiers.push({ pattern: this.normalizeRegExp(entityName), modifier });
361
+ this.patternModifiers.push({ pattern: this.normalizeRegExp(entityName), modifier, order: resolvedOrder });
361
362
  return;
362
363
  }
363
364
  if (entityName.includes('*')) {
364
365
  const pattern = this.wildcardToRegExp(entityName);
365
- this.patternModifiers.push({ pattern, modifier });
366
+ this.patternModifiers.push({ pattern, modifier, order: resolvedOrder });
366
367
  return;
367
368
  }
368
- this.exactModifiers.set(entityName, modifier);
369
+ this.exactModifiers.set(entityName, { modifier, order: resolvedOrder });
369
370
  }
370
371
  //#endregion
371
372
  //#region ---- Processing ----
372
373
  async process(entity) {
373
- // First, expand action plugins if entity.plugins exists
374
374
  const context = createModifierContext(entity);
375
- const plugins = entity.plugins;
376
- if (plugins && plugins.length) {
377
- const sorted = [...this.providedActionPlugins].sort((a, b) => (a.order ?? 0) - (b.order ?? 0));
378
- for (const p of plugins) {
379
- const contrib = sorted.find((x) => x.name === p.name);
380
- if (contrib) {
381
- try {
382
- await runInInjectionContext(this.injector, () => contrib.apply(context, p.options));
383
- }
384
- catch (err) {
385
- console.error('[AXPEntityMiddleware] action plugin failed:', p.name, err);
386
- }
387
- }
388
- }
389
- }
390
- // Then apply entity-specific modifiers
391
- // Collect all matching modifiers
392
- const modifiers = [];
393
- // Exact match first
375
+ const steps = [];
394
376
  const exact = this.exactModifiers.get(entity.name);
395
377
  if (exact) {
396
- modifiers.push(exact);
378
+ steps.push(this.createModifierStep(exact, context));
397
379
  }
398
- // Then all pattern matches
399
- for (const { pattern, modifier } of this.patternModifiers) {
400
- if (pattern.test(entity.name)) {
401
- modifiers.push(modifier);
380
+ for (const entry of this.patternModifiers) {
381
+ if (entry.pattern.test(entity.name)) {
382
+ steps.push(this.createModifierStep(entry, context));
402
383
  }
403
384
  }
404
- // Apply all matching modifiers in order
405
- for (const modifier of modifiers) {
406
- runInInjectionContext(this.injector, () => modifier(context));
385
+ const entityPlugins = entity.plugins ?? [];
386
+ for (const pluginRef of entityPlugins) {
387
+ const contrib = this.providedActionPlugins.find((x) => x.name === pluginRef.name);
388
+ if (contrib) {
389
+ steps.push(this.createPluginStep(contrib, pluginRef.name, context));
390
+ }
391
+ }
392
+ const sorted = steps.sort((a, b) => a.order - b.order);
393
+ for (const step of sorted) {
394
+ try {
395
+ await runInInjectionContext(this.injector, step.run);
396
+ }
397
+ catch (err) {
398
+ console.error('[AXPEntityMiddleware] entity processing step failed:', err);
399
+ }
407
400
  }
408
401
  return context.toEntity();
409
402
  }
410
403
  //#endregion
404
+ //#region ---- Step Factories ----
405
+ createModifierStep(entry, context) {
406
+ return {
407
+ order: entry.order,
408
+ run: () => entry.modifier(context),
409
+ };
410
+ }
411
+ createPluginStep(contrib, pluginName, context) {
412
+ return {
413
+ order: contrib.order ?? 0,
414
+ run: async () => {
415
+ const pluginRef = context.plugins.find(pluginName).get();
416
+ if (!pluginRef) {
417
+ return;
418
+ }
419
+ await contrib.apply(context, pluginRef.options);
420
+ },
421
+ };
422
+ }
423
+ //#endregion
411
424
  //#region ---- Helpers ----
412
425
  wildcardToRegExp(pattern) {
413
426
  const escaped = pattern.replace(/[.+?^${}()|\[\]\\]/g, '\\$&');
@@ -3307,6 +3320,118 @@ const AXPEntityEventsKeys = {
3307
3320
  REFRESH_DATA: 'entity:refresh-data',
3308
3321
  };
3309
3322
 
3323
+ /**
3324
+ * Resolves a stable row id from entity list row data.
3325
+ */
3326
+ function getEntityListRowId(data, key = 'id') {
3327
+ const value = data[key];
3328
+ if (value != null && value !== '') {
3329
+ return String(value);
3330
+ }
3331
+ return '';
3332
+ }
3333
+ /**
3334
+ * Finds row data in a hierarchical grid tree (root rows and nested children).
3335
+ */
3336
+ function findEntityListRowDataInTree(items, id, key) {
3337
+ for (const item of items) {
3338
+ if (item && typeof item === 'object' && String(item[key]) === id) {
3339
+ return item;
3340
+ }
3341
+ const rec = item;
3342
+ const metaChildren = rec?.['__meta__']?.['children'];
3343
+ const directChildren = rec?.['children'];
3344
+ const childArr = Array.isArray(metaChildren)
3345
+ ? metaChildren
3346
+ : Array.isArray(directChildren)
3347
+ ? directChildren
3348
+ : null;
3349
+ if (childArr?.length) {
3350
+ const found = findEntityListRowDataInTree(childArr, id, key);
3351
+ if (found) {
3352
+ return found;
3353
+ }
3354
+ }
3355
+ }
3356
+ return null;
3357
+ }
3358
+ /**
3359
+ * Restores expanded rows after data load (parents before children).
3360
+ */
3361
+ async function restoreEntityListExpandedRows(options) {
3362
+ const pending = [...new Set(options.expandedRowIds.filter(Boolean))];
3363
+ if (!pending.length) {
3364
+ return;
3365
+ }
3366
+ let safety = 0;
3367
+ const maxPasses = Math.max(pending.length * 3, 10);
3368
+ while (pending.length > 0 && safety++ < maxPasses) {
3369
+ const rows = options.getDisplayedRows();
3370
+ let progressed = false;
3371
+ for (let i = pending.length - 1; i >= 0; i--) {
3372
+ const id = pending[i];
3373
+ const item = findEntityListRowDataInTree(rows, id, options.rowKey);
3374
+ if (!item) {
3375
+ continue;
3376
+ }
3377
+ const meta = item['__meta__'];
3378
+ if (meta?.['expanded'] !== true) {
3379
+ await options.expandRow({ data: item });
3380
+ }
3381
+ pending.splice(i, 1);
3382
+ progressed = true;
3383
+ }
3384
+ if (!progressed) {
3385
+ break;
3386
+ }
3387
+ }
3388
+ }
3389
+
3390
+ /**
3391
+ * Applies take/skip to the data source without triggering {@link AXDataSource.load}.
3392
+ */
3393
+ function applyDataSourcePagingWithoutLoad(dataSource, paging) {
3394
+ const take = Math.max(1, paging.take);
3395
+ const skip = Math.max(0, paging.skip);
3396
+ const page = Math.floor(skip / take);
3397
+ const ds = dataSource;
3398
+ dataSource.config.pageSize = take;
3399
+ if (ds._query) {
3400
+ ds._query.take = take;
3401
+ ds._query.skip = skip;
3402
+ }
3403
+ ds._page = page;
3404
+ }
3405
+ function getDataSourcePageIndex(dataSource) {
3406
+ const ds = dataSource;
3407
+ return ds._page ?? 0;
3408
+ }
3409
+ function normalizeListPaging(paging, defaultTake) {
3410
+ const take = typeof paging?.take === 'number' && paging.take > 0 ? paging.take : defaultTake;
3411
+ const skip = typeof paging?.skip === 'number' && paging.skip >= 0 ? paging.skip : 0;
3412
+ return { take, skip };
3413
+ }
3414
+
3415
+ const AXPEntityListPersistenceModeDefault = 'persistent';
3416
+ function normalizeEntityListPersistenceMode(value) {
3417
+ if (value === 'none' || value === 'persistent' || value === 'route') {
3418
+ return value;
3419
+ }
3420
+ return AXPEntityListPersistenceModeDefault;
3421
+ }
3422
+ function canPersistEntityListState(mode) {
3423
+ return mode !== 'none';
3424
+ }
3425
+ /** `none` never reads list state from user settings. */
3426
+ function shouldLoadEntityListStateFromStorage(mode) {
3427
+ return mode !== 'none';
3428
+ }
3429
+ /** `route` clears stored list state when the route entity (module + name) changes. */
3430
+ function shouldResetEntityListStateOnRouteEntry(mode) {
3431
+ return mode === 'route';
3432
+ }
3433
+ const ENTITY_LIST_ROUTE_CONTEXT_SESSION_KEY = 'axp-entity-list-route-context';
3434
+
3310
3435
  /**
3311
3436
  * Entity Event Dispatcher - A wrapper for entity-specific events
3312
3437
  * Handles pattern-based dispatching for entity operations with wildcard support
@@ -3606,14 +3731,17 @@ class AXPEntityMasterListViewModel {
3606
3731
  return `${resolvedCommand}${suffix}`;
3607
3732
  }
3608
3733
  async setView(viewName = null) {
3609
- const entitySetting = await this.settings.get(this.settingEntityKey);
3610
- const selectedViewName = entitySetting?.list?.currentView;
3734
+ let selectedViewName;
3735
+ if (await this.shouldLoadPersistedListState()) {
3736
+ const entitySetting = await this.settings.get(this.settingEntityKey);
3737
+ selectedViewName = entitySetting?.list?.currentView;
3738
+ }
3611
3739
  if (viewName != this.view().name) {
3612
3740
  this.view.set(this.views().find((c) => c.name == (viewName || selectedViewName)) ?? this.views()[0]);
3613
3741
  this.applyViewSorts();
3614
3742
  this.applyViewColumns();
3615
3743
  this.applyViewFilters();
3616
- // this.applyFilterAndSort();
3744
+ this.resolvedListPaging.set(null);
3617
3745
  await this.applySettings();
3618
3746
  }
3619
3747
  }
@@ -3637,6 +3765,15 @@ class AXPEntityMasterListViewModel {
3637
3765
  this.lastAppliedSortKey = null;
3638
3766
  this.lastAppliedFilterKey = null;
3639
3767
  this.hasQueryParamsFilters = false; // Flag to prevent overriding queryParams filters
3768
+ /** Persisted expanded row ids for hierarchical lists (per view). */
3769
+ this.expandedRowIds = signal([], ...(ngDevMode ? [{ debugName: "expandedRowIds" }] : []));
3770
+ /** When true, row expand/collapse is not written to user settings (restore in progress). */
3771
+ this.skipExpandedRowPersistence = false;
3772
+ /** Resolved take/skip for the current view (null until loaded from settings). */
3773
+ this.resolvedListPaging = signal(null, ...(ngDevMode ? [{ debugName: "resolvedListPaging" }] : []));
3774
+ /** When true, pager changes are not persisted (programmatic UI sync). */
3775
+ this.skipListPagingPersistence = false;
3776
+ this.listPersistenceMode = null;
3640
3777
  this.events$ = new Subject();
3641
3778
  //****************** Views ******************//
3642
3779
  this.views = computed(() => {
@@ -3830,12 +3967,70 @@ class AXPEntityMasterListViewModel {
3830
3967
  this.showRowIndexColumnEnabled.set(false);
3831
3968
  }
3832
3969
  }
3970
+ /**
3971
+ * Applies {@link AXPCommonSettings.EntityListPersistenceMode} for this list instance.
3972
+ * Call once when the list view model is created (before loading list UI state).
3973
+ */
3974
+ async initializeListPersistence() {
3975
+ const mode = await this.getListPersistenceMode();
3976
+ debugger;
3977
+ if (!shouldResetEntityListStateOnRouteEntry(mode)) {
3978
+ return;
3979
+ }
3980
+ const routeKey = this.settingEntityKey;
3981
+ let previousRouteKey = null;
3982
+ try {
3983
+ previousRouteKey = sessionStorage.getItem(ENTITY_LIST_ROUTE_CONTEXT_SESSION_KEY);
3984
+ }
3985
+ catch {
3986
+ previousRouteKey = null;
3987
+ }
3988
+ if (previousRouteKey !== routeKey) {
3989
+ await this.clearEntityListSettings();
3990
+ try {
3991
+ sessionStorage.setItem(ENTITY_LIST_ROUTE_CONTEXT_SESSION_KEY, routeKey);
3992
+ }
3993
+ catch {
3994
+ // sessionStorage may be unavailable
3995
+ }
3996
+ }
3997
+ }
3998
+ async getListPersistenceMode() {
3999
+ if (this.listPersistenceMode != null) {
4000
+ return this.listPersistenceMode;
4001
+ }
4002
+ const value = await this.settings.get(AXPCommonSettings.EntityListPersistenceMode);
4003
+ this.listPersistenceMode = normalizeEntityListPersistenceMode(value);
4004
+ return this.listPersistenceMode;
4005
+ }
4006
+ async shouldLoadPersistedListState() {
4007
+ return shouldLoadEntityListStateFromStorage(await this.getListPersistenceMode());
4008
+ }
4009
+ async shouldPersistListState() {
4010
+ return canPersistEntityListState(await this.getListPersistenceMode());
4011
+ }
4012
+ async clearEntityListSettings() {
4013
+ await this.settings.scope(AXPPlatformScope.User).update(this.settingEntityKey, (prev) => {
4014
+ if (!prev || typeof prev !== 'object') {
4015
+ return {};
4016
+ }
4017
+ const next = { ...prev };
4018
+ delete next['list'];
4019
+ return next;
4020
+ });
4021
+ }
3833
4022
  async applySettings() {
3834
- this.saveSettings('view');
4023
+ if (await this.shouldPersistListState()) {
4024
+ this.saveSettings('view');
4025
+ }
4026
+ if (!(await this.shouldLoadPersistedListState())) {
4027
+ this.loadListPagingFromViewSettings(null);
4028
+ this.expandedRowIds.set([]);
4029
+ return;
4030
+ }
3835
4031
  const listViewSetting = await this.settings.get(this.settingEntityKey);
3836
4032
  if (listViewSetting) {
3837
4033
  const columns = listViewSetting.list?.views?.[this.view().name]?.columns;
3838
- const pageSize = listViewSetting.list?.views?.[this.view().name]?.pageSize;
3839
4034
  const sorts = listViewSetting.list?.views?.[this.view().name]?.sorts;
3840
4035
  const filters = listViewSetting.list?.views?.[this.view().name]?.filters;
3841
4036
  let columnVisibilityMap;
@@ -3844,7 +4039,7 @@ class AXPEntityMasterListViewModel {
3844
4039
  columnVisibilityMap = new Map(columns.map((col) => [col.name, col.visible]));
3845
4040
  columnWidthsMap = new Map(columns.map((col) => [col.name, col.width]));
3846
4041
  }
3847
- // Do not set pageSize here to avoid triggering an extra load
4042
+ this.loadListPagingFromViewSettings(listViewSetting);
3848
4043
  if (columns && columnVisibilityMap && columnWidthsMap) {
3849
4044
  this.columns.update((prev) => prev
3850
4045
  .map((c) => {
@@ -3866,16 +4061,102 @@ class AXPEntityMasterListViewModel {
3866
4061
  if (Array.isArray(filters) && !this.hasQueryParamsFilters) {
3867
4062
  this.filterQueries.set(filters);
3868
4063
  }
4064
+ const expandedRowIds = listViewSetting.list?.views?.[this.view().name]?.expandedRowIds;
4065
+ if (Array.isArray(expandedRowIds)) {
4066
+ this.expandedRowIds.set(expandedRowIds.map((id) => String(id)).filter(Boolean));
4067
+ }
4068
+ else {
4069
+ this.expandedRowIds.set([]);
4070
+ }
4071
+ }
4072
+ else {
4073
+ this.loadListPagingFromViewSettings(null);
4074
+ }
4075
+ }
4076
+ async ensureListPagingResolved() {
4077
+ if (this.resolvedListPaging() != null) {
4078
+ return;
4079
+ }
4080
+ if (!(await this.shouldLoadPersistedListState())) {
4081
+ this.loadListPagingFromViewSettings(null);
4082
+ return;
4083
+ }
4084
+ const entitySetting = await this.settings.get(this.settingEntityKey);
4085
+ this.loadListPagingFromViewSettings(entitySetting);
4086
+ }
4087
+ getResolvedListPaging() {
4088
+ return (this.resolvedListPaging() ??
4089
+ normalizeListPaging(undefined, this.view().pageSize || this.dataSource.config.pageSize || 10));
4090
+ }
4091
+ applyPagingToDataSourceWithoutLoad() {
4092
+ applyDataSourcePagingWithoutLoad(this.dataSource, this.getResolvedListPaging());
4093
+ }
4094
+ saveListPaging(take, skip) {
4095
+ const paging = normalizeListPaging({ take, skip }, this.view().pageSize || 10);
4096
+ this.resolvedListPaging.set(paging);
4097
+ this.saveSettings('listPaging', paging);
4098
+ }
4099
+ resetListPagingSkip() {
4100
+ const paging = normalizeListPaging({ take: this.getResolvedListPaging().take, skip: 0 }, this.view().pageSize || 10);
4101
+ this.resolvedListPaging.set(paging);
4102
+ this.saveSettings('listPaging', paging);
4103
+ }
4104
+ loadListPagingFromViewSettings(entitySetting) {
4105
+ const viewSettings = entitySetting?.list?.views?.[this.view().name];
4106
+ const defaultTake = this.view().pageSize || 10;
4107
+ let paging = viewSettings?.paging;
4108
+ if (!paging && typeof viewSettings?.pageSize === 'number') {
4109
+ paging = { take: viewSettings.pageSize, skip: 0 };
4110
+ }
4111
+ this.resolvedListPaging.set(normalizeListPaging(paging, defaultTake));
4112
+ }
4113
+ getExpandedRowIds() {
4114
+ return this.expandedRowIds();
4115
+ }
4116
+ /**
4117
+ * Updates persisted expanded row ids when the user expands or collapses a tree row.
4118
+ */
4119
+ updateExpandedRowId(rowId, expanded) {
4120
+ if (!rowId || !this.parentKey()) {
4121
+ return;
4122
+ }
4123
+ const next = new Set(this.expandedRowIds());
4124
+ if (expanded) {
4125
+ next.add(rowId);
4126
+ }
4127
+ else {
4128
+ next.delete(rowId);
4129
+ }
4130
+ const ids = Array.from(next);
4131
+ this.expandedRowIds.set(ids);
4132
+ this.saveSettings('expandedRows', ids);
4133
+ }
4134
+ handleRowExpandChange(rowData) {
4135
+ if (this.skipExpandedRowPersistence || !this.parentKey()) {
4136
+ return;
4137
+ }
4138
+ const key = this.dataSource.config?.key ?? 'id';
4139
+ const rowId = getEntityListRowId(rowData, key);
4140
+ if (!rowId) {
4141
+ return;
3869
4142
  }
4143
+ // onItemExpanded fires before the grid toggles __meta__.expanded on expandedItem.
4144
+ const meta = rowData['__meta__'];
4145
+ const wasExpanded = meta?.['expanded'] === true;
4146
+ this.updateExpandedRowId(rowId, !wasExpanded);
3870
4147
  }
3871
4148
  async saveSettings(changesType, data) {
4149
+ if (!(await this.shouldPersistListState())) {
4150
+ return;
4151
+ }
3872
4152
  const updateSettings = (updateFn) => {
3873
4153
  this.settings.scope(AXPPlatformScope.User).update(this.settingEntityKey, updateFn);
3874
4154
  };
3875
4155
  switch (changesType) {
3876
- case 'columnSizes':
4156
+ case 'columnSizes': {
4157
+ const columnSizeData = data;
3877
4158
  updateSettings((prev) => {
3878
- const field = data.dataField.split('-')[1];
4159
+ const field = columnSizeData.dataField.split('-')[1];
3879
4160
  const newSettings = { ...prev };
3880
4161
  const existingColumns = prev?.list?.views?.[this.view().name]?.columns;
3881
4162
  const baseColumns = Array.isArray(existingColumns) && existingColumns.length
@@ -3887,7 +4168,7 @@ class AXPEntityMasterListViewModel {
3887
4168
  }));
3888
4169
  const updatedColumns = baseColumns.map((c) => ({
3889
4170
  ...c,
3890
- width: c.name === field ? data.width : c.width,
4171
+ width: c.name === field ? columnSizeData.width : c.width,
3891
4172
  }));
3892
4173
  const x = this.allAvailableColumns().map((c) => ({
3893
4174
  name: c.column?.options?.dataPath ?? c.name,
@@ -3899,10 +4180,12 @@ class AXPEntityMasterListViewModel {
3899
4180
  return newSettings;
3900
4181
  });
3901
4182
  break;
3902
- case 'columnOrders':
4183
+ }
4184
+ case 'columnOrders': {
4185
+ const orderedColumns = data;
3903
4186
  updateSettings((prev) => {
3904
4187
  const newSettings = { ...prev };
3905
- set(newSettings, `list.views.${this.view().name}.columns`, data.map((c) => ({
4188
+ set(newSettings, `list.views.${this.view().name}.columns`, orderedColumns.map((c) => ({
3906
4189
  name: c.column?.options?.dataPath ?? c.name,
3907
4190
  visible: c.visible,
3908
4191
  width: c.width,
@@ -3910,6 +4193,7 @@ class AXPEntityMasterListViewModel {
3910
4193
  return newSettings;
3911
4194
  });
3912
4195
  break;
4196
+ }
3913
4197
  case 'view':
3914
4198
  updateSettings((prev) => ({
3915
4199
  ...prev,
@@ -3929,6 +4213,26 @@ class AXPEntityMasterListViewModel {
3929
4213
  [this.view().name]: {
3930
4214
  ...prev?.list?.views?.[this.view().name],
3931
4215
  pageSize: data,
4216
+ paging: normalizeListPaging({
4217
+ take: data,
4218
+ skip: prev?.list?.views?.[this.view().name]?.paging?.skip,
4219
+ }, this.view().pageSize || 10),
4220
+ },
4221
+ },
4222
+ },
4223
+ }));
4224
+ break;
4225
+ case 'listPaging':
4226
+ updateSettings((prev) => ({
4227
+ ...prev,
4228
+ list: {
4229
+ ...prev?.list,
4230
+ views: {
4231
+ ...prev?.list?.views,
4232
+ [this.view().name]: {
4233
+ ...prev?.list?.views?.[this.view().name],
4234
+ paging: data,
4235
+ pageSize: data.take,
3932
4236
  },
3933
4237
  },
3934
4238
  },
@@ -3964,6 +4268,21 @@ class AXPEntityMasterListViewModel {
3964
4268
  },
3965
4269
  }));
3966
4270
  break;
4271
+ case 'expandedRows':
4272
+ updateSettings((prev) => ({
4273
+ ...prev,
4274
+ list: {
4275
+ ...prev?.list,
4276
+ views: {
4277
+ ...prev?.list?.views,
4278
+ [this.view().name]: {
4279
+ ...prev?.list?.views?.[this.view().name],
4280
+ expandedRowIds: data,
4281
+ },
4282
+ },
4283
+ },
4284
+ }));
4285
+ break;
3967
4286
  default:
3968
4287
  break;
3969
4288
  }
@@ -4200,6 +4519,7 @@ class AXPEntityMasterListViewModel {
4200
4519
  this.applyViewFilters();
4201
4520
  }
4202
4521
  async applyFilterAndSort() {
4522
+ await this.ensureListPagingResolved();
4203
4523
  const sorts = this.sortedFields()
4204
4524
  .filter((sf) => sf.dir)
4205
4525
  .map((s) => ({ name: s.name, dir: s.dir }));
@@ -4209,10 +4529,12 @@ class AXPEntityMasterListViewModel {
4209
4529
  if (sortKey === this.lastAppliedSortKey && filterKey === this.lastAppliedFilterKey) {
4210
4530
  return; // No effective change; avoid redundant refresh
4211
4531
  }
4212
- // Determine if filters changed (for pagination reset)
4213
- const filtersChanged = filterKey !== this.lastAppliedFilterKey;
4532
+ const filtersChanged = this.lastAppliedFilterKey != null && filterKey !== this.lastAppliedFilterKey;
4214
4533
  this.lastAppliedSortKey = sortKey;
4215
4534
  this.lastAppliedFilterKey = filterKey;
4535
+ if (filtersChanged) {
4536
+ this.resetListPagingSkip();
4537
+ }
4216
4538
  this.dataSource.clearFilter();
4217
4539
  this.dataSource.sort(...sorts.map((s) => ({ dir: s.dir, field: s.name })));
4218
4540
  this.dataSource.filter(this.filterOperatorMiddleware.transformFilter({
@@ -4386,7 +4708,9 @@ class AXPEntityListViewModelFactory {
4386
4708
  this.layout.setNavigationLoading(true);
4387
4709
  const config = await this.entityService.resolve(moduleName, entityName);
4388
4710
  this.layout.setNavigationLoading(false);
4389
- return new AXPEntityMasterListViewModel(this.injector, config);
4711
+ const vm = new AXPEntityMasterListViewModel(this.injector, config);
4712
+ await vm.initializeListPersistence();
4713
+ return vm;
4390
4714
  }
4391
4715
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: AXPEntityListViewModelFactory, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
4392
4716
  static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: AXPEntityListViewModelFactory, providedIn: 'root' }); }
@@ -7371,6 +7695,7 @@ const AXPCrudModifier = {
7371
7695
  if (!queries?.list) {
7372
7696
  queries.list = {
7373
7697
  execute: async (e) => {
7698
+ console.log(e, 'e', ctx.name.get(), ctx.module.get());
7374
7699
  return await dataService.query(e);
7375
7700
  },
7376
7701
  type: AXPEntityQueryType.List,
@@ -16437,5 +16762,5 @@ function detectEntityChanges(oldObj, newObj) {
16437
16762
  * Generated bundle index. Do not edit.
16438
16763
  */
16439
16764
 
16440
- export { AXMEntityCrudService, AXMEntityCrudServiceImpl, AXPCategoryTreeService, AXPCreateEntityCommand, AXPCreateEntityWorkflow, AXPDataSeederService, AXPDeleteEntityWorkflow, AXPEntitiesListDataSourceDefinition, AXPEntityApplyUpdatesAction, AXPEntityCategoryTreeSelectorComponent, AXPEntityCategoryWidget, AXPEntityCategoryWidgetColumnComponent, AXPEntityCategoryWidgetEditComponent, AXPEntityCategoryWidgetViewComponent, AXPEntityCommandTriggerViewModel, AXPEntityCreateEvent, AXPEntityCreatePopupAction, AXPEntityCreateSubmittedAction, AXPEntityCreateViewElementViewModel, AXPEntityCreateViewModelFactory, AXPEntityCreateViewSectionViewModel, AXPEntityDataProvider, AXPEntityDataProviderImpl, AXPEntityDataSelectorService, AXPEntityDefinitionRegistryService, AXPEntityDeletedEvent, AXPEntityDetailListViewModel, AXPEntityDetailPopoverComponent, AXPEntityDetailPopoverService, AXPEntityDetailViewModelFactory, AXPEntityDetailViewModelResolver, AXPEntityEventDispatcherService, AXPEntityEventsKeys, AXPEntityFormBuilderService, AXPEntityListTableService, AXPEntityListToolbarService, AXPEntityListViewColumnViewModel, AXPEntityListViewModelFactory, AXPEntityListViewModelResolver, AXPEntityListWidget, AXPEntityListWidgetViewComponent, AXPEntityMasterCreateViewModel, AXPEntityMasterListViewModel, AXPEntityMasterListViewQueryViewModel, AXPEntityMasterSingleElementViewModel, AXPEntityMasterSingleViewGroupViewModel, AXPEntityMasterSingleViewModel, AXPEntityMasterUpdateElementViewModel, AXPEntityMasterUpdateViewModel, AXPEntityMasterUpdateViewModelFactory, AXPEntityMiddleware, AXPEntityModifyConfirmedAction, AXPEntityModifyEvent, AXPEntityModifySectionPopupAction, AXPEntityModule, AXPEntityPerformDeleteAction, AXPEntityPreloadFiltersContainerComponent, AXPEntityPreloadFiltersViewModel, AXPEntityPreloadFiltersViewModelResolver, AXPEntityResolver, AXPEntityService, AXPEntityStorageService, AXPEntityUpdateViewSectionViewModel, AXPGetEntityDetailsQuery, AXPLayoutOrderingConfigService, AXPLookupWidget, AXPLookupWidgetColumnComponent, AXPLookupWidgetEditComponent, AXPLookupWidgetViewComponent, AXPMiddlewareAbortError, AXPMiddlewareEntityStorageService, AXPModifyEntitySectionWorkflow, AXPMultiSourceDefinitionProviderContext, AXPMultiSourceDefinitionProviderService, AXPMultiSourceFederatedSearchService, AXPMultiSourceSelectorComponent, AXPMultiSourceSelectorService, AXPMultiSourceSelectorWidget, AXPMultiSourceSelectorWidgetColumnComponent, AXPMultiSourceSelectorWidgetEditComponent, AXPMultiSourceSelectorWidgetViewComponent, AXPMultiSourceType, AXPOpenEntityDetailsCommand, AXPQuickEntityModifyPopupAction, AXPQuickModifyEntityWorkflow, AXPShowDetailViewAction, AXPShowDetailsViewWorkflow, AXPShowListViewAction, AXPShowListViewWorkflow, AXPTruncatedBreadcrumbComponent, AXPUpdateEntityCommand, AXPViewEntityDetailsCommand, AXP_DATA_SEEDER_TOKEN, AXP_ENTITY_ACTION_PLUGIN, AXP_ENTITY_CONFIG_TOKEN, AXP_ENTITY_DEFINITION_LOADER, AXP_ENTITY_MODIFIER, AXP_ENTITY_STORAGE_BACKEND, AXP_ENTITY_STORAGE_MIDDLEWARE, AXP_MULTI_SOURCE_DEFINITION_PROVIDER, DEFAULT_PROPERTY_ORDER, DEFAULT_SECTION_ORDER, EntityBuilder, EntityDataAccessor, actionExists, cloneLayoutArrays, columnWidthMiddleware, columnWidthMiddlewareProvider, createLayoutOrderingMiddlewareProvider, createModifierContext, detectEntityChanges, ensureLayoutPropertyView, ensureLayoutSection, ensureListActions, entityDetailsCreateActions, entityDetailsCrudActions, entityDetailsEditAction, entityDetailsNewEditAction, entityDetailsReferenceCondition, entityDetailsReferenceCreateActions, entityDetailsSimpleCondition, entityMasterBulkDeleteAction, entityMasterCreateAction, entityMasterCrudActions, entityMasterDeleteAction, entityMasterEditAction, entityMasterRecordActions, entityMasterViewAction, entityOverrideDetailsViewAction, eventDispatchMiddleware, isAXPMiddlewareAbortError, layoutOrderingMiddlewareFactory, layoutOrderingMiddlewareProvider };
16765
+ export { AXMEntityCrudService, AXMEntityCrudServiceImpl, AXPCategoryTreeService, AXPCreateEntityCommand, AXPCreateEntityWorkflow, AXPDataSeederService, AXPDeleteEntityWorkflow, AXPEntitiesListDataSourceDefinition, AXPEntityApplyUpdatesAction, AXPEntityCategoryTreeSelectorComponent, AXPEntityCategoryWidget, AXPEntityCategoryWidgetColumnComponent, AXPEntityCategoryWidgetEditComponent, AXPEntityCategoryWidgetViewComponent, AXPEntityCommandTriggerViewModel, AXPEntityCreateEvent, AXPEntityCreatePopupAction, AXPEntityCreateSubmittedAction, AXPEntityCreateViewElementViewModel, AXPEntityCreateViewModelFactory, AXPEntityCreateViewSectionViewModel, AXPEntityDataProvider, AXPEntityDataProviderImpl, AXPEntityDataSelectorService, AXPEntityDefinitionRegistryService, AXPEntityDeletedEvent, AXPEntityDetailListViewModel, AXPEntityDetailPopoverComponent, AXPEntityDetailPopoverService, AXPEntityDetailViewModelFactory, AXPEntityDetailViewModelResolver, AXPEntityEventDispatcherService, AXPEntityEventsKeys, AXPEntityFormBuilderService, AXPEntityListPersistenceModeDefault, AXPEntityListTableService, AXPEntityListToolbarService, AXPEntityListViewColumnViewModel, AXPEntityListViewModelFactory, AXPEntityListViewModelResolver, AXPEntityListWidget, AXPEntityListWidgetViewComponent, AXPEntityMasterCreateViewModel, AXPEntityMasterListViewModel, AXPEntityMasterListViewQueryViewModel, AXPEntityMasterSingleElementViewModel, AXPEntityMasterSingleViewGroupViewModel, AXPEntityMasterSingleViewModel, AXPEntityMasterUpdateElementViewModel, AXPEntityMasterUpdateViewModel, AXPEntityMasterUpdateViewModelFactory, AXPEntityMiddleware, AXPEntityModifyConfirmedAction, AXPEntityModifyEvent, AXPEntityModifySectionPopupAction, AXPEntityModule, AXPEntityPerformDeleteAction, AXPEntityPreloadFiltersContainerComponent, AXPEntityPreloadFiltersViewModel, AXPEntityPreloadFiltersViewModelResolver, AXPEntityResolver, AXPEntityService, AXPEntityStorageService, AXPEntityUpdateViewSectionViewModel, AXPGetEntityDetailsQuery, AXPLayoutOrderingConfigService, AXPLookupWidget, AXPLookupWidgetColumnComponent, AXPLookupWidgetEditComponent, AXPLookupWidgetViewComponent, AXPMiddlewareAbortError, AXPMiddlewareEntityStorageService, AXPModifyEntitySectionWorkflow, AXPMultiSourceDefinitionProviderContext, AXPMultiSourceDefinitionProviderService, AXPMultiSourceFederatedSearchService, AXPMultiSourceSelectorComponent, AXPMultiSourceSelectorService, AXPMultiSourceSelectorWidget, AXPMultiSourceSelectorWidgetColumnComponent, AXPMultiSourceSelectorWidgetEditComponent, AXPMultiSourceSelectorWidgetViewComponent, AXPMultiSourceType, AXPOpenEntityDetailsCommand, AXPQuickEntityModifyPopupAction, AXPQuickModifyEntityWorkflow, AXPShowDetailViewAction, AXPShowDetailsViewWorkflow, AXPShowListViewAction, AXPShowListViewWorkflow, AXPTruncatedBreadcrumbComponent, AXPUpdateEntityCommand, AXPViewEntityDetailsCommand, AXP_DATA_SEEDER_TOKEN, AXP_ENTITY_ACTION_PLUGIN, AXP_ENTITY_CONFIG_TOKEN, AXP_ENTITY_DEFINITION_LOADER, AXP_ENTITY_MODIFIER, AXP_ENTITY_STORAGE_BACKEND, AXP_ENTITY_STORAGE_MIDDLEWARE, AXP_MULTI_SOURCE_DEFINITION_PROVIDER, DEFAULT_PROPERTY_ORDER, DEFAULT_SECTION_ORDER, ENTITY_LIST_ROUTE_CONTEXT_SESSION_KEY, EntityBuilder, EntityDataAccessor, actionExists, applyDataSourcePagingWithoutLoad, canPersistEntityListState, cloneLayoutArrays, columnWidthMiddleware, columnWidthMiddlewareProvider, createLayoutOrderingMiddlewareProvider, createModifierContext, detectEntityChanges, ensureLayoutPropertyView, ensureLayoutSection, ensureListActions, entityDetailsCreateActions, entityDetailsCrudActions, entityDetailsEditAction, entityDetailsNewEditAction, entityDetailsReferenceCondition, entityDetailsReferenceCreateActions, entityDetailsSimpleCondition, entityMasterBulkDeleteAction, entityMasterCreateAction, entityMasterCrudActions, entityMasterDeleteAction, entityMasterEditAction, entityMasterRecordActions, entityMasterViewAction, entityOverrideDetailsViewAction, eventDispatchMiddleware, findEntityListRowDataInTree, getDataSourcePageIndex, getEntityListRowId, isAXPMiddlewareAbortError, layoutOrderingMiddlewareFactory, layoutOrderingMiddlewareProvider, normalizeEntityListPersistenceMode, normalizeListPaging, restoreEntityListExpandedRows, shouldLoadEntityListStateFromStorage, shouldResetEntityListStateOnRouteEntry };
16441
16766
  //# sourceMappingURL=acorex-platform-layout-entity.mjs.map