@acorex/platform 21.0.0-beta.7 → 21.0.0-beta.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.
Files changed (31) hide show
  1. package/fesm2022/acorex-platform-auth.mjs +4 -0
  2. package/fesm2022/acorex-platform-auth.mjs.map +1 -1
  3. package/fesm2022/{acorex-platform-common-common-settings.provider-lWz_f-Ia.mjs → acorex-platform-common-common-settings.provider-Bi1RYif5.mjs} +41 -3
  4. package/fesm2022/acorex-platform-common-common-settings.provider-Bi1RYif5.mjs.map +1 -0
  5. package/fesm2022/acorex-platform-common.mjs +205 -164
  6. package/fesm2022/acorex-platform-common.mjs.map +1 -1
  7. package/fesm2022/acorex-platform-core.mjs +5 -4
  8. package/fesm2022/acorex-platform-core.mjs.map +1 -1
  9. package/fesm2022/acorex-platform-layout-components.mjs +2 -2
  10. package/fesm2022/acorex-platform-layout-components.mjs.map +1 -1
  11. package/fesm2022/acorex-platform-layout-entity.mjs +952 -64
  12. package/fesm2022/acorex-platform-layout-entity.mjs.map +1 -1
  13. package/fesm2022/acorex-platform-layout-views.mjs +7 -5
  14. package/fesm2022/acorex-platform-layout-views.mjs.map +1 -1
  15. package/fesm2022/acorex-platform-layout-widget-core.mjs +72 -6
  16. package/fesm2022/acorex-platform-layout-widget-core.mjs.map +1 -1
  17. package/fesm2022/acorex-platform-layout-widgets.mjs +114 -136
  18. package/fesm2022/acorex-platform-layout-widgets.mjs.map +1 -1
  19. package/fesm2022/acorex-platform-themes-default.mjs +119 -13
  20. package/fesm2022/acorex-platform-themes-default.mjs.map +1 -1
  21. package/fesm2022/acorex-platform-workflow.mjs +85 -4
  22. package/fesm2022/acorex-platform-workflow.mjs.map +1 -1
  23. package/package.json +6 -6
  24. package/types/acorex-platform-common.d.ts +66 -48
  25. package/types/acorex-platform-core.d.ts +1 -1
  26. package/types/acorex-platform-layout-entity.d.ts +245 -8
  27. package/types/acorex-platform-layout-widget-core.d.ts +15 -0
  28. package/types/acorex-platform-layout-widgets.d.ts +15 -19
  29. package/types/acorex-platform-themes-default.d.ts +8 -0
  30. package/types/acorex-platform-workflow.d.ts +68 -2
  31. package/fesm2022/acorex-platform-common-common-settings.provider-lWz_f-Ia.mjs.map +0 -1
@@ -357,65 +357,78 @@ class AXPEntityMiddleware {
357
357
  this.providedModifiers = inject(AXP_ENTITY_MODIFIER, { optional: true }) || [];
358
358
  this.providedActionPlugins = inject(AXP_ENTITY_ACTION_PLUGIN, { optional: true }) || [];
359
359
  this.injector = inject(Injector);
360
- for (const { entityName, modifier } of this.providedModifiers) {
361
- this.register(entityName, modifier);
360
+ for (const { entityName, modifier, order } of this.providedModifiers) {
361
+ this.register(entityName, modifier, order);
362
362
  }
363
363
  }
364
364
  //#endregion
365
365
  //#region ---- Registration Methods ----
366
- register(entityName, modifier) {
366
+ register(entityName, modifier, order) {
367
+ const resolvedOrder = order ?? 0;
367
368
  if (entityName instanceof RegExp) {
368
- this.patternModifiers.push({ pattern: this.normalizeRegExp(entityName), modifier });
369
+ this.patternModifiers.push({ pattern: this.normalizeRegExp(entityName), modifier, order: resolvedOrder });
369
370
  return;
370
371
  }
371
372
  if (entityName.includes('*')) {
372
373
  const pattern = this.wildcardToRegExp(entityName);
373
- this.patternModifiers.push({ pattern, modifier });
374
+ this.patternModifiers.push({ pattern, modifier, order: resolvedOrder });
374
375
  return;
375
376
  }
376
- this.exactModifiers.set(entityName, modifier);
377
+ this.exactModifiers.set(entityName, { modifier, order: resolvedOrder });
377
378
  }
378
379
  //#endregion
379
380
  //#region ---- Processing ----
380
381
  async process(entity) {
381
- // First, expand action plugins if entity.plugins exists
382
382
  const context = createModifierContext(entity);
383
- const plugins = entity.plugins;
384
- if (plugins && plugins.length) {
385
- const sorted = [...this.providedActionPlugins].sort((a, b) => (a.order ?? 0) - (b.order ?? 0));
386
- for (const p of plugins) {
387
- const contrib = sorted.find((x) => x.name === p.name);
388
- if (contrib) {
389
- try {
390
- await runInInjectionContext(this.injector, () => contrib.apply(context, p.options));
391
- }
392
- catch (err) {
393
- console.error('[AXPEntityMiddleware] action plugin failed:', p.name, err);
394
- }
395
- }
396
- }
397
- }
398
- // Then apply entity-specific modifiers
399
- // Collect all matching modifiers
400
- const modifiers = [];
401
- // Exact match first
383
+ const steps = [];
402
384
  const exact = this.exactModifiers.get(entity.name);
403
385
  if (exact) {
404
- modifiers.push(exact);
386
+ steps.push(this.createModifierStep(exact, context));
405
387
  }
406
- // Then all pattern matches
407
- for (const { pattern, modifier } of this.patternModifiers) {
408
- if (pattern.test(entity.name)) {
409
- modifiers.push(modifier);
388
+ for (const entry of this.patternModifiers) {
389
+ if (entry.pattern.test(entity.name)) {
390
+ steps.push(this.createModifierStep(entry, context));
410
391
  }
411
392
  }
412
- // Apply all matching modifiers in order
413
- for (const modifier of modifiers) {
414
- runInInjectionContext(this.injector, () => modifier(context));
393
+ const entityPlugins = entity.plugins ?? [];
394
+ for (const pluginRef of entityPlugins) {
395
+ const contrib = this.providedActionPlugins.find((x) => x.name === pluginRef.name);
396
+ if (contrib) {
397
+ steps.push(this.createPluginStep(contrib, pluginRef.name, context));
398
+ }
399
+ }
400
+ const sorted = steps.sort((a, b) => a.order - b.order);
401
+ for (const step of sorted) {
402
+ try {
403
+ await runInInjectionContext(this.injector, step.run);
404
+ }
405
+ catch (err) {
406
+ console.error('[AXPEntityMiddleware] entity processing step failed:', err);
407
+ }
415
408
  }
416
409
  return context.toEntity();
417
410
  }
418
411
  //#endregion
412
+ //#region ---- Step Factories ----
413
+ createModifierStep(entry, context) {
414
+ return {
415
+ order: entry.order,
416
+ run: () => entry.modifier(context),
417
+ };
418
+ }
419
+ createPluginStep(contrib, pluginName, context) {
420
+ return {
421
+ order: contrib.order ?? 0,
422
+ run: async () => {
423
+ const pluginRef = context.plugins.find(pluginName).get();
424
+ if (!pluginRef) {
425
+ return;
426
+ }
427
+ await contrib.apply(context, pluginRef.options);
428
+ },
429
+ };
430
+ }
431
+ //#endregion
419
432
  //#region ---- Helpers ----
420
433
  wildcardToRegExp(pattern) {
421
434
  const escaped = pattern.replace(/[.+?^${}()|\[\]\\]/g, '\\$&');
@@ -3215,6 +3228,24 @@ class AXPEntityDataProviderImpl {
3215
3228
  insertOne(entity) {
3216
3229
  return this.storageService.insertOne(this.entityName, entity);
3217
3230
  }
3231
+ count(request) {
3232
+ return this.storageService.count(this.entityName, request);
3233
+ }
3234
+ queryAll(request, options) {
3235
+ return this.storageService.queryAll(this.entityName, request, options);
3236
+ }
3237
+ getMany(ids) {
3238
+ return this.storageService.getMany(this.entityName, ids);
3239
+ }
3240
+ exists(id) {
3241
+ return this.storageService.exists(this.entityName, id);
3242
+ }
3243
+ upsertOne(entity, options) {
3244
+ return this.storageService.upsertOne(this.entityName, entity, options);
3245
+ }
3246
+ aggregate(request, options) {
3247
+ return this.storageService.aggregate(this.entityName, request, options);
3248
+ }
3218
3249
  }
3219
3250
  class AXMEntityCrudService {
3220
3251
  }
@@ -3316,6 +3347,24 @@ class AXMEntityCrudServiceImpl {
3316
3347
  get storageService() {
3317
3348
  return this._storageService;
3318
3349
  }
3350
+ async count(request) {
3351
+ return this._entityDataProvider.count(request);
3352
+ }
3353
+ async queryAll(request, options) {
3354
+ return this._entityDataProvider.queryAll(request, options);
3355
+ }
3356
+ async getMany(ids) {
3357
+ return this._entityDataProvider.getMany(ids);
3358
+ }
3359
+ async exists(id) {
3360
+ return this._entityDataProvider.exists(id);
3361
+ }
3362
+ async upsertOne(entity, options) {
3363
+ return this._entityDataProvider.upsertOne(entity, options);
3364
+ }
3365
+ async aggregate(request, options) {
3366
+ return this._entityDataProvider.aggregate(request, options);
3367
+ }
3319
3368
  async custom(request) { }
3320
3369
  }
3321
3370
 
@@ -3943,6 +3992,11 @@ class AXPEntityDetailListViewModel {
3943
3992
  this.filterOperatorMiddleware = this.injector.get(AXPFilterOperatorMiddlewareService);
3944
3993
  this.expressionEvaluator = this.injector.get(AXPExpressionEvaluatorService);
3945
3994
  this.queryExecutor = this.injector.get(AXPQueryExecutor);
3995
+ this.settingsService = this.injector.get(AXPSettingsService);
3996
+ this.destroyed = new Subject();
3997
+ this.showRowIndexColumnEnabled = signal(false, ...(ngDevMode ? [{ debugName: "showRowIndexColumnEnabled" }] : /* istanbul ignore next */ []));
3998
+ /** Whether the row index column is shown (user setting). */
3999
+ this.showIndexColumn = computed(() => this.showRowIndexColumnEnabled(), ...(ngDevMode ? [{ debugName: "showIndexColumn" }] : /* istanbul ignore next */ []));
3946
4000
  this.dataSource = new AXDataSource({
3947
4001
  byKey: async (key) => {
3948
4002
  const execute = this.detailEntity()?.queries?.byKey?.execute;
@@ -4082,8 +4136,28 @@ class AXPEntityDetailListViewModel {
4082
4136
  };
4083
4137
  return await this.expressionEvaluator.evaluate(actionData, scope);
4084
4138
  };
4139
+ void this.syncShowRowIndexColumnSetting();
4140
+ this.settingsService.onLoaded.pipe(takeUntil(this.destroyed)).subscribe(() => {
4141
+ void this.syncShowRowIndexColumnSetting();
4142
+ });
4143
+ this.settingsService.onChanged.pipe(takeUntil(this.destroyed)).subscribe(() => {
4144
+ void this.syncShowRowIndexColumnSetting();
4145
+ });
4085
4146
  this.initialize();
4086
4147
  }
4148
+ async syncShowRowIndexColumnSetting() {
4149
+ try {
4150
+ const value = await this.settingsService.get(AXPCommonSettings.ShowRowIndexColumn);
4151
+ this.showRowIndexColumnEnabled.set(value ?? false);
4152
+ }
4153
+ catch {
4154
+ this.showRowIndexColumnEnabled.set(false);
4155
+ }
4156
+ }
4157
+ destroy() {
4158
+ this.destroyed.next();
4159
+ this.destroyed.complete();
4160
+ }
4087
4161
  async initialize() {
4088
4162
  const entityResolver = this.injector.get(AXPEntityDefinitionRegistryService);
4089
4163
  const [moduleName, entityName] = this.detailEntityConfig.entity.split('.');
@@ -4223,6 +4297,118 @@ const AXPEntityEventsKeys = {
4223
4297
  REFRESH_DATA: 'entity:refresh-data',
4224
4298
  };
4225
4299
 
4300
+ /**
4301
+ * Resolves a stable row id from entity list row data.
4302
+ */
4303
+ function getEntityListRowId(data, key = 'id') {
4304
+ const value = data[key];
4305
+ if (value != null && value !== '') {
4306
+ return String(value);
4307
+ }
4308
+ return '';
4309
+ }
4310
+ /**
4311
+ * Finds row data in a hierarchical grid tree (root rows and nested children).
4312
+ */
4313
+ function findEntityListRowDataInTree(items, id, key) {
4314
+ for (const item of items) {
4315
+ if (item && typeof item === 'object' && String(item[key]) === id) {
4316
+ return item;
4317
+ }
4318
+ const rec = item;
4319
+ const metaChildren = rec?.['__meta__']?.['children'];
4320
+ const directChildren = rec?.['children'];
4321
+ const childArr = Array.isArray(metaChildren)
4322
+ ? metaChildren
4323
+ : Array.isArray(directChildren)
4324
+ ? directChildren
4325
+ : null;
4326
+ if (childArr?.length) {
4327
+ const found = findEntityListRowDataInTree(childArr, id, key);
4328
+ if (found) {
4329
+ return found;
4330
+ }
4331
+ }
4332
+ }
4333
+ return null;
4334
+ }
4335
+ /**
4336
+ * Restores expanded rows after data load (parents before children).
4337
+ */
4338
+ async function restoreEntityListExpandedRows(options) {
4339
+ const pending = [...new Set(options.expandedRowIds.filter(Boolean))];
4340
+ if (!pending.length) {
4341
+ return;
4342
+ }
4343
+ let safety = 0;
4344
+ const maxPasses = Math.max(pending.length * 3, 10);
4345
+ while (pending.length > 0 && safety++ < maxPasses) {
4346
+ const rows = options.getDisplayedRows();
4347
+ let progressed = false;
4348
+ for (let i = pending.length - 1; i >= 0; i--) {
4349
+ const id = pending[i];
4350
+ const item = findEntityListRowDataInTree(rows, id, options.rowKey);
4351
+ if (!item) {
4352
+ continue;
4353
+ }
4354
+ const meta = item['__meta__'];
4355
+ if (meta?.['expanded'] !== true) {
4356
+ await options.expandRow({ data: item });
4357
+ }
4358
+ pending.splice(i, 1);
4359
+ progressed = true;
4360
+ }
4361
+ if (!progressed) {
4362
+ break;
4363
+ }
4364
+ }
4365
+ }
4366
+
4367
+ /**
4368
+ * Applies take/skip to the data source without triggering {@link AXDataSource.load}.
4369
+ */
4370
+ function applyDataSourcePagingWithoutLoad(dataSource, paging) {
4371
+ const take = Math.max(1, paging.take);
4372
+ const skip = Math.max(0, paging.skip);
4373
+ const page = Math.floor(skip / take);
4374
+ const ds = dataSource;
4375
+ dataSource.config.pageSize = take;
4376
+ if (ds._query) {
4377
+ ds._query.take = take;
4378
+ ds._query.skip = skip;
4379
+ }
4380
+ ds._page = page;
4381
+ }
4382
+ function getDataSourcePageIndex(dataSource) {
4383
+ const ds = dataSource;
4384
+ return ds._page ?? 0;
4385
+ }
4386
+ function normalizeListPaging(paging, defaultTake) {
4387
+ const take = typeof paging?.take === 'number' && paging.take > 0 ? paging.take : defaultTake;
4388
+ const skip = typeof paging?.skip === 'number' && paging.skip >= 0 ? paging.skip : 0;
4389
+ return { take, skip };
4390
+ }
4391
+
4392
+ const AXPEntityListPersistenceModeDefault = 'persistent';
4393
+ function normalizeEntityListPersistenceMode(value) {
4394
+ if (value === 'none' || value === 'persistent' || value === 'route') {
4395
+ return value;
4396
+ }
4397
+ return AXPEntityListPersistenceModeDefault;
4398
+ }
4399
+ function canPersistEntityListState(mode) {
4400
+ return mode !== 'none';
4401
+ }
4402
+ /** `none` never reads list state from user settings. */
4403
+ function shouldLoadEntityListStateFromStorage(mode) {
4404
+ return mode !== 'none';
4405
+ }
4406
+ /** `route` clears stored list state when the route entity (module + name) changes. */
4407
+ function shouldResetEntityListStateOnRouteEntry(mode) {
4408
+ return mode === 'route';
4409
+ }
4410
+ const ENTITY_LIST_ROUTE_CONTEXT_SESSION_KEY = 'axp-entity-list-route-context';
4411
+
4226
4412
  /**
4227
4413
  * Entity Event Dispatcher - A wrapper for entity-specific events
4228
4414
  * Handles pattern-based dispatching for entity operations with wildcard support
@@ -4556,14 +4742,17 @@ class AXPEntityMasterListViewModel {
4556
4742
  return `${resolvedCommand}${suffix}`;
4557
4743
  }
4558
4744
  async setView(viewName = null) {
4559
- const entitySetting = await this.settings.get(this.settingEntityKey);
4560
- const selectedViewName = entitySetting?.list?.currentView;
4745
+ let selectedViewName;
4746
+ if (await this.shouldLoadPersistedListState()) {
4747
+ const entitySetting = await this.settings.get(this.settingEntityKey);
4748
+ selectedViewName = entitySetting?.list?.currentView;
4749
+ }
4561
4750
  if (viewName != this.view().name) {
4562
4751
  this.view.set(this.views().find((c) => c.name == (viewName || selectedViewName)) ?? this.views()[0]);
4563
4752
  this.applyViewSorts();
4564
4753
  this.applyViewColumns();
4565
4754
  this.applyViewFilters();
4566
- // this.applyFilterAndSort();
4755
+ this.resolvedListPaging.set(null);
4567
4756
  await this.applySettings();
4568
4757
  }
4569
4758
  }
@@ -4587,6 +4776,15 @@ class AXPEntityMasterListViewModel {
4587
4776
  this.lastAppliedSortKey = null;
4588
4777
  this.lastAppliedFilterKey = null;
4589
4778
  this.hasQueryParamsFilters = false; // Flag to prevent overriding queryParams filters
4779
+ /** Persisted expanded row ids for hierarchical lists (per view). */
4780
+ this.expandedRowIds = signal([], ...(ngDevMode ? [{ debugName: "expandedRowIds" }] : /* istanbul ignore next */ []));
4781
+ /** When true, row expand/collapse is not written to user settings (restore in progress). */
4782
+ this.skipExpandedRowPersistence = false;
4783
+ /** Resolved take/skip for the current view (null until loaded from settings). */
4784
+ this.resolvedListPaging = signal(null, ...(ngDevMode ? [{ debugName: "resolvedListPaging" }] : /* istanbul ignore next */ []));
4785
+ /** When true, pager changes are not persisted (programmatic UI sync). */
4786
+ this.skipListPagingPersistence = false;
4787
+ this.listPersistenceMode = null;
4590
4788
  this.events$ = new Subject();
4591
4789
  //****************** Views ******************//
4592
4790
  this.views = computed(() => {
@@ -4596,6 +4794,18 @@ class AXPEntityMasterListViewModel {
4596
4794
  });
4597
4795
  }, ...(ngDevMode ? [{ debugName: "views" }] : /* istanbul ignore next */ []));
4598
4796
  this.view = signal(this.views()[0], ...(ngDevMode ? [{ debugName: "view" }] : /* istanbul ignore next */ []));
4797
+ this.showRowIndexColumnEnabled = signal(false, ...(ngDevMode ? [{ debugName: "showRowIndexColumnEnabled" }] : /* istanbul ignore next */ []));
4798
+ /**
4799
+ * Row index column: if the list view defines `indexCol` (true/false), that overrides the user setting;
4800
+ * if `indexCol` is omitted, visibility follows {@link AXPCommonSettings.ShowRowIndexColumn}.
4801
+ */
4802
+ this.showIndexColumn = computed(() => {
4803
+ const indexCol = this.view().indexCol;
4804
+ if (indexCol !== undefined) {
4805
+ return indexCol;
4806
+ }
4807
+ return this.showRowIndexColumnEnabled();
4808
+ }, ...(ngDevMode ? [{ debugName: "showIndexColumn" }] : /* istanbul ignore next */ []));
4599
4809
  this.dataSource = new AXDataSource({
4600
4810
  byKey: async (key) => {
4601
4811
  const execute = this.entityDef.queries?.byKey?.execute;
@@ -4766,13 +4976,88 @@ class AXPEntityMasterListViewModel {
4766
4976
  }
4767
4977
  });
4768
4978
  this.sortedFields.set(this.sortableFields());
4979
+ void this.syncShowRowIndexColumnSetting();
4980
+ this.settings.onLoaded.pipe(takeUntil(this.destroyed)).subscribe(() => {
4981
+ void this.syncShowRowIndexColumnSetting();
4982
+ });
4983
+ this.settings.onChanged.pipe(takeUntil(this.destroyed)).subscribe(() => {
4984
+ void this.syncShowRowIndexColumnSetting();
4985
+ });
4986
+ }
4987
+ async syncShowRowIndexColumnSetting() {
4988
+ try {
4989
+ const value = await this.settings.get(AXPCommonSettings.ShowRowIndexColumn);
4990
+ this.showRowIndexColumnEnabled.set(value ?? false);
4991
+ }
4992
+ catch {
4993
+ console.log('catch');
4994
+ this.showRowIndexColumnEnabled.set(false);
4995
+ }
4996
+ }
4997
+ /**
4998
+ * Applies {@link AXPCommonSettings.EntityListPersistenceMode} for this list instance.
4999
+ * Call once when the list view model is created (before loading list UI state).
5000
+ */
5001
+ async initializeListPersistence() {
5002
+ const mode = await this.getListPersistenceMode();
5003
+ debugger;
5004
+ if (!shouldResetEntityListStateOnRouteEntry(mode)) {
5005
+ return;
5006
+ }
5007
+ const routeKey = this.settingEntityKey;
5008
+ let previousRouteKey = null;
5009
+ try {
5010
+ previousRouteKey = sessionStorage.getItem(ENTITY_LIST_ROUTE_CONTEXT_SESSION_KEY);
5011
+ }
5012
+ catch {
5013
+ previousRouteKey = null;
5014
+ }
5015
+ if (previousRouteKey !== routeKey) {
5016
+ await this.clearEntityListSettings();
5017
+ try {
5018
+ sessionStorage.setItem(ENTITY_LIST_ROUTE_CONTEXT_SESSION_KEY, routeKey);
5019
+ }
5020
+ catch {
5021
+ // sessionStorage may be unavailable
5022
+ }
5023
+ }
5024
+ }
5025
+ async getListPersistenceMode() {
5026
+ if (this.listPersistenceMode != null) {
5027
+ return this.listPersistenceMode;
5028
+ }
5029
+ const value = await this.settings.get(AXPCommonSettings.EntityListPersistenceMode);
5030
+ this.listPersistenceMode = normalizeEntityListPersistenceMode(value);
5031
+ return this.listPersistenceMode;
5032
+ }
5033
+ async shouldLoadPersistedListState() {
5034
+ return shouldLoadEntityListStateFromStorage(await this.getListPersistenceMode());
5035
+ }
5036
+ async shouldPersistListState() {
5037
+ return canPersistEntityListState(await this.getListPersistenceMode());
5038
+ }
5039
+ async clearEntityListSettings() {
5040
+ await this.settings.scope(AXPPlatformScope.User).update(this.settingEntityKey, (prev) => {
5041
+ if (!prev || typeof prev !== 'object') {
5042
+ return {};
5043
+ }
5044
+ const next = { ...prev };
5045
+ delete next['list'];
5046
+ return next;
5047
+ });
4769
5048
  }
4770
5049
  async applySettings() {
4771
- this.saveSettings('view');
5050
+ if (await this.shouldPersistListState()) {
5051
+ this.saveSettings('view');
5052
+ }
5053
+ if (!(await this.shouldLoadPersistedListState())) {
5054
+ this.loadListPagingFromViewSettings(null);
5055
+ this.expandedRowIds.set([]);
5056
+ return;
5057
+ }
4772
5058
  const listViewSetting = await this.settings.get(this.settingEntityKey);
4773
5059
  if (listViewSetting) {
4774
5060
  const columns = listViewSetting.list?.views?.[this.view().name]?.columns;
4775
- const pageSize = listViewSetting.list?.views?.[this.view().name]?.pageSize;
4776
5061
  const sorts = listViewSetting.list?.views?.[this.view().name]?.sorts;
4777
5062
  const filters = listViewSetting.list?.views?.[this.view().name]?.filters;
4778
5063
  let columnVisibilityMap;
@@ -4781,7 +5066,7 @@ class AXPEntityMasterListViewModel {
4781
5066
  columnVisibilityMap = new Map(columns.map((col) => [col.name, col.visible]));
4782
5067
  columnWidthsMap = new Map(columns.map((col) => [col.name, col.width]));
4783
5068
  }
4784
- // Do not set pageSize here to avoid triggering an extra load
5069
+ this.loadListPagingFromViewSettings(listViewSetting);
4785
5070
  if (columns && columnVisibilityMap && columnWidthsMap) {
4786
5071
  this.columns.update((prev) => prev
4787
5072
  .map((c) => {
@@ -4803,16 +5088,102 @@ class AXPEntityMasterListViewModel {
4803
5088
  if (Array.isArray(filters) && !this.hasQueryParamsFilters) {
4804
5089
  this.filterQueries.set(filters);
4805
5090
  }
5091
+ const expandedRowIds = listViewSetting.list?.views?.[this.view().name]?.expandedRowIds;
5092
+ if (Array.isArray(expandedRowIds)) {
5093
+ this.expandedRowIds.set(expandedRowIds.map((id) => String(id)).filter(Boolean));
5094
+ }
5095
+ else {
5096
+ this.expandedRowIds.set([]);
5097
+ }
5098
+ }
5099
+ else {
5100
+ this.loadListPagingFromViewSettings(null);
5101
+ }
5102
+ }
5103
+ async ensureListPagingResolved() {
5104
+ if (this.resolvedListPaging() != null) {
5105
+ return;
5106
+ }
5107
+ if (!(await this.shouldLoadPersistedListState())) {
5108
+ this.loadListPagingFromViewSettings(null);
5109
+ return;
5110
+ }
5111
+ const entitySetting = await this.settings.get(this.settingEntityKey);
5112
+ this.loadListPagingFromViewSettings(entitySetting);
5113
+ }
5114
+ getResolvedListPaging() {
5115
+ return (this.resolvedListPaging() ??
5116
+ normalizeListPaging(undefined, this.view().pageSize || this.dataSource.config.pageSize || 10));
5117
+ }
5118
+ applyPagingToDataSourceWithoutLoad() {
5119
+ applyDataSourcePagingWithoutLoad(this.dataSource, this.getResolvedListPaging());
5120
+ }
5121
+ saveListPaging(take, skip) {
5122
+ const paging = normalizeListPaging({ take, skip }, this.view().pageSize || 10);
5123
+ this.resolvedListPaging.set(paging);
5124
+ this.saveSettings('listPaging', paging);
5125
+ }
5126
+ resetListPagingSkip() {
5127
+ const paging = normalizeListPaging({ take: this.getResolvedListPaging().take, skip: 0 }, this.view().pageSize || 10);
5128
+ this.resolvedListPaging.set(paging);
5129
+ this.saveSettings('listPaging', paging);
5130
+ }
5131
+ loadListPagingFromViewSettings(entitySetting) {
5132
+ const viewSettings = entitySetting?.list?.views?.[this.view().name];
5133
+ const defaultTake = this.view().pageSize || 10;
5134
+ let paging = viewSettings?.paging;
5135
+ if (!paging && typeof viewSettings?.pageSize === 'number') {
5136
+ paging = { take: viewSettings.pageSize, skip: 0 };
5137
+ }
5138
+ this.resolvedListPaging.set(normalizeListPaging(paging, defaultTake));
5139
+ }
5140
+ getExpandedRowIds() {
5141
+ return this.expandedRowIds();
5142
+ }
5143
+ /**
5144
+ * Updates persisted expanded row ids when the user expands or collapses a tree row.
5145
+ */
5146
+ updateExpandedRowId(rowId, expanded) {
5147
+ if (!rowId || !this.parentKey()) {
5148
+ return;
5149
+ }
5150
+ const next = new Set(this.expandedRowIds());
5151
+ if (expanded) {
5152
+ next.add(rowId);
5153
+ }
5154
+ else {
5155
+ next.delete(rowId);
5156
+ }
5157
+ const ids = Array.from(next);
5158
+ this.expandedRowIds.set(ids);
5159
+ this.saveSettings('expandedRows', ids);
5160
+ }
5161
+ handleRowExpandChange(rowData) {
5162
+ if (this.skipExpandedRowPersistence || !this.parentKey()) {
5163
+ return;
5164
+ }
5165
+ const key = this.dataSource.config?.key ?? 'id';
5166
+ const rowId = getEntityListRowId(rowData, key);
5167
+ if (!rowId) {
5168
+ return;
4806
5169
  }
5170
+ // onItemExpanded fires before the grid toggles __meta__.expanded on expandedItem.
5171
+ const meta = rowData['__meta__'];
5172
+ const wasExpanded = meta?.['expanded'] === true;
5173
+ this.updateExpandedRowId(rowId, !wasExpanded);
4807
5174
  }
4808
5175
  async saveSettings(changesType, data) {
5176
+ if (!(await this.shouldPersistListState())) {
5177
+ return;
5178
+ }
4809
5179
  const updateSettings = (updateFn) => {
4810
5180
  this.settings.scope(AXPPlatformScope.User).update(this.settingEntityKey, updateFn);
4811
5181
  };
4812
5182
  switch (changesType) {
4813
- case 'columnSizes':
5183
+ case 'columnSizes': {
5184
+ const columnSizeData = data;
4814
5185
  updateSettings((prev) => {
4815
- const field = data.dataField.split('-')[1];
5186
+ const field = columnSizeData.dataField.split('-')[1];
4816
5187
  const newSettings = { ...prev };
4817
5188
  const existingColumns = prev?.list?.views?.[this.view().name]?.columns;
4818
5189
  const baseColumns = Array.isArray(existingColumns) && existingColumns.length
@@ -4824,7 +5195,7 @@ class AXPEntityMasterListViewModel {
4824
5195
  }));
4825
5196
  const updatedColumns = baseColumns.map((c) => ({
4826
5197
  ...c,
4827
- width: c.name === field ? data.width : c.width,
5198
+ width: c.name === field ? columnSizeData.width : c.width,
4828
5199
  }));
4829
5200
  const x = this.allAvailableColumns().map((c) => ({
4830
5201
  name: c.column?.options?.dataPath ?? c.name,
@@ -4835,10 +5206,12 @@ class AXPEntityMasterListViewModel {
4835
5206
  return newSettings;
4836
5207
  });
4837
5208
  break;
4838
- case 'columnOrders':
5209
+ }
5210
+ case 'columnOrders': {
5211
+ const orderedColumns = data;
4839
5212
  updateSettings((prev) => {
4840
5213
  const newSettings = { ...prev };
4841
- set(newSettings, `list.views.${this.view().name}.columns`, data.map((c) => ({
5214
+ set(newSettings, `list.views.${this.view().name}.columns`, orderedColumns.map((c) => ({
4842
5215
  name: c.column?.options?.dataPath ?? c.name,
4843
5216
  visible: c.visible,
4844
5217
  width: c.width,
@@ -4846,6 +5219,7 @@ class AXPEntityMasterListViewModel {
4846
5219
  return newSettings;
4847
5220
  });
4848
5221
  break;
5222
+ }
4849
5223
  case 'view':
4850
5224
  updateSettings((prev) => ({
4851
5225
  ...prev,
@@ -4865,6 +5239,26 @@ class AXPEntityMasterListViewModel {
4865
5239
  [this.view().name]: {
4866
5240
  ...prev?.list?.views?.[this.view().name],
4867
5241
  pageSize: data,
5242
+ paging: normalizeListPaging({
5243
+ take: data,
5244
+ skip: prev?.list?.views?.[this.view().name]?.paging?.skip,
5245
+ }, this.view().pageSize || 10),
5246
+ },
5247
+ },
5248
+ },
5249
+ }));
5250
+ break;
5251
+ case 'listPaging':
5252
+ updateSettings((prev) => ({
5253
+ ...prev,
5254
+ list: {
5255
+ ...prev?.list,
5256
+ views: {
5257
+ ...prev?.list?.views,
5258
+ [this.view().name]: {
5259
+ ...prev?.list?.views?.[this.view().name],
5260
+ paging: data,
5261
+ pageSize: data.take,
4868
5262
  },
4869
5263
  },
4870
5264
  },
@@ -4900,6 +5294,21 @@ class AXPEntityMasterListViewModel {
4900
5294
  },
4901
5295
  }));
4902
5296
  break;
5297
+ case 'expandedRows':
5298
+ updateSettings((prev) => ({
5299
+ ...prev,
5300
+ list: {
5301
+ ...prev?.list,
5302
+ views: {
5303
+ ...prev?.list?.views,
5304
+ [this.view().name]: {
5305
+ ...prev?.list?.views?.[this.view().name],
5306
+ expandedRowIds: data,
5307
+ },
5308
+ },
5309
+ },
5310
+ }));
5311
+ break;
4903
5312
  default:
4904
5313
  break;
4905
5314
  }
@@ -5139,6 +5548,7 @@ class AXPEntityMasterListViewModel {
5139
5548
  this.applyViewFilters();
5140
5549
  }
5141
5550
  async applyFilterAndSort() {
5551
+ await this.ensureListPagingResolved();
5142
5552
  const sorts = this.sortedFields()
5143
5553
  .filter((sf) => sf.dir)
5144
5554
  .map((s) => ({ name: s.name, dir: s.dir }));
@@ -5148,10 +5558,12 @@ class AXPEntityMasterListViewModel {
5148
5558
  if (sortKey === this.lastAppliedSortKey && filterKey === this.lastAppliedFilterKey) {
5149
5559
  return; // No effective change; avoid redundant refresh
5150
5560
  }
5151
- // Determine if filters changed (for pagination reset)
5152
- const filtersChanged = filterKey !== this.lastAppliedFilterKey;
5561
+ const filtersChanged = this.lastAppliedFilterKey != null && filterKey !== this.lastAppliedFilterKey;
5153
5562
  this.lastAppliedSortKey = sortKey;
5154
5563
  this.lastAppliedFilterKey = filterKey;
5564
+ if (filtersChanged) {
5565
+ this.resetListPagingSkip();
5566
+ }
5155
5567
  this.dataSource.clearFilter();
5156
5568
  this.dataSource.sort(...sorts.map((s) => ({ dir: s.dir, field: s.name })));
5157
5569
  this.dataSource.filter(this.filterOperatorMiddleware.transformFilter({
@@ -5358,7 +5770,9 @@ class AXPEntityListViewModelFactory {
5358
5770
  this.layout.setNavigationLoading(true);
5359
5771
  const config = await this.entityService.resolve(moduleName, entityName);
5360
5772
  this.layout.setNavigationLoading(false);
5361
- return new AXPEntityMasterListViewModel(this.injector, config);
5773
+ const vm = new AXPEntityMasterListViewModel(this.injector, config);
5774
+ await vm.initializeListPersistence();
5775
+ return vm;
5362
5776
  }
5363
5777
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPEntityListViewModelFactory, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
5364
5778
  static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPEntityListViewModelFactory, providedIn: 'root' }); }
@@ -6343,6 +6757,225 @@ const AXPEntityPreloadFiltersViewModelResolver = async (route, state) => {
6343
6757
  };
6344
6758
  //#endregion
6345
6759
 
6760
+ //#region ---- Path / numeric helpers ----
6761
+ function getPath(obj, path) {
6762
+ if (obj == null || path.length === 0) {
6763
+ return undefined;
6764
+ }
6765
+ const parts = path.split('.');
6766
+ let cur = obj;
6767
+ for (const p of parts) {
6768
+ if (cur == null || typeof cur !== 'object') {
6769
+ return undefined;
6770
+ }
6771
+ cur = cur[p];
6772
+ }
6773
+ return cur;
6774
+ }
6775
+ function toNumber(value) {
6776
+ if (typeof value === 'number' && Number.isFinite(value)) {
6777
+ return value;
6778
+ }
6779
+ if (typeof value === 'string' && value.trim().length > 0) {
6780
+ const n = Number(value);
6781
+ return Number.isFinite(n) ? n : null;
6782
+ }
6783
+ return null;
6784
+ }
6785
+ function defaultAlias(measure, index) {
6786
+ if (measure.alias?.trim()) {
6787
+ return measure.alias.trim();
6788
+ }
6789
+ if (measure.reducer === 'count') {
6790
+ return index === 0 ? 'count' : `count_${index}`;
6791
+ }
6792
+ const field = measure.field ?? 'value';
6793
+ const safeField = field.replace(/\./g, '_');
6794
+ return `${measure.reducer}_${safeField}`;
6795
+ }
6796
+ /**
6797
+ * Pure aggregation over already-filtered plain rows (e.g. outputs of {@link filterSortEntityRows}).
6798
+ */
6799
+ function computeEntityAggregates(rows, request) {
6800
+ const groupBy = request.groupBy ?? [];
6801
+ const measures = request.measures ?? [];
6802
+ if (measures.length === 0) {
6803
+ return [];
6804
+ }
6805
+ const groups = new Map();
6806
+ const stableGroupKey = (row) => {
6807
+ const parts = groupBy.map((path) => getPath(row, path));
6808
+ return JSON.stringify(parts);
6809
+ };
6810
+ for (const row of rows) {
6811
+ const k = stableGroupKey(row);
6812
+ let bucket = groups.get(k);
6813
+ if (!bucket) {
6814
+ bucket = {
6815
+ keyParts: groupBy.map((path) => getPath(row, path)),
6816
+ rows: [],
6817
+ };
6818
+ groups.set(k, bucket);
6819
+ }
6820
+ bucket.rows.push(row);
6821
+ }
6822
+ const result = [];
6823
+ for (const bucket of groups.values()) {
6824
+ const out = {};
6825
+ groupBy.forEach((field, i) => {
6826
+ out[field] = bucket.keyParts[i];
6827
+ });
6828
+ measures.forEach((measure, index) => {
6829
+ const alias = defaultAlias(measure, index);
6830
+ const gRows = bucket.rows;
6831
+ if (measure.reducer === 'count') {
6832
+ out[alias] = gRows.length;
6833
+ return;
6834
+ }
6835
+ const fieldPath = measure.field;
6836
+ if (!fieldPath) {
6837
+ out[alias] = null;
6838
+ return;
6839
+ }
6840
+ const nums = gRows.map((r) => toNumber(getPath(r, fieldPath))).filter((n) => n !== null);
6841
+ switch (measure.reducer) {
6842
+ case 'sum':
6843
+ out[alias] = nums.reduce((a, b) => a + b, 0);
6844
+ break;
6845
+ case 'min':
6846
+ out[alias] = nums.length ? Math.min(...nums) : null;
6847
+ break;
6848
+ case 'max':
6849
+ out[alias] = nums.length ? Math.max(...nums) : null;
6850
+ break;
6851
+ case 'avg':
6852
+ out[alias] = nums.length ? nums.reduce((a, b) => a + b, 0) / nums.length : null;
6853
+ break;
6854
+ default:
6855
+ out[alias] = null;
6856
+ }
6857
+ });
6858
+ result.push(out);
6859
+ }
6860
+ return result;
6861
+ }
6862
+ //#endregion
6863
+
6864
+ //#endregion
6865
+ //#region ---- Pure helpers ----
6866
+ /**
6867
+ * Fields where `contains` means hierarchical category membership (expand to descendants).
6868
+ * Excludes e.g. `roleIds`, which uses array membership only and must use normal filter logic.
6869
+ */
6870
+ function isCategoryContainsFieldName(field) {
6871
+ if (field === 'categoryIds') {
6872
+ return true;
6873
+ }
6874
+ if (typeof field === 'string' && field.endsWith('Ids') && field !== 'roleIds') {
6875
+ return true;
6876
+ }
6877
+ return false;
6878
+ }
6879
+ /**
6880
+ * Check if the entity is a category entity (ends with 'Category').
6881
+ */
6882
+ function isCategoryEntity(entityName) {
6883
+ return entityName.endsWith('Category');
6884
+ }
6885
+ /**
6886
+ * Check if the filter is a category filter (contains operator on categoryIds field).
6887
+ * Handles both simple filters and compound filters.
6888
+ */
6889
+ function isCategoryFilter(filter) {
6890
+ if (filter?.operator?.type === 'contains' && isCategoryContainsFieldName(filter.field)) {
6891
+ return true;
6892
+ }
6893
+ if (filter?.logic && filter?.filters && Array.isArray(filter.filters)) {
6894
+ return filter.filters.some((nestedFilter) => nestedFilter?.operator?.type === 'contains' && isCategoryContainsFieldName(nestedFilter.field));
6895
+ }
6896
+ return false;
6897
+ }
6898
+ //#endregion
6899
+ //#region ---- Query execution ----
6900
+ /**
6901
+ * Apply recursive category filtering: entities that belong to the category or any of its children.
6902
+ */
6903
+ async function applyRecursiveCategoryFilter(result, filter, entityName, getAllChildCategoryIds) {
6904
+ let categoryFilter = filter;
6905
+ let otherFilters = [];
6906
+ if (filter?.logic && filter?.filters && Array.isArray(filter.filters)) {
6907
+ const categoryFilterIndex = filter.filters.findIndex((f) => f?.operator?.type === 'contains' && isCategoryContainsFieldName(f.field));
6908
+ if (categoryFilterIndex !== -1) {
6909
+ categoryFilter = filter.filters[categoryFilterIndex];
6910
+ otherFilters = filter.filters.filter((_, index) => index !== categoryFilterIndex);
6911
+ }
6912
+ }
6913
+ if (!categoryFilter) {
6914
+ return applyFilterArray(result, [filter]);
6915
+ }
6916
+ const categoryId = categoryFilter.value;
6917
+ const categoryField = categoryFilter.field;
6918
+ const allCategoryIds = await getAllChildCategoryIds(categoryId, entityName);
6919
+ let filteredResult = result.filter((item) => {
6920
+ const categoryIds = item[categoryField];
6921
+ if (!categoryIds)
6922
+ return false;
6923
+ const itemCategoryIds = Array.isArray(categoryIds) ? categoryIds : [categoryIds];
6924
+ return itemCategoryIds.some((itemCategoryId) => allCategoryIds.includes(itemCategoryId));
6925
+ });
6926
+ if (otherFilters.length > 0) {
6927
+ filteredResult = applyFilterArray(filteredResult, otherFilters);
6928
+ }
6929
+ return filteredResult;
6930
+ }
6931
+ /**
6932
+ * Calculate childrenCount for each category entity when missing.
6933
+ */
6934
+ async function calculateChildrenCounts(items, entityName, getDirectChildCount) {
6935
+ return Promise.all(items.map(async (item) => {
6936
+ if (typeof item.childrenCount === 'number') {
6937
+ return { ...item };
6938
+ }
6939
+ const childrenCount = await getDirectChildCount(item.id, entityName);
6940
+ return { ...item, childrenCount };
6941
+ }));
6942
+ }
6943
+ /**
6944
+ * Loads raw rows for an entity and applies the same sorting and filtering as {@link runEntityQuery},
6945
+ * without pagination.
6946
+ */
6947
+ async function filterSortEntityRows(entityName, request, adapters) {
6948
+ let result = await adapters.getRawAll(entityName);
6949
+ if (request.sort && request.sort.length) {
6950
+ result = applySortArray(result, request.sort);
6951
+ }
6952
+ if (request.filter && isCategoryFilter(request.filter)) {
6953
+ result = await applyRecursiveCategoryFilter(result, request.filter, entityName, adapters.getAllChildCategoryIds);
6954
+ }
6955
+ else {
6956
+ result = applyFilterArray(result, request.filter ? [request.filter] : []);
6957
+ }
6958
+ if (isCategoryEntity(entityName)) {
6959
+ result = await calculateChildrenCounts(result, entityName, adapters.getDirectChildCount);
6960
+ }
6961
+ return result;
6962
+ }
6963
+ /**
6964
+ * Shared entity query logic: sort, filter (including recursive category filter), childrenCount, pagination.
6965
+ */
6966
+ async function runEntityQuery(entityName, request, adapters) {
6967
+ const rows = await filterSortEntityRows(entityName, request, adapters);
6968
+ const skip = request.skip ?? 0;
6969
+ const take = request.take ?? 0;
6970
+ return {
6971
+ total: rows.length,
6972
+ items: rows.slice(skip, skip + take),
6973
+ };
6974
+ }
6975
+ //#endregion
6976
+
6977
+ //#endregion
6978
+
6346
6979
  //#region ---- Imports ----
6347
6980
  //#endregion
6348
6981
  //#region ---- Constants ----
@@ -7082,7 +7715,7 @@ class AXPEntityCategoryTreeSelectorComponent extends AXBasePageComponent {
7082
7715
  // Use setTimeout to ensure DOM is updated after tree reload
7083
7716
  setTimeout(() => {
7084
7717
  if (this.searchValue().trim()) {
7085
- this.highlightService.highlight('ax-tree-view .ax-truncate', this.searchValue().trim());
7718
+ this.highlightService.highlight('ax-tree-view .truncate', this.searchValue().trim());
7086
7719
  }
7087
7720
  }, 100);
7088
7721
  }
@@ -10581,6 +11214,7 @@ class AXPEntityListTableService {
10581
11214
  this.workflow = inject(AXPWorkflowService);
10582
11215
  this.commandService = inject(AXPCommandService);
10583
11216
  this.expressionEvaluator = inject(AXPExpressionEvaluatorService);
11217
+ this.settings = inject(AXPSettingsService);
10584
11218
  this.evaluateExpressions = async (options, data) => {
10585
11219
  if (!options) {
10586
11220
  return {};
@@ -10601,6 +11235,20 @@ class AXPEntityListTableService {
10601
11235
  * Convert Entity to List Widget Options
10602
11236
  */
10603
11237
  async convertEntityToListOptions(entity, options, allActions) {
11238
+ const viewIndexCol = entity.interfaces?.master?.list?.views?.[0]?.indexCol;
11239
+ let showIndex = false;
11240
+ if (viewIndexCol !== undefined) {
11241
+ showIndex = viewIndexCol;
11242
+ }
11243
+ else {
11244
+ try {
11245
+ const fromSetting = await this.settings.get(AXPCommonSettings.ShowRowIndexColumn);
11246
+ showIndex = fromSetting ?? false;
11247
+ }
11248
+ catch {
11249
+ showIndex = false;
11250
+ }
11251
+ }
10604
11252
  const listOptions = {
10605
11253
  // 📊 Data Source
10606
11254
  dataSource: this.createDataSource(entity),
@@ -10610,7 +11258,7 @@ class AXPEntityListTableService {
10610
11258
  primaryCommands: this.createRowCommands(allActions, 'primary'),
10611
11259
  secondaryCommands: this.createRowCommands(allActions, 'secondary'),
10612
11260
  // ⚙️ Table Features
10613
- showIndex: entity.interfaces?.master?.list?.views?.[0]?.indexCol ?? false,
11261
+ showIndex,
10614
11262
  allowSelection: this.hasSelectedScopeActions(entity),
10615
11263
  paging: true,
10616
11264
  showHeader: true,
@@ -10627,7 +11275,6 @@ class AXPEntityListTableService {
10627
11275
  // 🎪 Events
10628
11276
  ...this.createDefaultEvents(entity, allActions, options?.excludeProperties),
10629
11277
  };
10630
- console.log('listOptions', listOptions);
10631
11278
  return listOptions;
10632
11279
  }
10633
11280
  //#endregion
@@ -11015,6 +11662,7 @@ class AXPEntityListWidgetViewComponent extends AXPValueWidgetComponent {
11015
11662
  this.commandService = inject(AXPCommandService);
11016
11663
  this.eventService = inject(AXPBroadcastEventService);
11017
11664
  this.expressionEvaluator = inject(AXPExpressionEvaluatorService);
11665
+ this.route = inject(ActivatedRoute);
11018
11666
  this.isMounted = signal(false, ...(ngDevMode ? [{ debugName: "isMounted" }] : /* istanbul ignore next */ []));
11019
11667
  this.entity = signal(null, ...(ngDevMode ? [{ debugName: "entity" }] : /* istanbul ignore next */ []));
11020
11668
  this.listNode = signal(null, ...(ngDevMode ? [{ debugName: "listNode" }] : /* istanbul ignore next */ []));
@@ -11188,13 +11836,7 @@ class AXPEntityListWidgetViewComponent extends AXPValueWidgetComponent {
11188
11836
  // console.log(this.listWidget()?.instance.output('selectedRows'));
11189
11837
  // }
11190
11838
  async execute(commandName, _data) {
11191
- const action = this.allActions().find((c) => {
11192
- return (c.name == commandName &&
11193
- ((this.selectedItems().length
11194
- ? c.scope == AXPEntityCommandScope.Selected
11195
- : c.scope == AXPEntityCommandScope.Individual) ||
11196
- c.scope == AXPEntityCommandScope.TypeLevel));
11197
- });
11839
+ const action = this.findToolbarAction(commandName);
11198
11840
  const command = commandName.split('&')[0];
11199
11841
  const commandData = action?.scope == AXPEntityCommandScope.Selected
11200
11842
  ? this.selectedItems()
@@ -11260,6 +11902,29 @@ class AXPEntityListWidgetViewComponent extends AXPValueWidgetComponent {
11260
11902
  });
11261
11903
  }
11262
11904
  }
11905
+ /**
11906
+ * Resolves toolbar commands including nested dropdown (`items`) actions.
11907
+ */
11908
+ findToolbarAction(commandName) {
11909
+ const scopeMatches = (c) => (this.selectedItems().length
11910
+ ? c.scope === AXPEntityCommandScope.Selected
11911
+ : c.scope === AXPEntityCommandScope.Individual) || c.scope === AXPEntityCommandScope.TypeLevel;
11912
+ const visit = (nodes) => {
11913
+ for (const node of nodes) {
11914
+ if (node.name === commandName && scopeMatches(node)) {
11915
+ return node;
11916
+ }
11917
+ if (node.items?.length) {
11918
+ const nested = visit(node.items);
11919
+ if (nested) {
11920
+ return nested;
11921
+ }
11922
+ }
11923
+ }
11924
+ return undefined;
11925
+ };
11926
+ return visit(this.allActions());
11927
+ }
11263
11928
  async evaluateToolbarExpressions(opts, expressionData) {
11264
11929
  if (!opts) {
11265
11930
  return {};
@@ -11272,6 +11937,92 @@ class AXPEntityListWidgetViewComponent extends AXPValueWidgetComponent {
11272
11937
  };
11273
11938
  return (await this.expressionEvaluator.evaluate(opts, scope));
11274
11939
  }
11940
+ /**
11941
+ * Parses the `filters` query param (same shape as standalone entity list routes).
11942
+ */
11943
+ parseFiltersFromRoute() {
11944
+ const filtersJson = this.route.snapshot.queryParamMap.get('filters');
11945
+ if (!filtersJson) {
11946
+ return [];
11947
+ }
11948
+ try {
11949
+ const parsed = JSON.parse(filtersJson);
11950
+ const rows = [];
11951
+ if (Array.isArray(parsed)) {
11952
+ for (const item of parsed) {
11953
+ if (item && typeof item === 'object' && typeof item.field === 'string') {
11954
+ rows.push(item);
11955
+ }
11956
+ }
11957
+ }
11958
+ else if (parsed !== null && typeof parsed === 'object') {
11959
+ for (const [field, value] of Object.entries(parsed)) {
11960
+ rows.push({ field, value, operator: { type: 'equal' } });
11961
+ }
11962
+ }
11963
+ return rows
11964
+ .filter((row) => row.field && row.value !== undefined && row.value !== null && row.value !== '')
11965
+ .map((row) => ({
11966
+ field: row.field,
11967
+ operator: row.operator && typeof row.operator === 'object' && 'type' in row.operator
11968
+ ? row.operator
11969
+ : { type: 'equal' },
11970
+ value: row.value,
11971
+ hidden: true,
11972
+ }));
11973
+ }
11974
+ catch {
11975
+ return [];
11976
+ }
11977
+ }
11978
+ /**
11979
+ * Route `filters` apply only when the active details `page` matches this list's entity
11980
+ * (e.g. WorkOrder filters must not affect FailureRegister on the same asset layout).
11981
+ */
11982
+ shouldApplyRouteFilters() {
11983
+ const pageId = this.route.snapshot.queryParamMap.get('page');
11984
+ if (!pageId) {
11985
+ return false;
11986
+ }
11987
+ const entitySource = this.entitySource();
11988
+ if (!entitySource) {
11989
+ return false;
11990
+ }
11991
+ const [, entityName] = entitySource.split('.');
11992
+ return !!entityName && pageId === entityName;
11993
+ }
11994
+ /**
11995
+ * Merges route filters into related-entity toolbar filters (route wins per field).
11996
+ */
11997
+ mergeToolbarFilters(baseFilters, routeFilters) {
11998
+ const byField = new Map(baseFilters.map((filter) => [filter.field, filter]));
11999
+ for (const filter of routeFilters) {
12000
+ byField.set(filter.field, filter);
12001
+ }
12002
+ return [...byField.values()];
12003
+ }
12004
+ getMergedToolbarFilters() {
12005
+ const base = (this.getValue()?.toolbar?.filters ?? []);
12006
+ if (!this.shouldApplyRouteFilters()) {
12007
+ return base;
12008
+ }
12009
+ const routeFilters = this.parseFiltersFromRoute();
12010
+ return routeFilters.length ? this.mergeToolbarFilters(base, routeFilters) : base;
12011
+ }
12012
+ /**
12013
+ * Applies merged route + parent-scope filters to the widget value and data source.
12014
+ */
12015
+ applyMergedRouteFiltersToList() {
12016
+ const merged = this.getMergedToolbarFilters();
12017
+ const current = this.getValue();
12018
+ if (!isEqual$1(current?.toolbar?.filters, merged)) {
12019
+ this.setValue({
12020
+ ...current,
12021
+ toolbar: { ...(current?.toolbar ?? {}), filters: merged },
12022
+ });
12023
+ }
12024
+ this.pushToolbarFiltersToDataSource();
12025
+ }
11275
12026
  /**
11276
12027
  * Re-evaluates related-entity list filters from the live dialog form context (e.g. after create saves the main row id).
11277
12028
  */
@@ -11461,23 +12212,27 @@ class AXPEntityListWidgetViewComponent extends AXPValueWidgetComponent {
11461
12212
  mode: 'view',
11462
12213
  defaultValue: this.getValue()?.table,
11463
12214
  });
12215
+ const mergedToolbarFilters = this.getMergedToolbarFilters();
11464
12216
  this.toolbarNode.set({
11465
12217
  type: AXPWidgetsCatalog.listToolbar,
11466
12218
  path: `toolbar`,
11467
12219
  options: toolbarOptions,
11468
12220
  mode: 'view',
11469
12221
  defaultValue: {
11470
- filters: this.getValue()?.toolbar?.filters,
12222
+ filters: mergedToolbarFilters,
11471
12223
  sorts: this.getValue()?.toolbar?.sorts,
11472
12224
  columns: this.getValue()?.toolbar?.columns,
11473
12225
  },
11474
12226
  });
11475
12227
  queueMicrotask(() => {
11476
- void this.pushToolbarFiltersToDataSource();
12228
+ this.applyMergedRouteFiltersToList();
11477
12229
  });
11478
12230
  }, 100);
11479
12231
  }
11480
12232
  async ngAfterViewInit() {
12233
+ this.route.queryParamMap.pipe(takeUntil(this.destroyed)).subscribe(() => {
12234
+ this.applyMergedRouteFiltersToList();
12235
+ });
11481
12236
  this.workflow.events$
11482
12237
  .pipe(ofType(AXPRefreshEvent))
11483
12238
  .pipe(takeUntil(this.destroyed))
@@ -13269,6 +14024,14 @@ class AXPLookupWidgetEditComponent extends AXPValueWidgetComponent {
13269
14024
  }
13270
14025
  });
13271
14026
  }
14027
+ outputs() {
14028
+ return [
14029
+ {
14030
+ name: 'selectedItems',
14031
+ value: this.selectedItems(),
14032
+ },
14033
+ ];
14034
+ }
13272
14035
  singleOrMultiple(values) {
13273
14036
  return this.multiple() ? values : values[0];
13274
14037
  }
@@ -17430,9 +18193,16 @@ class AXPPageListConverter extends AXPBaseRelatedEntityConverter {
17430
18193
  return result;
17431
18194
  };
17432
18195
  const flatActions = flattenActions(mergedActions);
17433
- const action = flatActions.find((a) => {
17434
- return a.name === command.name || a.name === commandName || a.name.split('&')[0] === commandName;
17435
- });
18196
+ /**
18197
+ * Toolbar keys are `commandKey&action.name`. Several dropdown items can share the same `commandKey`
18198
+ * (e.g. multiple `WorkflowManagement.WorkflowDefinition:Execute` lifecycle templates). Matching only by
18199
+ * prefix makes `.find` return the first sibling — wrong template (e.g. offboarding runs onboarding).
18200
+ */
18201
+ const action = command.name.includes('&')
18202
+ ? flatActions.find((a) => a.name === command.name)
18203
+ : flatActions.find((a) => {
18204
+ return a.name === command.name || a.name === commandName || a.name.split('&')[0] === commandName;
18205
+ });
17436
18206
  if (!action) {
17437
18207
  console.warn(`Action ${commandName} not found in entity definition`);
17438
18208
  return {
@@ -19388,6 +20158,9 @@ function getDedupKey(op, entityName, init) {
19388
20158
  if (op === 'getOne' && init?.id !== undefined) {
19389
20159
  return `getOne:${entityName}:${String(init.id)}`;
19390
20160
  }
20161
+ if (op === 'exists' && init?.id !== undefined) {
20162
+ return `exists:${entityName}:${String(init.id)}`;
20163
+ }
19391
20164
  if (op === 'getAll') {
19392
20165
  return `getAll:${entityName}`;
19393
20166
  }
@@ -19395,6 +20168,20 @@ function getDedupKey(op, entityName, init) {
19395
20168
  const r = init.request;
19396
20169
  return `query:${entityName}:${r.skip ?? 0}:${r.take ?? 0}:${JSON.stringify(r.filter ?? null)}:${JSON.stringify(r.sort ?? null)}:${JSON.stringify(r.params ?? null)}`;
19397
20170
  }
20171
+ if (op === 'count' && init?.request) {
20172
+ const r = init.request;
20173
+ return `count:${entityName}:${JSON.stringify(r.filter ?? null)}:${JSON.stringify(r.sort ?? null)}`;
20174
+ }
20175
+ if (op === 'queryAll' && init?.request) {
20176
+ const r = init.request;
20177
+ return `queryAll:${entityName}:${JSON.stringify(r.filter ?? null)}:${JSON.stringify(r.sort ?? null)}:${JSON.stringify(init.queryAllOptions ?? null)}`;
20178
+ }
20179
+ if (op === 'getMany' && init?.ids) {
20180
+ return `getMany:${entityName}:${init.ids.map(String).join(',')}`;
20181
+ }
20182
+ if (op === 'aggregate' && init?.aggregateRequest) {
20183
+ return `aggregate:${entityName}:${JSON.stringify(init.aggregateRequest)}:${JSON.stringify(init.aggregateOptions ?? null)}`;
20184
+ }
19398
20185
  return '';
19399
20186
  }
19400
20187
  class AXPMiddlewareEntityStorageService extends AXPEntityStorageService {
@@ -19454,6 +20241,13 @@ class AXPMiddlewareEntityStorageService extends AXPEntityStorageService {
19454
20241
  insertOne: (name, e) => this.backend.insertOne(name, e),
19455
20242
  query: (name, request) => this.backend.query(name, request),
19456
20243
  updateOne: (name, id, data) => this.backend.updateOne(name, id, data),
20244
+ deleteOne: (name, id) => this.backend.deleteOne(name, id),
20245
+ count: (name, request) => this.backend.count(name, request),
20246
+ queryAll: (name, request, options) => this.backend.queryAll(name, request, options),
20247
+ getMany: (name, ids) => this.backend.getMany(name, ids),
20248
+ exists: (name, id) => this.backend.exists(name, id),
20249
+ upsertOne: (name, entity, options) => this.backend.upsertOne(name, entity, options),
20250
+ aggregate: (name, request, options) => this.backend.aggregate(name, request, options),
19457
20251
  },
19458
20252
  ...init,
19459
20253
  };
@@ -19525,6 +20319,100 @@ class AXPMiddlewareEntityStorageService extends AXPEntityStorageService {
19525
20319
  const ctx = this.createCtx('query', entityName, { request });
19526
20320
  return this.run(ctx, () => this.backend.query(ctx.entityName, request));
19527
20321
  }
20322
+ async count(entityName, request) {
20323
+ const filterSortRequest = { ...request, skip: 0, take: 0 };
20324
+ const key = getDedupKey('count', entityName, { request: filterSortRequest });
20325
+ if (key) {
20326
+ const existing = this.inFlight.get(key);
20327
+ if (existing) {
20328
+ return existing;
20329
+ }
20330
+ const promise = this.runWithDedup(key, () => {
20331
+ const ctx = this.createCtx('count', entityName, { request: filterSortRequest });
20332
+ return this.run(ctx, () => this.backend.count(ctx.entityName, request));
20333
+ });
20334
+ this.inFlight.set(key, promise);
20335
+ return promise;
20336
+ }
20337
+ const ctx = this.createCtx('count', entityName, { request: filterSortRequest });
20338
+ return this.run(ctx, () => this.backend.count(ctx.entityName, request));
20339
+ }
20340
+ async queryAll(entityName, request, options) {
20341
+ const filterSortRequest = { ...request, skip: 0, take: 0 };
20342
+ const key = getDedupKey('queryAll', entityName, { request: filterSortRequest, queryAllOptions: options });
20343
+ if (key) {
20344
+ const existing = this.inFlight.get(key);
20345
+ if (existing) {
20346
+ return existing;
20347
+ }
20348
+ const promise = this.runWithDedup(key, () => {
20349
+ const ctx = this.createCtx('queryAll', entityName, { request: filterSortRequest });
20350
+ return this.run(ctx, () => this.backend.queryAll(ctx.entityName, request, options));
20351
+ });
20352
+ this.inFlight.set(key, promise);
20353
+ return promise;
20354
+ }
20355
+ const ctx = this.createCtx('queryAll', entityName, { request: filterSortRequest });
20356
+ return this.run(ctx, () => this.backend.queryAll(ctx.entityName, request, options));
20357
+ }
20358
+ async getMany(entityName, ids) {
20359
+ const key = getDedupKey('getMany', entityName, { ids: ids });
20360
+ if (key) {
20361
+ const existing = this.inFlight.get(key);
20362
+ if (existing) {
20363
+ return existing;
20364
+ }
20365
+ const promise = this.runWithDedup(key, () => {
20366
+ const ctx = this.createCtx('getMany', entityName);
20367
+ return this.run(ctx, () => this.backend.getMany(ctx.entityName, ids));
20368
+ });
20369
+ this.inFlight.set(key, promise);
20370
+ return promise;
20371
+ }
20372
+ const ctx = this.createCtx('getMany', entityName);
20373
+ return this.run(ctx, () => this.backend.getMany(ctx.entityName, ids));
20374
+ }
20375
+ async exists(entityName, id) {
20376
+ const key = getDedupKey('exists', entityName, { id });
20377
+ if (key) {
20378
+ const existing = this.inFlight.get(key);
20379
+ if (existing) {
20380
+ return existing;
20381
+ }
20382
+ const promise = this.runWithDedup(key, () => {
20383
+ const ctx = this.createCtx('exists', entityName, { id });
20384
+ return this.run(ctx, () => this.backend.exists(ctx.entityName, id));
20385
+ });
20386
+ this.inFlight.set(key, promise);
20387
+ return promise;
20388
+ }
20389
+ const ctx = this.createCtx('exists', entityName, { id });
20390
+ return this.run(ctx, () => this.backend.exists(ctx.entityName, id));
20391
+ }
20392
+ async upsertOne(entityName, entity, options) {
20393
+ const ctx = this.createCtx('upsertOne', entityName, { data: entity });
20394
+ ctx.locals.set('upsertOptions', options);
20395
+ return this.run(ctx, () => this.backend.upsertOne(ctx.entityName, entity, options));
20396
+ }
20397
+ async aggregate(entityName, request, options) {
20398
+ const key = getDedupKey('aggregate', entityName, { aggregateRequest: request, aggregateOptions: options });
20399
+ if (key) {
20400
+ const existing = this.inFlight.get(key);
20401
+ if (existing) {
20402
+ return existing;
20403
+ }
20404
+ const promise = this.runWithDedup(key, () => {
20405
+ const ctx = this.createCtx('aggregate', entityName);
20406
+ ctx.locals.set('aggregateRequest', request);
20407
+ ctx.locals.set('aggregateOptions', options);
20408
+ return this.run(ctx, () => this.backend.aggregate(ctx.entityName, request, options));
20409
+ });
20410
+ this.inFlight.set(key, promise);
20411
+ return promise;
20412
+ }
20413
+ const ctx = this.createCtx('aggregate', entityName);
20414
+ return this.run(ctx, () => this.backend.aggregate(ctx.entityName, request, options));
20415
+ }
19528
20416
  async runWithDedup(key, fn) {
19529
20417
  try {
19530
20418
  return await fn();
@@ -20485,5 +21373,5 @@ var getEntityDetails_query = /*#__PURE__*/Object.freeze({
20485
21373
  * Generated bundle index. Do not edit.
20486
21374
  */
20487
21375
 
20488
- 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, AXPEntityDefinitionProviderWidget, AXPEntityDefinitionProviderWidgetEditComponent, 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, AXPRelatedColumnEnrichmentService, AXPRelatedColumnMetadataResolver, AXPSelectorStructureWidget, AXPSelectorStructureWidgetColumnComponent, AXPSelectorStructureWidgetEditComponent, AXPSelectorStructureWidgetViewComponent, AXPShowDetailViewAction, AXPShowDetailsViewWorkflow, AXPShowListViewAction, AXPShowListViewWorkflow, AXPTruncatedBreadcrumbComponent, AXPUpdateEntityCommand, AXPViewEntityDetailsCommand, AXP_CATEGORY_TREE_ROOT_TITLE_I18N_KEY, 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_COLUMN_ORDER, DEFAULT_PAIR_SPAN_RULES, DEFAULT_PROPERTY_ORDER, DEFAULT_SECTION_ORDER, EntityBuilder, EntityDataAccessor, actionExists, axpCreateEntityAiToolInputDefaults, axpCreateEntityCommandDefinition, cloneLayoutArrays, collectEntityQuickSearchFieldPaths, collectNestedCreateHiddenProperties, collectNestedFieldPathsFromEntityColumns, collectQuickSearchPathsFromSingleEntityDefinition, columnOrderingMiddleware, columnOrderingMiddlewareProvider, columnWidthMiddleware, columnWidthMiddlewareProvider, createColumnOrderingMiddlewareProvider, createLayoutOrderingMiddlewareProvider, createModifierContext, defaultMultiLanguageMiddleware, defaultMultiLanguageMiddlewareProvider, detectEntityChanges, ensureLayoutPropertyView, ensureLayoutSection, ensureListActions, entityDetailsCreateActions, entityDetailsCreateActionsDeferredParent, entityDetailsCrudActions, entityDetailsEditAction, entityDetailsNewEditAction, entityDetailsReferenceCondition, entityDetailsReferenceCreateActions, entityDetailsSimpleCondition, entityMasterBulkDeleteAction, entityMasterCreateAction, entityMasterCrudActions, entityMasterDeleteAction, entityMasterEditAction, entityMasterRecordActions, entityMasterViewAction, entityOverrideDetailsViewAction, eventDispatchMiddleware, getMasterInterfacePropertySortKey, isAXPMiddlewareAbortError, layoutOrderingMiddlewareFactory, layoutOrderingMiddlewareProvider, mergeForeignKeyFieldIntoCreateActions, provideEntity, resolveEntityPluginDetailPageOrder, searchResultDescriptionMiddleware, searchResultDescriptionMiddlewareProvider };
21376
+ 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, AXPEntityDefinitionProviderWidget, AXPEntityDefinitionProviderWidgetEditComponent, 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, AXPRelatedColumnEnrichmentService, AXPRelatedColumnMetadataResolver, AXPSelectorStructureWidget, AXPSelectorStructureWidgetColumnComponent, AXPSelectorStructureWidgetEditComponent, AXPSelectorStructureWidgetViewComponent, AXPShowDetailViewAction, AXPShowDetailsViewWorkflow, AXPShowListViewAction, AXPShowListViewWorkflow, AXPTruncatedBreadcrumbComponent, AXPUpdateEntityCommand, AXPViewEntityDetailsCommand, AXP_CATEGORY_TREE_ROOT_TITLE_I18N_KEY, 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_COLUMN_ORDER, DEFAULT_PAIR_SPAN_RULES, DEFAULT_PROPERTY_ORDER, DEFAULT_SECTION_ORDER, ENTITY_LIST_ROUTE_CONTEXT_SESSION_KEY, EntityBuilder, EntityDataAccessor, actionExists, applyDataSourcePagingWithoutLoad, axpCreateEntityAiToolInputDefaults, axpCreateEntityCommandDefinition, canPersistEntityListState, cloneLayoutArrays, collectEntityQuickSearchFieldPaths, collectNestedCreateHiddenProperties, collectNestedFieldPathsFromEntityColumns, collectQuickSearchPathsFromSingleEntityDefinition, columnOrderingMiddleware, columnOrderingMiddlewareProvider, columnWidthMiddleware, columnWidthMiddlewareProvider, computeEntityAggregates, createColumnOrderingMiddlewareProvider, createLayoutOrderingMiddlewareProvider, createModifierContext, defaultMultiLanguageMiddleware, defaultMultiLanguageMiddlewareProvider, detectEntityChanges, ensureLayoutPropertyView, ensureLayoutSection, ensureListActions, entityDetailsCreateActions, entityDetailsCreateActionsDeferredParent, entityDetailsCrudActions, entityDetailsEditAction, entityDetailsNewEditAction, entityDetailsReferenceCondition, entityDetailsReferenceCreateActions, entityDetailsSimpleCondition, entityMasterBulkDeleteAction, entityMasterCreateAction, entityMasterCrudActions, entityMasterDeleteAction, entityMasterEditAction, entityMasterRecordActions, entityMasterViewAction, entityOverrideDetailsViewAction, eventDispatchMiddleware, filterSortEntityRows, findEntityListRowDataInTree, getDataSourcePageIndex, getEntityListRowId, getMasterInterfacePropertySortKey, isAXPMiddlewareAbortError, isCategoryEntity, isCategoryFilter, layoutOrderingMiddlewareFactory, layoutOrderingMiddlewareProvider, mergeForeignKeyFieldIntoCreateActions, normalizeEntityListPersistenceMode, normalizeListPaging, provideEntity, resolveEntityPluginDetailPageOrder, restoreEntityListExpandedRows, runEntityQuery, searchResultDescriptionMiddleware, searchResultDescriptionMiddlewareProvider, shouldLoadEntityListStateFromStorage, shouldResetEntityListStateOnRouteEntry };
20489
21377
  //# sourceMappingURL=acorex-platform-layout-entity.mjs.map