@acorex/platform 20.5.0-next.0 → 20.5.0-next.2
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/common/index.d.ts +8 -0
- package/fesm2022/acorex-platform-common.mjs +32 -9
- package/fesm2022/acorex-platform-common.mjs.map +1 -1
- package/fesm2022/acorex-platform-layout-builder.mjs +417 -112
- package/fesm2022/acorex-platform-layout-builder.mjs.map +1 -1
- package/fesm2022/acorex-platform-layout-entity.mjs +129 -125
- package/fesm2022/acorex-platform-layout-entity.mjs.map +1 -1
- package/fesm2022/acorex-platform-layout-widget-core.mjs +19 -0
- package/fesm2022/acorex-platform-layout-widget-core.mjs.map +1 -1
- package/fesm2022/acorex-platform-layout-widgets.mjs +478 -85
- package/fesm2022/acorex-platform-layout-widgets.mjs.map +1 -1
- package/fesm2022/{acorex-platform-themes-default-entity-master-list-view.component-rdKxuMC_.mjs → acorex-platform-themes-default-entity-master-list-view.component-ccqB5ShI.mjs} +7 -1
- package/fesm2022/{acorex-platform-themes-default-entity-master-list-view.component-rdKxuMC_.mjs.map → acorex-platform-themes-default-entity-master-list-view.component-ccqB5ShI.mjs.map} +1 -1
- package/fesm2022/acorex-platform-themes-default.mjs +2 -2
- package/layout/builder/index.d.ts +127 -28
- package/layout/widget-core/index.d.ts +20 -1
- package/layout/widgets/index.d.ts +162 -6
- package/package.json +2 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as i4 from '@angular/common';
|
|
2
2
|
import { CommonModule } from '@angular/common';
|
|
3
3
|
import * as i0 from '@angular/core';
|
|
4
4
|
import { inject, Injectable, input, model, signal, effect, output, viewChild, ChangeDetectionStrategy, Component, NgModule, EventEmitter, Output, Input } from '@angular/core';
|
|
@@ -10,11 +10,11 @@ import * as i1 from '@acorex/platform/layout/widget-core';
|
|
|
10
10
|
import { AXPWidgetContainerComponent, AXPPageStatus, AXPWidgetCoreModule } from '@acorex/platform/layout/widget-core';
|
|
11
11
|
import { isEqual, get, cloneDeep } from 'lodash-es';
|
|
12
12
|
import { Subject, debounceTime, distinctUntilChanged, startWith } from 'rxjs';
|
|
13
|
-
import * as
|
|
13
|
+
import * as i1$1 from '@acorex/components/button';
|
|
14
14
|
import { AXButtonModule } from '@acorex/components/button';
|
|
15
|
-
import * as
|
|
15
|
+
import * as i2$1 from '@acorex/components/decorators';
|
|
16
16
|
import { AXDecoratorModule } from '@acorex/components/decorators';
|
|
17
|
-
import * as
|
|
17
|
+
import * as i3 from '@acorex/components/loading';
|
|
18
18
|
import { AXLoadingModule } from '@acorex/components/loading';
|
|
19
19
|
import { AXBasePageComponent } from '@acorex/components/page';
|
|
20
20
|
import * as i5 from '@acorex/core/translation';
|
|
@@ -170,12 +170,24 @@ class LayoutBuilder {
|
|
|
170
170
|
return this;
|
|
171
171
|
}
|
|
172
172
|
dialog(delegate) {
|
|
173
|
+
if (!this.popupService) {
|
|
174
|
+
throw new Error('LayoutBuilder requires AXPopupService to create dialogs. Please inject it in the service constructor.');
|
|
175
|
+
}
|
|
173
176
|
const container = new DialogContainerBuilder(this.popupService);
|
|
174
177
|
if (delegate) {
|
|
175
178
|
delegate(container);
|
|
176
179
|
}
|
|
177
180
|
return container;
|
|
178
181
|
}
|
|
182
|
+
stepWizard(delegate) {
|
|
183
|
+
const wizard = new StepWizardBuilder();
|
|
184
|
+
wizard.withInheritanceContext(this.inheritanceContext);
|
|
185
|
+
if (delegate) {
|
|
186
|
+
delegate(wizard);
|
|
187
|
+
}
|
|
188
|
+
this.root.children.push(wizard.build());
|
|
189
|
+
return this;
|
|
190
|
+
}
|
|
179
191
|
formField(label, delegate) {
|
|
180
192
|
const field = new FormFieldBuilder(label);
|
|
181
193
|
field.withInheritanceContext(this.inheritanceContext);
|
|
@@ -448,6 +460,16 @@ class ChildContainerMixin extends LayoutContainerMixin {
|
|
|
448
460
|
}
|
|
449
461
|
return container;
|
|
450
462
|
}
|
|
463
|
+
stepWizard(delegate) {
|
|
464
|
+
const wizard = new StepWizardBuilder();
|
|
465
|
+
wizard.withInheritanceContext(this.inheritanceContext);
|
|
466
|
+
if (delegate) {
|
|
467
|
+
delegate(wizard);
|
|
468
|
+
}
|
|
469
|
+
this.ensureChildren();
|
|
470
|
+
this.containerState.children.push(wizard.build());
|
|
471
|
+
return this;
|
|
472
|
+
}
|
|
451
473
|
formField(label, delegate) {
|
|
452
474
|
const field = new FormFieldBuilder(label);
|
|
453
475
|
field.withInheritanceContext(this.inheritanceContext);
|
|
@@ -1031,6 +1053,23 @@ class DialogContainerBuilder {
|
|
|
1031
1053
|
}
|
|
1032
1054
|
return this;
|
|
1033
1055
|
}
|
|
1056
|
+
addCustomAction(action) {
|
|
1057
|
+
// Add to actions based on position
|
|
1058
|
+
const position = action.position || 'suffix';
|
|
1059
|
+
if (position === 'prefix') {
|
|
1060
|
+
if (!this.dialogState.actions.footer.prefix) {
|
|
1061
|
+
this.dialogState.actions.footer.prefix = [];
|
|
1062
|
+
}
|
|
1063
|
+
this.dialogState.actions.footer.prefix.push(action);
|
|
1064
|
+
}
|
|
1065
|
+
else {
|
|
1066
|
+
if (!this.dialogState.actions.footer.suffix) {
|
|
1067
|
+
this.dialogState.actions.footer.suffix = [];
|
|
1068
|
+
}
|
|
1069
|
+
this.dialogState.actions.footer.suffix.push(action);
|
|
1070
|
+
}
|
|
1071
|
+
return this;
|
|
1072
|
+
}
|
|
1034
1073
|
// Build method to create dialog node
|
|
1035
1074
|
build() {
|
|
1036
1075
|
// If we have content layout, use it directly to avoid extra wrapper
|
|
@@ -1255,6 +1294,138 @@ class ActionBuilder {
|
|
|
1255
1294
|
return this;
|
|
1256
1295
|
}
|
|
1257
1296
|
}
|
|
1297
|
+
//#endregion
|
|
1298
|
+
//#region ---- Step Wizard Builder Implementation ----
|
|
1299
|
+
/**
|
|
1300
|
+
* Step Builder - Builds individual steps for step wizard
|
|
1301
|
+
*/
|
|
1302
|
+
class StepBuilder {
|
|
1303
|
+
constructor(id, title) {
|
|
1304
|
+
this.id = id;
|
|
1305
|
+
this.title = title;
|
|
1306
|
+
this.skippable = false;
|
|
1307
|
+
this.inheritanceContext = {};
|
|
1308
|
+
}
|
|
1309
|
+
setIcon(icon) {
|
|
1310
|
+
this.icon = icon;
|
|
1311
|
+
return this;
|
|
1312
|
+
}
|
|
1313
|
+
setDescription(description) {
|
|
1314
|
+
this.description = description;
|
|
1315
|
+
return this;
|
|
1316
|
+
}
|
|
1317
|
+
setSkippable(skippable) {
|
|
1318
|
+
this.skippable = skippable;
|
|
1319
|
+
return this;
|
|
1320
|
+
}
|
|
1321
|
+
content(delegate) {
|
|
1322
|
+
if (delegate) {
|
|
1323
|
+
// Create LayoutBuilder in injection context (will be called from component)
|
|
1324
|
+
const layoutBuilder = new LayoutBuilder();
|
|
1325
|
+
// ✅ IMPORTANT: Propagate inheritance context to content
|
|
1326
|
+
layoutBuilder.inheritanceContext = { ...this.inheritanceContext };
|
|
1327
|
+
delegate(layoutBuilder);
|
|
1328
|
+
this.contentNode = layoutBuilder.build();
|
|
1329
|
+
}
|
|
1330
|
+
return this;
|
|
1331
|
+
}
|
|
1332
|
+
withInheritanceContext(context) {
|
|
1333
|
+
this.inheritanceContext = mergeInheritanceContext(context);
|
|
1334
|
+
return this;
|
|
1335
|
+
}
|
|
1336
|
+
build() {
|
|
1337
|
+
if (!this.contentNode) {
|
|
1338
|
+
throw new Error(`Step '${this.id}' must have content`);
|
|
1339
|
+
}
|
|
1340
|
+
return {
|
|
1341
|
+
id: this.id,
|
|
1342
|
+
title: this.title,
|
|
1343
|
+
icon: this.icon,
|
|
1344
|
+
description: this.description,
|
|
1345
|
+
skippable: this.skippable,
|
|
1346
|
+
content: this.contentNode,
|
|
1347
|
+
};
|
|
1348
|
+
}
|
|
1349
|
+
}
|
|
1350
|
+
/**
|
|
1351
|
+
* Step Wizard Builder - Builds step wizard widget
|
|
1352
|
+
*/
|
|
1353
|
+
class StepWizardBuilder extends LayoutContainerMixin {
|
|
1354
|
+
constructor() {
|
|
1355
|
+
super('step-wizard');
|
|
1356
|
+
this.steps = [];
|
|
1357
|
+
this.linear = true;
|
|
1358
|
+
this.wizardDirection = 'horizontal';
|
|
1359
|
+
}
|
|
1360
|
+
setLinear(linear) {
|
|
1361
|
+
this.linear = linear;
|
|
1362
|
+
return this;
|
|
1363
|
+
}
|
|
1364
|
+
setDirection(direction) {
|
|
1365
|
+
this.wizardDirection = direction;
|
|
1366
|
+
return this;
|
|
1367
|
+
}
|
|
1368
|
+
setLook(look) {
|
|
1369
|
+
this.look = look;
|
|
1370
|
+
return this;
|
|
1371
|
+
}
|
|
1372
|
+
setShowActions(show) {
|
|
1373
|
+
this.showActions = show;
|
|
1374
|
+
return this;
|
|
1375
|
+
}
|
|
1376
|
+
setActions(actions) {
|
|
1377
|
+
this.wizardActions = actions;
|
|
1378
|
+
return this;
|
|
1379
|
+
}
|
|
1380
|
+
setGuards(guards) {
|
|
1381
|
+
this.guards = guards;
|
|
1382
|
+
return this;
|
|
1383
|
+
}
|
|
1384
|
+
setEvents(events) {
|
|
1385
|
+
this.events = events;
|
|
1386
|
+
return this;
|
|
1387
|
+
}
|
|
1388
|
+
step(id, title, delegate) {
|
|
1389
|
+
const stepBuilder = new StepBuilder(id, title);
|
|
1390
|
+
// ✅ IMPORTANT: Propagate inheritance context to step
|
|
1391
|
+
stepBuilder.withInheritanceContext(this.inheritanceContext);
|
|
1392
|
+
if (delegate) {
|
|
1393
|
+
delegate(stepBuilder);
|
|
1394
|
+
}
|
|
1395
|
+
this.steps.push(stepBuilder.build());
|
|
1396
|
+
return this;
|
|
1397
|
+
}
|
|
1398
|
+
build() {
|
|
1399
|
+
// ✅ Validation
|
|
1400
|
+
if (this.steps.length === 0) {
|
|
1401
|
+
throw new Error('StepWizard must have at least one step');
|
|
1402
|
+
}
|
|
1403
|
+
// ✅ Check duplicate IDs
|
|
1404
|
+
const ids = this.steps.map((s) => s.id);
|
|
1405
|
+
const duplicates = ids.filter((id, index) => ids.indexOf(id) !== index);
|
|
1406
|
+
if (duplicates.length > 0) {
|
|
1407
|
+
throw new Error(`Duplicate step IDs found: ${duplicates.join(', ')}`);
|
|
1408
|
+
}
|
|
1409
|
+
const definition = {
|
|
1410
|
+
steps: this.steps,
|
|
1411
|
+
linear: this.linear,
|
|
1412
|
+
direction: this.wizardDirection,
|
|
1413
|
+
look: this.look,
|
|
1414
|
+
// Do not auto-detect based on dialog context; keep explicit or undefined
|
|
1415
|
+
showActions: this.showActions,
|
|
1416
|
+
actions: this.wizardActions,
|
|
1417
|
+
guards: this.guards,
|
|
1418
|
+
events: this.events,
|
|
1419
|
+
};
|
|
1420
|
+
const node = {
|
|
1421
|
+
name: this.containerState.name,
|
|
1422
|
+
type: 'step-wizard',
|
|
1423
|
+
options: { definition },
|
|
1424
|
+
mode: this.containerState.mode,
|
|
1425
|
+
};
|
|
1426
|
+
return node;
|
|
1427
|
+
}
|
|
1428
|
+
}
|
|
1258
1429
|
|
|
1259
1430
|
class AXPLayoutConversionService {
|
|
1260
1431
|
constructor() {
|
|
@@ -1884,29 +2055,60 @@ class AXPDialogRendererComponent extends AXBasePageComponent {
|
|
|
1884
2055
|
constructor() {
|
|
1885
2056
|
super(...arguments);
|
|
1886
2057
|
this.result = new EventEmitter();
|
|
2058
|
+
this.expressionEvaluator = inject(AXPExpressionEvaluatorService);
|
|
1887
2059
|
this.context = signal({}, ...(ngDevMode ? [{ debugName: "context" }] : []));
|
|
1888
2060
|
// This will be set by the popup service automatically - same as dynamic-dialog
|
|
1889
2061
|
this.callBack = () => { };
|
|
1890
2062
|
this.isDialogLoading = signal(false, ...(ngDevMode ? [{ debugName: "isDialogLoading" }] : []));
|
|
2063
|
+
// Aggregated actions for footer rendering
|
|
2064
|
+
this.footerPrefix = signal([], ...(ngDevMode ? [{ debugName: "footerPrefix" }] : []));
|
|
2065
|
+
this.footerSuffix = signal([], ...(ngDevMode ? [{ debugName: "footerSuffix" }] : []));
|
|
2066
|
+
//#endregion
|
|
2067
|
+
//#region ---- View Accessors ----
|
|
2068
|
+
// Access the internal layout renderer to reach the widgets container injector
|
|
2069
|
+
this.layoutRenderer = viewChild(AXPLayoutRendererComponent, ...(ngDevMode ? [{ debugName: "layoutRenderer" }] : []));
|
|
2070
|
+
this.#eff = effect(() => {
|
|
2071
|
+
let count = 0;
|
|
2072
|
+
if (!this.widgetCoreService) {
|
|
2073
|
+
const renderer = this.layoutRenderer();
|
|
2074
|
+
const container = renderer?.getContainer();
|
|
2075
|
+
this.widgetCoreService = container?.builderService ?? null;
|
|
2076
|
+
count = this.widgetCoreService.registeredWidgetsCount();
|
|
2077
|
+
}
|
|
2078
|
+
else {
|
|
2079
|
+
count = this.widgetCoreService.registeredWidgetsCount();
|
|
2080
|
+
// Clear existing timer
|
|
2081
|
+
if (this.debounceTimer) {
|
|
2082
|
+
clearTimeout(this.debounceTimer);
|
|
2083
|
+
}
|
|
2084
|
+
// Set new timer to call after 200ms of no count changes
|
|
2085
|
+
this.debounceTimer = setTimeout(() => {
|
|
2086
|
+
this.aggregateAndEvaluateActions();
|
|
2087
|
+
}, 200);
|
|
2088
|
+
}
|
|
2089
|
+
}, ...(ngDevMode ? [{ debugName: "#eff" }] : []));
|
|
1891
2090
|
}
|
|
2091
|
+
//#endregion
|
|
2092
|
+
//#region ---- Lifecycle ----
|
|
1892
2093
|
ngOnInit() {
|
|
1893
2094
|
// Initialize context with provided context
|
|
1894
2095
|
this.context.set(this.config?.context || {});
|
|
1895
2096
|
}
|
|
2097
|
+
#eff;
|
|
2098
|
+
//#endregion
|
|
1896
2099
|
handleContextChanged(event) {
|
|
1897
2100
|
this.context.set(event);
|
|
2101
|
+
this.aggregateAndEvaluateActions();
|
|
1898
2102
|
}
|
|
1899
2103
|
handleContextInitiated(event) {
|
|
1900
2104
|
this.context.set(event);
|
|
2105
|
+
this.aggregateAndEvaluateActions();
|
|
1901
2106
|
}
|
|
1902
|
-
|
|
1903
|
-
return this.
|
|
2107
|
+
footerPrefixActions() {
|
|
2108
|
+
return this.footerPrefix();
|
|
1904
2109
|
}
|
|
1905
|
-
|
|
1906
|
-
return
|
|
1907
|
-
{ title: 'Cancel', color: 'secondary', command: { name: 'cancel' } },
|
|
1908
|
-
{ title: 'Confirm', color: 'primary', command: { name: 'confirm' } },
|
|
1909
|
-
]);
|
|
2110
|
+
footerSuffixActions() {
|
|
2111
|
+
return this.footerSuffix();
|
|
1910
2112
|
}
|
|
1911
2113
|
isFormLoading() {
|
|
1912
2114
|
return this.isDialogLoading();
|
|
@@ -1915,43 +2117,166 @@ class AXPDialogRendererComponent extends AXBasePageComponent {
|
|
|
1915
2117
|
return this.isDialogLoading();
|
|
1916
2118
|
}
|
|
1917
2119
|
async executeAction(action) {
|
|
1918
|
-
const
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
|
|
2120
|
+
const cmd = action.command;
|
|
2121
|
+
if (cmd !== 'cancel') {
|
|
2122
|
+
const isValid = await this.layoutRenderer()?.validate();
|
|
2123
|
+
if (!isValid?.result) {
|
|
2124
|
+
return;
|
|
2125
|
+
}
|
|
2126
|
+
}
|
|
2127
|
+
if (typeof cmd === 'string' && cmd.startsWith('widget:')) {
|
|
2128
|
+
const parsed = this.parseWidgetCommand(cmd);
|
|
2129
|
+
if (parsed.widgetName && parsed.action) {
|
|
2130
|
+
await this.executeWidgetApi(parsed.widgetName, parsed.action);
|
|
2131
|
+
await this.aggregateAndEvaluateActions();
|
|
2132
|
+
return;
|
|
2133
|
+
}
|
|
2134
|
+
}
|
|
2135
|
+
// Fallback: treat as regular dialog action (cancel/confirm/custom)
|
|
2136
|
+
const result = { context: this.context(), action: cmd };
|
|
1925
2137
|
this.dialogResult = result;
|
|
1926
|
-
// Store in popup data for DialogRef access
|
|
1927
2138
|
if (this.data) {
|
|
1928
2139
|
this.data.context = result.context;
|
|
1929
2140
|
this.data.action = result.action;
|
|
1930
2141
|
}
|
|
1931
|
-
// Call the callback with DialogRef - same pattern as dynamic-dialog
|
|
1932
2142
|
this.callBack({
|
|
1933
2143
|
close: (result) => {
|
|
1934
2144
|
this.close(result);
|
|
1935
2145
|
},
|
|
1936
|
-
context: () =>
|
|
1937
|
-
|
|
1938
|
-
},
|
|
1939
|
-
action: () => {
|
|
1940
|
-
return result.action;
|
|
1941
|
-
},
|
|
2146
|
+
context: () => this.context(),
|
|
2147
|
+
action: () => result.action,
|
|
1942
2148
|
setLoading: (loading) => {
|
|
1943
2149
|
this.isDialogLoading.set(loading);
|
|
1944
2150
|
},
|
|
1945
2151
|
});
|
|
1946
2152
|
}
|
|
1947
|
-
|
|
2153
|
+
parseWidgetCommand(cmd) {
|
|
2154
|
+
// Expected 'widget:<widgetName>.<action>'
|
|
2155
|
+
if (!cmd?.startsWith('widget:'))
|
|
2156
|
+
return {};
|
|
2157
|
+
const rest = cmd.slice('widget:'.length);
|
|
2158
|
+
const dot = rest.lastIndexOf('.');
|
|
2159
|
+
if (dot <= 0)
|
|
2160
|
+
return {};
|
|
2161
|
+
return { widgetName: rest.slice(0, dot), action: rest.slice(dot + 1) };
|
|
2162
|
+
}
|
|
2163
|
+
async executeWidgetApi(widgetName, apiMethod) {
|
|
2164
|
+
if (!this.widgetCoreService)
|
|
2165
|
+
return;
|
|
2166
|
+
try {
|
|
2167
|
+
const widget = this.widgetCoreService.getWidget(widgetName);
|
|
2168
|
+
const api = widget?.api?.();
|
|
2169
|
+
const fn = api?.[apiMethod];
|
|
2170
|
+
if (typeof fn === 'function') {
|
|
2171
|
+
await Promise.resolve(fn({
|
|
2172
|
+
close: (result) => {
|
|
2173
|
+
this.close(result);
|
|
2174
|
+
},
|
|
2175
|
+
context: () => this.context(),
|
|
2176
|
+
setLoading: (loading) => {
|
|
2177
|
+
this.isDialogLoading.set(loading);
|
|
2178
|
+
},
|
|
2179
|
+
}));
|
|
2180
|
+
}
|
|
2181
|
+
}
|
|
2182
|
+
catch { }
|
|
2183
|
+
}
|
|
2184
|
+
async close(result) {
|
|
1948
2185
|
if (result) {
|
|
1949
|
-
this.
|
|
2186
|
+
const isValid = await this.layoutRenderer()?.validate();
|
|
2187
|
+
if (isValid?.result) {
|
|
2188
|
+
this.result.emit(result);
|
|
2189
|
+
}
|
|
1950
2190
|
}
|
|
1951
2191
|
super.close(result);
|
|
1952
2192
|
}
|
|
2193
|
+
// --- Actions aggregation & evaluation ---
|
|
2194
|
+
async aggregateAndEvaluateActions() {
|
|
2195
|
+
const widgetActions = await this.collectWidgetActions();
|
|
2196
|
+
const dialogActions = this.collectDialogActionsFromConfig();
|
|
2197
|
+
const all = [...widgetActions, ...dialogActions];
|
|
2198
|
+
const evaluated = await this.evaluatePredicates(all);
|
|
2199
|
+
const visible = evaluated.filter((a) => a.hidden !== true);
|
|
2200
|
+
const prefix = visible.filter((a) => (a.zone ?? 'footer') === 'footer' && (a.placement ?? 'suffix') === 'prefix');
|
|
2201
|
+
const suffix = visible.filter((a) => (a.zone ?? 'footer') === 'footer' && (a.placement ?? 'suffix') === 'suffix');
|
|
2202
|
+
this.footerPrefix.set(prefix);
|
|
2203
|
+
this.footerSuffix.set(suffix);
|
|
2204
|
+
}
|
|
2205
|
+
async collectWidgetActions() {
|
|
2206
|
+
if (!this.widgetCoreService)
|
|
2207
|
+
return [];
|
|
2208
|
+
const names = this.widgetCoreService.listRegisteredWidgetNames();
|
|
2209
|
+
const actions = [];
|
|
2210
|
+
for (const name of names) {
|
|
2211
|
+
try {
|
|
2212
|
+
const widget = this.widgetCoreService.getWidget(name);
|
|
2213
|
+
const widgetActs = widget?.actions?.() ?? [];
|
|
2214
|
+
actions.push(...widgetActs);
|
|
2215
|
+
}
|
|
2216
|
+
catch { }
|
|
2217
|
+
}
|
|
2218
|
+
return actions;
|
|
2219
|
+
}
|
|
2220
|
+
collectDialogActionsFromConfig() {
|
|
2221
|
+
const footer = this.config?.actions?.footer;
|
|
2222
|
+
const mapOne = (a, placement) => ({
|
|
2223
|
+
title: a.title,
|
|
2224
|
+
command: typeof a.command === 'string' ? a.command : a.command?.name,
|
|
2225
|
+
icon: a.icon,
|
|
2226
|
+
color: a.color,
|
|
2227
|
+
disabled: a.disabled,
|
|
2228
|
+
hidden: a.hidden,
|
|
2229
|
+
zone: 'footer',
|
|
2230
|
+
placement,
|
|
2231
|
+
scope: a.scope,
|
|
2232
|
+
});
|
|
2233
|
+
const prefix = (footer?.prefix || []).map((a) => mapOne(a, 'prefix'));
|
|
2234
|
+
const suffix = (footer?.suffix || []).map((a) => mapOne(a, 'suffix'));
|
|
2235
|
+
return [...prefix, ...suffix];
|
|
2236
|
+
}
|
|
2237
|
+
async evaluatePredicates(actions) {
|
|
2238
|
+
const out = [];
|
|
2239
|
+
for (const a of actions) {
|
|
2240
|
+
const parsed = typeof a.command === 'string' ? this.parseWidgetCommand(a.command) : {};
|
|
2241
|
+
const api = parsed.widgetName ? await this.resolveApi(parsed.widgetName) : undefined;
|
|
2242
|
+
const scope = {
|
|
2243
|
+
api,
|
|
2244
|
+
widget: { name: parsed.widgetName },
|
|
2245
|
+
dialog: { context: this.context() },
|
|
2246
|
+
context: this.context(),
|
|
2247
|
+
};
|
|
2248
|
+
const disabled = await this.evalBool(a.disabled, scope);
|
|
2249
|
+
const hidden = await this.evalBool(a.hidden, scope);
|
|
2250
|
+
out.push({ ...a, disabled, hidden });
|
|
2251
|
+
}
|
|
2252
|
+
return out;
|
|
2253
|
+
}
|
|
2254
|
+
async evalBool(value, scope) {
|
|
2255
|
+
if (typeof value === 'boolean')
|
|
2256
|
+
return value;
|
|
2257
|
+
if (typeof value === 'string') {
|
|
2258
|
+
try {
|
|
2259
|
+
const result = await this.expressionEvaluator.evaluate(value, scope);
|
|
2260
|
+
return !!result;
|
|
2261
|
+
}
|
|
2262
|
+
catch {
|
|
2263
|
+
return false;
|
|
2264
|
+
}
|
|
2265
|
+
}
|
|
2266
|
+
return value;
|
|
2267
|
+
}
|
|
2268
|
+
async resolveApi(widgetName) {
|
|
2269
|
+
try {
|
|
2270
|
+
await this.widgetCoreService?.waitForWidget(widgetName, 2000);
|
|
2271
|
+
const widget = this.widgetCoreService?.getWidget(widgetName);
|
|
2272
|
+
return widget?.api?.();
|
|
2273
|
+
}
|
|
2274
|
+
catch {
|
|
2275
|
+
return undefined;
|
|
2276
|
+
}
|
|
2277
|
+
}
|
|
1953
2278
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: AXPDialogRendererComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
|
|
1954
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.4", type: AXPDialogRendererComponent, isStandalone: true, selector: "axp-dialog-renderer", inputs: { config: "config" }, outputs: { result: "result" }, usesInheritance: true, ngImport: i0, template: `
|
|
2279
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.4", type: AXPDialogRendererComponent, isStandalone: true, selector: "axp-dialog-renderer", inputs: { config: "config" }, outputs: { result: "result" }, viewQueries: [{ propertyName: "layoutRenderer", first: true, predicate: AXPLayoutRendererComponent, descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: `
|
|
1955
2280
|
<div class="ax-p-4">
|
|
1956
2281
|
<axp-layout-renderer
|
|
1957
2282
|
[layout]="config.definition"
|
|
@@ -1964,52 +2289,42 @@ class AXPDialogRendererComponent extends AXBasePageComponent {
|
|
|
1964
2289
|
|
|
1965
2290
|
<ax-footer>
|
|
1966
2291
|
<ax-prefix>
|
|
1967
|
-
|
|
2292
|
+
@for (action of footerPrefixActions(); track $index) {
|
|
2293
|
+
<ax-button
|
|
2294
|
+
[disabled]="action.disabled || isFormLoading()"
|
|
2295
|
+
[text]="(action.title | translate | async)!"
|
|
2296
|
+
[look]="'outline'"
|
|
2297
|
+
[color]="action.color"
|
|
2298
|
+
(onClick)="executeAction(action)"
|
|
2299
|
+
>
|
|
2300
|
+
<ax-prefix>
|
|
2301
|
+
<i class="{{ action.icon }}"></i>
|
|
2302
|
+
</ax-prefix>
|
|
2303
|
+
</ax-button>
|
|
2304
|
+
}
|
|
1968
2305
|
</ax-prefix>
|
|
1969
2306
|
<ax-suffix>
|
|
1970
|
-
|
|
2307
|
+
@for (action of footerSuffixActions(); track $index) {
|
|
2308
|
+
<ax-button
|
|
2309
|
+
[disabled]="action.disabled || isSubmitting()"
|
|
2310
|
+
[text]="(action.title | translate | async)!"
|
|
2311
|
+
[look]="'solid'"
|
|
2312
|
+
[color]="action.color"
|
|
2313
|
+
(onClick)="executeAction(action)"
|
|
2314
|
+
>
|
|
2315
|
+
@if (isFormLoading()) {
|
|
2316
|
+
<ax-loading></ax-loading>
|
|
2317
|
+
}
|
|
2318
|
+
@if (action.icon) {
|
|
2319
|
+
<ax-prefix>
|
|
2320
|
+
<ax-icon icon="{{ action.icon }}"></ax-icon>
|
|
2321
|
+
</ax-prefix>
|
|
2322
|
+
}
|
|
2323
|
+
</ax-button>
|
|
2324
|
+
}
|
|
1971
2325
|
</ax-suffix>
|
|
1972
2326
|
</ax-footer>
|
|
1973
|
-
|
|
1974
|
-
<!-- Footer Prefix Actions -->
|
|
1975
|
-
<ng-template #footerPrefixActions>
|
|
1976
|
-
@for (action of visibleFooterPrefixActions(); track $index) {
|
|
1977
|
-
<ax-button
|
|
1978
|
-
[disabled]="action.disabled || isFormLoading()"
|
|
1979
|
-
[text]="(action.title | translate | async)!"
|
|
1980
|
-
[look]="'outline'"
|
|
1981
|
-
[color]="action.color"
|
|
1982
|
-
(onClick)="executeAction(action)"
|
|
1983
|
-
>
|
|
1984
|
-
@if (isFormLoading() && action.command?.name != 'cancel') {
|
|
1985
|
-
<ax-loading></ax-loading>
|
|
1986
|
-
}
|
|
1987
|
-
<ax-prefix>
|
|
1988
|
-
<i class="{{ action.icon }}"></i>
|
|
1989
|
-
</ax-prefix>
|
|
1990
|
-
</ax-button>
|
|
1991
|
-
}
|
|
1992
|
-
</ng-template>
|
|
1993
|
-
|
|
1994
|
-
<!-- Footer Suffix Actions -->
|
|
1995
|
-
<ng-template #footerSuffixActions>
|
|
1996
|
-
@for (action of visibleFooterSuffixActions(); track $index) {
|
|
1997
|
-
<ax-button
|
|
1998
|
-
[disabled]="action.disabled || isSubmitting()"
|
|
1999
|
-
[text]="(action.title | translate | async)!"
|
|
2000
|
-
[look]="'solid'"
|
|
2001
|
-
[color]="action.color"
|
|
2002
|
-
(onClick)="executeAction(action)"
|
|
2003
|
-
>
|
|
2004
|
-
@if (action.icon) {
|
|
2005
|
-
<ax-prefix>
|
|
2006
|
-
<ax-icon icon="{{ action.icon }}"></ax-icon>
|
|
2007
|
-
</ax-prefix>
|
|
2008
|
-
}
|
|
2009
|
-
</ax-button>
|
|
2010
|
-
}
|
|
2011
|
-
</ng-template>
|
|
2012
|
-
`, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: AXPLayoutRendererComponent, selector: "axp-layout-renderer", inputs: ["layout", "context", "look", "mode"], outputs: ["contextChange", "contextInitiated", "validityChange"] }, { kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i2$1.AXButtonComponent, selector: "ax-button", inputs: ["disabled", "size", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i3.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "component", type: i3.AXDecoratorGenericComponent, selector: "ax-footer, ax-header, ax-content, ax-divider, ax-form-hint, ax-prefix, ax-suffix, ax-text, ax-title, ax-subtitle, ax-placeholder, ax-overlay" }, { kind: "ngmodule", type: AXLoadingModule }, { kind: "component", type: i4.AXLoadingComponent, selector: "ax-loading", inputs: ["visible", "type", "context"], outputs: ["visibleChange"] }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "pipe", type: i1$1.AsyncPipe, name: "async" }, { kind: "pipe", type: i5.AXTranslatorPipe, name: "translate" }] }); }
|
|
2327
|
+
`, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: AXPLayoutRendererComponent, selector: "axp-layout-renderer", inputs: ["layout", "context", "look", "mode"], outputs: ["contextChange", "contextInitiated", "validityChange"] }, { kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i1$1.AXButtonComponent, selector: "ax-button", inputs: ["disabled", "size", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i2$1.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "component", type: i2$1.AXDecoratorGenericComponent, selector: "ax-footer, ax-header, ax-content, ax-divider, ax-form-hint, ax-prefix, ax-suffix, ax-text, ax-title, ax-subtitle, ax-placeholder, ax-overlay" }, { kind: "ngmodule", type: AXLoadingModule }, { kind: "component", type: i3.AXLoadingComponent, selector: "ax-loading", inputs: ["visible", "type", "context"], outputs: ["visibleChange"] }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "pipe", type: i4.AsyncPipe, name: "async" }, { kind: "pipe", type: i5.AXTranslatorPipe, name: "translate" }] }); }
|
|
2013
2328
|
}
|
|
2014
2329
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: AXPDialogRendererComponent, decorators: [{
|
|
2015
2330
|
type: Component,
|
|
@@ -2037,51 +2352,41 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.4", ngImpor
|
|
|
2037
2352
|
|
|
2038
2353
|
<ax-footer>
|
|
2039
2354
|
<ax-prefix>
|
|
2040
|
-
|
|
2355
|
+
@for (action of footerPrefixActions(); track $index) {
|
|
2356
|
+
<ax-button
|
|
2357
|
+
[disabled]="action.disabled || isFormLoading()"
|
|
2358
|
+
[text]="(action.title | translate | async)!"
|
|
2359
|
+
[look]="'outline'"
|
|
2360
|
+
[color]="action.color"
|
|
2361
|
+
(onClick)="executeAction(action)"
|
|
2362
|
+
>
|
|
2363
|
+
<ax-prefix>
|
|
2364
|
+
<i class="{{ action.icon }}"></i>
|
|
2365
|
+
</ax-prefix>
|
|
2366
|
+
</ax-button>
|
|
2367
|
+
}
|
|
2041
2368
|
</ax-prefix>
|
|
2042
2369
|
<ax-suffix>
|
|
2043
|
-
|
|
2370
|
+
@for (action of footerSuffixActions(); track $index) {
|
|
2371
|
+
<ax-button
|
|
2372
|
+
[disabled]="action.disabled || isSubmitting()"
|
|
2373
|
+
[text]="(action.title | translate | async)!"
|
|
2374
|
+
[look]="'solid'"
|
|
2375
|
+
[color]="action.color"
|
|
2376
|
+
(onClick)="executeAction(action)"
|
|
2377
|
+
>
|
|
2378
|
+
@if (isFormLoading()) {
|
|
2379
|
+
<ax-loading></ax-loading>
|
|
2380
|
+
}
|
|
2381
|
+
@if (action.icon) {
|
|
2382
|
+
<ax-prefix>
|
|
2383
|
+
<ax-icon icon="{{ action.icon }}"></ax-icon>
|
|
2384
|
+
</ax-prefix>
|
|
2385
|
+
}
|
|
2386
|
+
</ax-button>
|
|
2387
|
+
}
|
|
2044
2388
|
</ax-suffix>
|
|
2045
2389
|
</ax-footer>
|
|
2046
|
-
|
|
2047
|
-
<!-- Footer Prefix Actions -->
|
|
2048
|
-
<ng-template #footerPrefixActions>
|
|
2049
|
-
@for (action of visibleFooterPrefixActions(); track $index) {
|
|
2050
|
-
<ax-button
|
|
2051
|
-
[disabled]="action.disabled || isFormLoading()"
|
|
2052
|
-
[text]="(action.title | translate | async)!"
|
|
2053
|
-
[look]="'outline'"
|
|
2054
|
-
[color]="action.color"
|
|
2055
|
-
(onClick)="executeAction(action)"
|
|
2056
|
-
>
|
|
2057
|
-
@if (isFormLoading() && action.command?.name != 'cancel') {
|
|
2058
|
-
<ax-loading></ax-loading>
|
|
2059
|
-
}
|
|
2060
|
-
<ax-prefix>
|
|
2061
|
-
<i class="{{ action.icon }}"></i>
|
|
2062
|
-
</ax-prefix>
|
|
2063
|
-
</ax-button>
|
|
2064
|
-
}
|
|
2065
|
-
</ng-template>
|
|
2066
|
-
|
|
2067
|
-
<!-- Footer Suffix Actions -->
|
|
2068
|
-
<ng-template #footerSuffixActions>
|
|
2069
|
-
@for (action of visibleFooterSuffixActions(); track $index) {
|
|
2070
|
-
<ax-button
|
|
2071
|
-
[disabled]="action.disabled || isSubmitting()"
|
|
2072
|
-
[text]="(action.title | translate | async)!"
|
|
2073
|
-
[look]="'solid'"
|
|
2074
|
-
[color]="action.color"
|
|
2075
|
-
(onClick)="executeAction(action)"
|
|
2076
|
-
>
|
|
2077
|
-
@if (action.icon) {
|
|
2078
|
-
<ax-prefix>
|
|
2079
|
-
<ax-icon icon="{{ action.icon }}"></ax-icon>
|
|
2080
|
-
</ax-prefix>
|
|
2081
|
-
}
|
|
2082
|
-
</ax-button>
|
|
2083
|
-
}
|
|
2084
|
-
</ng-template>
|
|
2085
2390
|
`,
|
|
2086
2391
|
}]
|
|
2087
2392
|
}], propDecorators: { config: [{
|