@acorex/platform 21.0.0-beta.8 → 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.
- package/fesm2022/{acorex-platform-common-common-settings.provider-lWz_f-Ia.mjs → acorex-platform-common-common-settings.provider-Bi1RYif5.mjs} +41 -3
- package/fesm2022/acorex-platform-common-common-settings.provider-Bi1RYif5.mjs.map +1 -0
- package/fesm2022/acorex-platform-common.mjs +205 -164
- package/fesm2022/acorex-platform-common.mjs.map +1 -1
- package/fesm2022/acorex-platform-core.mjs +5 -4
- package/fesm2022/acorex-platform-core.mjs.map +1 -1
- package/fesm2022/acorex-platform-layout-components.mjs +2 -2
- package/fesm2022/acorex-platform-layout-components.mjs.map +1 -1
- package/fesm2022/acorex-platform-layout-entity.mjs +578 -63
- package/fesm2022/acorex-platform-layout-entity.mjs.map +1 -1
- package/fesm2022/acorex-platform-layout-views.mjs +5 -3
- package/fesm2022/acorex-platform-layout-views.mjs.map +1 -1
- package/fesm2022/acorex-platform-layout-widget-core.mjs +72 -6
- package/fesm2022/acorex-platform-layout-widget-core.mjs.map +1 -1
- package/fesm2022/acorex-platform-layout-widgets.mjs +109 -131
- package/fesm2022/acorex-platform-layout-widgets.mjs.map +1 -1
- package/fesm2022/acorex-platform-themes-default.mjs +118 -12
- package/fesm2022/acorex-platform-themes-default.mjs.map +1 -1
- package/fesm2022/acorex-platform-workflow.mjs +85 -4
- package/fesm2022/acorex-platform-workflow.mjs.map +1 -1
- package/package.json +6 -6
- package/types/acorex-platform-common.d.ts +65 -47
- package/types/acorex-platform-layout-entity.d.ts +121 -4
- package/types/acorex-platform-layout-widget-core.d.ts +15 -0
- package/types/acorex-platform-layout-widgets.d.ts +15 -19
- package/types/acorex-platform-themes-default.d.ts +8 -0
- package/types/acorex-platform-workflow.d.ts +68 -2
- 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
|
|
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
|
-
|
|
386
|
+
steps.push(this.createModifierStep(exact, context));
|
|
387
|
+
}
|
|
388
|
+
for (const entry of this.patternModifiers) {
|
|
389
|
+
if (entry.pattern.test(entity.name)) {
|
|
390
|
+
steps.push(this.createModifierStep(entry, context));
|
|
391
|
+
}
|
|
405
392
|
}
|
|
406
|
-
|
|
407
|
-
for (const
|
|
408
|
-
|
|
409
|
-
|
|
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));
|
|
410
398
|
}
|
|
411
399
|
}
|
|
412
|
-
|
|
413
|
-
for (const
|
|
414
|
-
|
|
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, '\\$&');
|
|
@@ -3979,6 +3992,11 @@ class AXPEntityDetailListViewModel {
|
|
|
3979
3992
|
this.filterOperatorMiddleware = this.injector.get(AXPFilterOperatorMiddlewareService);
|
|
3980
3993
|
this.expressionEvaluator = this.injector.get(AXPExpressionEvaluatorService);
|
|
3981
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 */ []));
|
|
3982
4000
|
this.dataSource = new AXDataSource({
|
|
3983
4001
|
byKey: async (key) => {
|
|
3984
4002
|
const execute = this.detailEntity()?.queries?.byKey?.execute;
|
|
@@ -4118,8 +4136,28 @@ class AXPEntityDetailListViewModel {
|
|
|
4118
4136
|
};
|
|
4119
4137
|
return await this.expressionEvaluator.evaluate(actionData, scope);
|
|
4120
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
|
+
});
|
|
4121
4146
|
this.initialize();
|
|
4122
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
|
+
}
|
|
4123
4161
|
async initialize() {
|
|
4124
4162
|
const entityResolver = this.injector.get(AXPEntityDefinitionRegistryService);
|
|
4125
4163
|
const [moduleName, entityName] = this.detailEntityConfig.entity.split('.');
|
|
@@ -4259,6 +4297,118 @@ const AXPEntityEventsKeys = {
|
|
|
4259
4297
|
REFRESH_DATA: 'entity:refresh-data',
|
|
4260
4298
|
};
|
|
4261
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
|
+
|
|
4262
4412
|
/**
|
|
4263
4413
|
* Entity Event Dispatcher - A wrapper for entity-specific events
|
|
4264
4414
|
* Handles pattern-based dispatching for entity operations with wildcard support
|
|
@@ -4592,14 +4742,17 @@ class AXPEntityMasterListViewModel {
|
|
|
4592
4742
|
return `${resolvedCommand}${suffix}`;
|
|
4593
4743
|
}
|
|
4594
4744
|
async setView(viewName = null) {
|
|
4595
|
-
|
|
4596
|
-
|
|
4745
|
+
let selectedViewName;
|
|
4746
|
+
if (await this.shouldLoadPersistedListState()) {
|
|
4747
|
+
const entitySetting = await this.settings.get(this.settingEntityKey);
|
|
4748
|
+
selectedViewName = entitySetting?.list?.currentView;
|
|
4749
|
+
}
|
|
4597
4750
|
if (viewName != this.view().name) {
|
|
4598
4751
|
this.view.set(this.views().find((c) => c.name == (viewName || selectedViewName)) ?? this.views()[0]);
|
|
4599
4752
|
this.applyViewSorts();
|
|
4600
4753
|
this.applyViewColumns();
|
|
4601
4754
|
this.applyViewFilters();
|
|
4602
|
-
|
|
4755
|
+
this.resolvedListPaging.set(null);
|
|
4603
4756
|
await this.applySettings();
|
|
4604
4757
|
}
|
|
4605
4758
|
}
|
|
@@ -4623,6 +4776,15 @@ class AXPEntityMasterListViewModel {
|
|
|
4623
4776
|
this.lastAppliedSortKey = null;
|
|
4624
4777
|
this.lastAppliedFilterKey = null;
|
|
4625
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;
|
|
4626
4788
|
this.events$ = new Subject();
|
|
4627
4789
|
//****************** Views ******************//
|
|
4628
4790
|
this.views = computed(() => {
|
|
@@ -4632,6 +4794,18 @@ class AXPEntityMasterListViewModel {
|
|
|
4632
4794
|
});
|
|
4633
4795
|
}, ...(ngDevMode ? [{ debugName: "views" }] : /* istanbul ignore next */ []));
|
|
4634
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 */ []));
|
|
4635
4809
|
this.dataSource = new AXDataSource({
|
|
4636
4810
|
byKey: async (key) => {
|
|
4637
4811
|
const execute = this.entityDef.queries?.byKey?.execute;
|
|
@@ -4802,13 +4976,88 @@ class AXPEntityMasterListViewModel {
|
|
|
4802
4976
|
}
|
|
4803
4977
|
});
|
|
4804
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
|
+
});
|
|
4805
5048
|
}
|
|
4806
5049
|
async applySettings() {
|
|
4807
|
-
this.
|
|
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
|
+
}
|
|
4808
5058
|
const listViewSetting = await this.settings.get(this.settingEntityKey);
|
|
4809
5059
|
if (listViewSetting) {
|
|
4810
5060
|
const columns = listViewSetting.list?.views?.[this.view().name]?.columns;
|
|
4811
|
-
const pageSize = listViewSetting.list?.views?.[this.view().name]?.pageSize;
|
|
4812
5061
|
const sorts = listViewSetting.list?.views?.[this.view().name]?.sorts;
|
|
4813
5062
|
const filters = listViewSetting.list?.views?.[this.view().name]?.filters;
|
|
4814
5063
|
let columnVisibilityMap;
|
|
@@ -4817,7 +5066,7 @@ class AXPEntityMasterListViewModel {
|
|
|
4817
5066
|
columnVisibilityMap = new Map(columns.map((col) => [col.name, col.visible]));
|
|
4818
5067
|
columnWidthsMap = new Map(columns.map((col) => [col.name, col.width]));
|
|
4819
5068
|
}
|
|
4820
|
-
|
|
5069
|
+
this.loadListPagingFromViewSettings(listViewSetting);
|
|
4821
5070
|
if (columns && columnVisibilityMap && columnWidthsMap) {
|
|
4822
5071
|
this.columns.update((prev) => prev
|
|
4823
5072
|
.map((c) => {
|
|
@@ -4839,16 +5088,102 @@ class AXPEntityMasterListViewModel {
|
|
|
4839
5088
|
if (Array.isArray(filters) && !this.hasQueryParamsFilters) {
|
|
4840
5089
|
this.filterQueries.set(filters);
|
|
4841
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;
|
|
4842
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;
|
|
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);
|
|
4843
5174
|
}
|
|
4844
5175
|
async saveSettings(changesType, data) {
|
|
5176
|
+
if (!(await this.shouldPersistListState())) {
|
|
5177
|
+
return;
|
|
5178
|
+
}
|
|
4845
5179
|
const updateSettings = (updateFn) => {
|
|
4846
5180
|
this.settings.scope(AXPPlatformScope.User).update(this.settingEntityKey, updateFn);
|
|
4847
5181
|
};
|
|
4848
5182
|
switch (changesType) {
|
|
4849
|
-
case 'columnSizes':
|
|
5183
|
+
case 'columnSizes': {
|
|
5184
|
+
const columnSizeData = data;
|
|
4850
5185
|
updateSettings((prev) => {
|
|
4851
|
-
const field =
|
|
5186
|
+
const field = columnSizeData.dataField.split('-')[1];
|
|
4852
5187
|
const newSettings = { ...prev };
|
|
4853
5188
|
const existingColumns = prev?.list?.views?.[this.view().name]?.columns;
|
|
4854
5189
|
const baseColumns = Array.isArray(existingColumns) && existingColumns.length
|
|
@@ -4860,7 +5195,7 @@ class AXPEntityMasterListViewModel {
|
|
|
4860
5195
|
}));
|
|
4861
5196
|
const updatedColumns = baseColumns.map((c) => ({
|
|
4862
5197
|
...c,
|
|
4863
|
-
width: c.name === field ?
|
|
5198
|
+
width: c.name === field ? columnSizeData.width : c.width,
|
|
4864
5199
|
}));
|
|
4865
5200
|
const x = this.allAvailableColumns().map((c) => ({
|
|
4866
5201
|
name: c.column?.options?.dataPath ?? c.name,
|
|
@@ -4871,10 +5206,12 @@ class AXPEntityMasterListViewModel {
|
|
|
4871
5206
|
return newSettings;
|
|
4872
5207
|
});
|
|
4873
5208
|
break;
|
|
4874
|
-
|
|
5209
|
+
}
|
|
5210
|
+
case 'columnOrders': {
|
|
5211
|
+
const orderedColumns = data;
|
|
4875
5212
|
updateSettings((prev) => {
|
|
4876
5213
|
const newSettings = { ...prev };
|
|
4877
|
-
set(newSettings, `list.views.${this.view().name}.columns`,
|
|
5214
|
+
set(newSettings, `list.views.${this.view().name}.columns`, orderedColumns.map((c) => ({
|
|
4878
5215
|
name: c.column?.options?.dataPath ?? c.name,
|
|
4879
5216
|
visible: c.visible,
|
|
4880
5217
|
width: c.width,
|
|
@@ -4882,6 +5219,7 @@ class AXPEntityMasterListViewModel {
|
|
|
4882
5219
|
return newSettings;
|
|
4883
5220
|
});
|
|
4884
5221
|
break;
|
|
5222
|
+
}
|
|
4885
5223
|
case 'view':
|
|
4886
5224
|
updateSettings((prev) => ({
|
|
4887
5225
|
...prev,
|
|
@@ -4901,6 +5239,26 @@ class AXPEntityMasterListViewModel {
|
|
|
4901
5239
|
[this.view().name]: {
|
|
4902
5240
|
...prev?.list?.views?.[this.view().name],
|
|
4903
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,
|
|
4904
5262
|
},
|
|
4905
5263
|
},
|
|
4906
5264
|
},
|
|
@@ -4936,6 +5294,21 @@ class AXPEntityMasterListViewModel {
|
|
|
4936
5294
|
},
|
|
4937
5295
|
}));
|
|
4938
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;
|
|
4939
5312
|
default:
|
|
4940
5313
|
break;
|
|
4941
5314
|
}
|
|
@@ -5175,6 +5548,7 @@ class AXPEntityMasterListViewModel {
|
|
|
5175
5548
|
this.applyViewFilters();
|
|
5176
5549
|
}
|
|
5177
5550
|
async applyFilterAndSort() {
|
|
5551
|
+
await this.ensureListPagingResolved();
|
|
5178
5552
|
const sorts = this.sortedFields()
|
|
5179
5553
|
.filter((sf) => sf.dir)
|
|
5180
5554
|
.map((s) => ({ name: s.name, dir: s.dir }));
|
|
@@ -5184,10 +5558,12 @@ class AXPEntityMasterListViewModel {
|
|
|
5184
5558
|
if (sortKey === this.lastAppliedSortKey && filterKey === this.lastAppliedFilterKey) {
|
|
5185
5559
|
return; // No effective change; avoid redundant refresh
|
|
5186
5560
|
}
|
|
5187
|
-
|
|
5188
|
-
const filtersChanged = filterKey !== this.lastAppliedFilterKey;
|
|
5561
|
+
const filtersChanged = this.lastAppliedFilterKey != null && filterKey !== this.lastAppliedFilterKey;
|
|
5189
5562
|
this.lastAppliedSortKey = sortKey;
|
|
5190
5563
|
this.lastAppliedFilterKey = filterKey;
|
|
5564
|
+
if (filtersChanged) {
|
|
5565
|
+
this.resetListPagingSkip();
|
|
5566
|
+
}
|
|
5191
5567
|
this.dataSource.clearFilter();
|
|
5192
5568
|
this.dataSource.sort(...sorts.map((s) => ({ dir: s.dir, field: s.name })));
|
|
5193
5569
|
this.dataSource.filter(this.filterOperatorMiddleware.transformFilter({
|
|
@@ -5394,7 +5770,9 @@ class AXPEntityListViewModelFactory {
|
|
|
5394
5770
|
this.layout.setNavigationLoading(true);
|
|
5395
5771
|
const config = await this.entityService.resolve(moduleName, entityName);
|
|
5396
5772
|
this.layout.setNavigationLoading(false);
|
|
5397
|
-
|
|
5773
|
+
const vm = new AXPEntityMasterListViewModel(this.injector, config);
|
|
5774
|
+
await vm.initializeListPersistence();
|
|
5775
|
+
return vm;
|
|
5398
5776
|
}
|
|
5399
5777
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPEntityListViewModelFactory, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
5400
5778
|
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPEntityListViewModelFactory, providedIn: 'root' }); }
|
|
@@ -10836,6 +11214,7 @@ class AXPEntityListTableService {
|
|
|
10836
11214
|
this.workflow = inject(AXPWorkflowService);
|
|
10837
11215
|
this.commandService = inject(AXPCommandService);
|
|
10838
11216
|
this.expressionEvaluator = inject(AXPExpressionEvaluatorService);
|
|
11217
|
+
this.settings = inject(AXPSettingsService);
|
|
10839
11218
|
this.evaluateExpressions = async (options, data) => {
|
|
10840
11219
|
if (!options) {
|
|
10841
11220
|
return {};
|
|
@@ -10856,6 +11235,20 @@ class AXPEntityListTableService {
|
|
|
10856
11235
|
* Convert Entity to List Widget Options
|
|
10857
11236
|
*/
|
|
10858
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
|
+
}
|
|
10859
11252
|
const listOptions = {
|
|
10860
11253
|
// 📊 Data Source
|
|
10861
11254
|
dataSource: this.createDataSource(entity),
|
|
@@ -10865,7 +11258,7 @@ class AXPEntityListTableService {
|
|
|
10865
11258
|
primaryCommands: this.createRowCommands(allActions, 'primary'),
|
|
10866
11259
|
secondaryCommands: this.createRowCommands(allActions, 'secondary'),
|
|
10867
11260
|
// ⚙️ Table Features
|
|
10868
|
-
showIndex
|
|
11261
|
+
showIndex,
|
|
10869
11262
|
allowSelection: this.hasSelectedScopeActions(entity),
|
|
10870
11263
|
paging: true,
|
|
10871
11264
|
showHeader: true,
|
|
@@ -10882,7 +11275,6 @@ class AXPEntityListTableService {
|
|
|
10882
11275
|
// 🎪 Events
|
|
10883
11276
|
...this.createDefaultEvents(entity, allActions, options?.excludeProperties),
|
|
10884
11277
|
};
|
|
10885
|
-
console.log('listOptions', listOptions);
|
|
10886
11278
|
return listOptions;
|
|
10887
11279
|
}
|
|
10888
11280
|
//#endregion
|
|
@@ -11270,6 +11662,7 @@ class AXPEntityListWidgetViewComponent extends AXPValueWidgetComponent {
|
|
|
11270
11662
|
this.commandService = inject(AXPCommandService);
|
|
11271
11663
|
this.eventService = inject(AXPBroadcastEventService);
|
|
11272
11664
|
this.expressionEvaluator = inject(AXPExpressionEvaluatorService);
|
|
11665
|
+
this.route = inject(ActivatedRoute);
|
|
11273
11666
|
this.isMounted = signal(false, ...(ngDevMode ? [{ debugName: "isMounted" }] : /* istanbul ignore next */ []));
|
|
11274
11667
|
this.entity = signal(null, ...(ngDevMode ? [{ debugName: "entity" }] : /* istanbul ignore next */ []));
|
|
11275
11668
|
this.listNode = signal(null, ...(ngDevMode ? [{ debugName: "listNode" }] : /* istanbul ignore next */ []));
|
|
@@ -11443,13 +11836,7 @@ class AXPEntityListWidgetViewComponent extends AXPValueWidgetComponent {
|
|
|
11443
11836
|
// console.log(this.listWidget()?.instance.output('selectedRows'));
|
|
11444
11837
|
// }
|
|
11445
11838
|
async execute(commandName, _data) {
|
|
11446
|
-
const action = this.
|
|
11447
|
-
return (c.name == commandName &&
|
|
11448
|
-
((this.selectedItems().length
|
|
11449
|
-
? c.scope == AXPEntityCommandScope.Selected
|
|
11450
|
-
: c.scope == AXPEntityCommandScope.Individual) ||
|
|
11451
|
-
c.scope == AXPEntityCommandScope.TypeLevel));
|
|
11452
|
-
});
|
|
11839
|
+
const action = this.findToolbarAction(commandName);
|
|
11453
11840
|
const command = commandName.split('&')[0];
|
|
11454
11841
|
const commandData = action?.scope == AXPEntityCommandScope.Selected
|
|
11455
11842
|
? this.selectedItems()
|
|
@@ -11515,6 +11902,29 @@ class AXPEntityListWidgetViewComponent extends AXPValueWidgetComponent {
|
|
|
11515
11902
|
});
|
|
11516
11903
|
}
|
|
11517
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
|
+
}
|
|
11518
11928
|
async evaluateToolbarExpressions(opts, expressionData) {
|
|
11519
11929
|
if (!opts) {
|
|
11520
11930
|
return {};
|
|
@@ -11527,6 +11937,92 @@ class AXPEntityListWidgetViewComponent extends AXPValueWidgetComponent {
|
|
|
11527
11937
|
};
|
|
11528
11938
|
return (await this.expressionEvaluator.evaluate(opts, scope));
|
|
11529
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
|
+
}
|
|
11530
12026
|
/**
|
|
11531
12027
|
* Re-evaluates related-entity list filters from the live dialog form context (e.g. after create saves the main row id).
|
|
11532
12028
|
*/
|
|
@@ -11716,23 +12212,27 @@ class AXPEntityListWidgetViewComponent extends AXPValueWidgetComponent {
|
|
|
11716
12212
|
mode: 'view',
|
|
11717
12213
|
defaultValue: this.getValue()?.table,
|
|
11718
12214
|
});
|
|
12215
|
+
const mergedToolbarFilters = this.getMergedToolbarFilters();
|
|
11719
12216
|
this.toolbarNode.set({
|
|
11720
12217
|
type: AXPWidgetsCatalog.listToolbar,
|
|
11721
12218
|
path: `toolbar`,
|
|
11722
12219
|
options: toolbarOptions,
|
|
11723
12220
|
mode: 'view',
|
|
11724
12221
|
defaultValue: {
|
|
11725
|
-
filters:
|
|
12222
|
+
filters: mergedToolbarFilters,
|
|
11726
12223
|
sorts: this.getValue()?.toolbar?.sorts,
|
|
11727
12224
|
columns: this.getValue()?.toolbar?.columns,
|
|
11728
12225
|
},
|
|
11729
12226
|
});
|
|
11730
12227
|
queueMicrotask(() => {
|
|
11731
|
-
|
|
12228
|
+
this.applyMergedRouteFiltersToList();
|
|
11732
12229
|
});
|
|
11733
12230
|
}, 100);
|
|
11734
12231
|
}
|
|
11735
12232
|
async ngAfterViewInit() {
|
|
12233
|
+
this.route.queryParamMap.pipe(takeUntil(this.destroyed)).subscribe(() => {
|
|
12234
|
+
this.applyMergedRouteFiltersToList();
|
|
12235
|
+
});
|
|
11736
12236
|
this.workflow.events$
|
|
11737
12237
|
.pipe(ofType(AXPRefreshEvent))
|
|
11738
12238
|
.pipe(takeUntil(this.destroyed))
|
|
@@ -13524,6 +14024,14 @@ class AXPLookupWidgetEditComponent extends AXPValueWidgetComponent {
|
|
|
13524
14024
|
}
|
|
13525
14025
|
});
|
|
13526
14026
|
}
|
|
14027
|
+
outputs() {
|
|
14028
|
+
return [
|
|
14029
|
+
{
|
|
14030
|
+
name: 'selectedItems',
|
|
14031
|
+
value: this.selectedItems(),
|
|
14032
|
+
},
|
|
14033
|
+
];
|
|
14034
|
+
}
|
|
13527
14035
|
singleOrMultiple(values) {
|
|
13528
14036
|
return this.multiple() ? values : values[0];
|
|
13529
14037
|
}
|
|
@@ -17685,9 +18193,16 @@ class AXPPageListConverter extends AXPBaseRelatedEntityConverter {
|
|
|
17685
18193
|
return result;
|
|
17686
18194
|
};
|
|
17687
18195
|
const flatActions = flattenActions(mergedActions);
|
|
17688
|
-
|
|
17689
|
-
|
|
17690
|
-
|
|
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
|
+
});
|
|
17691
18206
|
if (!action) {
|
|
17692
18207
|
console.warn(`Action ${commandName} not found in entity definition`);
|
|
17693
18208
|
return {
|
|
@@ -20858,5 +21373,5 @@ var getEntityDetails_query = /*#__PURE__*/Object.freeze({
|
|
|
20858
21373
|
* Generated bundle index. Do not edit.
|
|
20859
21374
|
*/
|
|
20860
21375
|
|
|
20861
|
-
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, 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, getMasterInterfacePropertySortKey, isAXPMiddlewareAbortError, isCategoryEntity, isCategoryFilter, layoutOrderingMiddlewareFactory, layoutOrderingMiddlewareProvider, mergeForeignKeyFieldIntoCreateActions, provideEntity, resolveEntityPluginDetailPageOrder, runEntityQuery, 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 };
|
|
20862
21377
|
//# sourceMappingURL=acorex-platform-layout-entity.mjs.map
|