@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.
- package/esm2022/common/lib/layout/sticky.directive.mjs +15 -11
- package/esm2022/layout/builder/lib/builder/widget-column-renderer.mjs +22 -11
- package/esm2022/layout/designer/lib/designer/components/size-mode/view-size-toolbar.component.mjs +27 -32
- package/esm2022/layout/entity/lib/entity-master-list.viewmodel.mjs +33 -8
- package/esm2022/layout/entity/lib/entity.module.mjs +1 -17
- package/esm2022/layout/entity/lib/index.mjs +5 -4
- package/esm2022/layout/setting/lib/convert-setting-data.mjs +59 -0
- package/esm2022/layout/setting/lib/setting.viewmodel.mjs +123 -41
- package/esm2022/layouts/lib/admin/entity-layout/entity-list-view/entity-list-view.component.mjs +3 -3
- package/esm2022/themes/default/lib/default.module.mjs +83 -39
- package/esm2022/themes/default/lib/layouts/entity-layouts/entity-detail-list-view/entity-detail-list-view.component.mjs +3 -3
- package/esm2022/themes/default/lib/layouts/entity-layouts/entity-master-list-view/entity-master-list-view.component.mjs +18 -18
- package/esm2022/themes/default/lib/layouts/entity-layouts/entity-master-list-view/list-view-option-columns/list-view-option-columns.component.mjs +18 -8
- package/esm2022/themes/default/lib/layouts/root-layout/components/menu/root-menu.component.mjs +1 -1
- package/esm2022/themes/default/lib/layouts/setting-layout/index.mjs +3 -3
- package/esm2022/themes/default/lib/layouts/setting-layout/setting-menu/setting-menu.component.mjs +28 -0
- package/esm2022/themes/default/lib/layouts/setting-layout/setting-view/setting-view.component.mjs +42 -0
- package/esm2022/widgets/lib/widgets/advance/cron-job/cron-job-widget-edit.component.mjs +2 -2
- package/esm2022/widgets/lib/widgets/advance/cron-job/cron-job-widget.config.mjs +3 -2
- package/esm2022/workflow/lib/workflow.service.mjs +1 -1
- package/fesm2022/acorex-platform-common.mjs +13 -9
- package/fesm2022/acorex-platform-common.mjs.map +1 -1
- package/fesm2022/acorex-platform-layout-builder.mjs +18 -7
- package/fesm2022/acorex-platform-layout-builder.mjs.map +1 -1
- package/fesm2022/acorex-platform-layout-designer.mjs +25 -30
- package/fesm2022/acorex-platform-layout-designer.mjs.map +1 -1
- package/fesm2022/acorex-platform-layout-entity.mjs +842 -833
- package/fesm2022/acorex-platform-layout-entity.mjs.map +1 -1
- package/fesm2022/acorex-platform-layout-setting.mjs +180 -40
- package/fesm2022/acorex-platform-layout-setting.mjs.map +1 -1
- package/fesm2022/acorex-platform-layouts.mjs.map +1 -1
- 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
- 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
- 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
- package/fesm2022/acorex-platform-themes-default-entity-master-list-view.component-DPHXeucj.mjs.map +1 -0
- 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
- 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
- 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
- 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
- package/fesm2022/acorex-platform-themes-default.mjs +153 -257
- package/fesm2022/acorex-platform-themes-default.mjs.map +1 -1
- package/fesm2022/acorex-platform-widgets.mjs +3 -2
- package/fesm2022/acorex-platform-widgets.mjs.map +1 -1
- package/fesm2022/acorex-platform-workflow.mjs.map +1 -1
- package/layout/builder/lib/builder/widget-column-renderer.d.ts +1 -1
- package/layout/entity/lib/entity-master-list.viewmodel.d.ts +6 -2
- package/layout/entity/lib/index.d.ts +4 -3
- package/layout/setting/README.md +2 -3
- package/{themes/default/lib/layouts/setting-layout → layout/setting/lib}/convert-setting-data.d.ts +6 -6
- package/layout/setting/lib/setting.viewmodel.d.ts +35 -9
- package/package.json +7 -7
- package/themes/default/lib/default.module.d.ts +3 -4
- package/themes/default/lib/layouts/entity-layouts/entity-master-list-view/list-view-option-columns/list-view-option-columns.component.d.ts +3 -0
- package/themes/default/lib/layouts/setting-layout/index.d.ts +2 -2
- package/themes/default/lib/layouts/setting-layout/setting-menu/setting-menu.component.d.ts +12 -0
- package/themes/default/lib/layouts/setting-layout/setting-view/setting-view.component.d.ts +7 -0
- package/widgets/lib/widgets/advance/cron-job/cron-job-widget-edit.component.d.ts +1 -2
- package/workflow/lib/workflow.service.d.ts +1 -1
- package/esm2022/themes/default/lib/layout.routes.mjs +0 -20
- package/esm2022/themes/default/lib/layouts/setting-layout/convert-setting-data.mjs +0 -49
- package/esm2022/themes/default/lib/layouts/setting-layout/setting-preview/setting-preview.component.mjs +0 -104
- package/esm2022/themes/default/lib/layouts/setting-layout/setting-view/setting-menu.component.mjs +0 -44
- package/fesm2022/acorex-platform-themes-default-entity-master-list-view.component-C6zgLyry.mjs.map +0 -1
- package/themes/default/lib/layout.routes.d.ts +0 -2
- package/themes/default/lib/layouts/setting-layout/setting-preview/setting-preview.component.d.ts +0 -24
- 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 {
|
|
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
|
|
6
|
-
import {
|
|
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 {
|
|
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
|
|
145
|
-
constructor(entity,
|
|
146
|
-
this.
|
|
147
|
-
|
|
148
|
-
this.
|
|
149
|
-
this.
|
|
150
|
-
this.
|
|
151
|
-
|
|
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
|
|
300
|
-
constructor(entity,
|
|
610
|
+
class AXPEntityMasterListViewQueryViewModel {
|
|
611
|
+
constructor(entity, section, view) {
|
|
301
612
|
this.entity = entity;
|
|
302
|
-
this.
|
|
303
|
-
this.
|
|
304
|
-
this.
|
|
305
|
-
this.
|
|
306
|
-
this.
|
|
307
|
-
|
|
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
|
|
336
|
-
constructor(injector, config
|
|
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.
|
|
344
|
-
this.
|
|
345
|
-
this.
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
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
|
|
508
|
-
|
|
509
|
-
|
|
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
|
-
|
|
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.
|
|
522
|
-
return list.map((tr) => new AXPEntityCommandTriggerViewModel(this.
|
|
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.
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
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.
|
|
775
|
+
this.sortedFields.set(this.sortableFields());
|
|
557
776
|
}
|
|
558
|
-
async
|
|
559
|
-
|
|
560
|
-
const
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
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
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
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
|
-
|
|
810
|
+
this.dataSource.sort(...this.sortedFields().map((s) => ({ dir: s.dir, field: s.name })));
|
|
591
811
|
//
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
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
|
|
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 &&
|
|
614
|
-
this.dataSource.filter(this.filterOperatorMiddleware.transformFilter(
|
|
823
|
+
else if (!inline && advance) {
|
|
824
|
+
this.dataSource.filter(this.filterOperatorMiddleware.transformFilter(this.advanceFilters));
|
|
615
825
|
}
|
|
616
|
-
else if (inline &&
|
|
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,
|
|
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.
|
|
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
|
-
|
|
656
|
-
|
|
657
|
-
this.
|
|
658
|
-
this.
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
this.
|
|
662
|
-
|
|
663
|
-
|
|
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
|
-
|
|
693
|
-
|
|
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.
|
|
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
|
|
704
|
-
const source = cloneDeep(
|
|
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
|
-
|
|
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
|
|
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.
|
|
733
|
-
this.translateService = this.injector.get(AXTranslationService);
|
|
991
|
+
this.isInProgress = signal(false);
|
|
734
992
|
this.context = signal(cloneDeep(this.entityData));
|
|
735
|
-
this.
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
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
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
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
|
-
|
|
818
|
-
|
|
819
|
-
|
|
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
|
|
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
|
|
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:
|
|
853
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.0", ngImport: i0, type:
|
|
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:
|
|
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
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
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
|
|
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.
|
|
886
|
-
const {
|
|
887
|
-
const
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
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
|
|
900
|
-
constructor(entity, section,
|
|
1165
|
+
class AXPEntityMasterSingleElementViewModel {
|
|
1166
|
+
constructor(entity, section, propertyView) {
|
|
901
1167
|
this.entity = entity;
|
|
902
1168
|
this.section = section;
|
|
903
|
-
this.
|
|
904
|
-
this.
|
|
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
|
|
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:
|
|
1186
|
+
mode: 'view',
|
|
925
1187
|
path: this.name(),
|
|
926
1188
|
children: widget.children,
|
|
927
1189
|
formula: widget.formula,
|
|
928
|
-
|
|
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
|
|
937
|
-
constructor(injector, config,
|
|
1195
|
+
class AXPEntityMasterSingleViewModel {
|
|
1196
|
+
constructor(injector, config, entityData) {
|
|
938
1197
|
this.injector = injector;
|
|
939
1198
|
this.config = config;
|
|
940
|
-
this.
|
|
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.
|
|
944
|
-
this.
|
|
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
|
|
948
|
-
const
|
|
949
|
-
const
|
|
950
|
-
return
|
|
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
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
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
|
|
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:
|
|
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.
|
|
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
|
-
|
|
1080
|
-
|
|
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
|
-
|
|
1162
|
-
this.
|
|
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
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
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
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
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:
|
|
1302
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.0", ngImport: i0, type:
|
|
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:
|
|
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
|
|
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
|