@acorex/platform 18.2.3 → 18.2.4

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 (66) hide show
  1. package/esm2022/common/lib/layout/sticky.directive.mjs +15 -11
  2. package/esm2022/layout/builder/lib/builder/widget-column-renderer.mjs +22 -11
  3. package/esm2022/layout/designer/lib/designer/components/size-mode/view-size-toolbar.component.mjs +27 -32
  4. package/esm2022/layout/entity/lib/entity-master-list.viewmodel.mjs +33 -8
  5. package/esm2022/layout/entity/lib/entity.module.mjs +1 -17
  6. package/esm2022/layout/entity/lib/index.mjs +5 -4
  7. package/esm2022/layout/setting/lib/convert-setting-data.mjs +59 -0
  8. package/esm2022/layout/setting/lib/setting.viewmodel.mjs +123 -41
  9. package/esm2022/layouts/lib/admin/entity-layout/entity-list-view/entity-list-view.component.mjs +3 -3
  10. package/esm2022/themes/default/lib/default.module.mjs +83 -39
  11. package/esm2022/themes/default/lib/layouts/entity-layouts/entity-detail-list-view/entity-detail-list-view.component.mjs +3 -3
  12. package/esm2022/themes/default/lib/layouts/entity-layouts/entity-master-list-view/entity-master-list-view.component.mjs +18 -18
  13. package/esm2022/themes/default/lib/layouts/entity-layouts/entity-master-list-view/list-view-option-columns/list-view-option-columns.component.mjs +18 -8
  14. package/esm2022/themes/default/lib/layouts/root-layout/components/menu/root-menu.component.mjs +1 -1
  15. package/esm2022/themes/default/lib/layouts/setting-layout/index.mjs +3 -3
  16. package/esm2022/themes/default/lib/layouts/setting-layout/setting-menu/setting-menu.component.mjs +28 -0
  17. package/esm2022/themes/default/lib/layouts/setting-layout/setting-view/setting-view.component.mjs +42 -0
  18. package/esm2022/widgets/lib/widgets/advance/cron-job/cron-job-widget-edit.component.mjs +2 -2
  19. package/esm2022/widgets/lib/widgets/advance/cron-job/cron-job-widget.config.mjs +3 -2
  20. package/esm2022/workflow/lib/workflow.service.mjs +1 -1
  21. package/fesm2022/acorex-platform-common.mjs +13 -9
  22. package/fesm2022/acorex-platform-common.mjs.map +1 -1
  23. package/fesm2022/acorex-platform-layout-builder.mjs +18 -7
  24. package/fesm2022/acorex-platform-layout-builder.mjs.map +1 -1
  25. package/fesm2022/acorex-platform-layout-designer.mjs +25 -30
  26. package/fesm2022/acorex-platform-layout-designer.mjs.map +1 -1
  27. package/fesm2022/acorex-platform-layout-entity.mjs +842 -833
  28. package/fesm2022/acorex-platform-layout-entity.mjs.map +1 -1
  29. package/fesm2022/acorex-platform-layout-setting.mjs +180 -40
  30. package/fesm2022/acorex-platform-layout-setting.mjs.map +1 -1
  31. package/fesm2022/acorex-platform-layouts.mjs.map +1 -1
  32. package/fesm2022/{acorex-platform-themes-default-entity-master-create-view.component-CJY8R3sa.mjs → acorex-platform-themes-default-entity-master-create-view.component-Bs6fn6z2.mjs} +3 -3
  33. package/fesm2022/{acorex-platform-themes-default-entity-master-create-view.component-CJY8R3sa.mjs.map → acorex-platform-themes-default-entity-master-create-view.component-Bs6fn6z2.mjs.map} +1 -1
  34. package/fesm2022/{acorex-platform-themes-default-entity-master-list-view.component-C6zgLyry.mjs → acorex-platform-themes-default-entity-master-list-view.component-DPHXeucj.mjs} +39 -30
  35. package/fesm2022/acorex-platform-themes-default-entity-master-list-view.component-DPHXeucj.mjs.map +1 -0
  36. package/fesm2022/{acorex-platform-themes-default-entity-master-modify-view.component-wPZPhMgy.mjs → acorex-platform-themes-default-entity-master-modify-view.component-CWrpcOC2.mjs} +3 -3
  37. package/fesm2022/{acorex-platform-themes-default-entity-master-modify-view.component-wPZPhMgy.mjs.map → acorex-platform-themes-default-entity-master-modify-view.component-CWrpcOC2.mjs.map} +1 -1
  38. package/fesm2022/{acorex-platform-themes-default-entity-master-single-view.component-DNXWb6ij.mjs → acorex-platform-themes-default-entity-master-single-view.component-DHfe0Qtu.mjs} +10 -10
  39. package/fesm2022/{acorex-platform-themes-default-entity-master-single-view.component-DNXWb6ij.mjs.map → acorex-platform-themes-default-entity-master-single-view.component-DHfe0Qtu.mjs.map} +1 -1
  40. package/fesm2022/acorex-platform-themes-default.mjs +153 -257
  41. package/fesm2022/acorex-platform-themes-default.mjs.map +1 -1
  42. package/fesm2022/acorex-platform-widgets.mjs +3 -2
  43. package/fesm2022/acorex-platform-widgets.mjs.map +1 -1
  44. package/fesm2022/acorex-platform-workflow.mjs.map +1 -1
  45. package/layout/builder/lib/builder/widget-column-renderer.d.ts +1 -1
  46. package/layout/entity/lib/entity-master-list.viewmodel.d.ts +6 -2
  47. package/layout/entity/lib/index.d.ts +4 -3
  48. package/layout/setting/README.md +2 -3
  49. package/{themes/default/lib/layouts/setting-layout → layout/setting/lib}/convert-setting-data.d.ts +6 -6
  50. package/layout/setting/lib/setting.viewmodel.d.ts +35 -9
  51. package/package.json +7 -7
  52. package/themes/default/lib/default.module.d.ts +3 -4
  53. package/themes/default/lib/layouts/entity-layouts/entity-master-list-view/list-view-option-columns/list-view-option-columns.component.d.ts +3 -0
  54. package/themes/default/lib/layouts/setting-layout/index.d.ts +2 -2
  55. package/themes/default/lib/layouts/setting-layout/setting-menu/setting-menu.component.d.ts +12 -0
  56. package/themes/default/lib/layouts/setting-layout/setting-view/setting-view.component.d.ts +7 -0
  57. package/widgets/lib/widgets/advance/cron-job/cron-job-widget-edit.component.d.ts +1 -2
  58. package/workflow/lib/workflow.service.d.ts +1 -1
  59. package/esm2022/themes/default/lib/layout.routes.mjs +0 -20
  60. package/esm2022/themes/default/lib/layouts/setting-layout/convert-setting-data.mjs +0 -49
  61. package/esm2022/themes/default/lib/layouts/setting-layout/setting-preview/setting-preview.component.mjs +0 -104
  62. package/esm2022/themes/default/lib/layouts/setting-layout/setting-view/setting-menu.component.mjs +0 -44
  63. package/fesm2022/acorex-platform-themes-default-entity-master-list-view.component-C6zgLyry.mjs.map +0 -1
  64. package/themes/default/lib/layout.routes.d.ts +0 -2
  65. package/themes/default/lib/layouts/setting-layout/setting-preview/setting-preview.component.d.ts +0 -24
  66. package/themes/default/lib/layouts/setting-layout/setting-view/setting-menu.component.d.ts +0 -20
@@ -1,21 +1,21 @@
1
+ import * as i2$1 from '@acorex/components/common';
2
+ import { AXDataSource, AXCommonModule } from '@acorex/components/common';
1
3
  import { AXFormatService } from '@acorex/core/format';
2
- import { cloneDeep, set, merge, isNil, get, sortBy } from 'lodash-es';
4
+ import { resolveActionLook, AXPFilterOperatorMiddlewareService, AXPEntityCommandScope, getEntityInfo, AXPSettingsService, AXPWorkflowNavigateAction } from '@acorex/platform/common';
5
+ import * as i1$3 from '@acorex/platform/workflow';
6
+ import { AXPWorkflowService, createWorkFlowEvent, AXPWorkflowAction, ofType, AXPWorkflowModule } from '@acorex/platform/workflow';
3
7
  import * as i0 from '@angular/core';
4
8
  import { InjectionToken, inject, Injectable, computed, signal, Injector, effect, HostBinding, ChangeDetectionStrategy, Component, DestroyRef, ViewChild, NgModule } from '@angular/core';
5
- import * as i1$3 from '@acorex/platform/workflow';
6
- import { createWorkFlowEvent, AXPWorkflowAction, AXPWorkflowService, ofType, AXPWorkflowModule } from '@acorex/platform/workflow';
9
+ import { cloneDeep, set, merge, isNil, get, sortBy } from 'lodash-es';
10
+ import { AXPLayoutThemeService } from '@acorex/platform/themes/shared';
7
11
  import { AXPSessionService, AXPAuthGuard } from '@acorex/platform/auth';
8
- import { resolveActionLook, AXPFilterOperatorMiddlewareService, AXPEntityCommandScope, getEntityInfo, AXPWorkflowNavigateAction } from '@acorex/platform/common';
12
+ import { Subject, takeUntil } from 'rxjs';
9
13
  import { AXDialogService } from '@acorex/components/dialog';
10
14
  import { AXLoadingDialogService } from '@acorex/components/loading-dialog';
11
15
  import * as i8 from '@acorex/core/translation';
12
16
  import { AXTranslationService, AXTranslationModule } from '@acorex/core/translation';
13
17
  import { AXPopupService } from '@acorex/components/popup';
14
18
  import { AXPlatform } from '@acorex/core/platform';
15
- import { AXPLayoutThemeService } from '@acorex/platform/themes/shared';
16
- import * as i2$1 from '@acorex/components/common';
17
- import { AXDataSource, AXCommonModule } from '@acorex/components/common';
18
- import { Subject, takeUntil } from 'rxjs';
19
19
  import * as i7 from '@acorex/platform/layout/builder';
20
20
  import { AXPWidgetComponent, AXPLayoutBuilderModule, AXPLayoutBuilderService, AXPColumnWidgetComponent, AXPWidgetsCatalog, AXP_WIDGETS_EDITOR_GROUP, AXPWidgetRegistryService } from '@acorex/platform/layout/builder';
21
21
  import { RouterModule, ROUTES } from '@angular/router';
@@ -75,6 +75,213 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.0", ngImpor
75
75
  args: [{ providedIn: 'root' }]
76
76
  }] });
77
77
 
78
+ class AXPEntityCommandTriggerViewModel {
79
+ constructor(entity, action) {
80
+ this.name = action.command;
81
+ const resolvedLook = resolveActionLook(action);
82
+ this.priority = action.priority;
83
+ this.title = action.title;
84
+ this.separated = action.separated ?? false;
85
+ this.color = action.color ?? resolvedLook.color;
86
+ this.icon = action.icon ?? resolvedLook.icon;
87
+ this.scope = action.scope;
88
+ }
89
+ }
90
+ class AXPEntityListViewColumnViewModel {
91
+ constructor(property, column) {
92
+ this.property = property;
93
+ this.column = column;
94
+ this.name = this.property.name;
95
+ this.title = this.column.title ?? this.property.title;
96
+ this.visible = this.column?.options?.visible ?? true;
97
+ this.dir = this.column.sort?.dir;
98
+ this.sortEnabled = this.property.options?.sort?.enabled;
99
+ this.node = computed(() => {
100
+ const widget = this.property.schema.interface;
101
+ return {
102
+ path: this.column.options?.dataPath ?? this.name,
103
+ type: widget.type,
104
+ options: { ...widget?.options, ...this.column?.options },
105
+ };
106
+ });
107
+ }
108
+ }
109
+
110
+ class AXPEntityDetailListViewModel {
111
+ constructor(injector, detailEntityConfig, parent) {
112
+ this.injector = injector;
113
+ this.detailEntityConfig = detailEntityConfig;
114
+ this.parent = parent;
115
+ this.detailEntity = signal(null);
116
+ this.formatService = this.injector.get(AXFormatService);
117
+ this.workflow = this.injector.get(AXPWorkflowService);
118
+ this.filterOperatorMiddleware = this.injector.get(AXPFilterOperatorMiddlewareService);
119
+ this.dataSource = new AXDataSource({
120
+ byKey: (key) => {
121
+ const func = this.detailEntity()?.queries.byKey.execute;
122
+ return func();
123
+ },
124
+ load: (e) => {
125
+ const func = this.detailEntity()?.queries.list?.execute;
126
+ return func(e);
127
+ },
128
+ pageSize: 5,
129
+ key: 'id',
130
+ });
131
+ this.selectedItems = signal([]);
132
+ this.hasSelectedItems = computed(() => {
133
+ return this.selectedItems().length > 0;
134
+ });
135
+ //****************** Title ******************//
136
+ this.title = computed(() => {
137
+ return (this.detailEntityConfig.title ??
138
+ this.detailEntity()?.interfaces?.detail?.list?.title ??
139
+ this.detailEntity()?.formats.plural);
140
+ });
141
+ //****************** Inline filter ******************//
142
+ this.inlineFiltersPlaceholders = computed(() => {
143
+ //return this.entityDef.properties.filter(p => p.options?.filter?.inline?.enabled).map(c => c.title);
144
+ return [];
145
+ });
146
+ this.hasInlineFilters = computed(() => {
147
+ return this.inlineFiltersPlaceholders().length > 0;
148
+ });
149
+ //****************** Actions ******************//
150
+ this.allActions = computed(() => {
151
+ const list = this.detailEntity()?.interfaces?.master?.list?.actions ?? [];
152
+ return list.map((tr) => new AXPEntityCommandTriggerViewModel(this.detailEntity(), tr)) ?? [];
153
+ });
154
+ this.primaryActions = computed(() => {
155
+ return this.allActions().filter((a) => a.priority == 'primary' &&
156
+ ((a.scope == AXPEntityCommandScope.Selected && this.hasSelectedItems()) ||
157
+ (a.scope == AXPEntityCommandScope.TypeLevel && !this.hasSelectedItems())));
158
+ });
159
+ this.secondaryActions = computed(() => {
160
+ return this.allActions().filter((a) => a.priority == 'secondary' &&
161
+ ((a.scope == AXPEntityCommandScope.Selected && this.hasSelectedItems()) ||
162
+ (a.scope == AXPEntityCommandScope.TypeLevel && !this.hasSelectedItems())));
163
+ });
164
+ this.primaryRowActions = computed(() => this.allActions().filter((a) => a.scope == AXPEntityCommandScope.Individual && a.priority === 'primary'));
165
+ this.secondaryRowActions = computed(() => this.allActions().filter((a) => a.scope == AXPEntityCommandScope.Individual && a.priority === 'secondary'));
166
+ //****************** Filter ******************//
167
+ this.inlineFilters = {
168
+ field: null,
169
+ logic: 'or',
170
+ operator: null,
171
+ filters: [],
172
+ };
173
+ //****************** Columns ******************//
174
+ this.columns = computed(() => {
175
+ if (this.detailEntity()) {
176
+ const detailColumns = this.detailEntityConfig.columns ?? [];
177
+ const columns = this.detailEntity()?.columns?.map((c) => c.name) ?? [];
178
+ const props = this.detailEntity()?.properties.filter((p) => p.schema.hidden != true && (detailColumns?.length == 0 || detailColumns?.includes(p.name))) ?? [];
179
+ const displayColumns = props.filter((p) => columns.some((c) => c == p.name));
180
+ return displayColumns.map((p) => {
181
+ return new AXPEntityListViewColumnViewModel(p, this.detailEntity()?.columns?.find((c) => c.name == p.name));
182
+ });
183
+ }
184
+ return [];
185
+ });
186
+ this.initialize();
187
+ }
188
+ async initialize() {
189
+ const entityResolver = this.injector.get(AXPEntityResolver);
190
+ const [moduleName, entityName] = this.detailEntityConfig.entity.split('.');
191
+ const entity = await entityResolver.get(moduleName, entityName);
192
+ if (!entity) {
193
+ throw Error(`Invalid enitity name: ${this.detailEntityConfig.entity}`);
194
+ }
195
+ this.detailEntity.set(entity);
196
+ this.applyFilterAndSort();
197
+ }
198
+ clearSelection() {
199
+ this.selectedItems.set([]);
200
+ }
201
+ applyInlineFilter(value) {
202
+ // const props = this.entityDef.properties.filter(c => c.options?.filter?.inline?.enabled);
203
+ // this.inlineFilters.filters = [];
204
+ // if (value) {
205
+ // props.forEach(p => {
206
+ // this.inlineFilters.filters?.push({
207
+ // field: p.name,
208
+ // operator: {
209
+ // type: 'contains'
210
+ // },
211
+ // value
212
+ // })
213
+ // })
214
+ // }
215
+ this.applyFilterAndSort();
216
+ }
217
+ applyFilterAndSort() {
218
+ this.dataSource.clearFilter();
219
+ //
220
+ //this.dataSource.sort(...this.detailEntity.().map(s => ({ dir: s.dir, field: s.name } as AXDataSourceSortOption)));
221
+ //
222
+ const parentFilters = this.detailEntityConfig.conditions?.map((c) => {
223
+ return {
224
+ field: c.name,
225
+ operator: c.operator,
226
+ value: this.parent.data?.id,
227
+ };
228
+ }) ?? [];
229
+ const parentFilterWrapper = {
230
+ field: null,
231
+ logic: 'and',
232
+ operator: null,
233
+ filters: parentFilters,
234
+ };
235
+ //
236
+ const inline = this.inlineFilters.filters?.length ?? 0;
237
+ const parent = parentFilterWrapper.filters?.length ?? 0;
238
+ //
239
+ debugger;
240
+ if (inline) {
241
+ this.dataSource.filter(this.filterOperatorMiddleware.transformFilter(this.inlineFilters));
242
+ }
243
+ else if (!inline && parent) {
244
+ this.dataSource.filter(this.filterOperatorMiddleware.transformFilter(parentFilterWrapper));
245
+ }
246
+ else if (inline && parent) {
247
+ this.dataSource.filter(this.filterOperatorMiddleware.transformFilter({
248
+ field: null,
249
+ logic: 'and',
250
+ operator: null,
251
+ filters: [this.inlineFilters, parentFilterWrapper],
252
+ }));
253
+ }
254
+ //
255
+ this.dataSource.refresh();
256
+ }
257
+ //****************** Commands ******************//
258
+ async executeCommand(commandName, data = null) {
259
+ const action = this.allActions().find((c) => c.name == commandName &&
260
+ ((this.selectedItems().length
261
+ ? c.scope == AXPEntityCommandScope.Selected
262
+ : c.scope == AXPEntityCommandScope.Individual) ||
263
+ c.scope == AXPEntityCommandScope.TypeLevel));
264
+ if (action?.scope == AXPEntityCommandScope.TypeLevel) {
265
+ if (data == null) {
266
+ data = {};
267
+ }
268
+ let relatedColumn = null;
269
+ this.detailEntityConfig.conditions?.forEach((condition) => {
270
+ if (condition.value == 'id') {
271
+ relatedColumn = condition.name;
272
+ }
273
+ });
274
+ if (relatedColumn != null) {
275
+ data[relatedColumn] = this.parent.data['id'];
276
+ }
277
+ }
278
+ await this.workflow.execute(commandName, {
279
+ entity: getEntityInfo(this.detailEntity()).source,
280
+ data: action?.scope == AXPEntityCommandScope.Selected ? this.selectedItems() : data,
281
+ });
282
+ }
283
+ }
284
+
78
285
  class AXPEntityDefinitionRegistryService {
79
286
  constructor() {
80
287
  // Stores AXPEntityConfig objects, keyed by a combination of module and entity name.
@@ -141,37 +348,141 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.0", ngImpor
141
348
  }]
142
349
  }] });
143
350
 
144
- class AXPEntityCommandTriggerViewModel {
145
- constructor(entity, action) {
146
- this.name = action.command;
147
- const resolvedLook = resolveActionLook(action);
148
- this.priority = action.priority;
149
- this.title = action.title;
150
- this.separated = action.separated ?? false;
151
- this.color = action.color ?? resolvedLook.color;
152
- this.icon = action.icon ?? resolvedLook.icon;
153
- this.scope = action.scope;
154
- }
155
- }
156
- class AXPEntityListViewColumnViewModel {
157
- constructor(property, column) {
158
- this.property = property;
159
- this.column = column;
160
- this.name = this.property.name;
161
- this.title = this.column.title ?? this.property.title;
162
- this.visible = this.column?.options?.visible ?? true;
163
- this.dir = this.column.sort?.dir;
164
- this.sortEnabled = this.property.options?.sort?.enabled;
165
- this.node = computed(() => {
166
- const widget = this.property.schema.interface;
167
- return {
168
- path: this.column.options?.dataPath ?? this.name,
169
- type: widget.type,
170
- options: { ...widget?.options, ...this.column?.options },
171
- };
351
+ class AXPEntityCreateViewSectionViewModel {
352
+ constructor(entity, section) {
353
+ this.entity = entity;
354
+ this.section = section;
355
+ this.group = this.entity.groups?.find(c => c.id == this.section.id);
356
+ this.name = signal(this.group.id);
357
+ this.title = computed(() => {
358
+ return this.group.title ?? this.group.id;
172
359
  });
173
- }
360
+ this.description = computed(() => {
361
+ return this.group.description;
362
+ ;
363
+ });
364
+ this.layout = computed(() => {
365
+ const source = cloneDeep(this.section.layout ?? {});
366
+ set(source, "positions.default.colSpan", 12);
367
+ return source;
368
+ });
369
+ this.elements = computed(() => {
370
+ const { interfaces, properties } = this.entity;
371
+ const createProps = interfaces?.master?.create?.properties ?? [];
372
+ const createPropNames = new Set(createProps.map(({ name }) => name));
373
+ const filteredProperties = properties.filter(({ groupId, schema, name }) => groupId === this.group.id &&
374
+ !schema.hidden &&
375
+ createPropNames.has(name));
376
+ return filteredProperties.map(property => {
377
+ const createProp = createProps.find(({ name }) => name === property.name);
378
+ return new AXPEntityCreateViewElementViewModel(this.entity, this, property, createProp);
379
+ });
380
+ });
381
+ }
382
+ }
383
+ class AXPEntityCreateViewElementViewModel {
384
+ constructor(entity, section, property, createProp) {
385
+ this.entity = entity;
386
+ this.section = section;
387
+ this.property = property;
388
+ this.createProp = createProp;
389
+ this.name = signal(this.property.name);
390
+ this.title = signal(this.property.title);
391
+ this.description = signal(this.property.description);
392
+ this.editable = computed(() => {
393
+ return !(this.property.schema.readonly ?? false);
394
+ });
395
+ this.isRequired = computed(() => {
396
+ return this.property.validations?.some(c => c.rule == 'required') || false;
397
+ });
398
+ this.layout = computed(() => {
399
+ const source = cloneDeep(this.createProp.layout ?? {});
400
+ set(source, "positions.default.colSpan", 12);
401
+ return source;
402
+ });
403
+ this.node = computed(() => {
404
+ const schema = this.property.schema;
405
+ const widget = schema.interface;
406
+ return {
407
+ type: widget.type,
408
+ mode: this.editable() ? 'edit' : 'view',
409
+ path: this.name(),
410
+ children: widget.children,
411
+ formula: widget.formula,
412
+ triggers: widget.triggers,
413
+ options: merge(schema.interface?.options,
414
+ //this.property.options?.create?.widget,
415
+ { validationRules: this.property.validations })
416
+ };
417
+ });
418
+ }
419
+ }
420
+ class AXPEntityMasterCreateViewModel {
421
+ constructor(injector, config, initialData = {}) {
422
+ this.injector = injector;
423
+ this.config = config;
424
+ this.initialData = initialData;
425
+ this.entityDef = cloneDeep(this.config);
426
+ this.workflow = this.injector.get(AXPWorkflowService);
427
+ this.context = signal(this.initialData ?? {});
428
+ this.isInProgress = signal(false);
429
+ this.sections = computed(() => {
430
+ const { interfaces, properties } = this.entityDef;
431
+ const createProps = interfaces?.master?.create?.properties?.map(({ name }) => name) ?? [];
432
+ const visibleProperties = properties.filter(({ groupId, schema, name }) => groupId && !schema.hidden && createProps.includes(name));
433
+ const sections = interfaces?.master?.create?.sections?.filter(({ id }) => visibleProperties.some(({ groupId }) => groupId === id)) ?? [];
434
+ return sections.map(section => new AXPEntityCreateViewSectionViewModel(this.entityDef, section));
435
+ });
436
+ if (!initialData)
437
+ initialData = {};
438
+ this.config.properties
439
+ .filter(c => c.schema.defaultValue != null)
440
+ .forEach(p => {
441
+ if (typeof p.schema.defaultValue === 'function') {
442
+ const func = p.schema.defaultValue;
443
+ set(initialData, p.name, func(initialData));
444
+ }
445
+ else {
446
+ set(initialData, p.name, p.schema.defaultValue);
447
+ }
448
+ });
449
+ this.context.set(initialData);
450
+ }
451
+ async save() {
452
+ try {
453
+ this.isInProgress.set(true);
454
+ const exec = this.entityDef.commands?.create?.execute;
455
+ return await exec((this.context()));
456
+ }
457
+ finally {
458
+ this.isInProgress.set(false);
459
+ }
460
+ }
461
+ async createNewOne() {
462
+ await this.workflow.execute('create-entity', {
463
+ entity: getEntityInfo(this.entityDef).source
464
+ });
465
+ }
466
+ }
467
+ class AXPEntityCreateViewModelFactory {
468
+ constructor() {
469
+ this.entityService = inject(AXPEntityDefinitionRegistryService);
470
+ this.layout = inject(AXPLayoutThemeService);
471
+ this.injector = inject(Injector);
472
+ }
473
+ async create(moduleName, entityName, initialData = null) {
474
+ this.layout.setNavigationLoading(true);
475
+ const config = await this.entityService.resolve(moduleName, entityName);
476
+ this.layout.setNavigationLoading(false);
477
+ return new AXPEntityMasterCreateViewModel(this.injector, config, initialData);
478
+ }
479
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.0", ngImport: i0, type: AXPEntityCreateViewModelFactory, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
480
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.0", ngImport: i0, type: AXPEntityCreateViewModelFactory, providedIn: 'root' }); }
174
481
  }
482
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.0", ngImport: i0, type: AXPEntityCreateViewModelFactory, decorators: [{
483
+ type: Injectable,
484
+ args: [{ providedIn: 'root' }]
485
+ }] });
175
486
 
176
487
  const AXPEntityDeletedEvent = createWorkFlowEvent('[Entity] Deleted');
177
488
  class AXPEntityPerformDeleteAction extends AXPWorkflowAction {
@@ -296,207 +607,44 @@ const AXPDeleteEntityWorkflow = {
296
607
  },
297
608
  };
298
609
 
299
- class AXPEntityMasterUpdateElementViewModel {
300
- constructor(entity, property) {
610
+ class AXPEntityMasterListViewQueryViewModel {
611
+ constructor(entity, section, view) {
301
612
  this.entity = entity;
302
- this.property = property;
303
- this.name = signal(this.property.name);
304
- this.title = signal(this.property.title);
305
- this.description = signal(this.property.description);
306
- this.editable = computed(() => {
307
- return !(this.property.schema.readonly ?? false);
308
- });
309
- this.isRequired = computed(() => {
310
- return this.property.validations?.some(c => c.rule == 'required') || false;
311
- });
312
- this.layout = computed(() => {
313
- const updateProp = this.entity.interfaces?.master?.update?.properties?.find(c => c.name == this.property.name);
314
- const source = cloneDeep(updateProp?.layout ?? {});
315
- set(source, "positions.default.colSpan", 12);
316
- return source;
317
- });
318
- this.node = computed(() => {
319
- const schema = this.property.schema;
320
- const widget = schema.interface;
321
- return {
322
- type: widget.type,
323
- mode: this.editable() ? 'edit' : 'view',
324
- path: this.name(),
325
- children: widget.children,
326
- formula: widget.formula,
327
- triggers: widget.triggers,
328
- options: merge(schema.interface?.options,
329
- //this.property.options?.create?.widget,
330
- { validationRules: this.property.validations })
331
- };
332
- });
613
+ this.section = section;
614
+ this.view = view;
615
+ this.name = this.view.name;
616
+ this.title = this.view.title;
617
+ this.sorts = this.view.sorts;
618
+ this.columns = this.view.columns;
619
+ this.conditions = this.view.conditions;
333
620
  }
334
621
  }
335
- class AXPEntityMasterUpdateViewModel {
336
- constructor(injector, config, entityData, props) {
622
+ class AXPEntityMasterListViewModel {
623
+ constructor(injector, config) {
337
624
  this.injector = injector;
338
625
  this.config = config;
339
- this.entityData = entityData;
340
- this.props = props;
341
626
  this.entityDef = cloneDeep(this.config);
627
+ this._viewDef = cloneDeep(this.entityDef.interfaces?.master?.list);
628
+ this.formatService = this.injector.get(AXFormatService);
629
+ this.session = this.injector.get(AXPSessionService);
342
630
  this.workflow = this.injector.get(AXPWorkflowService);
343
- this.isInProgress = signal(false);
344
- this.context = signal(cloneDeep(this.entityData));
345
- this.elements = computed(() => {
346
- const props = this.entityDef.properties.filter(c => this.props.includes(c.name) &&
347
- c.schema.hidden != true);
348
- return props.map(e => {
349
- return new AXPEntityMasterUpdateElementViewModel(this.entityDef, e);
350
- });
351
- });
352
- }
353
- async save() {
354
- this.isInProgress.set(true);
355
- try {
356
- const com = this.entityDef.commands?.update;
357
- if (com) {
358
- const exec = com.execute;
359
- return await exec(this.context());
360
- }
361
- }
362
- finally {
363
- this.isInProgress.set(false);
364
- }
365
- }
366
- reset() {
367
- this.context.set(cloneDeep(this.entityData));
368
- }
369
- }
370
- class AXPEntityMasterUpdateViewModelFactory {
371
- constructor() {
372
- this.entityService = inject(AXPEntityDefinitionRegistryService);
373
- this.layout = inject(AXPLayoutThemeService);
374
- this.injector = inject(Injector);
375
- }
376
- async create(moduleName, entityName, id, props) {
377
- const config = await this.entityService.resolve(moduleName, entityName);
378
- this.layout.setNavigationLoading(true);
379
- if (config.queries.byKey) {
380
- const func = config.queries.byKey.execute;
381
- const data = await func(id);
382
- this.layout.setNavigationLoading(false);
383
- return new AXPEntityMasterUpdateViewModel(this.injector, config, data, props);
384
- }
385
- this.layout.setNavigationLoading(false);
386
- return Promise.reject('cannot fetch ');
387
- }
388
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.0", ngImport: i0, type: AXPEntityMasterUpdateViewModelFactory, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
389
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.0", ngImport: i0, type: AXPEntityMasterUpdateViewModelFactory, providedIn: 'root' }); }
390
- }
391
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.0", ngImport: i0, type: AXPEntityMasterUpdateViewModelFactory, decorators: [{
392
- type: Injectable,
393
- args: [{ providedIn: 'root' }]
394
- }] });
395
-
396
- const AXPEntityModifyEvent = createWorkFlowEvent('[Entity] Modified');
397
- class AXPEntityModifySectionPopupAction extends AXPWorkflowAction {
398
- constructor() {
399
- super(...arguments);
400
- this.popupService = inject(AXPopupService);
401
- this.platform = inject(AXPlatform);
402
- this.translateService = inject(AXTranslationService);
403
- this.entityRegistery = inject(AXPEntityDefinitionRegistryService);
404
- this.config = inject(AXP_ENTITY_CONFIG_TOKEN);
405
- this.factory = inject(AXPEntityMasterUpdateViewModelFactory);
406
- }
407
- async execute(context) {
408
- const [moduleName, entityName] = context.getVariable('entity').split('.');
409
- const { properties, id, title } = context.getVariable('data');
410
- const entityRef = await this.entityRegistery.resolve(moduleName, entityName);
411
- const vm = await this.factory.create(moduleName, entityName, id, properties);
412
- const com = await this.config.viewers.master.modify();
413
- const popup = await this.popupService.open(com, {
414
- title: title ?? `${this.translateService.translateSync('entity.modify')} ${this.translateService.translateSync(entityRef.formats.individual)}`,
415
- size: this.platform.is('Mobile') || this.platform.is('SM') ? 'full' : 'md',
416
- data: {
417
- vm,
418
- properties,
419
- entity: entityRef,
420
- },
421
- });
422
- context.setOutput('result', false);
423
- if (popup.data?.result == true) {
424
- context.setOutput('result', true);
425
- context.setVariable('data', cloneDeep(popup.data.context));
426
- }
427
- }
428
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.0", ngImport: i0, type: AXPEntityModifySectionPopupAction, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
429
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.0", ngImport: i0, type: AXPEntityModifySectionPopupAction }); }
430
- }
431
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.0", ngImport: i0, type: AXPEntityModifySectionPopupAction, decorators: [{
432
- type: Injectable
433
- }] });
434
- class AXPEntityModifyConfirmedAction extends AXPWorkflowAction {
435
- async execute(context) {
436
- const updatedData = context.getVariable('data');
437
- this.dispatch(AXPEntityModifyEvent({ entity: context.getVariable('entity'), values: updatedData }));
438
- }
439
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.0", ngImport: i0, type: AXPEntityModifyConfirmedAction, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
440
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.0", ngImport: i0, type: AXPEntityModifyConfirmedAction }); }
441
- }
442
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.0", ngImport: i0, type: AXPEntityModifyConfirmedAction, decorators: [{
443
- type: Injectable
444
- }] });
445
- const AXPModifyEntitySectionWorkflow = {
446
- startStepId: 'modifyPopup',
447
- steps: {
448
- modifyPopup: {
449
- id: 'modifyPopup',
450
- action: 'AXPEntityModifySectionPopupAction',
451
- nextSteps: [
452
- {
453
- conditions: [{ type: 'SINGLE', expression: 'context.getOutput("result") == true' }],
454
- nextStepId: 'successToast',
455
- },
456
- ],
457
- },
458
- successToast: {
459
- id: 'successToast',
460
- action: 'AXPToastAction',
461
- input: {
462
- color: 'success',
463
- title: 'workflow.entity-modified-title',
464
- content: 'workflow.entity-modified-body',
465
- },
466
- nextSteps: [
467
- {
468
- conditions: [],
469
- nextStepId: 'modifyConfirmed',
470
- },
471
- ],
472
- },
473
- modifyConfirmed: {
474
- id: 'modifyConfirmed',
475
- action: 'AXPEntityModifyConfirmedAction',
476
- },
477
- },
478
- };
479
-
480
- class AXPEntityDetailListViewModel {
481
- constructor(injector, detailEntityConfig, parent) {
482
- this.injector = injector;
483
- this.detailEntityConfig = detailEntityConfig;
484
- this.parent = parent;
485
- this.detailEntity = signal(null);
486
- this.formatService = this.injector.get(AXFormatService);
487
- this.workflow = this.injector.get(AXPWorkflowService);
488
- this.filterOperatorMiddleware = this.injector.get(AXPFilterOperatorMiddlewareService);
489
- this.dataSource = new AXDataSource({
490
- byKey: (key) => {
491
- const func = this.detailEntity()?.queries.byKey.execute;
492
- return func();
493
- },
494
- load: (e) => {
495
- const func = this.detailEntity()?.queries.list?.execute;
496
- return func(e);
497
- },
498
- pageSize: 5,
499
- key: 'id',
631
+ this.settings = this.injector.get(AXPSettingsService);
632
+ this.filterOperatorMiddleware = this.injector.get(AXPFilterOperatorMiddlewareService);
633
+ this.settingListViewKey = '';
634
+ this.settingSelectedViewKey = '';
635
+ this.destroyed = new Subject();
636
+ this.events$ = new Subject();
637
+ this.dataSource = new AXDataSource({
638
+ byKey: (key) => {
639
+ const func = this.entityDef.queries.byKey.execute;
640
+ return func();
641
+ },
642
+ load: (e) => {
643
+ const func = this.entityDef.queries.list?.execute;
644
+ return func(e);
645
+ },
646
+ pageSize: 10,
647
+ key: 'id',
500
648
  });
501
649
  this.selectedItems = signal([]);
502
650
  this.hasSelectedItems = computed(() => {
@@ -504,22 +652,44 @@ class AXPEntityDetailListViewModel {
504
652
  });
505
653
  //****************** Title ******************//
506
654
  this.title = computed(() => {
507
- return (this.detailEntityConfig.title ??
508
- this.detailEntity()?.interfaces?.detail?.list?.title ??
509
- this.detailEntity()?.formats.plural);
655
+ return this._viewDef.title ?? this.entityDef.formats.plural;
656
+ });
657
+ //****************** Description ******************//
658
+ this.description = computed(() => {
659
+ return this._viewDef.description ?? null;
510
660
  });
511
661
  //****************** Inline filter ******************//
512
662
  this.inlineFiltersPlaceholders = computed(() => {
513
- //return this.entityDef.properties.filter(p => p.options?.filter?.inline?.enabled).map(c => c.title);
514
- return [];
663
+ return this.entityDef.properties.filter((p) => p.options?.filter?.inline?.enabled).map((c) => c.title ?? c.name);
515
664
  });
516
665
  this.hasInlineFilters = computed(() => {
517
666
  return this.inlineFiltersPlaceholders().length > 0;
518
667
  });
668
+ //****************** Beardcrumbs ******************//
669
+ this.beardcrumbs = computed(() => {
670
+ return [
671
+ {
672
+ title: 'entity.home',
673
+ icon: 'fa-solid fa-home ax-text-xs ax-me-2',
674
+ url: [`/${this.session.application?.name}`],
675
+ },
676
+ {
677
+ title: this.title(),
678
+ url: [
679
+ `/${this.session.application?.name}`,
680
+ 'm',
681
+ `${this.entityDef.module}`,
682
+ 'e',
683
+ `${this.entityDef.name}`,
684
+ 'list',
685
+ ],
686
+ },
687
+ ];
688
+ });
519
689
  //****************** Actions ******************//
520
690
  this.allActions = computed(() => {
521
- const list = this.detailEntity()?.interfaces?.master?.list?.actions ?? [];
522
- return list.map((tr) => new AXPEntityCommandTriggerViewModel(this.detailEntity(), tr)) ?? [];
691
+ const list = this.entityDef.interfaces?.master?.list?.actions ?? [];
692
+ return list.map((tr) => new AXPEntityCommandTriggerViewModel(this.entityDef, tr)) ?? [];
523
693
  });
524
694
  this.primaryActions = computed(() => {
525
695
  return this.allActions().filter((a) => a.priority == 'primary' &&
@@ -540,90 +710,196 @@ class AXPEntityDetailListViewModel {
540
710
  operator: null,
541
711
  filters: [],
542
712
  };
713
+ this.advanceFilters = {
714
+ field: null,
715
+ logic: 'and',
716
+ operator: null,
717
+ filters: [],
718
+ };
543
719
  //****************** Columns ******************//
544
- this.columns = computed(() => {
545
- if (this.detailEntity()) {
546
- const detailColumns = this.detailEntityConfig.columns ?? [];
547
- const columns = this.detailEntity()?.columns?.map((c) => c.name) ?? [];
548
- const props = this.detailEntity()?.properties.filter((p) => p.schema.hidden != true && (detailColumns?.length == 0 || detailColumns?.includes(p.name))) ?? [];
549
- const displayColumns = props.filter((p) => columns.some((c) => c == p.name));
550
- return displayColumns.map((p) => {
551
- return new AXPEntityListViewColumnViewModel(p, this.detailEntity()?.columns?.find((c) => c.name == p.name));
552
- });
720
+ this.allAvailableColumns = () => {
721
+ const { columns = [], properties } = this.entityDef;
722
+ const visibleProperties = properties.filter(({ schema }) => !schema?.hidden);
723
+ const visiblePropNames = new Set(visibleProperties.map(({ name }) => name));
724
+ return columns
725
+ .filter(({ name }) => visiblePropNames.has(name))
726
+ .map((column) => {
727
+ const property = visibleProperties.find(({ name }) => name === column.name);
728
+ return new AXPEntityListViewColumnViewModel(property, column);
729
+ });
730
+ };
731
+ this.visibleColumnCount = () => {
732
+ return this.columns().filter((c) => c.visible == true).length;
733
+ };
734
+ this.columns = signal([]);
735
+ //****************** Sort ******************//
736
+ this.sortableFields = () => {
737
+ const props = this.entityDef.properties.filter((c) => c.options?.sort?.enabled);
738
+ return props.map((e) => {
739
+ return {
740
+ name: e.name,
741
+ title: e.title,
742
+ dir: undefined,
743
+ };
744
+ });
745
+ };
746
+ this.sortableFieldsCount = () => {
747
+ return this.entityDef.properties.filter((c) => c.options?.sort?.enabled).length ?? 0;
748
+ };
749
+ this.canSort = () => {
750
+ return this.sortableFieldsCount() > 0;
751
+ };
752
+ this.canAddMoreSort = () => {
753
+ return this.sortedCount() < this.sortableFieldsCount();
754
+ };
755
+ this.sortedCount = () => {
756
+ return this.sortedFields().filter((i) => i.dir).length;
757
+ };
758
+ this.sortedFields = signal([]);
759
+ this.views = computed(() => {
760
+ const views = this.entityDef.interfaces?.master?.list?.views ?? [];
761
+ return views.map((v) => {
762
+ return new AXPEntityMasterListViewQueryViewModel(this.entityDef, this, v);
763
+ });
764
+ });
765
+ this.view = signal(this.views()[0]);
766
+ this.workflow.events$
767
+ .pipe(ofType(AXPEntityDeletedEvent))
768
+ .pipe(takeUntil(this.destroyed))
769
+ .subscribe((event) => {
770
+ if (event.payload.entity == getEntityInfo(this.entityDef).source) {
771
+ this.selectedItems.set([]);
772
+ this.events$.next({ action: 'refresh' });
553
773
  }
554
- return [];
555
774
  });
556
- this.initialize();
775
+ this.sortedFields.set(this.sortableFields());
557
776
  }
558
- async initialize() {
559
- const entityResolver = this.injector.get(AXPEntityResolver);
560
- const [moduleName, entityName] = this.detailEntityConfig.entity.split('.');
561
- const entity = await entityResolver.get(moduleName, entityName);
562
- if (!entity) {
563
- throw Error(`Invalid enitity name: ${this.detailEntityConfig.entity}`);
777
+ async applySettings() {
778
+ this.settingListViewKey = `${this.config.module}:${this.config.name}:list-view:${this.view().name}`;
779
+ const listViewSetting = await this.settings.get(this.settingListViewKey);
780
+ if (listViewSetting) {
781
+ const columnVisibilityMap = new Map(listViewSetting.columns.map((col) => [col.name, col.visible]));
782
+ this.columns.update((prev) => prev
783
+ .map((c) => ({ ...c, visible: columnVisibilityMap.get(c.name) ?? c.visible })) // Update visibility
784
+ .sort((a, b) => listViewSetting.columns.findIndex((col) => col.name === a.name) -
785
+ listViewSetting.columns.findIndex((col) => col.name === b.name)));
564
786
  }
565
- this.detailEntity.set(entity);
566
- this.applyFilterAndSort();
567
787
  }
568
788
  clearSelection() {
569
789
  this.selectedItems.set([]);
570
790
  }
571
791
  applyInlineFilter(value) {
572
- // const props = this.entityDef.properties.filter(c => c.options?.filter?.inline?.enabled);
573
- // this.inlineFilters.filters = [];
574
- // if (value) {
575
- // props.forEach(p => {
576
- // this.inlineFilters.filters?.push({
577
- // field: p.name,
578
- // operator: {
579
- // type: 'contains'
580
- // },
581
- // value
582
- // })
583
- // })
584
- // }
792
+ const props = this.entityDef.properties.filter((c) => c.options?.filter?.inline?.enabled);
793
+ this.inlineFilters.filters = [];
794
+ if (value) {
795
+ props.forEach((p) => {
796
+ this.inlineFilters.filters?.push({
797
+ field: p.name,
798
+ operator: {
799
+ type: 'contains',
800
+ },
801
+ value,
802
+ });
803
+ });
804
+ }
585
805
  this.applyFilterAndSort();
586
806
  }
587
807
  applyFilterAndSort() {
588
808
  this.dataSource.clearFilter();
589
809
  //
590
- //this.dataSource.sort(...this.detailEntity.().map(s => ({ dir: s.dir, field: s.name } as AXDataSourceSortOption)));
810
+ this.dataSource.sort(...this.sortedFields().map((s) => ({ dir: s.dir, field: s.name })));
591
811
  //
592
- const parentFilters = this.detailEntityConfig.conditions?.map((c) => {
593
- return {
594
- field: c.name,
595
- operator: c.operator,
596
- value: this.parent.data?.id,
597
- };
598
- }) ?? [];
599
- const parentFilterWrapper = {
600
- field: null,
601
- logic: 'and',
602
- operator: null,
603
- filters: parentFilters,
604
- };
812
+ this.advanceFilters.filters = this.view().conditions.map((f) => ({
813
+ field: f.name,
814
+ operator: f.operator,
815
+ value: f.value,
816
+ }));
605
817
  //
606
818
  const inline = this.inlineFilters.filters?.length ?? 0;
607
- const parent = parentFilterWrapper.filters?.length ?? 0;
608
- //
609
- debugger;
610
- if (inline) {
819
+ const advance = this.advanceFilters.filters?.length ?? 0;
820
+ if (inline && !advance) {
611
821
  this.dataSource.filter(this.filterOperatorMiddleware.transformFilter(this.inlineFilters));
612
822
  }
613
- else if (!inline && parent) {
614
- this.dataSource.filter(this.filterOperatorMiddleware.transformFilter(parentFilterWrapper));
823
+ else if (!inline && advance) {
824
+ this.dataSource.filter(this.filterOperatorMiddleware.transformFilter(this.advanceFilters));
615
825
  }
616
- else if (inline && parent) {
826
+ else if (inline && advance) {
617
827
  this.dataSource.filter(this.filterOperatorMiddleware.transformFilter({
618
828
  field: null,
619
829
  logic: 'and',
620
830
  operator: null,
621
- filters: [this.inlineFilters, parentFilterWrapper],
831
+ filters: [this.inlineFilters, this.advanceFilters],
622
832
  }));
623
833
  }
624
834
  //
625
835
  this.dataSource.refresh();
626
836
  }
837
+ resetColumns() {
838
+ this.applyViewColumns();
839
+ }
840
+ async onColumnsChanged(columns) {
841
+ const listViewSetting = await this.settings.get(this.settingListViewKey);
842
+ console.log(this.settingListViewKey);
843
+ if (this.settingListViewKey) {
844
+ this.settings.set(this.settingListViewKey, {
845
+ ...listViewSetting,
846
+ columns: columns.map((c) => ({ name: c.name, visible: c.visible })),
847
+ });
848
+ }
849
+ }
850
+ applyViewColumns() {
851
+ const cols = this.view().columns;
852
+ const cloned = this.allAvailableColumns().map((c) => {
853
+ const column = this.entityDef.columns?.find((cc) => cc.name == c.name);
854
+ const prop = this.entityDef.properties.find((p) => p.name == c.name);
855
+ const col = new AXPEntityListViewColumnViewModel(prop, column);
856
+ col.visible = !cols.some((c) => c == col.name) && col.visible != false;
857
+ return col;
858
+ });
859
+ this.columns.set(cloned);
860
+ }
861
+ resetSorts() {
862
+ this.applyViewSorts();
863
+ }
864
+ applySorts() {
865
+ this.applyFilterAndSort();
866
+ }
867
+ addSort() {
868
+ const prop = this.sortableFields().find((c) => !this.sortedFields().some((s) => s.name == c.name));
869
+ if (prop) {
870
+ this.sortedFields.set([...this.sortedFields(), ...[prop]]);
871
+ }
872
+ }
873
+ removeSort(name) {
874
+ this.sortedFields.set(this.sortedFields().filter((c) => c.name != name));
875
+ }
876
+ applyViewSorts() {
877
+ const viewSorts = this.view().sorts;
878
+ this.sortedFields.update((prev) => {
879
+ const viewSortsMap = new Map(viewSorts.map((vs) => [vs.name, vs]));
880
+ return prev.map((sf) => {
881
+ const updatedSort = viewSortsMap.get(sf.name);
882
+ if (updatedSort) {
883
+ return { ...updatedSort, title: sf.title };
884
+ }
885
+ return sf;
886
+ });
887
+ });
888
+ }
889
+ //****************** Views ******************//
890
+ async setView(viewName = null) {
891
+ this.settingSelectedViewKey = `${this.config.module}:${this.config.name}:selected-view`;
892
+ const savedViewName = await this.settings.get(this.settingSelectedViewKey);
893
+ // this.settings.set()
894
+ if (viewName != this.view().name) {
895
+ this.view.set(this.views().find((c) => c.name == (viewName || savedViewName)) ?? this.views()[0]);
896
+ this.settings.set(this.settingSelectedViewKey, this.view().name);
897
+ this.applyViewSorts();
898
+ this.applyViewColumns();
899
+ this.applyFilterAndSort();
900
+ this.applySettings();
901
+ }
902
+ }
627
903
  //****************** Commands ******************//
628
904
  async executeCommand(commandName, data = null) {
629
905
  const action = this.allActions().find((c) => c.name == commandName &&
@@ -631,77 +907,59 @@ class AXPEntityDetailListViewModel {
631
907
  ? c.scope == AXPEntityCommandScope.Selected
632
908
  : c.scope == AXPEntityCommandScope.Individual) ||
633
909
  c.scope == AXPEntityCommandScope.TypeLevel));
634
- if (action?.scope == AXPEntityCommandScope.TypeLevel) {
635
- if (data == null) {
636
- data = {};
637
- }
638
- let relatedColumn = null;
639
- this.detailEntityConfig.conditions?.forEach((condition) => {
640
- if (condition.value == 'id') {
641
- relatedColumn = condition.name;
642
- }
643
- });
644
- if (relatedColumn != null) {
645
- data[relatedColumn] = this.parent.data['id'];
646
- }
647
- }
648
910
  await this.workflow.execute(commandName, {
649
- entity: getEntityInfo(this.detailEntity()).source,
911
+ entity: getEntityInfo(this.entityDef).source,
650
912
  data: action?.scope == AXPEntityCommandScope.Selected ? this.selectedItems() : data,
651
913
  });
652
914
  }
915
+ //
916
+ destroy() {
917
+ this.destroyed.next();
918
+ this.destroyed.complete();
919
+ }
653
920
  }
654
-
655
- class AXPEntityMasterSingleViewGroupViewModel {
656
- constructor(entity, section) {
657
- this.entity = entity;
658
- this.section = section;
659
- this.group = this.entity.groups?.find(c => c.id == this.section.id);
660
- this.name = signal(this.group.id);
661
- this.isLoading = signal(false);
662
- this.title = computed(() => {
663
- return this.group.title ?? this.group.id;
664
- });
665
- this.description = computed(() => {
666
- return this.group.description;
667
- });
668
- this.layout = computed(() => {
669
- const source = cloneDeep(this.section.layout ?? {});
670
- set(source, "positions.default.colSpan", 12);
671
- return source;
672
- });
673
- this.props = computed(() => {
674
- const { properties, interfaces } = this.entity;
675
- const groupProperties = properties
676
- .filter(({ groupId, schema }) => groupId === this.group.id && !schema.hidden)
677
- .map(({ name }) => name);
678
- const viewProperties = interfaces?.master?.single?.properties?.filter(({ name }) => groupProperties.includes(name)) ?? [];
679
- return viewProperties.map(prop => new AXPEntityMasterSingleElementViewModel(this.entity, this, prop));
680
- });
681
- this.editableProps = computed(() => {
682
- const { properties, interfaces } = this.entity;
683
- const editablePropertyNames = interfaces?.master?.update?.properties?.map(({ name }) => name) ?? [];
684
- const filteredProperties = properties.filter(({ groupId, schema, name }) => groupId === this.group.id && !schema.hidden && editablePropertyNames.includes(name));
685
- return filteredProperties.map(prop => new AXPEntityMasterSingleElementViewModel(this.entity, this, prop));
686
- });
687
- this.editable = computed(() => {
688
- return this.editableProps().length > 0;
689
- });
921
+ class AXPEntityListViewModelFactory {
922
+ constructor() {
923
+ this.entityService = inject(AXPEntityDefinitionRegistryService);
924
+ this.layout = inject(AXPLayoutThemeService);
925
+ this.injector = inject(Injector);
926
+ }
927
+ async create(moduleName, entityName) {
928
+ this.layout.setNavigationLoading(true);
929
+ const config = await this.entityService.resolve(moduleName, entityName);
930
+ this.layout.setNavigationLoading(false);
931
+ return new AXPEntityMasterListViewModel(this.injector, config);
690
932
  }
933
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.0", ngImport: i0, type: AXPEntityListViewModelFactory, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
934
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.0", ngImport: i0, type: AXPEntityListViewModelFactory, providedIn: 'root' }); }
691
935
  }
692
- class AXPEntityMasterSingleElementViewModel {
693
- constructor(entity, section, propertyView) {
936
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.0", ngImport: i0, type: AXPEntityListViewModelFactory, decorators: [{
937
+ type: Injectable,
938
+ args: [{ providedIn: 'root' }]
939
+ }] });
940
+ const AXPEntityListViewModelResolver = (route, state, service = inject(AXPEntityListViewModelFactory)) => {
941
+ const moduleName = route.parent?.paramMap.get('module');
942
+ const entityName = route.paramMap.get('entity');
943
+ //
944
+ return service.create(moduleName, entityName);
945
+ };
946
+
947
+ class AXPEntityMasterUpdateElementViewModel {
948
+ constructor(entity, property) {
694
949
  this.entity = entity;
695
- this.section = section;
696
- this.propertyView = propertyView;
697
- this.property = this.entity.properties.find(c => c.name == this.propertyView.name);
950
+ this.property = property;
698
951
  this.name = signal(this.property.name);
699
952
  this.title = signal(this.property.title);
700
- this.showLabel = signal(this.propertyView.layout?.label?.visible != false);
701
953
  this.description = signal(this.property.description);
954
+ this.editable = computed(() => {
955
+ return !(this.property.schema.readonly ?? false);
956
+ });
957
+ this.isRequired = computed(() => {
958
+ return this.property.validations?.some(c => c.rule == 'required') || false;
959
+ });
702
960
  this.layout = computed(() => {
703
- const viewProp = this.entity.interfaces?.master?.single?.properties?.find(c => c.name == this.property.name);
704
- const source = cloneDeep(viewProp?.layout ?? {});
961
+ const updateProp = this.entity.interfaces?.master?.update?.properties?.find(c => c.name == this.property.name);
962
+ const source = cloneDeep(updateProp?.layout ?? {});
705
963
  set(source, "positions.default.colSpan", 12);
706
964
  return source;
707
965
  });
@@ -710,209 +968,213 @@ class AXPEntityMasterSingleElementViewModel {
710
968
  const widget = schema.interface;
711
969
  return {
712
970
  type: widget.type,
713
- mode: 'view',
971
+ mode: this.editable() ? 'edit' : 'view',
714
972
  path: this.name(),
715
973
  children: widget.children,
716
974
  formula: widget.formula,
717
- options: merge(schema.interface?.options)
975
+ triggers: widget.triggers,
976
+ options: merge(schema.interface?.options,
977
+ //this.property.options?.create?.widget,
978
+ { validationRules: this.property.validations })
718
979
  };
719
980
  });
720
981
  }
721
982
  }
722
- class AXPEntityMasterSingleViewModel {
723
- constructor(injector, config, entityData) {
983
+ class AXPEntityMasterUpdateViewModel {
984
+ constructor(injector, config, entityData, props) {
724
985
  this.injector = injector;
725
986
  this.config = config;
726
987
  this.entityData = entityData;
988
+ this.props = props;
727
989
  this.entityDef = cloneDeep(this.config);
728
- this._viewDef = cloneDeep(this.entityDef.interfaces?.master?.single);
729
- this.session = this.injector.get(AXPSessionService);
730
- this.formatService = this.injector.get(AXFormatService);
731
990
  this.workflow = this.injector.get(AXPWorkflowService);
732
- this.destroyed = new Subject();
733
- this.translateService = this.injector.get(AXTranslationService);
991
+ this.isInProgress = signal(false);
734
992
  this.context = signal(cloneDeep(this.entityData));
735
- this.actions = computed(() => {
736
- return this.entityDef.interfaces?.master?.single?.actions?.map((tr) => new AXPEntityCommandTriggerViewModel(this.entityDef, tr)) ?? [];
737
- });
738
- this.primaryActions = computed(() => {
739
- return this.actions().filter(c => c.priority == 'primary');
740
- });
741
- this.secondaryActions = computed(() => {
742
- return this.actions().filter(c => c.priority == 'secondary');
743
- });
744
- this.sections = computed(() => {
745
- const { interfaces, properties } = this.entityDef;
746
- const viewProps = interfaces?.master?.single?.properties?.map(({ name }) => name) ?? [];
747
- const filteredProperties = properties.filter(({ groupId, schema, name }) => groupId && !schema.hidden && viewProps.includes(name));
748
- const groups = interfaces?.master?.single?.sections?.filter(({ id }) => filteredProperties.some(({ groupId }) => groupId === id)) ?? [];
749
- return groups.map(section => new AXPEntityMasterSingleViewGroupViewModel(this.entityDef, section));
750
- });
751
- //****************** Title ******************//
752
- this.title = computed(() => {
753
- const suggestedProps = this.entityDef.properties.find((c) => ['title', 'name', 'code'].includes(c.name));
754
- let suggestedFormat = 'Item #{{id}}';
755
- if (suggestedProps)
756
- suggestedFormat = `{{${suggestedProps.name}}}`;
757
- return this.formatService.format(this._viewDef.title ?? suggestedFormat, 'string', this.context());
758
- });
759
- //****************** Description ******************//
760
- this.description = computed(() => {
761
- return this._viewDef.description ? this.formatService.format(this._viewDef.description, 'string', this.context()) : null;
762
- });
763
- //****************** Beardcrumbs ******************//
764
- this.beardcrumbs = computed(() => {
765
- return [
766
- {
767
- title: this.translateService.translateSync('entity.home'),
768
- icon: "fa-solid fa-home ax-text-xs ax-me-2",
769
- url: [`/${this.session.application?.name}`]
770
- },
771
- {
772
- title: this.entityDef.formats.plural ?? this.entityDef.formats.individual,
773
- url: [`/${this.session.application?.name}`, 'm', `${this.entityDef.module}`, 'e', `${this.entityDef.name}`, 'list']
774
- },
775
- {
776
- title: this.title(),
777
- }
778
- ];
779
- });
780
- this.relatedEntities = computed(() => {
781
- return this.entityDef.relatedEntities?.map(re => new AXPEntityDetailListViewModel(this.injector, re, { entity: this.entityDef, data: this.entityData })) ?? [];
782
- });
783
- this.workflow.events$
784
- .pipe(ofType(AXPEntityDeletedEvent))
785
- .pipe(takeUntil(this.destroyed))
786
- .subscribe((event) => {
787
- if (event.payload.entity == getEntityInfo(this.entityDef).source &&
788
- event.payload.ids.includes(this.context().id)) {
789
- this.workflow.execute('show-list-view', {
790
- entity: getEntityInfo(this.entityDef).source
791
- });
792
- }
793
- });
794
- this.workflow.events$
795
- .pipe(ofType(AXPEntityModifyEvent))
796
- .pipe(takeUntil(this.destroyed))
797
- .subscribe(async (event) => {
798
- if (event.payload.entity == getEntityInfo(this.entityDef).source &&
799
- event.payload.values.id === this.context().id) {
800
- this.context.set(event.payload.values);
801
- }
993
+ this.elements = computed(() => {
994
+ const props = this.entityDef.properties.filter(c => this.props.includes(c.name) &&
995
+ c.schema.hidden != true);
996
+ return props.map(e => {
997
+ return new AXPEntityMasterUpdateElementViewModel(this.entityDef, e);
998
+ });
802
999
  });
803
1000
  }
804
- async executeCommand(commandName, data = null) {
805
- //TODO: syntact for workflow
806
- switch (commandName) {
807
- case 'modify-entity-section': {
808
- this.workflow.execute('modify-entity-section', {
809
- entity: getEntityInfo(this.entityDef).source,
810
- data: {
811
- id: this.context().id,
812
- properties: data.editableProps().map(m => m.name()),
813
- },
814
- });
815
- break;
1001
+ async save() {
1002
+ this.isInProgress.set(true);
1003
+ try {
1004
+ const com = this.entityDef.commands?.update;
1005
+ if (com) {
1006
+ const exec = com.execute;
1007
+ return await exec(this.context());
816
1008
  }
817
- default:
818
- {
819
- const action = this.actions().find(c => c.name == commandName);
820
- this.workflow.execute(commandName, {
821
- entity: getEntityInfo(this.entityDef).source,
822
- data: action?.scope == AXPEntityCommandScope.Individual ? this.context() : null
823
- });
824
- }
1009
+ }
1010
+ finally {
1011
+ this.isInProgress.set(false);
825
1012
  }
826
1013
  }
827
- //
828
- //
829
- destroy() {
830
- this.destroyed.next();
831
- this.destroyed.complete();
1014
+ reset() {
1015
+ this.context.set(cloneDeep(this.entityData));
832
1016
  }
833
1017
  }
834
- class AXPEntityDetailViewModelFactory {
1018
+ class AXPEntityMasterUpdateViewModelFactory {
835
1019
  constructor() {
836
1020
  this.entityService = inject(AXPEntityDefinitionRegistryService);
837
1021
  this.layout = inject(AXPLayoutThemeService);
838
1022
  this.injector = inject(Injector);
839
1023
  }
840
- async create(moduleName, entityName, id) {
1024
+ async create(moduleName, entityName, id, props) {
841
1025
  const config = await this.entityService.resolve(moduleName, entityName);
842
1026
  this.layout.setNavigationLoading(true);
843
1027
  if (config.queries.byKey) {
844
1028
  const func = config.queries.byKey.execute;
845
1029
  const data = await func(id);
846
1030
  this.layout.setNavigationLoading(false);
847
- return new AXPEntityMasterSingleViewModel(this.injector, config, data);
1031
+ return new AXPEntityMasterUpdateViewModel(this.injector, config, data, props);
848
1032
  }
849
1033
  this.layout.setNavigationLoading(false);
850
1034
  return Promise.reject('cannot fetch ');
851
1035
  }
852
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.0", ngImport: i0, type: AXPEntityDetailViewModelFactory, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
853
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.0", ngImport: i0, type: AXPEntityDetailViewModelFactory, providedIn: 'root' }); }
1036
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.0", ngImport: i0, type: AXPEntityMasterUpdateViewModelFactory, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
1037
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.0", ngImport: i0, type: AXPEntityMasterUpdateViewModelFactory, providedIn: 'root' }); }
854
1038
  }
855
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.0", ngImport: i0, type: AXPEntityDetailViewModelFactory, decorators: [{
1039
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.0", ngImport: i0, type: AXPEntityMasterUpdateViewModelFactory, decorators: [{
856
1040
  type: Injectable,
857
1041
  args: [{ providedIn: 'root' }]
858
1042
  }] });
859
- const AXPEntityDetailViewModelResolver = (route, state, service = inject(AXPEntityDetailViewModelFactory)) => {
860
- const moduleName = route.parent?.paramMap.get('module');
861
- const entityName = route.paramMap.get('entity');
862
- const id = route.paramMap.get('id');
863
- //
864
- return service.create(moduleName, entityName, id);
1043
+
1044
+ const AXPEntityModifyEvent = createWorkFlowEvent('[Entity] Modified');
1045
+ class AXPEntityModifySectionPopupAction extends AXPWorkflowAction {
1046
+ constructor() {
1047
+ super(...arguments);
1048
+ this.popupService = inject(AXPopupService);
1049
+ this.platform = inject(AXPlatform);
1050
+ this.translateService = inject(AXTranslationService);
1051
+ this.entityRegistery = inject(AXPEntityDefinitionRegistryService);
1052
+ this.config = inject(AXP_ENTITY_CONFIG_TOKEN);
1053
+ this.factory = inject(AXPEntityMasterUpdateViewModelFactory);
1054
+ }
1055
+ async execute(context) {
1056
+ const [moduleName, entityName] = context.getVariable('entity').split('.');
1057
+ const { properties, id, title } = context.getVariable('data');
1058
+ const entityRef = await this.entityRegistery.resolve(moduleName, entityName);
1059
+ const vm = await this.factory.create(moduleName, entityName, id, properties);
1060
+ const com = await this.config.viewers.master.modify();
1061
+ const popup = await this.popupService.open(com, {
1062
+ title: title ?? `${this.translateService.translateSync('entity.modify')} ${this.translateService.translateSync(entityRef.formats.individual)}`,
1063
+ size: this.platform.is('Mobile') || this.platform.is('SM') ? 'full' : 'md',
1064
+ data: {
1065
+ vm,
1066
+ properties,
1067
+ entity: entityRef,
1068
+ },
1069
+ });
1070
+ context.setOutput('result', false);
1071
+ if (popup.data?.result == true) {
1072
+ context.setOutput('result', true);
1073
+ context.setVariable('data', cloneDeep(popup.data.context));
1074
+ }
1075
+ }
1076
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.0", ngImport: i0, type: AXPEntityModifySectionPopupAction, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
1077
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.0", ngImport: i0, type: AXPEntityModifySectionPopupAction }); }
1078
+ }
1079
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.0", ngImport: i0, type: AXPEntityModifySectionPopupAction, decorators: [{
1080
+ type: Injectable
1081
+ }] });
1082
+ class AXPEntityModifyConfirmedAction extends AXPWorkflowAction {
1083
+ async execute(context) {
1084
+ const updatedData = context.getVariable('data');
1085
+ this.dispatch(AXPEntityModifyEvent({ entity: context.getVariable('entity'), values: updatedData }));
1086
+ }
1087
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.0", ngImport: i0, type: AXPEntityModifyConfirmedAction, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
1088
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.0", ngImport: i0, type: AXPEntityModifyConfirmedAction }); }
1089
+ }
1090
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.0", ngImport: i0, type: AXPEntityModifyConfirmedAction, decorators: [{
1091
+ type: Injectable
1092
+ }] });
1093
+ const AXPModifyEntitySectionWorkflow = {
1094
+ startStepId: 'modifyPopup',
1095
+ steps: {
1096
+ modifyPopup: {
1097
+ id: 'modifyPopup',
1098
+ action: 'AXPEntityModifySectionPopupAction',
1099
+ nextSteps: [
1100
+ {
1101
+ conditions: [{ type: 'SINGLE', expression: 'context.getOutput("result") == true' }],
1102
+ nextStepId: 'successToast',
1103
+ },
1104
+ ],
1105
+ },
1106
+ successToast: {
1107
+ id: 'successToast',
1108
+ action: 'AXPToastAction',
1109
+ input: {
1110
+ color: 'success',
1111
+ title: 'workflow.entity-modified-title',
1112
+ content: 'workflow.entity-modified-body',
1113
+ },
1114
+ nextSteps: [
1115
+ {
1116
+ conditions: [],
1117
+ nextStepId: 'modifyConfirmed',
1118
+ },
1119
+ ],
1120
+ },
1121
+ modifyConfirmed: {
1122
+ id: 'modifyConfirmed',
1123
+ action: 'AXPEntityModifyConfirmedAction',
1124
+ },
1125
+ },
865
1126
  };
866
1127
 
867
- class AXPEntityCreateViewSectionViewModel {
1128
+ class AXPEntityMasterSingleViewGroupViewModel {
868
1129
  constructor(entity, section) {
869
1130
  this.entity = entity;
870
1131
  this.section = section;
871
1132
  this.group = this.entity.groups?.find(c => c.id == this.section.id);
872
1133
  this.name = signal(this.group.id);
1134
+ this.isLoading = signal(false);
873
1135
  this.title = computed(() => {
874
1136
  return this.group.title ?? this.group.id;
875
1137
  });
876
1138
  this.description = computed(() => {
877
1139
  return this.group.description;
878
- ;
879
1140
  });
880
1141
  this.layout = computed(() => {
881
1142
  const source = cloneDeep(this.section.layout ?? {});
882
1143
  set(source, "positions.default.colSpan", 12);
883
1144
  return source;
884
1145
  });
885
- this.elements = computed(() => {
886
- const { interfaces, properties } = this.entity;
887
- const createProps = interfaces?.master?.create?.properties ?? [];
888
- const createPropNames = new Set(createProps.map(({ name }) => name));
889
- const filteredProperties = properties.filter(({ groupId, schema, name }) => groupId === this.group.id &&
890
- !schema.hidden &&
891
- createPropNames.has(name));
892
- return filteredProperties.map(property => {
893
- const createProp = createProps.find(({ name }) => name === property.name);
894
- return new AXPEntityCreateViewElementViewModel(this.entity, this, property, createProp);
895
- });
1146
+ this.props = computed(() => {
1147
+ const { properties, interfaces } = this.entity;
1148
+ const groupProperties = properties
1149
+ .filter(({ groupId, schema }) => groupId === this.group.id && !schema.hidden)
1150
+ .map(({ name }) => name);
1151
+ const viewProperties = interfaces?.master?.single?.properties?.filter(({ name }) => groupProperties.includes(name)) ?? [];
1152
+ return viewProperties.map(prop => new AXPEntityMasterSingleElementViewModel(this.entity, this, prop));
1153
+ });
1154
+ this.editableProps = computed(() => {
1155
+ const { properties, interfaces } = this.entity;
1156
+ const editablePropertyNames = interfaces?.master?.update?.properties?.map(({ name }) => name) ?? [];
1157
+ const filteredProperties = properties.filter(({ groupId, schema, name }) => groupId === this.group.id && !schema.hidden && editablePropertyNames.includes(name));
1158
+ return filteredProperties.map(prop => new AXPEntityMasterSingleElementViewModel(this.entity, this, prop));
1159
+ });
1160
+ this.editable = computed(() => {
1161
+ return this.editableProps().length > 0;
896
1162
  });
897
1163
  }
898
1164
  }
899
- class AXPEntityCreateViewElementViewModel {
900
- constructor(entity, section, property, createProp) {
1165
+ class AXPEntityMasterSingleElementViewModel {
1166
+ constructor(entity, section, propertyView) {
901
1167
  this.entity = entity;
902
1168
  this.section = section;
903
- this.property = property;
904
- this.createProp = createProp;
1169
+ this.propertyView = propertyView;
1170
+ this.property = this.entity.properties.find(c => c.name == this.propertyView.name);
905
1171
  this.name = signal(this.property.name);
906
1172
  this.title = signal(this.property.title);
1173
+ this.showLabel = signal(this.propertyView.layout?.label?.visible != false);
907
1174
  this.description = signal(this.property.description);
908
- this.editable = computed(() => {
909
- return !(this.property.schema.readonly ?? false);
910
- });
911
- this.isRequired = computed(() => {
912
- return this.property.validations?.some(c => c.rule == 'required') || false;
913
- });
914
1175
  this.layout = computed(() => {
915
- const source = cloneDeep(this.createProp.layout ?? {});
1176
+ const viewProp = this.entity.interfaces?.master?.single?.properties?.find(c => c.name == this.property.name);
1177
+ const source = cloneDeep(viewProp?.layout ?? {});
916
1178
  set(source, "positions.default.colSpan", 12);
917
1179
  return source;
918
1180
  });
@@ -921,395 +1183,158 @@ class AXPEntityCreateViewElementViewModel {
921
1183
  const widget = schema.interface;
922
1184
  return {
923
1185
  type: widget.type,
924
- mode: this.editable() ? 'edit' : 'view',
1186
+ mode: 'view',
925
1187
  path: this.name(),
926
1188
  children: widget.children,
927
1189
  formula: widget.formula,
928
- triggers: widget.triggers,
929
- options: merge(schema.interface?.options,
930
- //this.property.options?.create?.widget,
931
- { validationRules: this.property.validations })
1190
+ options: merge(schema.interface?.options)
932
1191
  };
933
1192
  });
934
1193
  }
935
1194
  }
936
- class AXPEntityMasterCreateViewModel {
937
- constructor(injector, config, initialData = {}) {
1195
+ class AXPEntityMasterSingleViewModel {
1196
+ constructor(injector, config, entityData) {
938
1197
  this.injector = injector;
939
1198
  this.config = config;
940
- this.initialData = initialData;
1199
+ this.entityData = entityData;
941
1200
  this.entityDef = cloneDeep(this.config);
1201
+ this._viewDef = cloneDeep(this.entityDef.interfaces?.master?.single);
1202
+ this.session = this.injector.get(AXPSessionService);
1203
+ this.formatService = this.injector.get(AXFormatService);
942
1204
  this.workflow = this.injector.get(AXPWorkflowService);
943
- this.context = signal(this.initialData ?? {});
944
- this.isInProgress = signal(false);
1205
+ this.destroyed = new Subject();
1206
+ this.translateService = this.injector.get(AXTranslationService);
1207
+ this.context = signal(cloneDeep(this.entityData));
1208
+ this.actions = computed(() => {
1209
+ return this.entityDef.interfaces?.master?.single?.actions?.map((tr) => new AXPEntityCommandTriggerViewModel(this.entityDef, tr)) ?? [];
1210
+ });
1211
+ this.primaryActions = computed(() => {
1212
+ return this.actions().filter(c => c.priority == 'primary');
1213
+ });
1214
+ this.secondaryActions = computed(() => {
1215
+ return this.actions().filter(c => c.priority == 'secondary');
1216
+ });
945
1217
  this.sections = computed(() => {
946
1218
  const { interfaces, properties } = this.entityDef;
947
- const createProps = interfaces?.master?.create?.properties?.map(({ name }) => name) ?? [];
948
- const visibleProperties = properties.filter(({ groupId, schema, name }) => groupId && !schema.hidden && createProps.includes(name));
949
- const sections = interfaces?.master?.create?.sections?.filter(({ id }) => visibleProperties.some(({ groupId }) => groupId === id)) ?? [];
950
- return sections.map(section => new AXPEntityCreateViewSectionViewModel(this.entityDef, section));
1219
+ const viewProps = interfaces?.master?.single?.properties?.map(({ name }) => name) ?? [];
1220
+ const filteredProperties = properties.filter(({ groupId, schema, name }) => groupId && !schema.hidden && viewProps.includes(name));
1221
+ const groups = interfaces?.master?.single?.sections?.filter(({ id }) => filteredProperties.some(({ groupId }) => groupId === id)) ?? [];
1222
+ return groups.map(section => new AXPEntityMasterSingleViewGroupViewModel(this.entityDef, section));
951
1223
  });
952
- if (!initialData)
953
- initialData = {};
954
- this.config.properties
955
- .filter(c => c.schema.defaultValue != null)
956
- .forEach(p => {
957
- if (typeof p.schema.defaultValue === 'function') {
958
- const func = p.schema.defaultValue;
959
- set(initialData, p.name, func(initialData));
960
- }
961
- else {
962
- set(initialData, p.name, p.schema.defaultValue);
963
- }
964
- });
965
- this.context.set(initialData);
966
- }
967
- async save() {
968
- try {
969
- this.isInProgress.set(true);
970
- const exec = this.entityDef.commands?.create?.execute;
971
- return await exec((this.context()));
972
- }
973
- finally {
974
- this.isInProgress.set(false);
975
- }
976
- }
977
- async createNewOne() {
978
- await this.workflow.execute('create-entity', {
979
- entity: getEntityInfo(this.entityDef).source
980
- });
981
- }
982
- }
983
- class AXPEntityCreateViewModelFactory {
984
- constructor() {
985
- this.entityService = inject(AXPEntityDefinitionRegistryService);
986
- this.layout = inject(AXPLayoutThemeService);
987
- this.injector = inject(Injector);
988
- }
989
- async create(moduleName, entityName, initialData = null) {
990
- this.layout.setNavigationLoading(true);
991
- const config = await this.entityService.resolve(moduleName, entityName);
992
- this.layout.setNavigationLoading(false);
993
- return new AXPEntityMasterCreateViewModel(this.injector, config, initialData);
994
- }
995
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.0", ngImport: i0, type: AXPEntityCreateViewModelFactory, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
996
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.0", ngImport: i0, type: AXPEntityCreateViewModelFactory, providedIn: 'root' }); }
997
- }
998
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.0", ngImport: i0, type: AXPEntityCreateViewModelFactory, decorators: [{
999
- type: Injectable,
1000
- args: [{ providedIn: 'root' }]
1001
- }] });
1002
-
1003
- class AXPEntityMasterListViewQueryViewModel {
1004
- constructor(entity, section, view) {
1005
- this.entity = entity;
1006
- this.section = section;
1007
- this.view = view;
1008
- this.name = this.view.name;
1009
- this.title = this.view.title;
1010
- this.sorts = this.view.sorts;
1011
- this.columns = this.view.columns;
1012
- this.conditions = this.view.conditions;
1013
- }
1014
- }
1015
- class AXPEntityMasterListViewModel {
1016
- constructor(injector, config) {
1017
- this.injector = injector;
1018
- this.config = config;
1019
- this.entityDef = cloneDeep(this.config);
1020
- this._viewDef = cloneDeep(this.entityDef.interfaces?.master?.list);
1021
- this.formatService = this.injector.get(AXFormatService);
1022
- this.session = this.injector.get(AXPSessionService);
1023
- this.workflow = this.injector.get(AXPWorkflowService);
1024
- this.filterOperatorMiddleware = this.injector.get(AXPFilterOperatorMiddlewareService);
1025
- this.destroyed = new Subject();
1026
- this.events$ = new Subject();
1027
- this.dataSource = new AXDataSource({
1028
- byKey: (key) => {
1029
- const func = this.entityDef.queries.byKey.execute;
1030
- return func();
1031
- },
1032
- load: (e) => {
1033
- const func = this.entityDef.queries.list?.execute;
1034
- return func(e);
1035
- },
1036
- pageSize: 10,
1037
- key: 'id',
1038
- });
1039
- this.selectedItems = signal([]);
1040
- this.hasSelectedItems = computed(() => {
1041
- return this.selectedItems().length > 0;
1042
- });
1043
- //****************** Title ******************//
1044
- this.title = computed(() => {
1045
- return this._viewDef.title ?? this.entityDef.formats.plural;
1224
+ //****************** Title ******************//
1225
+ this.title = computed(() => {
1226
+ const suggestedProps = this.entityDef.properties.find((c) => ['title', 'name', 'code'].includes(c.name));
1227
+ let suggestedFormat = 'Item #{{id}}';
1228
+ if (suggestedProps)
1229
+ suggestedFormat = `{{${suggestedProps.name}}}`;
1230
+ return this.formatService.format(this._viewDef.title ?? suggestedFormat, 'string', this.context());
1046
1231
  });
1047
1232
  //****************** Description ******************//
1048
1233
  this.description = computed(() => {
1049
- return this._viewDef.description ?? null;
1050
- });
1051
- //****************** Inline filter ******************//
1052
- this.inlineFiltersPlaceholders = computed(() => {
1053
- return this.entityDef.properties.filter((p) => p.options?.filter?.inline?.enabled).map((c) => c.title ?? c.name);
1054
- });
1055
- this.hasInlineFilters = computed(() => {
1056
- return this.inlineFiltersPlaceholders().length > 0;
1234
+ return this._viewDef.description ? this.formatService.format(this._viewDef.description, 'string', this.context()) : null;
1057
1235
  });
1058
1236
  //****************** Beardcrumbs ******************//
1059
1237
  this.beardcrumbs = computed(() => {
1060
1238
  return [
1061
1239
  {
1062
- title: 'entity.home',
1063
- icon: 'fa-solid fa-home ax-text-xs ax-me-2',
1064
- url: [`/${this.session.application?.name}`],
1240
+ title: this.translateService.translateSync('entity.home'),
1241
+ icon: "fa-solid fa-home ax-text-xs ax-me-2",
1242
+ url: [`/${this.session.application?.name}`]
1065
1243
  },
1066
1244
  {
1067
- title: this.title(),
1068
- url: [
1069
- `/${this.session.application?.name}`,
1070
- 'm',
1071
- `${this.entityDef.module}`,
1072
- 'e',
1073
- `${this.entityDef.name}`,
1074
- 'list',
1075
- ],
1245
+ title: this.entityDef.formats.plural ?? this.entityDef.formats.individual,
1246
+ url: [`/${this.session.application?.name}`, 'm', `${this.entityDef.module}`, 'e', `${this.entityDef.name}`, 'list']
1076
1247
  },
1248
+ {
1249
+ title: this.title(),
1250
+ }
1077
1251
  ];
1078
1252
  });
1079
- //****************** Actions ******************//
1080
- this.allActions = computed(() => {
1081
- const list = this.entityDef.interfaces?.master?.list?.actions ?? [];
1082
- return list.map((tr) => new AXPEntityCommandTriggerViewModel(this.entityDef, tr)) ?? [];
1083
- });
1084
- this.primaryActions = computed(() => {
1085
- return this.allActions().filter((a) => a.priority == 'primary' &&
1086
- ((a.scope == AXPEntityCommandScope.Selected && this.hasSelectedItems()) ||
1087
- (a.scope == AXPEntityCommandScope.TypeLevel && !this.hasSelectedItems())));
1088
- });
1089
- this.secondaryActions = computed(() => {
1090
- return this.allActions().filter((a) => a.priority == 'secondary' &&
1091
- ((a.scope == AXPEntityCommandScope.Selected && this.hasSelectedItems()) ||
1092
- (a.scope == AXPEntityCommandScope.TypeLevel && !this.hasSelectedItems())));
1093
- });
1094
- this.primaryRowActions = computed(() => this.allActions().filter((a) => a.scope == AXPEntityCommandScope.Individual && a.priority === 'primary'));
1095
- this.secondaryRowActions = computed(() => this.allActions().filter((a) => a.scope == AXPEntityCommandScope.Individual && a.priority === 'secondary'));
1096
- //****************** Filter ******************//
1097
- this.inlineFilters = {
1098
- field: null,
1099
- logic: 'or',
1100
- operator: null,
1101
- filters: [],
1102
- };
1103
- this.advanceFilters = {
1104
- field: null,
1105
- logic: 'and',
1106
- operator: null,
1107
- filters: [],
1108
- };
1109
- //****************** Columns ******************//
1110
- this.allAvailableColumns = () => {
1111
- const { columns = [], properties } = this.entityDef;
1112
- const visibleProperties = properties.filter(({ schema }) => !schema?.hidden);
1113
- const visiblePropNames = new Set(visibleProperties.map(({ name }) => name));
1114
- return columns
1115
- .filter(({ name }) => visiblePropNames.has(name))
1116
- .map((column) => {
1117
- const property = visibleProperties.find(({ name }) => name === column.name);
1118
- return new AXPEntityListViewColumnViewModel(property, column);
1119
- });
1120
- };
1121
- this.visibleColumnCount = () => {
1122
- return this.columns().filter((c) => c.visible == true).length;
1123
- };
1124
- this.columns = signal([]);
1125
- //****************** Sort ******************//
1126
- this.sortableFields = () => {
1127
- const props = this.entityDef.properties.filter((c) => c.options?.sort?.enabled);
1128
- return props.map((e) => {
1129
- return {
1130
- name: e.name,
1131
- title: e.title,
1132
- dir: undefined,
1133
- };
1134
- });
1135
- };
1136
- this.sortableFieldsCount = () => {
1137
- return this.entityDef.properties.filter((c) => c.options?.sort?.enabled).length ?? 0;
1138
- };
1139
- this.canSort = () => {
1140
- return this.sortableFieldsCount() > 0;
1141
- };
1142
- this.canAddMoreSort = () => {
1143
- return this.sortedCount() < this.sortableFieldsCount();
1144
- };
1145
- this.sortedCount = () => {
1146
- return this.sortedFields().filter((i) => i.dir).length;
1147
- };
1148
- this.sortedFields = signal([]);
1149
- this.views = computed(() => {
1150
- const views = this.entityDef.interfaces?.master?.list?.views ?? [];
1151
- return views.map((v) => {
1152
- return new AXPEntityMasterListViewQueryViewModel(this.entityDef, this, v);
1153
- });
1253
+ this.relatedEntities = computed(() => {
1254
+ return this.entityDef.relatedEntities?.map(re => new AXPEntityDetailListViewModel(this.injector, re, { entity: this.entityDef, data: this.entityData })) ?? [];
1154
1255
  });
1155
- this.view = signal(this.views()[0]);
1156
1256
  this.workflow.events$
1157
1257
  .pipe(ofType(AXPEntityDeletedEvent))
1158
1258
  .pipe(takeUntil(this.destroyed))
1159
1259
  .subscribe((event) => {
1160
- if (event.payload.entity == getEntityInfo(this.entityDef).source) {
1161
- this.selectedItems.set([]);
1162
- this.events$.next({ action: 'refresh' });
1260
+ if (event.payload.entity == getEntityInfo(this.entityDef).source &&
1261
+ event.payload.ids.includes(this.context().id)) {
1262
+ this.workflow.execute('show-list-view', {
1263
+ entity: getEntityInfo(this.entityDef).source
1264
+ });
1265
+ }
1266
+ });
1267
+ this.workflow.events$
1268
+ .pipe(ofType(AXPEntityModifyEvent))
1269
+ .pipe(takeUntil(this.destroyed))
1270
+ .subscribe(async (event) => {
1271
+ if (event.payload.entity == getEntityInfo(this.entityDef).source &&
1272
+ event.payload.values.id === this.context().id) {
1273
+ this.context.set(event.payload.values);
1163
1274
  }
1164
1275
  });
1165
- console.log(this.sortableFields());
1166
- this.sortedFields.set(this.sortableFields());
1167
- }
1168
- clearSelection() {
1169
- this.selectedItems.set([]);
1170
1276
  }
1171
- applyInlineFilter(value) {
1172
- const props = this.entityDef.properties.filter((c) => c.options?.filter?.inline?.enabled);
1173
- this.inlineFilters.filters = [];
1174
- if (value) {
1175
- props.forEach((p) => {
1176
- this.inlineFilters.filters?.push({
1177
- field: p.name,
1178
- operator: {
1179
- type: 'contains',
1277
+ async executeCommand(commandName, data = null) {
1278
+ //TODO: syntact for workflow
1279
+ switch (commandName) {
1280
+ case 'modify-entity-section': {
1281
+ this.workflow.execute('modify-entity-section', {
1282
+ entity: getEntityInfo(this.entityDef).source,
1283
+ data: {
1284
+ id: this.context().id,
1285
+ properties: data.editableProps().map(m => m.name()),
1180
1286
  },
1181
- value,
1182
1287
  });
1183
- });
1184
- }
1185
- this.applyFilterAndSort();
1186
- }
1187
- applyFilterAndSort() {
1188
- this.dataSource.clearFilter();
1189
- //
1190
- this.dataSource.sort(...this.sortedFields().map((s) => ({ dir: s.dir, field: s.name })));
1191
- //
1192
- this.advanceFilters.filters = this.view().conditions.map((f) => ({
1193
- field: f.name,
1194
- operator: f.operator,
1195
- value: f.value,
1196
- }));
1197
- //
1198
- const inline = this.inlineFilters.filters?.length ?? 0;
1199
- const advance = this.advanceFilters.filters?.length ?? 0;
1200
- if (inline && !advance) {
1201
- this.dataSource.filter(this.filterOperatorMiddleware.transformFilter(this.inlineFilters));
1202
- }
1203
- else if (!inline && advance) {
1204
- this.dataSource.filter(this.filterOperatorMiddleware.transformFilter(this.advanceFilters));
1205
- }
1206
- else if (inline && advance) {
1207
- this.dataSource.filter(this.filterOperatorMiddleware.transformFilter({
1208
- field: null,
1209
- logic: 'and',
1210
- operator: null,
1211
- filters: [this.inlineFilters, this.advanceFilters],
1212
- }));
1213
- }
1214
- //
1215
- this.dataSource.refresh();
1216
- }
1217
- resetColumns() {
1218
- this.applyViewColumns();
1219
- }
1220
- applyColumns() {
1221
- //this.columns.set(this.clonedColumns())
1222
- }
1223
- applyViewColumns() {
1224
- const cols = this.view().columns;
1225
- const cloned = this.allAvailableColumns().map((c) => {
1226
- const column = this.entityDef.columns?.find((cc) => cc.name == c.name);
1227
- const prop = this.entityDef.properties.find((p) => p.name == c.name);
1228
- const col = new AXPEntityListViewColumnViewModel(prop, column);
1229
- col.visible = !cols.some((c) => c == col.name) && col.visible != false;
1230
- return col;
1231
- });
1232
- this.columns.set(cloned);
1233
- }
1234
- resetSorts() {
1235
- this.applyViewSorts();
1236
- }
1237
- applySorts() {
1238
- this.applyFilterAndSort();
1239
- }
1240
- addSort() {
1241
- const prop = this.sortableFields().find((c) => !this.sortedFields().some((s) => s.name == c.name));
1242
- if (prop) {
1243
- this.sortedFields.set([...this.sortedFields(), ...[prop]]);
1244
- }
1245
- }
1246
- removeSort(name) {
1247
- this.sortedFields.set(this.sortedFields().filter((c) => c.name != name));
1248
- }
1249
- applyViewSorts() {
1250
- const viewSorts = this.view().sorts;
1251
- this.sortedFields.update((prev) => {
1252
- const viewSortsMap = new Map(viewSorts.map((vs) => [vs.name, vs]));
1253
- return prev.map((sf) => {
1254
- const updatedSort = viewSortsMap.get(sf.name);
1255
- if (updatedSort) {
1256
- return { ...updatedSort, title: sf.title };
1288
+ break;
1289
+ }
1290
+ default:
1291
+ {
1292
+ const action = this.actions().find(c => c.name == commandName);
1293
+ this.workflow.execute(commandName, {
1294
+ entity: getEntityInfo(this.entityDef).source,
1295
+ data: action?.scope == AXPEntityCommandScope.Individual ? this.context() : null
1296
+ });
1257
1297
  }
1258
- return sf;
1259
- });
1260
- });
1261
- }
1262
- //****************** Views ******************//
1263
- setView(viewName = null) {
1264
- if (viewName != this.view().name) {
1265
- this.view.set(this.views().find((c) => c.name == viewName) ?? this.views()[0]);
1266
- this.applyViewSorts();
1267
- this.applyViewColumns();
1268
- this.applyFilterAndSort();
1269
1298
  }
1270
1299
  }
1271
- //****************** Commands ******************//
1272
- async executeCommand(commandName, data = null) {
1273
- const action = this.allActions().find((c) => c.name == commandName &&
1274
- ((this.selectedItems().length
1275
- ? c.scope == AXPEntityCommandScope.Selected
1276
- : c.scope == AXPEntityCommandScope.Individual) ||
1277
- c.scope == AXPEntityCommandScope.TypeLevel));
1278
- await this.workflow.execute(commandName, {
1279
- entity: getEntityInfo(this.entityDef).source,
1280
- data: action?.scope == AXPEntityCommandScope.Selected ? this.selectedItems() : data,
1281
- });
1282
- }
1300
+ //
1283
1301
  //
1284
1302
  destroy() {
1285
1303
  this.destroyed.next();
1286
1304
  this.destroyed.complete();
1287
1305
  }
1288
1306
  }
1289
- class AXPEntityListViewModelFactory {
1307
+ class AXPEntityDetailViewModelFactory {
1290
1308
  constructor() {
1291
1309
  this.entityService = inject(AXPEntityDefinitionRegistryService);
1292
1310
  this.layout = inject(AXPLayoutThemeService);
1293
1311
  this.injector = inject(Injector);
1294
1312
  }
1295
- async create(moduleName, entityName) {
1296
- this.layout.setNavigationLoading(true);
1313
+ async create(moduleName, entityName, id) {
1297
1314
  const config = await this.entityService.resolve(moduleName, entityName);
1315
+ this.layout.setNavigationLoading(true);
1316
+ if (config.queries.byKey) {
1317
+ const func = config.queries.byKey.execute;
1318
+ const data = await func(id);
1319
+ this.layout.setNavigationLoading(false);
1320
+ return new AXPEntityMasterSingleViewModel(this.injector, config, data);
1321
+ }
1298
1322
  this.layout.setNavigationLoading(false);
1299
- return new AXPEntityMasterListViewModel(this.injector, config);
1323
+ return Promise.reject('cannot fetch ');
1300
1324
  }
1301
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.0", ngImport: i0, type: AXPEntityListViewModelFactory, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
1302
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.0", ngImport: i0, type: AXPEntityListViewModelFactory, providedIn: 'root' }); }
1325
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.0", ngImport: i0, type: AXPEntityDetailViewModelFactory, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
1326
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.0", ngImport: i0, type: AXPEntityDetailViewModelFactory, providedIn: 'root' }); }
1303
1327
  }
1304
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.0", ngImport: i0, type: AXPEntityListViewModelFactory, decorators: [{
1328
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.0", ngImport: i0, type: AXPEntityDetailViewModelFactory, decorators: [{
1305
1329
  type: Injectable,
1306
1330
  args: [{ providedIn: 'root' }]
1307
1331
  }] });
1308
- const AXPEntityListViewModelResolver = (route, state, service = inject(AXPEntityListViewModelFactory)) => {
1332
+ const AXPEntityDetailViewModelResolver = (route, state, service = inject(AXPEntityDetailViewModelFactory)) => {
1309
1333
  const moduleName = route.parent?.paramMap.get('module');
1310
1334
  const entityName = route.paramMap.get('entity');
1335
+ const id = route.paramMap.get('id');
1311
1336
  //
1312
- return service.create(moduleName, entityName);
1337
+ return service.create(moduleName, entityName, id);
1313
1338
  };
1314
1339
 
1315
1340
  class AXPLookupWidgetViewComponent extends AXPWidgetComponent {
@@ -2384,22 +2409,6 @@ function routesFacory() {
2384
2409
  {
2385
2410
  path: ':module',
2386
2411
  children: [
2387
- // {
2388
- // path: 'e/:entity/:id/view/:section',
2389
- // resolve: { loader: AXPEntityDetailViewLoaderResolver },
2390
- // component: AXPEntityDetailsViewComponent,
2391
- // },
2392
- // {
2393
- // path: 'settings',
2394
- // component: AXPSettingsMenuComponent,
2395
- // data: { reuse: true },
2396
- // children: [
2397
- // {
2398
- // path: ':group',
2399
- // component: AXPSettingsPreviewComponent,
2400
- // },
2401
- // ],
2402
- // },
2403
2412
  {
2404
2413
  path: 'e/:entity/list',
2405
2414
  loadComponent: () => {
@@ -2527,5 +2536,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.0", ngImpor
2527
2536
  * Generated bundle index. Do not edit.
2528
2537
  */
2529
2538
 
2530
- export { AXPEntityCreateViewElementViewModel, AXPEntityCreateViewModelFactory, AXPEntityCreateViewSectionViewModel, AXPEntityDefinitionRegistryService, AXPEntityDetailListViewModel, AXPEntityDetailViewModelFactory, AXPEntityDetailViewModelResolver, AXPEntityListViewModelFactory, AXPEntityListViewModelResolver, AXPEntityMasterCreateViewModel, AXPEntityMasterListViewModel, AXPEntityMasterListViewQueryViewModel, AXPEntityMasterSingleElementViewModel, AXPEntityMasterSingleViewGroupViewModel, AXPEntityMasterSingleViewModel, AXPEntityMasterUpdateElementViewModel, AXPEntityMasterUpdateViewModel, AXPEntityMasterUpdateViewModelFactory, AXPEntityModule, AXPEntityResolver, AXPEntityService, AXP_ENTITY_CONFIG_TOKEN, AXP_ENTITY_DEFINITION_LOADER };
2539
+ export { AXPEntityCommandTriggerViewModel, AXPEntityCreateViewElementViewModel, AXPEntityCreateViewModelFactory, AXPEntityCreateViewSectionViewModel, AXPEntityDefinitionRegistryService, AXPEntityDetailListViewModel, AXPEntityDetailViewModelFactory, AXPEntityDetailViewModelResolver, AXPEntityListViewColumnViewModel, AXPEntityListViewModelFactory, AXPEntityListViewModelResolver, AXPEntityMasterCreateViewModel, AXPEntityMasterListViewModel, AXPEntityMasterListViewQueryViewModel, AXPEntityMasterSingleElementViewModel, AXPEntityMasterSingleViewGroupViewModel, AXPEntityMasterSingleViewModel, AXPEntityMasterUpdateElementViewModel, AXPEntityMasterUpdateViewModel, AXPEntityMasterUpdateViewModelFactory, AXPEntityModule, AXPEntityResolver, AXPEntityService, AXP_ENTITY_CONFIG_TOKEN, AXP_ENTITY_DEFINITION_LOADER };
2531
2540
  //# sourceMappingURL=acorex-platform-layout-entity.mjs.map