@acorex-platform/framework-client 0.0.15 → 0.0.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/fesm2022/acorex-platform-framework-client-auth.mjs.map +1 -1
- package/fesm2022/acorex-platform-framework-client-common.mjs +25 -211
- package/fesm2022/acorex-platform-framework-client-common.mjs.map +1 -1
- package/fesm2022/acorex-platform-framework-client-core.mjs +8 -104
- package/fesm2022/acorex-platform-framework-client-core.mjs.map +1 -1
- package/fesm2022/acorex-platform-framework-client-layout-builder.mjs +57 -12
- package/fesm2022/acorex-platform-framework-client-layout-builder.mjs.map +1 -1
- package/fesm2022/acorex-platform-framework-client-layout-components.mjs +494 -561
- package/fesm2022/acorex-platform-framework-client-layout-components.mjs.map +1 -1
- package/fesm2022/acorex-platform-framework-client-layout-designer.mjs +8 -8
- package/fesm2022/acorex-platform-framework-client-layout-designer.mjs.map +1 -1
- package/fesm2022/acorex-platform-framework-client-layout-entity.mjs +1333 -1023
- package/fesm2022/acorex-platform-framework-client-layout-entity.mjs.map +1 -1
- package/fesm2022/acorex-platform-framework-client-layout-views.mjs +51 -9
- package/fesm2022/acorex-platform-framework-client-layout-views.mjs.map +1 -1
- package/fesm2022/acorex-platform-framework-client-layout-widget-core.mjs +29 -9
- package/fesm2022/acorex-platform-framework-client-layout-widget-core.mjs.map +1 -1
- package/fesm2022/acorex-platform-framework-client-layout-widgets.mjs +48 -15
- package/fesm2022/acorex-platform-framework-client-layout-widgets.mjs.map +1 -1
- package/fesm2022/acorex-platform-framework-client-themes-default.mjs +41 -26
- package/fesm2022/acorex-platform-framework-client-themes-default.mjs.map +1 -1
- package/fesm2022/acorex-platform-framework-client-themes-shared.mjs +4 -4
- package/fesm2022/acorex-platform-framework-client-themes-shared.mjs.map +1 -1
- package/fesm2022/acorex-platform-framework-client-workflow.mjs.map +1 -1
- package/package.json +7 -7
- package/types/acorex-platform-framework-client-auth.d.ts +2 -2
- package/types/acorex-platform-framework-client-common.d.ts +12 -125
- package/types/acorex-platform-framework-client-core.d.ts +5 -22
- package/types/acorex-platform-framework-client-layout-builder.d.ts +10 -0
- package/types/acorex-platform-framework-client-layout-components.d.ts +17 -68
- package/types/acorex-platform-framework-client-layout-entity.d.ts +80 -7
- package/types/acorex-platform-framework-client-layout-views.d.ts +11 -6
- package/types/acorex-platform-framework-client-layout-widgets.d.ts +1 -1
- package/types/acorex-platform-framework-client-workflow.d.ts +1 -2
|
@@ -2676,6 +2676,8 @@ class AXPDialogRendererComponent extends AXBasePageComponent {
|
|
|
2676
2676
|
this.aggregateAndEvaluateActions();
|
|
2677
2677
|
}, DIALOG_WIDGET_COUNT_STABLE_DELAY_MS);
|
|
2678
2678
|
}, ...(ngDevMode ? [{ debugName: "#widgetActionsEffect" }] : /* istanbul ignore next */ []));
|
|
2679
|
+
// --- Actions aggregation & evaluation ---
|
|
2680
|
+
this.footerActionsEvalSeq = 0;
|
|
2679
2681
|
}
|
|
2680
2682
|
/**
|
|
2681
2683
|
* Registers footer shortcuts on the platform registry at modal priority so they win over page
|
|
@@ -2845,9 +2847,7 @@ class AXPDialogRendererComponent extends AXBasePageComponent {
|
|
|
2845
2847
|
},
|
|
2846
2848
|
metadata: meta,
|
|
2847
2849
|
patchContext: (partial) => {
|
|
2848
|
-
|
|
2849
|
-
this.context.set(merged);
|
|
2850
|
-
this.layoutRenderer()?.updateContext(merged);
|
|
2850
|
+
this.applyDialogContextPatch(partial);
|
|
2851
2851
|
},
|
|
2852
2852
|
setLoading: (loading) => this.isDialogLoading.set(loading),
|
|
2853
2853
|
};
|
|
@@ -3012,17 +3012,49 @@ class AXPDialogRendererComponent extends AXBasePageComponent {
|
|
|
3012
3012
|
close: (res) => {
|
|
3013
3013
|
void this.closeWithOptionalSkipValidate(res);
|
|
3014
3014
|
},
|
|
3015
|
-
context: () =>
|
|
3015
|
+
context: () => {
|
|
3016
|
+
const store = this.getWidgetContainer()?.contextService;
|
|
3017
|
+
return (store?.data() ?? this.context());
|
|
3018
|
+
},
|
|
3016
3019
|
action: () => actionCmd,
|
|
3017
3020
|
setLoading: (loading) => this.isDialogLoading.set(loading),
|
|
3018
3021
|
patchContext: (partial) => {
|
|
3019
|
-
|
|
3020
|
-
this.context.set(merged);
|
|
3021
|
-
this.layoutRenderer()?.updateContext(merged);
|
|
3022
|
+
this.applyDialogContextPatch(partial);
|
|
3022
3023
|
},
|
|
3023
3024
|
invokeWidget: (widgetName, method, opts) => this.invokeWidget(widgetName, method, opts ?? {}),
|
|
3024
3025
|
};
|
|
3025
3026
|
}
|
|
3027
|
+
/**
|
|
3028
|
+
* Merges into the live widget-container store (not a possibly-stale dialog signal),
|
|
3029
|
+
* and forces persisted root `id` onto the store for create-wizard related steps.
|
|
3030
|
+
*/
|
|
3031
|
+
applyDialogContextPatch(partial) {
|
|
3032
|
+
const store = this.getWidgetContainer()?.contextService;
|
|
3033
|
+
const live = (store?.data() ?? this.context() ?? {});
|
|
3034
|
+
const merged = merge({}, live, partial);
|
|
3035
|
+
if (store) {
|
|
3036
|
+
const nextId = merged['id'] ?? merged['_id'];
|
|
3037
|
+
const currentId = store.data()['id'] ?? store.data()['_id'];
|
|
3038
|
+
const hasNext = (typeof nextId === 'string' && nextId.length > 0) ||
|
|
3039
|
+
(typeof nextId === 'number' && !Number.isNaN(nextId));
|
|
3040
|
+
const hasCurrent = (typeof currentId === 'string' && currentId.length > 0) ||
|
|
3041
|
+
(typeof currentId === 'number' && !Number.isNaN(currentId));
|
|
3042
|
+
if (hasNext && !hasCurrent) {
|
|
3043
|
+
const identity = { id: nextId };
|
|
3044
|
+
if (merged['_id'] !== undefined) {
|
|
3045
|
+
identity['_id'] = merged['_id'];
|
|
3046
|
+
}
|
|
3047
|
+
store.patch(identity, { updateSaved: true });
|
|
3048
|
+
}
|
|
3049
|
+
else {
|
|
3050
|
+
store.patch(partial, { updateSaved: false });
|
|
3051
|
+
}
|
|
3052
|
+
}
|
|
3053
|
+
this.context.set(merged);
|
|
3054
|
+
// Prefer identity-only sync via [context] binding + syncExternalContext identity path.
|
|
3055
|
+
// Passing the full merged object after updateSaved can clearWidgets and reset the wizard.
|
|
3056
|
+
this.layoutRenderer()?.updateContext(merged);
|
|
3057
|
+
}
|
|
3026
3058
|
async closeWithOptionalSkipValidate(result) {
|
|
3027
3059
|
if (result && typeof result === 'object' && result.skipValidate) {
|
|
3028
3060
|
this.result.emit(result);
|
|
@@ -3094,12 +3126,16 @@ class AXPDialogRendererComponent extends AXBasePageComponent {
|
|
|
3094
3126
|
}
|
|
3095
3127
|
super.close(result);
|
|
3096
3128
|
}
|
|
3097
|
-
// --- Actions aggregation & evaluation ---
|
|
3098
3129
|
async aggregateAndEvaluateActions() {
|
|
3130
|
+
const seq = ++this.footerActionsEvalSeq;
|
|
3099
3131
|
const widgetActions = await this.collectWidgetActions();
|
|
3100
3132
|
const dialogActions = this.collectDialogActionsFromConfig();
|
|
3101
3133
|
const all = [...widgetActions, ...dialogActions];
|
|
3102
3134
|
const evaluated = await this.evaluatePredicates(all);
|
|
3135
|
+
// Drop stale runs (e.g. nested Assign create triggers overlapping context refreshes).
|
|
3136
|
+
if (seq !== this.footerActionsEvalSeq) {
|
|
3137
|
+
return;
|
|
3138
|
+
}
|
|
3103
3139
|
const visible = evaluated.filter((a) => a.hidden !== true);
|
|
3104
3140
|
const prefix = visible.filter((a) => (a.zone ?? 'footer') === 'footer' && (a.placement ?? 'suffix') === 'prefix');
|
|
3105
3141
|
const suffix = visible.filter((a) => (a.zone ?? 'footer') === 'footer' && (a.placement ?? 'suffix') === 'suffix');
|
|
@@ -3157,23 +3193,32 @@ class AXPDialogRendererComponent extends AXBasePageComponent {
|
|
|
3157
3193
|
dialog: { context: this.context() },
|
|
3158
3194
|
context: this.context(),
|
|
3159
3195
|
};
|
|
3160
|
-
const
|
|
3161
|
-
const
|
|
3196
|
+
const hiddenNeedsApi = typeof a.hidden === 'string' && /\bapi\b/.test(a.hidden);
|
|
3197
|
+
const disabledNeedsApi = typeof a.disabled === 'string' && /\bapi\b/.test(a.disabled);
|
|
3198
|
+
// Fail closed: missing wizard api must not reveal step-scoped footer actions (Done / Continue).
|
|
3199
|
+
const disabled = disabledNeedsApi && !api ? true : await this.evalBool(a.disabled, scope, false);
|
|
3200
|
+
const hidden = hiddenNeedsApi && !api ? true : await this.evalBool(a.hidden, scope, true);
|
|
3162
3201
|
const resolvedTitle = (await this.evalActionTitle(a.title, scope)) ?? a.title;
|
|
3163
3202
|
out.push({ ...a, disabled, hidden, title: resolvedTitle });
|
|
3164
3203
|
}
|
|
3165
3204
|
return out;
|
|
3166
3205
|
}
|
|
3167
|
-
|
|
3206
|
+
/**
|
|
3207
|
+
* @param failClosed When evaluation throws / returns an error sentinel, use this value.
|
|
3208
|
+
* Footer `hidden` should fail closed (`true`) so step actions do not leak.
|
|
3209
|
+
*/
|
|
3210
|
+
async evalBool(value, scope, failClosed) {
|
|
3168
3211
|
if (typeof value === 'boolean')
|
|
3169
3212
|
return value;
|
|
3170
3213
|
if (typeof value === 'string') {
|
|
3171
3214
|
try {
|
|
3172
3215
|
const result = await this.expressionEvaluator.evaluate(value, scope);
|
|
3216
|
+
// Expression evaluator swallows errors and returns false — treat that as failClosed
|
|
3217
|
+
// only when the expression references api and api is missing (handled by caller).
|
|
3173
3218
|
return !!result;
|
|
3174
3219
|
}
|
|
3175
3220
|
catch {
|
|
3176
|
-
return
|
|
3221
|
+
return failClosed;
|
|
3177
3222
|
}
|
|
3178
3223
|
}
|
|
3179
3224
|
return value;
|