@nocobase/plugin-flow-engine 2.1.0-beta.37 → 2.1.0-beta.40
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/dist/externalVersion.js +9 -9
- package/dist/node_modules/@ant-design/icons-svg/package.json +1 -1
- package/dist/node_modules/acorn/package.json +1 -1
- package/dist/node_modules/acorn-jsx/package.json +1 -1
- package/dist/node_modules/acorn-walk/package.json +1 -1
- package/dist/node_modules/ses/package.json +1 -1
- package/dist/node_modules/zod/package.json +1 -1
- package/dist/server/flow-surfaces/apply/compiler.js +18 -3
- package/dist/server/flow-surfaces/apply/matching.js +2 -0
- package/dist/server/flow-surfaces/authoring-validation.js +621 -66
- package/dist/server/flow-surfaces/blueprint/compile-blocks.js +21 -3
- package/dist/server/flow-surfaces/blueprint/compile-plan.js +9 -9
- package/dist/server/flow-surfaces/catalog.js +3 -0
- package/dist/server/flow-surfaces/chart-config.js +14 -1
- package/dist/server/flow-surfaces/compose-compiler.d.ts +2 -0
- package/dist/server/flow-surfaces/compose-compiler.js +2 -0
- package/dist/server/flow-surfaces/compose-runtime.js +4 -7
- package/dist/server/flow-surfaces/configure-options.js +18 -7
- package/dist/server/flow-surfaces/locator.js +16 -2
- package/dist/server/flow-surfaces/runjs-authoring/index.js +5909 -2214
- package/dist/server/flow-surfaces/service-utils.d.ts +2 -0
- package/dist/server/flow-surfaces/service-utils.js +8 -0
- package/dist/server/flow-surfaces/service.d.ts +22 -0
- package/dist/server/flow-surfaces/service.js +722 -59
- package/dist/server/flow-surfaces/template-service-utils.d.ts +1 -0
- package/dist/swagger/flow-surfaces.d.ts +4 -2
- package/dist/swagger/flow-surfaces.examples.d.ts +6 -17
- package/dist/swagger/flow-surfaces.examples.js +5 -5
- package/dist/swagger/flow-surfaces.js +5 -3
- package/dist/swagger/index.d.ts +4 -2
- package/package.json +2 -2
|
@@ -42,6 +42,7 @@ module.exports = __toCommonJS(service_exports);
|
|
|
42
42
|
var import_crypto = require("crypto");
|
|
43
43
|
var import_utils = require("@nocobase/utils");
|
|
44
44
|
var import_lodash = __toESM(require("lodash"));
|
|
45
|
+
var antDesignIconAsn = __toESM(require("@ant-design/icons-svg"));
|
|
45
46
|
var import_repository = __toESM(require("../repository"));
|
|
46
47
|
var import_catalog = require("./catalog");
|
|
47
48
|
var import_action_scope = require("./action-scope");
|
|
@@ -102,6 +103,56 @@ var import_template_service_utils = require("./template-service-utils");
|
|
|
102
103
|
var import_hidden_popup_contract = require("./hidden-popup-contract");
|
|
103
104
|
var import_hidden_popup_calendar = require("./hidden-popup-calendar");
|
|
104
105
|
var import_hidden_popup_kanban = require("./hidden-popup-kanban");
|
|
106
|
+
const FLOW_SURFACE_CHART_REPAIR_HINT = "This is a chart payload shape problem. Repair the current chart block payload using assets.charts.<key>.query/visual plus block.chart, or localized settings.query/settings.visual. Do not change this block type to table, jsBlock, actionPanel, gridCard, or another block type. Do not drop or defer the chart. KPI / summary numbers should use jsBlock; charts are for trends, distributions, rankings, and visual analysis.";
|
|
107
|
+
const FLOW_SURFACE_CHART_REPAIR_STEPS = [
|
|
108
|
+
"Keep the block type as chart.",
|
|
109
|
+
"Define assets.charts.<key>.query and assets.charts.<key>.visual, or repair the localized settings.query/settings.visual on the existing chart block.",
|
|
110
|
+
"Reference the asset from the chart block with block.chart = <key> when using assets.charts.",
|
|
111
|
+
"Retry the chart payload instead of replacing the chart with another block type, omitting it, or deferring it."
|
|
112
|
+
];
|
|
113
|
+
const FLOW_SURFACE_CHART_EXPECTED_SHAPE = {
|
|
114
|
+
assets: {
|
|
115
|
+
charts: {
|
|
116
|
+
chartKey: {
|
|
117
|
+
query: "builder/sql query configuration",
|
|
118
|
+
visual: "basic/custom visual configuration"
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
},
|
|
122
|
+
block: {
|
|
123
|
+
type: "chart",
|
|
124
|
+
chart: "chartKey"
|
|
125
|
+
}
|
|
126
|
+
};
|
|
127
|
+
const FLOW_SURFACE_CHART_FORBIDDEN_FALLBACKS = [
|
|
128
|
+
"table",
|
|
129
|
+
"jsBlock",
|
|
130
|
+
"actionPanel",
|
|
131
|
+
"gridCard",
|
|
132
|
+
"drop chart",
|
|
133
|
+
"defer chart"
|
|
134
|
+
];
|
|
135
|
+
function withChartRepairMessage(message) {
|
|
136
|
+
return `${message}. ${FLOW_SURFACE_CHART_REPAIR_HINT}`;
|
|
137
|
+
}
|
|
138
|
+
function withFlowSurfaceChartRepairDetails(details = {}) {
|
|
139
|
+
return {
|
|
140
|
+
...details,
|
|
141
|
+
repairHint: FLOW_SURFACE_CHART_REPAIR_HINT,
|
|
142
|
+
repairSteps: FLOW_SURFACE_CHART_REPAIR_STEPS,
|
|
143
|
+
expectedShape: FLOW_SURFACE_CHART_EXPECTED_SHAPE,
|
|
144
|
+
forbiddenFallbacks: FLOW_SURFACE_CHART_FORBIDDEN_FALLBACKS
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
function throwChartRepairBadRequest(message, details = {}) {
|
|
148
|
+
(0, import_errors.throwBadRequest)(withChartRepairMessage(message), {
|
|
149
|
+
details: withFlowSurfaceChartRepairDetails(details)
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
function isFlowSurfaceChartRepairError(error) {
|
|
153
|
+
var _a, _b;
|
|
154
|
+
return error instanceof import_errors.FlowSurfaceBadRequestError && ((_b = (_a = error.options) == null ? void 0 : _a.details) == null ? void 0 : _b.repairHint) === FLOW_SURFACE_CHART_REPAIR_HINT;
|
|
155
|
+
}
|
|
105
156
|
const FORM_BLOCK_USES = /* @__PURE__ */ new Set(["FormBlockModel", "CreateFormModel", "EditFormModel", ...import_approval.APPROVAL_FORM_BLOCK_USES]);
|
|
106
157
|
const AUTO_SUBMIT_FORM_BLOCK_USES = /* @__PURE__ */ new Set(["CreateFormModel", "EditFormModel"]);
|
|
107
158
|
const FLOW_SURFACE_DEFAULT_ACTION_SETTINGS_KEYS = /* @__PURE__ */ new Set(["filter"]);
|
|
@@ -251,6 +302,17 @@ const JS_ACTION_USES = /* @__PURE__ */ new Set([
|
|
|
251
302
|
"JSActionModel"
|
|
252
303
|
]);
|
|
253
304
|
const JS_ITEM_ACTION_USES = /* @__PURE__ */ new Set(["JSItemActionModel"]);
|
|
305
|
+
const JS_POPUP_GUIDANCE_MESSAGE = "should use ctx.openView to open popup";
|
|
306
|
+
const JS_POPUP_GUIDANCE_USES = /* @__PURE__ */ new Set([
|
|
307
|
+
...JS_ACTION_USES,
|
|
308
|
+
...JS_ITEM_ACTION_USES,
|
|
309
|
+
"JSColumnModel",
|
|
310
|
+
"JSItemModel",
|
|
311
|
+
"JSFieldModel",
|
|
312
|
+
"JSEditableFieldModel",
|
|
313
|
+
"FormJSFieldItemModel"
|
|
314
|
+
]);
|
|
315
|
+
const JS_POPUP_GUIDANCE_PUBLIC_KEYS = /* @__PURE__ */ new Set(["js", "jsColumn", "jsItem"]);
|
|
254
316
|
const POPUP_ACTION_USES = /* @__PURE__ */ new Set([
|
|
255
317
|
"AddNewActionModel",
|
|
256
318
|
"ViewActionModel",
|
|
@@ -264,6 +326,24 @@ const POPUP_ACTION_USES = /* @__PURE__ */ new Set([
|
|
|
264
326
|
"AddChildActionModel",
|
|
265
327
|
"MailSendActionModel"
|
|
266
328
|
]);
|
|
329
|
+
function withJsPopupGuidance(message, value) {
|
|
330
|
+
const normalizedValue = String(value || "").trim();
|
|
331
|
+
if (JS_POPUP_GUIDANCE_USES.has(normalizedValue) || JS_POPUP_GUIDANCE_PUBLIC_KEYS.has(normalizedValue)) {
|
|
332
|
+
return `${message}; ${JS_POPUP_GUIDANCE_MESSAGE}`;
|
|
333
|
+
}
|
|
334
|
+
return message;
|
|
335
|
+
}
|
|
336
|
+
function assertNoJsDeclarativeOpenView(context, changes, use) {
|
|
337
|
+
const normalizedUse = String(use || "").trim();
|
|
338
|
+
if ((0, import_service_utils.hasOwnDefined)(changes, "openView") && JS_POPUP_GUIDANCE_USES.has(normalizedUse)) {
|
|
339
|
+
(0, import_errors.throwBadRequest)(
|
|
340
|
+
withJsPopupGuidance(
|
|
341
|
+
`flowSurfaces configure ${context} '${normalizedUse}' does not support openView`,
|
|
342
|
+
normalizedUse
|
|
343
|
+
)
|
|
344
|
+
);
|
|
345
|
+
}
|
|
346
|
+
}
|
|
267
347
|
const POPUP_HOST_DEFAULT_RECORD_CONTEXT_ACTION_USES = /* @__PURE__ */ new Set([
|
|
268
348
|
"ViewActionModel",
|
|
269
349
|
"EditActionModel",
|
|
@@ -457,6 +537,7 @@ const UPDATE_SETTINGS_STEP_PARAM_MIRRORS_BY_USE = {
|
|
|
457
537
|
DividerItemModel: DIVIDER_ITEM_STEP_PARAM_MIRRORS
|
|
458
538
|
};
|
|
459
539
|
const FLOW_SURFACE_MENU_BINDABLE_OPTION_KEY = "flowSurfaceMenuBindable";
|
|
540
|
+
const ANT_DESIGN_ICON_NAMES = new Set(Object.keys(antDesignIconAsn || {}));
|
|
460
541
|
const AI_EMPLOYEE_ACTION_USE = "AIEmployeeButtonModel";
|
|
461
542
|
const AI_EMPLOYEE_OWNER_PLUGIN = "@nocobase/plugin-ai";
|
|
462
543
|
const AI_EMPLOYEE_PUBLIC_SETTING_KEYS = ["username", "auto", "workContext", "tasks", "style"];
|
|
@@ -464,10 +545,13 @@ const AI_EMPLOYEE_INTERNAL_PROP_KEYS = ["aiEmployee", "context", "auto", "tasks"
|
|
|
464
545
|
const AI_EMPLOYEE_TASK_STEP_PARAMS_PATH = ["shortcutSettings", "editTasks", "tasks"];
|
|
465
546
|
const AI_EMPLOYEE_WORK_CONTEXT_PUBLIC_KEYS = ["type", "uid", "target"];
|
|
466
547
|
const AI_EMPLOYEE_TASK_PUBLIC_SETTING_KEYS = ["title", "message", "autoSend", "skillSettings", "model", "webSearch"];
|
|
548
|
+
const AI_EMPLOYEE_TASK_PATCH_PUBLIC_SETTING_KEYS = [...AI_EMPLOYEE_TASK_PUBLIC_SETTING_KEYS, "prompt"];
|
|
467
549
|
const AI_EMPLOYEE_TASK_MESSAGE_PUBLIC_KEYS = ["system", "user", "workContext"];
|
|
468
550
|
const AI_EMPLOYEE_TASK_MODEL_PUBLIC_KEYS = ["llmService", "model"];
|
|
469
551
|
const AI_EMPLOYEE_SKILL_SETTINGS_PUBLIC_KEYS = ["skills", "tools", "skillsVersion", "toolsVersion"];
|
|
470
552
|
const AI_EMPLOYEE_STYLE_PUBLIC_KEYS = ["size", "mask"];
|
|
553
|
+
const AI_EMPLOYEE_WORK_CONTEXT_REPAIR_HINT = 'Use workContext entries like { "target": "self" } or { "uid": "<flow-model-uid>" }. The only supported type is flow-model, so type is optional and defaults to flow-model.';
|
|
554
|
+
const AI_EMPLOYEE_TASK_REPAIR_HINT = "Use task keys title, message, prompt, autoSend, skillSettings, model, and webSearch. Put user instructions in tasks[n].message.user or the prompt alias; do not write raw props, stepParams, or prompt beside message.user.";
|
|
471
555
|
const AI_EMPLOYEE_PROMPT_CONTEXT_MAX_DEPTH = 8;
|
|
472
556
|
const AI_EMPLOYEE_PROMPT_VARIABLE_INVALID = "FLOW_SURFACE_AI_EMPLOYEE_PROMPT_VARIABLE_INVALID";
|
|
473
557
|
const AI_EMPLOYEE_CURRENT_RECORD_PROMPT_VARIABLE = "{{ ctx.record }}";
|
|
@@ -773,6 +857,18 @@ class FlowSurfacesService {
|
|
|
773
857
|
})
|
|
774
858
|
);
|
|
775
859
|
}
|
|
860
|
+
routeParentIdMatches(routeParentId, parentId) {
|
|
861
|
+
if (import_lodash.default.isNil(routeParentId) && import_lodash.default.isNil(parentId)) {
|
|
862
|
+
return true;
|
|
863
|
+
}
|
|
864
|
+
return String(routeParentId ?? "") === String(parentId ?? "");
|
|
865
|
+
}
|
|
866
|
+
async findMenuGroupRoutesByParentIdAndTitle(parentId, title, transaction) {
|
|
867
|
+
const routes = await this.findMenuGroupRoutesByTitle(title, transaction);
|
|
868
|
+
return routes.filter(
|
|
869
|
+
(route) => this.routeParentIdMatches(this.readRouteField(route, "parentId") ?? null, parentId)
|
|
870
|
+
);
|
|
871
|
+
}
|
|
776
872
|
async findFlowPageRoutesByParentIdAndTitle(parentId, title, transaction) {
|
|
777
873
|
const normalizedTitle = String(title || "").trim();
|
|
778
874
|
const normalizedParentId = String(parentId ?? "").trim();
|
|
@@ -854,20 +950,97 @@ class FlowSurfacesService {
|
|
|
854
950
|
...extras
|
|
855
951
|
};
|
|
856
952
|
}
|
|
953
|
+
isValidMenuIconName(value) {
|
|
954
|
+
const normalized = String(value || "").trim();
|
|
955
|
+
return !!normalized && ANT_DESIGN_ICON_NAMES.has(normalized);
|
|
956
|
+
}
|
|
957
|
+
assertVisibleNavigationIcon(actionName, path, values) {
|
|
958
|
+
if (values.hideInMenu === true) {
|
|
959
|
+
return;
|
|
960
|
+
}
|
|
961
|
+
const icon = String(values.icon || "").trim();
|
|
962
|
+
if (!icon) {
|
|
963
|
+
(0, import_errors.throwBadRequest)(`flowSurfaces ${actionName} ${path}.icon is required when creating a visible menu route`, {
|
|
964
|
+
ruleId: "navigation-icon-required",
|
|
965
|
+
path: `${path}.icon`,
|
|
966
|
+
details: {
|
|
967
|
+
repairHint: "Pass a valid Ant Design icon name such as AppstoreOutlined, DashboardOutlined, or FolderOpenOutlined."
|
|
968
|
+
}
|
|
969
|
+
});
|
|
970
|
+
}
|
|
971
|
+
if (!this.isValidMenuIconName(icon)) {
|
|
972
|
+
(0, import_errors.throwBadRequest)(`flowSurfaces ${actionName} ${path}.icon must be a valid Ant Design icon name`, {
|
|
973
|
+
ruleId: "navigation-icon-unknown",
|
|
974
|
+
path: `${path}.icon`,
|
|
975
|
+
details: {
|
|
976
|
+
icon
|
|
977
|
+
}
|
|
978
|
+
});
|
|
979
|
+
}
|
|
980
|
+
}
|
|
981
|
+
assertVisibleNavigationRouteIconUpdate(actionName, path, route, values) {
|
|
982
|
+
if (!Object.prototype.hasOwnProperty.call(values, "icon") || this.readRouteField(route, "hideInMenu") === true) {
|
|
983
|
+
return;
|
|
984
|
+
}
|
|
985
|
+
const icon = String(values.icon || "").trim();
|
|
986
|
+
if (!icon) {
|
|
987
|
+
(0, import_errors.throwBadRequest)(`flowSurfaces ${actionName} ${path}.icon cannot be empty for a visible menu route`, {
|
|
988
|
+
ruleId: "navigation-icon-required",
|
|
989
|
+
path: `${path}.icon`,
|
|
990
|
+
details: {
|
|
991
|
+
repairHint: "Pass a valid Ant Design icon name such as AppstoreOutlined, DashboardOutlined, or FolderOpenOutlined."
|
|
992
|
+
}
|
|
993
|
+
});
|
|
994
|
+
}
|
|
995
|
+
if (!this.isValidMenuIconName(icon)) {
|
|
996
|
+
(0, import_errors.throwBadRequest)(`flowSurfaces ${actionName} ${path}.icon must be a valid Ant Design icon name`, {
|
|
997
|
+
ruleId: "navigation-icon-unknown",
|
|
998
|
+
path: `${path}.icon`,
|
|
999
|
+
details: {
|
|
1000
|
+
icon
|
|
1001
|
+
}
|
|
1002
|
+
});
|
|
1003
|
+
}
|
|
1004
|
+
}
|
|
857
1005
|
async createFlowMenuGroup(values, transaction) {
|
|
858
1006
|
const parentRoute = await this.assertMenuParentIsGroup(values.parentMenuRouteId, transaction);
|
|
1007
|
+
const parentId = this.readRouteField(parentRoute, "id") ?? null;
|
|
1008
|
+
const title = String(values.title || "").trim();
|
|
1009
|
+
const existingGroups = await this.findMenuGroupRoutesByParentIdAndTitle(parentId, title, transaction);
|
|
1010
|
+
if (existingGroups.length === 1) {
|
|
1011
|
+
return this.buildMenuResult(existingGroups[0]);
|
|
1012
|
+
}
|
|
1013
|
+
if (existingGroups.length > 1) {
|
|
1014
|
+
(0, import_errors.throwBadRequest)(
|
|
1015
|
+
`flowSurfaces createMenu group title '${title}' is ambiguous under parentMenuRouteId '${values.parentMenuRouteId ?? "root"}'; use an explicit existing navigation.group.routeId or clean up duplicate menu groups before retrying`,
|
|
1016
|
+
{
|
|
1017
|
+
ruleId: "menu-group-title-ambiguous-under-parent",
|
|
1018
|
+
details: {
|
|
1019
|
+
title,
|
|
1020
|
+
parentMenuRouteId: values.parentMenuRouteId ?? null,
|
|
1021
|
+
matches: existingGroups.map((route2) => ({
|
|
1022
|
+
routeId: this.readRouteField(route2, "id"),
|
|
1023
|
+
parentMenuRouteId: this.readRouteField(route2, "parentId") ?? null,
|
|
1024
|
+
type: this.readRouteField(route2, "type"),
|
|
1025
|
+
schemaUid: this.readRouteField(route2, "schemaUid") ?? null
|
|
1026
|
+
}))
|
|
1027
|
+
}
|
|
1028
|
+
}
|
|
1029
|
+
);
|
|
1030
|
+
}
|
|
1031
|
+
this.assertVisibleNavigationIcon("createMenu", "values", values);
|
|
859
1032
|
const schemaUid = values.schemaUid || (0, import_utils.uid)();
|
|
860
1033
|
const desktopRoutes = this.db.getRepository("desktopRoutes");
|
|
861
1034
|
await desktopRoutes.create({
|
|
862
1035
|
values: {
|
|
863
1036
|
type: "group",
|
|
864
1037
|
sort: this.allocateRouteSortValue(),
|
|
865
|
-
title
|
|
1038
|
+
title,
|
|
866
1039
|
icon: values.icon,
|
|
867
1040
|
tooltip: values.tooltip,
|
|
868
1041
|
schemaUid,
|
|
869
1042
|
hideInMenu: !!values.hideInMenu,
|
|
870
|
-
parentId
|
|
1043
|
+
parentId
|
|
871
1044
|
},
|
|
872
1045
|
transaction
|
|
873
1046
|
});
|
|
@@ -880,6 +1053,7 @@ class FlowSurfacesService {
|
|
|
880
1053
|
async createFlowMenuItem(values, transaction) {
|
|
881
1054
|
var _a;
|
|
882
1055
|
const parentRoute = await this.assertMenuParentIsGroup(values.parentMenuRouteId, transaction);
|
|
1056
|
+
this.assertVisibleNavigationIcon("createMenu", "values", values);
|
|
883
1057
|
const pageSchemaUid = values.pageSchemaUid || (0, import_utils.uid)();
|
|
884
1058
|
const pageUid = values.pageUid || (0, import_utils.uid)();
|
|
885
1059
|
const tabSchemaUid = values.tabSchemaUid || (0, import_utils.uid)();
|
|
@@ -2607,6 +2781,10 @@ class FlowSurfacesService {
|
|
|
2607
2781
|
),
|
|
2608
2782
|
options.transaction
|
|
2609
2783
|
);
|
|
2784
|
+
if (!(rawNode == null ? void 0 : rawNode.uid)) {
|
|
2785
|
+
const resolvedUid = String((resolved == null ? void 0 : resolved.uid) || "").trim() || String(target.uid || target.tabSchemaUid || target.pageSchemaUid || target.routeId || "").trim() || "unknown";
|
|
2786
|
+
(0, import_errors.throwBadRequest)(`flowSurfaces:get target '${resolvedUid}' could not resolve a readable surface tree`);
|
|
2787
|
+
}
|
|
2610
2788
|
const publicNode = this.stripInternalSurfaceMetaFromNodeTree(import_lodash.default.cloneDeep(rawNode));
|
|
2611
2789
|
return this.buildSurfaceReadPayload(target, resolved, publicNode, options);
|
|
2612
2790
|
}
|
|
@@ -2778,13 +2956,13 @@ class FlowSurfacesService {
|
|
|
2778
2956
|
if (!groupTitle) {
|
|
2779
2957
|
return document;
|
|
2780
2958
|
}
|
|
2781
|
-
const matchedRoutes = await this.
|
|
2959
|
+
const matchedRoutes = await this.findMenuGroupRoutesByParentIdAndTitle(null, groupTitle, transaction);
|
|
2782
2960
|
if (!matchedRoutes.length) {
|
|
2783
2961
|
return document;
|
|
2784
2962
|
}
|
|
2785
2963
|
if (matchedRoutes.length > 1) {
|
|
2786
2964
|
(0, import_errors.throwBadRequest)(
|
|
2787
|
-
`flowSurfaces applyBlueprint navigation.group.title '${groupTitle}' matches ${matchedRoutes.length} existing menu groups; pass navigation.group.routeId explicitly`
|
|
2965
|
+
`flowSurfaces applyBlueprint navigation.group.title '${groupTitle}' matches ${matchedRoutes.length} existing root menu groups; pass navigation.group.routeId explicitly`
|
|
2788
2966
|
);
|
|
2789
2967
|
}
|
|
2790
2968
|
const routeId = this.readRouteField(matchedRoutes[0], "id");
|
|
@@ -3332,6 +3510,12 @@ class FlowSurfacesService {
|
|
|
3332
3510
|
options
|
|
3333
3511
|
);
|
|
3334
3512
|
const pageLocator = (0, import_blueprint.resolveApplyBlueprintPageLocator)(prepared, result);
|
|
3513
|
+
await this.ensureSurfaceTableDefaultActionIntegrity(pageLocator, {
|
|
3514
|
+
...options,
|
|
3515
|
+
enabledPackages: await this.resolveEnabledPluginPackages(options),
|
|
3516
|
+
popupTemplateAliasSession,
|
|
3517
|
+
popupTemplateTreeCache
|
|
3518
|
+
});
|
|
3335
3519
|
if (resultOptions.readSurface === false) {
|
|
3336
3520
|
return {
|
|
3337
3521
|
version: "1",
|
|
@@ -4008,8 +4192,8 @@ class FlowSurfacesService {
|
|
|
4008
4192
|
stepParams: (0, import_template_service_utils.buildFlowTemplateReferenceBlockStepParams)(template, templateTargetUid, init)
|
|
4009
4193
|
};
|
|
4010
4194
|
}
|
|
4011
|
-
buildPopupTemplateReferenceOpenView(template, templateTargetUid) {
|
|
4012
|
-
return this.buildPopupTemplateOpenView(template, "reference", templateTargetUid);
|
|
4195
|
+
buildPopupTemplateReferenceOpenView(template, templateTargetUid, options = {}) {
|
|
4196
|
+
return this.buildPopupTemplateOpenView(template, "reference", templateTargetUid, options);
|
|
4013
4197
|
}
|
|
4014
4198
|
shouldHydrateDetachedPopupTemplateBlockResourceContext(blockNode, context) {
|
|
4015
4199
|
if (!this.isCollectionBlockUse(blockNode == null ? void 0 : blockNode.use) || !context.associationName || !context.sourceId) {
|
|
@@ -4359,15 +4543,35 @@ class FlowSurfacesService {
|
|
|
4359
4543
|
}
|
|
4360
4544
|
const nextStepParams = import_lodash.default.cloneDeep(sourceNode.stepParams || {});
|
|
4361
4545
|
const currentGroup = import_lodash.default.isPlainObject(nextStepParams[openViewStep.flowKey]) ? import_lodash.default.cloneDeep(nextStepParams[openViewStep.flowKey]) : {};
|
|
4546
|
+
const popupProfile = await this.resolvePopupBlockProfile(sourceNode.uid, null, sourceNode, transaction).catch(
|
|
4547
|
+
() => null
|
|
4548
|
+
);
|
|
4549
|
+
const useRuntimeRecordFilterByTk = (popupProfile == null ? void 0 : popupProfile.hasCurrentRecord) === true;
|
|
4550
|
+
const filterTargetKey = useRuntimeRecordFilterByTk ? await this.resolveOpenViewRuntimeRecordFilterTargetKey(openViewStep.openView, template, {
|
|
4551
|
+
transaction,
|
|
4552
|
+
popupTemplateHostUid: sourceNode.uid,
|
|
4553
|
+
popupActionContext: {
|
|
4554
|
+
hasCurrentRecord: true
|
|
4555
|
+
}
|
|
4556
|
+
}) : void 0;
|
|
4557
|
+
const currentOpenView = import_lodash.default.omit(openViewStep.openView || {}, [
|
|
4558
|
+
"popupTemplateUid",
|
|
4559
|
+
"popupTemplateMode",
|
|
4560
|
+
"popupTemplateContext",
|
|
4561
|
+
"popupTemplateHasFilterByTk",
|
|
4562
|
+
"popupTemplateHasSourceId"
|
|
4563
|
+
]);
|
|
4564
|
+
if (useRuntimeRecordFilterByTk && this.shouldOmitRuntimeRecordFilterByTk(currentOpenView.filterByTk, {
|
|
4565
|
+
filterTargetKey
|
|
4566
|
+
})) {
|
|
4567
|
+
delete currentOpenView.filterByTk;
|
|
4568
|
+
}
|
|
4362
4569
|
let nextOpenView = {
|
|
4363
|
-
...
|
|
4364
|
-
|
|
4365
|
-
|
|
4366
|
-
|
|
4367
|
-
|
|
4368
|
-
"popupTemplateHasSourceId"
|
|
4369
|
-
]),
|
|
4370
|
-
...this.buildPopupTemplateReferenceOpenView(template, templateTargetUid)
|
|
4570
|
+
...currentOpenView,
|
|
4571
|
+
...this.buildPopupTemplateReferenceOpenView(template, templateTargetUid, {
|
|
4572
|
+
filterTargetKey,
|
|
4573
|
+
useRuntimeRecordFilterByTk
|
|
4574
|
+
})
|
|
4371
4575
|
};
|
|
4372
4576
|
if (String(sourceNode.use || "").trim() === "AddChildActionModel") {
|
|
4373
4577
|
nextOpenView = await this.normalizeAddChildOpenViewForAction(sourceNode, nextOpenView, transaction);
|
|
@@ -5109,6 +5313,13 @@ class FlowSurfacesService {
|
|
|
5109
5313
|
});
|
|
5110
5314
|
for (const [blockIndex, block] of result.blocks.entries()) {
|
|
5111
5315
|
const blockSpec = normalizedBlocks.find((item) => item.key === block.key);
|
|
5316
|
+
if ((blockSpec == null ? void 0 : blockSpec.type) === "table") {
|
|
5317
|
+
await this.ensureTableDefaultActionIntegrity(block.uid, {
|
|
5318
|
+
...runtimeOptions,
|
|
5319
|
+
enabledPackages,
|
|
5320
|
+
popupTemplateAliasSession
|
|
5321
|
+
});
|
|
5322
|
+
}
|
|
5112
5323
|
if ((blockSpec == null ? void 0 : blockSpec.type) === "table") {
|
|
5113
5324
|
const appliedTreeTableDefaults = await this.applyTreeTableCreatedBlockDefaults(
|
|
5114
5325
|
{
|
|
@@ -5242,7 +5453,7 @@ class FlowSurfacesService {
|
|
|
5242
5453
|
if ((current == null ? void 0 : current.use) === "DividerItemModel") {
|
|
5243
5454
|
return this.configureDividerItem(target, changes, options);
|
|
5244
5455
|
}
|
|
5245
|
-
return this.configureJSItem(target, changes, options);
|
|
5456
|
+
return this.configureJSItem(target, changes, { ...options, currentUse: (current == null ? void 0 : current.use) || "JSItemModel" });
|
|
5246
5457
|
}
|
|
5247
5458
|
if ((0, import_service_utils.isFieldNodeUse)(current == null ? void 0 : current.use)) {
|
|
5248
5459
|
return this.configureFieldNode(target, changes, configureOptions);
|
|
@@ -5317,6 +5528,7 @@ class FlowSurfacesService {
|
|
|
5317
5528
|
if (!this.isBindableMenuRoutePendingInitialization(route, structure)) {
|
|
5318
5529
|
(0, import_errors.throwBadRequest)(`flowSurfaces createPage does not allow re-initializing menu route '${routeId}'`);
|
|
5319
5530
|
}
|
|
5531
|
+
this.assertVisibleNavigationRouteIconUpdate("createPage", "values", route, values);
|
|
5320
5532
|
const existingPage = structure.pageModel;
|
|
5321
5533
|
const enableTabs = !!values.enableTabs;
|
|
5322
5534
|
const displayTitle = values.displayTitle !== false;
|
|
@@ -6396,7 +6608,7 @@ class FlowSurfacesService {
|
|
|
6396
6608
|
key: String((values == null ? void 0 : values.key) || catalogItem.key || (values == null ? void 0 : values.type) || (values == null ? void 0 : values.use) || "addBlock_inline").trim() || "addBlock_inline",
|
|
6397
6609
|
type: catalogItem.key || values.type,
|
|
6398
6610
|
fields: values.fields,
|
|
6399
|
-
fieldsLayout: values.fieldsLayout
|
|
6611
|
+
...Object.prototype.hasOwnProperty.call(values || {}, "fieldsLayout") ? { fieldsLayout: values.fieldsLayout } : {}
|
|
6400
6612
|
},
|
|
6401
6613
|
0,
|
|
6402
6614
|
enabledPackages,
|
|
@@ -6590,6 +6802,8 @@ class FlowSurfacesService {
|
|
|
6590
6802
|
...fieldSpec.popupSize ? { popupSize: fieldSpec.popupSize } : {},
|
|
6591
6803
|
...!import_lodash.default.isUndefined(fieldSpec.pageSize) ? { pageSize: fieldSpec.pageSize } : {},
|
|
6592
6804
|
...!import_lodash.default.isUndefined(fieldSpec.showIndex) ? { showIndex: fieldSpec.showIndex } : {},
|
|
6805
|
+
...fieldSpec.defaultTargetUid ? { defaultTargetUid: fieldSpec.defaultTargetUid } : {},
|
|
6806
|
+
...fieldSpec.targetBlockUid ? { targetBlockUid: fieldSpec.targetBlockUid } : {},
|
|
6593
6807
|
...fieldSpec.popup ? { popup: fieldSpec.popup } : {},
|
|
6594
6808
|
...fieldSpec.__autoPopupForRelationField ? { __autoPopupForRelationField: true } : {},
|
|
6595
6809
|
...fieldSpec[import_defaults.FLOW_SURFACE_APPLY_BLUEPRINT_POPUP_DEFAULTS_KEY] ? {
|
|
@@ -6664,6 +6878,13 @@ class FlowSurfacesService {
|
|
|
6664
6878
|
enabledPackages
|
|
6665
6879
|
}
|
|
6666
6880
|
);
|
|
6881
|
+
if (catalogItem.use === "TableBlockModel" && !options.skipDefaultBlockActions) {
|
|
6882
|
+
await this.ensureTableDefaultActionIntegrity(created, {
|
|
6883
|
+
...options,
|
|
6884
|
+
enabledPackages,
|
|
6885
|
+
popupTemplateTreeCache: options.popupTemplateTreeCache
|
|
6886
|
+
});
|
|
6887
|
+
}
|
|
6667
6888
|
if (!options.deferAutoLayout && (initialGrid == null ? void 0 : initialGrid.uid)) {
|
|
6668
6889
|
const finalGrid = await this.repository.findModelById(parentUid, {
|
|
6669
6890
|
transaction: options.transaction,
|
|
@@ -6731,7 +6952,9 @@ class FlowSurfacesService {
|
|
|
6731
6952
|
(0, import_errors.throwBadRequest)("flowSurfaces fieldType is only supported for relation fields");
|
|
6732
6953
|
}
|
|
6733
6954
|
if (inlinePopup) {
|
|
6734
|
-
(0, import_errors.throwBadRequest)(
|
|
6955
|
+
(0, import_errors.throwBadRequest)(
|
|
6956
|
+
withJsPopupGuidance(`flowSurfaces addField type '${values.type}' does not support popup`, values.type)
|
|
6957
|
+
);
|
|
6735
6958
|
}
|
|
6736
6959
|
if (isFilterFormItem) {
|
|
6737
6960
|
(0, import_errors.throwBadRequest)(`flowSurfaces addField type '${values.type}' is not allowed under filter-form`);
|
|
@@ -6926,9 +7149,18 @@ class FlowSurfacesService {
|
|
|
6926
7149
|
}
|
|
6927
7150
|
}
|
|
6928
7151
|
if (inlinePopup && !this.isPopupFieldHostUse(boundFieldCapability.fieldUse)) {
|
|
6929
|
-
(0, import_errors.throwBadRequest)(
|
|
7152
|
+
(0, import_errors.throwBadRequest)(
|
|
7153
|
+
withJsPopupGuidance(
|
|
7154
|
+
`flowSurfaces addField field '${boundFieldCapability.fieldUse}' does not support popup`,
|
|
7155
|
+
boundFieldCapability.fieldUse
|
|
7156
|
+
)
|
|
7157
|
+
);
|
|
6930
7158
|
}
|
|
6931
|
-
|
|
7159
|
+
const inlineSettingsOpenView = this.peekInlineFieldSettingsOpenView(
|
|
7160
|
+
inlineSettings,
|
|
7161
|
+
boundFieldCapability.wrapperUse
|
|
7162
|
+
);
|
|
7163
|
+
if (values.__autoPopupForRelationField === true && !inlinePopup && this.isPopupFieldHostUse(boundFieldCapability.fieldUse) && ((0, import_service_helpers.isAssociationField)(resolvedField.field) || !!normalizedFieldBinding.associationPathName) && !inlineSettingsOpenView) {
|
|
6932
7164
|
const popupDefaultsMetadata = values[import_defaults.FLOW_SURFACE_APPLY_BLUEPRINT_POPUP_DEFAULTS_KEY];
|
|
6933
7165
|
inlinePopup = this.normalizeInlinePopup("addField", {
|
|
6934
7166
|
tryTemplate: true,
|
|
@@ -6938,9 +7170,19 @@ class FlowSurfacesService {
|
|
|
6938
7170
|
} : {}
|
|
6939
7171
|
});
|
|
6940
7172
|
}
|
|
6941
|
-
|
|
6942
|
-
|
|
6943
|
-
|
|
7173
|
+
const hasExternalInlineSettingsOpenView = this.isExternalPopupOpenView(inlineSettingsOpenView);
|
|
7174
|
+
if (!inlinePopup && this.isPopupFieldHostUse(boundFieldCapability.fieldUse) && !hasExternalInlineSettingsOpenView && (this.isInlineFieldClickToOpenEnabled(inlineSettings, boundFieldCapability.wrapperUse) || import_lodash.default.isPlainObject(inlineSettingsOpenView))) {
|
|
7175
|
+
const popupDefaultsMetadata = values[import_defaults.FLOW_SURFACE_APPLY_BLUEPRINT_POPUP_DEFAULTS_KEY];
|
|
7176
|
+
inlinePopup = this.normalizeInlinePopup("addField", {
|
|
7177
|
+
tryTemplate: true,
|
|
7178
|
+
defaultType: "view",
|
|
7179
|
+
...import_lodash.default.isPlainObject(inlineSettingsOpenView) ? { openView: import_lodash.default.cloneDeep(inlineSettingsOpenView) } : {},
|
|
7180
|
+
...popupDefaultsMetadata ? {
|
|
7181
|
+
[import_defaults.FLOW_SURFACE_APPLY_BLUEPRINT_POPUP_DEFAULTS_KEY]: popupDefaultsMetadata
|
|
7182
|
+
} : {}
|
|
7183
|
+
});
|
|
7184
|
+
}
|
|
7185
|
+
if (inlinePopup && hasExternalInlineSettingsOpenView) {
|
|
6944
7186
|
(0, import_errors.throwBadRequest)(`flowSurfaces addField popup cannot be combined with external openView.uid`);
|
|
6945
7187
|
}
|
|
6946
7188
|
const defaultFieldState = (0, import_service_utils.buildDefaultFieldState)(
|
|
@@ -7079,7 +7321,12 @@ class FlowSurfacesService {
|
|
|
7079
7321
|
);
|
|
7080
7322
|
}
|
|
7081
7323
|
if (inlinePopup && !POPUP_ACTION_USES.has(actionCatalogItem.use)) {
|
|
7082
|
-
(0, import_errors.throwBadRequest)(
|
|
7324
|
+
(0, import_errors.throwBadRequest)(
|
|
7325
|
+
withJsPopupGuidance(
|
|
7326
|
+
`flowSurfaces addAction type '${actionCatalogItem.key}' does not support popup`,
|
|
7327
|
+
actionCatalogItem.key
|
|
7328
|
+
)
|
|
7329
|
+
);
|
|
7083
7330
|
}
|
|
7084
7331
|
await this.assertApprovalActionSingleton(container.parentUid, actionCatalogItem.use, options.transaction);
|
|
7085
7332
|
(0, import_action_scope.assertRequestedActionScope)({
|
|
@@ -7129,6 +7376,12 @@ class FlowSurfacesService {
|
|
|
7129
7376
|
actionSettingsPayload,
|
|
7130
7377
|
aiEmployeeSettingsPayload
|
|
7131
7378
|
);
|
|
7379
|
+
await this.assertNoDuplicateAIEmployeeAction(
|
|
7380
|
+
"addAction",
|
|
7381
|
+
container.parentUid,
|
|
7382
|
+
actionSettingsPayload,
|
|
7383
|
+
options.transaction
|
|
7384
|
+
);
|
|
7132
7385
|
}
|
|
7133
7386
|
const action = (0, import_builder.buildActionTree)({
|
|
7134
7387
|
use: actionCatalogItem.use,
|
|
@@ -7191,7 +7444,12 @@ class FlowSurfacesService {
|
|
|
7191
7444
|
);
|
|
7192
7445
|
const resolvedScope = actionCatalogItem.scope;
|
|
7193
7446
|
if (inlinePopup && !POPUP_ACTION_USES.has(actionCatalogItem.use)) {
|
|
7194
|
-
(0, import_errors.throwBadRequest)(
|
|
7447
|
+
(0, import_errors.throwBadRequest)(
|
|
7448
|
+
withJsPopupGuidance(
|
|
7449
|
+
`flowSurfaces addRecordAction type '${actionCatalogItem.key}' does not support popup`,
|
|
7450
|
+
actionCatalogItem.key
|
|
7451
|
+
)
|
|
7452
|
+
);
|
|
7195
7453
|
}
|
|
7196
7454
|
if (this.isAddChildCatalogItem(actionCatalogItem)) {
|
|
7197
7455
|
await this.assertAddChildSupportedForOwnerNode(container.ownerNode, "addRecordAction", options.transaction);
|
|
@@ -7245,6 +7503,12 @@ class FlowSurfacesService {
|
|
|
7245
7503
|
actionSettingsPayload,
|
|
7246
7504
|
aiEmployeeSettingsPayload
|
|
7247
7505
|
);
|
|
7506
|
+
await this.assertNoDuplicateAIEmployeeAction(
|
|
7507
|
+
"addRecordAction",
|
|
7508
|
+
materializedContainer.parentUid,
|
|
7509
|
+
actionSettingsPayload,
|
|
7510
|
+
options.transaction
|
|
7511
|
+
);
|
|
7248
7512
|
}
|
|
7249
7513
|
const action = (0, import_builder.buildActionTree)({
|
|
7250
7514
|
use: actionCatalogItem.use,
|
|
@@ -8181,6 +8445,17 @@ class FlowSurfacesService {
|
|
|
8181
8445
|
const { fieldChanges } = (0, import_service_utils.splitComposeFieldChanges)(settings, wrapperUse);
|
|
8182
8446
|
return fieldChanges.openView;
|
|
8183
8447
|
}
|
|
8448
|
+
isInlineFieldClickToOpenEnabled(settings, wrapperUse) {
|
|
8449
|
+
if (!settings || !Object.keys(settings).length) {
|
|
8450
|
+
return false;
|
|
8451
|
+
}
|
|
8452
|
+
const { fieldChanges } = (0, import_service_utils.splitComposeFieldChanges)(settings, wrapperUse);
|
|
8453
|
+
if (!Object.prototype.hasOwnProperty.call(fieldChanges, "clickToOpen")) {
|
|
8454
|
+
return false;
|
|
8455
|
+
}
|
|
8456
|
+
const value = fieldChanges.clickToOpen;
|
|
8457
|
+
return value === true || import_lodash.default.isPlainObject(value) && value.clickToOpen === true;
|
|
8458
|
+
}
|
|
8184
8459
|
async assertOpenViewUidTarget(actionName, uid2, options = {}) {
|
|
8185
8460
|
const targetNode = await this.repository.findModelById(uid2, {
|
|
8186
8461
|
transaction: options.transaction,
|
|
@@ -8711,15 +8986,71 @@ class FlowSurfacesService {
|
|
|
8711
8986
|
sourceId: String(template.sourceId || "").trim() || void 0
|
|
8712
8987
|
};
|
|
8713
8988
|
}
|
|
8714
|
-
|
|
8989
|
+
shouldUseRuntimeRecordFilterByTkForOpenView(openView, options = {}) {
|
|
8990
|
+
var _a;
|
|
8991
|
+
return !!String((openView == null ? void 0 : openView.popupTemplateUid) || "").trim() && ((_a = options.popupActionContext) == null ? void 0 : _a.hasCurrentRecord) === true;
|
|
8992
|
+
}
|
|
8993
|
+
resolveOpenViewFilterTargetKey(openView, template) {
|
|
8994
|
+
const dataSourceKey = String((openView == null ? void 0 : openView.dataSourceKey) || (template == null ? void 0 : template.dataSourceKey) || "main").trim() || "main";
|
|
8995
|
+
const collectionName = String((openView == null ? void 0 : openView.collectionName) || (template == null ? void 0 : template.collectionName) || "").trim();
|
|
8996
|
+
const collection = collectionName ? this.getCollection(dataSourceKey, collectionName) : null;
|
|
8997
|
+
return this.getCollectionFilterTargetKey(collection);
|
|
8998
|
+
}
|
|
8999
|
+
async resolvePopupHostCurrentRecordFilterTargetKey(hostUid, transaction) {
|
|
9000
|
+
var _a, _b, _c;
|
|
9001
|
+
const normalizedHostUid = String(hostUid || "").trim();
|
|
9002
|
+
if (!normalizedHostUid) {
|
|
9003
|
+
return void 0;
|
|
9004
|
+
}
|
|
9005
|
+
const hostNode = await this.repository.findModelById(normalizedHostUid, {
|
|
9006
|
+
transaction,
|
|
9007
|
+
includeAsyncNode: true
|
|
9008
|
+
}).catch(() => null);
|
|
9009
|
+
if (!(hostNode == null ? void 0 : hostNode.uid)) {
|
|
9010
|
+
return void 0;
|
|
9011
|
+
}
|
|
9012
|
+
const hostContext = await this.resolvePopupHostProfileContext(hostNode, transaction).catch(() => null);
|
|
9013
|
+
const ownerResourceInit = ((_a = hostContext == null ? void 0 : hostContext.resourceContext) == null ? void 0 : _a.resourceInit) || {};
|
|
9014
|
+
const dataSourceKey = String(((_b = hostContext == null ? void 0 : hostContext.associationContext) == null ? void 0 : _b.dataSourceKey) || ownerResourceInit.dataSourceKey || "main").trim() || "main";
|
|
9015
|
+
const collectionName = String(
|
|
9016
|
+
((_c = hostContext == null ? void 0 : hostContext.associationContext) == null ? void 0 : _c.collectionName) || ownerResourceInit.collectionName || ""
|
|
9017
|
+
).trim();
|
|
9018
|
+
const collection = collectionName ? this.getCollection(dataSourceKey, collectionName) : null;
|
|
9019
|
+
return collection ? this.getCollectionFilterTargetKey(collection) : void 0;
|
|
9020
|
+
}
|
|
9021
|
+
async resolveOpenViewRuntimeRecordFilterTargetKey(openView, template, options = {}) {
|
|
9022
|
+
var _a;
|
|
9023
|
+
const contextKey = String(((_a = options.popupActionContext) == null ? void 0 : _a.currentRecordFilterTargetKey) || "").trim();
|
|
9024
|
+
if (contextKey) {
|
|
9025
|
+
return contextKey;
|
|
9026
|
+
}
|
|
9027
|
+
const hostKey = await this.resolvePopupHostCurrentRecordFilterTargetKey(
|
|
9028
|
+
options.popupTemplateHostUid,
|
|
9029
|
+
options.transaction
|
|
9030
|
+
);
|
|
9031
|
+
return hostKey || this.resolveOpenViewFilterTargetKey(openView, template);
|
|
9032
|
+
}
|
|
9033
|
+
shouldOmitRuntimeRecordFilterByTk(value, options = {}) {
|
|
9034
|
+
const normalized = this.normalizeFlowContextTemplateValue(value);
|
|
9035
|
+
if (!normalized) {
|
|
9036
|
+
return false;
|
|
9037
|
+
}
|
|
9038
|
+
if (normalized === "{{ctx.view.inputArgs.filterByTk}}") {
|
|
9039
|
+
return true;
|
|
9040
|
+
}
|
|
9041
|
+
const filterTargetKey = String(options.filterTargetKey || "").trim();
|
|
9042
|
+
return !!filterTargetKey && normalized === `{{ctx.record.${filterTargetKey}}}`;
|
|
9043
|
+
}
|
|
9044
|
+
buildPopupTemplateOpenView(template, mode, uidValue, options = {}) {
|
|
8715
9045
|
const popupTemplateHasFilterByTk = !!String(template.filterByTk || "").trim();
|
|
8716
9046
|
const popupTemplateHasSourceId = !!String(template.sourceId || "").trim() || !!String(template.associationName || "").trim();
|
|
9047
|
+
const omitRuntimeRecordFilterByTk = options.useRuntimeRecordFilterByTk === true && this.shouldOmitRuntimeRecordFilterByTk(template.filterByTk, { filterTargetKey: options.filterTargetKey });
|
|
8717
9048
|
const base = (0, import_service_utils.buildDefinedPayload)({
|
|
8718
9049
|
uid: uidValue,
|
|
8719
9050
|
dataSourceKey: template.dataSourceKey,
|
|
8720
9051
|
collectionName: template.collectionName,
|
|
8721
9052
|
associationName: template.associationName,
|
|
8722
|
-
...popupTemplateHasFilterByTk ? { filterByTk: template.filterByTk } : {},
|
|
9053
|
+
...popupTemplateHasFilterByTk && !omitRuntimeRecordFilterByTk ? { filterByTk: template.filterByTk } : {},
|
|
8723
9054
|
...popupTemplateHasSourceId && template.sourceId ? { sourceId: template.sourceId } : {},
|
|
8724
9055
|
popupTemplateHasFilterByTk,
|
|
8725
9056
|
popupTemplateHasSourceId,
|
|
@@ -8792,7 +9123,7 @@ class FlowSurfacesService {
|
|
|
8792
9123
|
}
|
|
8793
9124
|
}
|
|
8794
9125
|
async normalizeOpenView(actionName, openView, options = {}) {
|
|
8795
|
-
var _a;
|
|
9126
|
+
var _a, _b, _c, _d;
|
|
8796
9127
|
if (import_lodash.default.isUndefined(openView) || import_lodash.default.isNull(openView)) {
|
|
8797
9128
|
return openView;
|
|
8798
9129
|
}
|
|
@@ -8859,17 +9190,39 @@ class FlowSurfacesService {
|
|
|
8859
9190
|
if (templateRef.mode === "copy") {
|
|
8860
9191
|
await this.ensurePopupSurface(resolvedUid, options.transaction);
|
|
8861
9192
|
}
|
|
8862
|
-
let
|
|
9193
|
+
let runtimeRecordFilterTargetKey;
|
|
9194
|
+
if (((_b = options.popupActionContext) == null ? void 0 : _b.hasCurrentRecord) === true) {
|
|
9195
|
+
runtimeRecordFilterTargetKey = await this.resolveOpenViewRuntimeRecordFilterTargetKey(
|
|
9196
|
+
normalizedOpenView,
|
|
9197
|
+
template,
|
|
9198
|
+
options
|
|
9199
|
+
);
|
|
9200
|
+
}
|
|
9201
|
+
const filterTargetKey = runtimeRecordFilterTargetKey || this.resolveOpenViewFilterTargetKey(normalizedOpenView, template);
|
|
9202
|
+
let nextTemplateOpenView = this.buildPopupTemplateOpenView(template, templateRef.mode, resolvedUid, {
|
|
9203
|
+
filterTargetKey,
|
|
9204
|
+
useRuntimeRecordFilterByTk: ((_c = options.popupActionContext) == null ? void 0 : _c.hasCurrentRecord) === true
|
|
9205
|
+
});
|
|
8863
9206
|
Object.keys(normalizedOpenView).forEach((key) => {
|
|
8864
9207
|
if (key === "template" || key === "popupTemplateUid" || key === "popupTemplateMode" || key === "popupTemplateContext" || key === "popupTemplateHasFilterByTk" || key === "popupTemplateHasSourceId") {
|
|
8865
9208
|
delete normalizedOpenView[key];
|
|
8866
9209
|
}
|
|
8867
9210
|
});
|
|
9211
|
+
if (((_d = options.popupActionContext) == null ? void 0 : _d.hasCurrentRecord) === true && this.shouldOmitRuntimeRecordFilterByTk(normalizedOpenView.filterByTk, {
|
|
9212
|
+
filterTargetKey
|
|
9213
|
+
})) {
|
|
9214
|
+
delete normalizedOpenView.filterByTk;
|
|
9215
|
+
}
|
|
8868
9216
|
if (String(options.popupTemplateHostUse || "").trim() === "AddChildActionModel") {
|
|
8869
9217
|
nextTemplateOpenView = import_lodash.default.omit(nextTemplateOpenView, ["sourceId"]);
|
|
8870
9218
|
}
|
|
8871
9219
|
Object.assign(normalizedOpenView, nextTemplateOpenView);
|
|
8872
9220
|
}
|
|
9221
|
+
if (this.shouldUseRuntimeRecordFilterByTkForOpenView(normalizedOpenView, options) && this.shouldOmitRuntimeRecordFilterByTk(normalizedOpenView.filterByTk, {
|
|
9222
|
+
filterTargetKey: await this.resolveOpenViewRuntimeRecordFilterTargetKey(normalizedOpenView, void 0, options)
|
|
9223
|
+
})) {
|
|
9224
|
+
delete normalizedOpenView.filterByTk;
|
|
9225
|
+
}
|
|
8873
9226
|
if (!import_lodash.default.isUndefined(normalizedOpenView.uid)) {
|
|
8874
9227
|
const normalizedUid = String(normalizedOpenView.uid || "").trim();
|
|
8875
9228
|
if (!normalizedUid) {
|
|
@@ -8910,7 +9263,8 @@ class FlowSurfacesService {
|
|
|
8910
9263
|
return void 0;
|
|
8911
9264
|
}
|
|
8912
9265
|
return {
|
|
8913
|
-
hasCurrentRecord: true
|
|
9266
|
+
hasCurrentRecord: true,
|
|
9267
|
+
currentRecordFilterTargetKey: await this.resolvePopupHostCurrentRecordFilterTargetKey(current.uid, transaction)
|
|
8914
9268
|
};
|
|
8915
9269
|
}
|
|
8916
9270
|
unsetPayloadPathAndPruneEmptyParents(payload, path) {
|
|
@@ -9068,7 +9422,12 @@ class FlowSurfacesService {
|
|
|
9068
9422
|
return {};
|
|
9069
9423
|
}
|
|
9070
9424
|
if (input.popup && !this.isPopupFieldHostUse(fieldNode.use)) {
|
|
9071
|
-
(0, import_errors.throwBadRequest)(
|
|
9425
|
+
(0, import_errors.throwBadRequest)(
|
|
9426
|
+
withJsPopupGuidance(
|
|
9427
|
+
`flowSurfaces ${actionName} field '${fieldNode.use}' does not support popup`,
|
|
9428
|
+
fieldNode.use
|
|
9429
|
+
)
|
|
9430
|
+
);
|
|
9072
9431
|
}
|
|
9073
9432
|
let openView = this.resolvePopupHostOpenView(fieldNode);
|
|
9074
9433
|
if (input.popup && this.isExternalPopupOpenView(openView, fieldHostUid)) {
|
|
@@ -9394,6 +9753,20 @@ class FlowSurfacesService {
|
|
|
9394
9753
|
isEmptyInlinePopupPayload(popup) {
|
|
9395
9754
|
return import_lodash.default.isPlainObject(popup) && Object.keys(popup).length === 0;
|
|
9396
9755
|
}
|
|
9756
|
+
isInlineFieldPopupDefaultShell(popup) {
|
|
9757
|
+
if (!import_lodash.default.isPlainObject(popup)) {
|
|
9758
|
+
return false;
|
|
9759
|
+
}
|
|
9760
|
+
const shellOnlyKeys = /* @__PURE__ */ new Set([
|
|
9761
|
+
"title",
|
|
9762
|
+
"mode",
|
|
9763
|
+
"openView",
|
|
9764
|
+
"tryTemplate",
|
|
9765
|
+
"defaultType",
|
|
9766
|
+
import_defaults.FLOW_SURFACE_APPLY_BLUEPRINT_POPUP_DEFAULTS_KEY
|
|
9767
|
+
]);
|
|
9768
|
+
return Object.keys(popup).every((key) => shellOnlyKeys.has(key));
|
|
9769
|
+
}
|
|
9397
9770
|
shouldAutoCompleteDefaultFieldPopup(fieldNode, popup, wrapperNode) {
|
|
9398
9771
|
if (!import_lodash.default.isPlainObject(popup)) {
|
|
9399
9772
|
return false;
|
|
@@ -9408,7 +9781,7 @@ class FlowSurfacesService {
|
|
|
9408
9781
|
if (!String(fieldContext.collectionName || "").trim()) {
|
|
9409
9782
|
return false;
|
|
9410
9783
|
}
|
|
9411
|
-
return popup.tryTemplate === true || !import_lodash.default.isUndefined(popup.defaultType) ||
|
|
9784
|
+
return popup.tryTemplate === true || !import_lodash.default.isUndefined(popup.defaultType) || this.isInlineFieldPopupDefaultShell(popup);
|
|
9412
9785
|
}
|
|
9413
9786
|
isInlineFieldPopupBlockMissingResource(block) {
|
|
9414
9787
|
if (!import_lodash.default.isPlainObject(block) || !import_lodash.default.isUndefined(block.template)) {
|
|
@@ -10470,14 +10843,21 @@ class FlowSurfacesService {
|
|
|
10470
10843
|
actionNode,
|
|
10471
10844
|
options.transaction
|
|
10472
10845
|
).catch(() => null);
|
|
10473
|
-
const
|
|
10846
|
+
const useRuntimeRecordFilterByTk = this.isReferencedPopupTemplateOpenView(currentOpenView, actionNode.uid);
|
|
10847
|
+
const filterTargetKey = useRuntimeRecordFilterByTk ? await this.resolveOpenViewRuntimeRecordFilterTargetKey(currentOpenView, void 0, {
|
|
10848
|
+
transaction: options.transaction,
|
|
10849
|
+
popupTemplateHostUid: actionNode.uid,
|
|
10850
|
+
popupActionContext: {
|
|
10851
|
+
hasCurrentRecord: true
|
|
10852
|
+
}
|
|
10853
|
+
}) : (popupProfile == null ? void 0 : popupProfile.currentCollection) ? this.getCollectionFilterTargetKey(popupProfile.currentCollection) : null;
|
|
10474
10854
|
const defaultFilterByTk = this.resolvePopupCurrentRecordResourceFilterByTk(popupProfile);
|
|
10475
10855
|
const currentFilterByTk = import_lodash.default.isString(currentOpenView.filterByTk) ? currentOpenView.filterByTk.trim() : "";
|
|
10476
|
-
const preserveCustomFilterByTk = currentFilterByTk &&
|
|
10856
|
+
const preserveCustomFilterByTk = currentFilterByTk && !this.shouldOmitRuntimeRecordFilterByTk(currentOpenView.filterByTk, { filterTargetKey: filterTargetKey || "" });
|
|
10477
10857
|
const nextOpenView = (0, import_service_utils.buildDefinedPayload)({
|
|
10478
|
-
...currentOpenView,
|
|
10858
|
+
...useRuntimeRecordFilterByTk && !preserveCustomFilterByTk ? import_lodash.default.omit(currentOpenView, ["filterByTk"]) : currentOpenView,
|
|
10479
10859
|
title: openViewTitle,
|
|
10480
|
-
filterByTk: preserveCustomFilterByTk ? currentOpenView.filterByTk : defaultFilterByTk || currentOpenView.filterByTk
|
|
10860
|
+
filterByTk: useRuntimeRecordFilterByTk ? preserveCustomFilterByTk ? currentOpenView.filterByTk : void 0 : preserveCustomFilterByTk ? currentOpenView.filterByTk : defaultFilterByTk || currentOpenView.filterByTk
|
|
10481
10861
|
});
|
|
10482
10862
|
if (import_lodash.default.isEqual(nextOpenView, currentOpenView)) {
|
|
10483
10863
|
return;
|
|
@@ -11700,7 +12080,12 @@ class FlowSurfacesService {
|
|
|
11700
12080
|
}
|
|
11701
12081
|
if (!((_c = sqlPreview.queryOutputs) == null ? void 0 : _c.length)) {
|
|
11702
12082
|
(0, import_errors.throwBadRequest)(
|
|
11703
|
-
|
|
12083
|
+
withChartRepairMessage(
|
|
12084
|
+
"chart visual.mode='basic' requires previewable SQL query outputs; write query first, then read flowSurfaces:context(path='chart'), or use visual.mode='custom' after browser verification"
|
|
12085
|
+
),
|
|
12086
|
+
{
|
|
12087
|
+
details: withFlowSurfaceChartRepairDetails()
|
|
12088
|
+
}
|
|
11704
12089
|
);
|
|
11705
12090
|
}
|
|
11706
12091
|
const supportedOutputs = new Set(
|
|
@@ -11709,7 +12094,14 @@ class FlowSurfacesService {
|
|
|
11709
12094
|
for (const mappingField of (0, import_chart_config.getChartVisualMappingAliases)(state.visual)) {
|
|
11710
12095
|
if (!supportedOutputs.has(mappingField)) {
|
|
11711
12096
|
(0, import_errors.throwBadRequest)(
|
|
11712
|
-
|
|
12097
|
+
withChartRepairMessage(
|
|
12098
|
+
`chart visual mappings only support SQL query output fields: ${Array.from(supportedOutputs).join(", ")}`
|
|
12099
|
+
),
|
|
12100
|
+
{
|
|
12101
|
+
details: withFlowSurfaceChartRepairDetails({
|
|
12102
|
+
supportedOutputs: Array.from(supportedOutputs)
|
|
12103
|
+
})
|
|
12104
|
+
}
|
|
11713
12105
|
);
|
|
11714
12106
|
}
|
|
11715
12107
|
}
|
|
@@ -11758,13 +12150,32 @@ class FlowSurfacesService {
|
|
|
11758
12150
|
continue;
|
|
11759
12151
|
}
|
|
11760
12152
|
(0, import_errors.throwBadRequest)(
|
|
11761
|
-
|
|
12153
|
+
withChartRepairMessage(
|
|
12154
|
+
`flowSurfaces ${actionName} ${item.path} '${fieldPath}' does not exist on collection '${dataSourceKey}.${collectionName}'`
|
|
12155
|
+
),
|
|
12156
|
+
{
|
|
12157
|
+
details: withFlowSurfaceChartRepairDetails({
|
|
12158
|
+
fieldPath,
|
|
12159
|
+
dataSourceKey,
|
|
12160
|
+
collectionName
|
|
12161
|
+
})
|
|
12162
|
+
}
|
|
11762
12163
|
);
|
|
11763
12164
|
}
|
|
11764
12165
|
if (!fieldPath.includes(".") && (0, import_service_helpers.isAssociationField)(field)) {
|
|
11765
12166
|
const suggestion = this.resolveBuilderChartAssociationSubfieldSuggestion(fieldPath, field, dataSourceKey);
|
|
11766
12167
|
(0, import_errors.throwBadRequest)(
|
|
11767
|
-
|
|
12168
|
+
withChartRepairMessage(
|
|
12169
|
+
`flowSurfaces ${actionName} ${item.path} '${fieldPath}' references an association field directly; use scalar subfield '${suggestion.suggestedFieldPath}' for builder charts`
|
|
12170
|
+
),
|
|
12171
|
+
{
|
|
12172
|
+
details: withFlowSurfaceChartRepairDetails({
|
|
12173
|
+
fieldPath,
|
|
12174
|
+
dataSourceKey,
|
|
12175
|
+
collectionName,
|
|
12176
|
+
...suggestion
|
|
12177
|
+
})
|
|
12178
|
+
}
|
|
11768
12179
|
);
|
|
11769
12180
|
}
|
|
11770
12181
|
}
|
|
@@ -11805,7 +12216,12 @@ class FlowSurfacesService {
|
|
|
11805
12216
|
}
|
|
11806
12217
|
if (!((_c = sqlPreview.queryOutputs) == null ? void 0 : _c.length)) {
|
|
11807
12218
|
(0, import_errors.throwBadRequest)(
|
|
11808
|
-
|
|
12219
|
+
withChartRepairMessage(
|
|
12220
|
+
"chart visual.mode='basic' requires previewable SQL query outputs; write query first, then read flowSurfaces:context(path='chart'), or use visual.mode='custom' after browser verification"
|
|
12221
|
+
),
|
|
12222
|
+
{
|
|
12223
|
+
details: withFlowSurfaceChartRepairDetails()
|
|
12224
|
+
}
|
|
11809
12225
|
);
|
|
11810
12226
|
}
|
|
11811
12227
|
const supportedOutputs = new Set(
|
|
@@ -11814,7 +12230,14 @@ class FlowSurfacesService {
|
|
|
11814
12230
|
for (const mappingField of (0, import_chart_config.getChartVisualMappingAliases)(state.visual)) {
|
|
11815
12231
|
if (!supportedOutputs.has(mappingField)) {
|
|
11816
12232
|
(0, import_errors.throwBadRequest)(
|
|
11817
|
-
|
|
12233
|
+
withChartRepairMessage(
|
|
12234
|
+
`chart visual mappings only support SQL query output fields: ${Array.from(supportedOutputs).join(", ")}`
|
|
12235
|
+
),
|
|
12236
|
+
{
|
|
12237
|
+
details: withFlowSurfaceChartRepairDetails({
|
|
12238
|
+
supportedOutputs: Array.from(supportedOutputs)
|
|
12239
|
+
})
|
|
12240
|
+
}
|
|
11818
12241
|
);
|
|
11819
12242
|
}
|
|
11820
12243
|
}
|
|
@@ -11826,16 +12249,16 @@ class FlowSurfacesService {
|
|
|
11826
12249
|
const normalized = (typeof sql === "string" ? sql : "").trim();
|
|
11827
12250
|
const inspected = this.stripChartSqlForInspection(normalized).replace(/;+\s*$/, "").trim();
|
|
11828
12251
|
if (!inspected) {
|
|
11829
|
-
(
|
|
12252
|
+
throwChartRepairBadRequest("chart query.sql cannot be empty");
|
|
11830
12253
|
}
|
|
11831
12254
|
if (inspected.includes(";")) {
|
|
11832
|
-
(
|
|
12255
|
+
throwChartRepairBadRequest("chart query.sql must be a single read-only SELECT statement");
|
|
11833
12256
|
}
|
|
11834
12257
|
if (!/^(with|select)\b/i.test(inspected)) {
|
|
11835
|
-
(
|
|
12258
|
+
throwChartRepairBadRequest("chart query.sql must start with SELECT or WITH");
|
|
11836
12259
|
}
|
|
11837
12260
|
if (/\b(insert|update|delete|drop|alter|truncate|create|replace|grant|revoke|merge|call|execute)\b/i.test(inspected)) {
|
|
11838
|
-
(
|
|
12261
|
+
throwChartRepairBadRequest("chart query.sql must be read-only");
|
|
11839
12262
|
}
|
|
11840
12263
|
return normalized.replace(/;+\s*$/, "").trim();
|
|
11841
12264
|
}
|
|
@@ -11853,7 +12276,7 @@ class FlowSurfacesService {
|
|
|
11853
12276
|
if ((_a = db == null ? void 0 : db.sequelize) == null ? void 0 : _a.query) {
|
|
11854
12277
|
return db.sequelize.query(sql, { bind, transaction });
|
|
11855
12278
|
}
|
|
11856
|
-
(
|
|
12279
|
+
throwChartRepairBadRequest("chart SQL preview is unavailable for the target data source");
|
|
11857
12280
|
}
|
|
11858
12281
|
extractSqlChartPreviewAliases(metadata) {
|
|
11859
12282
|
const pickName = (field) => {
|
|
@@ -11891,7 +12314,13 @@ class FlowSurfacesService {
|
|
|
11891
12314
|
async resolveSqlChartPreview(query, _transaction) {
|
|
11892
12315
|
var _a, _b;
|
|
11893
12316
|
const normalizedSql = this.normalizeReadOnlyChartSql(query == null ? void 0 : query.sql);
|
|
11894
|
-
|
|
12317
|
+
let transformed;
|
|
12318
|
+
try {
|
|
12319
|
+
transformed = await (0, import_utils.transformSQL)(normalizedSql);
|
|
12320
|
+
} catch (error) {
|
|
12321
|
+
const message = (error == null ? void 0 : error.message) || String(error);
|
|
12322
|
+
throwChartRepairBadRequest(`chart query.sql is invalid: ${message}`);
|
|
12323
|
+
}
|
|
11895
12324
|
const riskyHints = [];
|
|
11896
12325
|
const hasRuntimeContext = Object.keys((transformed == null ? void 0 : transformed.bind) || {}).length > 0 || Object.keys((transformed == null ? void 0 : transformed.liquidContext) || {}).length > 0;
|
|
11897
12326
|
if (hasRuntimeContext) {
|
|
@@ -11947,7 +12376,7 @@ class FlowSurfacesService {
|
|
|
11947
12376
|
}
|
|
11948
12377
|
const outputAliases = Object.keys(firstRow);
|
|
11949
12378
|
if (!outputAliases.length) {
|
|
11950
|
-
(
|
|
12379
|
+
throwChartRepairBadRequest("chart query.sql must expose at least one output column");
|
|
11951
12380
|
}
|
|
11952
12381
|
return {
|
|
11953
12382
|
queryOutputs: outputAliases.map((alias) => ({
|
|
@@ -11958,8 +12387,11 @@ class FlowSurfacesService {
|
|
|
11958
12387
|
riskyHints
|
|
11959
12388
|
};
|
|
11960
12389
|
} catch (error) {
|
|
12390
|
+
if (isFlowSurfaceChartRepairError(error)) {
|
|
12391
|
+
throw error;
|
|
12392
|
+
}
|
|
11961
12393
|
const message = (error == null ? void 0 : error.message) || String(error);
|
|
11962
|
-
(
|
|
12394
|
+
throwChartRepairBadRequest(`chart query.sql is invalid: ${message}`);
|
|
11963
12395
|
}
|
|
11964
12396
|
}
|
|
11965
12397
|
syncChartCardRuntimeStepParamsForUpdateSettings(current, nextPayload, replacementCardSettings) {
|
|
@@ -13967,6 +14399,97 @@ class FlowSurfacesService {
|
|
|
13967
14399
|
}
|
|
13968
14400
|
}
|
|
13969
14401
|
}
|
|
14402
|
+
hasActionWithPublicType(actions, type) {
|
|
14403
|
+
return actions.some((action) => import_catalog.ACTION_KEY_BY_USE.get(String((action == null ? void 0 : action.use) || "").trim()) === type);
|
|
14404
|
+
}
|
|
14405
|
+
async ensureTableDefaultActionIntegrity(tableUid, options = {}) {
|
|
14406
|
+
var _a, _b, _c, _d;
|
|
14407
|
+
let table = await this.repository.findModelById(tableUid, {
|
|
14408
|
+
transaction: options.transaction,
|
|
14409
|
+
includeAsyncNode: true
|
|
14410
|
+
});
|
|
14411
|
+
if ((table == null ? void 0 : table.use) !== "TableBlockModel" || this.resolveTreeTableCreationContext(table)) {
|
|
14412
|
+
return;
|
|
14413
|
+
}
|
|
14414
|
+
const descriptors = (0, import_default_block_actions.getFlowSurfaceDefaultBlockActions)({ blockType: "table" });
|
|
14415
|
+
const blockActionDescriptors = descriptors.filter((descriptor) => descriptor.scope === "actions");
|
|
14416
|
+
const recordActionDescriptors = descriptors.filter((descriptor) => descriptor.scope === "recordActions");
|
|
14417
|
+
let blockActions = import_lodash.default.castArray(((_a = table == null ? void 0 : table.subModels) == null ? void 0 : _a.actions) || []);
|
|
14418
|
+
for (const descriptor of blockActionDescriptors) {
|
|
14419
|
+
if (this.hasActionWithPublicType(blockActions, descriptor.type)) {
|
|
14420
|
+
continue;
|
|
14421
|
+
}
|
|
14422
|
+
await this.addAction(
|
|
14423
|
+
{
|
|
14424
|
+
target: { uid: tableUid },
|
|
14425
|
+
type: descriptor.type,
|
|
14426
|
+
...descriptor.popup ? { popup: import_lodash.default.cloneDeep(descriptor.popup) } : {}
|
|
14427
|
+
},
|
|
14428
|
+
options
|
|
14429
|
+
);
|
|
14430
|
+
table = await this.repository.findModelById(tableUid, {
|
|
14431
|
+
transaction: options.transaction,
|
|
14432
|
+
includeAsyncNode: true
|
|
14433
|
+
});
|
|
14434
|
+
blockActions = import_lodash.default.castArray(((_b = table == null ? void 0 : table.subModels) == null ? void 0 : _b.actions) || []);
|
|
14435
|
+
}
|
|
14436
|
+
const actionsColumnUid = await this.ensureTableActionsColumn(tableUid, options.transaction);
|
|
14437
|
+
let actionsColumn = await this.repository.findModelById(actionsColumnUid, {
|
|
14438
|
+
transaction: options.transaction,
|
|
14439
|
+
includeAsyncNode: true
|
|
14440
|
+
});
|
|
14441
|
+
let recordActions = import_lodash.default.castArray(((_c = actionsColumn == null ? void 0 : actionsColumn.subModels) == null ? void 0 : _c.actions) || []);
|
|
14442
|
+
for (const descriptor of recordActionDescriptors) {
|
|
14443
|
+
if (this.hasActionWithPublicType(recordActions, descriptor.type)) {
|
|
14444
|
+
continue;
|
|
14445
|
+
}
|
|
14446
|
+
await this.addRecordAction(
|
|
14447
|
+
{
|
|
14448
|
+
target: { uid: tableUid },
|
|
14449
|
+
type: descriptor.type,
|
|
14450
|
+
...descriptor.popup ? { popup: import_lodash.default.cloneDeep(descriptor.popup) } : {}
|
|
14451
|
+
},
|
|
14452
|
+
options
|
|
14453
|
+
);
|
|
14454
|
+
actionsColumn = await this.repository.findModelById(actionsColumnUid, {
|
|
14455
|
+
transaction: options.transaction,
|
|
14456
|
+
includeAsyncNode: true
|
|
14457
|
+
});
|
|
14458
|
+
recordActions = import_lodash.default.castArray(((_d = actionsColumn == null ? void 0 : actionsColumn.subModels) == null ? void 0 : _d.actions) || []);
|
|
14459
|
+
}
|
|
14460
|
+
const missingRecordActions = recordActionDescriptors.map((descriptor) => descriptor.type).filter((type) => !this.hasActionWithPublicType(recordActions, type));
|
|
14461
|
+
if (missingRecordActions.length) {
|
|
14462
|
+
(0, import_errors.throwBadRequest)(`flowSurfaces table '${tableUid}' is missing required default record actions`, {
|
|
14463
|
+
ruleId: "table-record-actions-required",
|
|
14464
|
+
details: {
|
|
14465
|
+
tableUid,
|
|
14466
|
+
missingRecordActions,
|
|
14467
|
+
repairHint: "Put row actions under recordActions, or omit/pass an empty recordActions array so Flow Surfaces can create the default View/Edit/Delete row actions."
|
|
14468
|
+
}
|
|
14469
|
+
});
|
|
14470
|
+
}
|
|
14471
|
+
}
|
|
14472
|
+
collectNodeTreeDescendants(node, predicate, bucket = []) {
|
|
14473
|
+
if (!node || typeof node !== "object") {
|
|
14474
|
+
return bucket;
|
|
14475
|
+
}
|
|
14476
|
+
if (predicate(node)) {
|
|
14477
|
+
bucket.push(node);
|
|
14478
|
+
}
|
|
14479
|
+
Object.values(import_lodash.default.isPlainObject(node.subModels) ? node.subModels : {}).forEach((subModel) => {
|
|
14480
|
+
import_lodash.default.castArray(subModel).forEach((child) => this.collectNodeTreeDescendants(child, predicate, bucket));
|
|
14481
|
+
});
|
|
14482
|
+
return bucket;
|
|
14483
|
+
}
|
|
14484
|
+
async ensureSurfaceTableDefaultActionIntegrity(pageLocator, options = {}) {
|
|
14485
|
+
const surface = await this.get(pageLocator, options);
|
|
14486
|
+
const tables = this.collectNodeTreeDescendants(surface == null ? void 0 : surface.tree, (item) => (item == null ? void 0 : item.use) === "TableBlockModel");
|
|
14487
|
+
for (const table of tables) {
|
|
14488
|
+
if (table == null ? void 0 : table.uid) {
|
|
14489
|
+
await this.ensureTableDefaultActionIntegrity(table.uid, options);
|
|
14490
|
+
}
|
|
14491
|
+
}
|
|
14492
|
+
}
|
|
13970
14493
|
async resolveReusableSingletonAction(input) {
|
|
13971
14494
|
var _a, _b, _c;
|
|
13972
14495
|
if (AUTO_SUBMIT_FORM_BLOCK_USES.has(input.ownerUse || "") && input.actionUse === "FormSubmitActionModel") {
|
|
@@ -14130,8 +14653,10 @@ class FlowSurfacesService {
|
|
|
14130
14653
|
if (blockCatalogItem) {
|
|
14131
14654
|
this.validateComposeActionGroups(blockCatalogItem.use, actions, recordActions, enabledPackages);
|
|
14132
14655
|
}
|
|
14133
|
-
const actionKeys = new Set(actions.map((item) => item.key).filter(Boolean));
|
|
14134
|
-
const recordActionKeys = new Set(
|
|
14656
|
+
const actionKeys = new Set(actions.map((item) => String(item.key || "").trim()).filter(Boolean));
|
|
14657
|
+
const recordActionKeys = new Set(
|
|
14658
|
+
recordActions.map((item) => String(item.key || "").trim()).filter(Boolean)
|
|
14659
|
+
);
|
|
14135
14660
|
const blockDescriptor = this.describeComposeBlock({
|
|
14136
14661
|
index: index + 1,
|
|
14137
14662
|
key,
|
|
@@ -14562,6 +15087,7 @@ class FlowSurfacesService {
|
|
|
14562
15087
|
...(0, import_service_utils.hasDefinedValue)(changes, [
|
|
14563
15088
|
"pageSize",
|
|
14564
15089
|
"density",
|
|
15090
|
+
"enableRowSelection",
|
|
14565
15091
|
"showRowNumbers",
|
|
14566
15092
|
"sorting",
|
|
14567
15093
|
"dataScope",
|
|
@@ -14575,6 +15101,7 @@ class FlowSurfacesService {
|
|
|
14575
15101
|
...(0, import_service_utils.hasOwnDefined)(changes, "pageSize") ? { pageSize: { pageSize: changes.pageSize } } : {},
|
|
14576
15102
|
...(0, import_service_utils.hasOwnDefined)(changes, "density") ? { tableDensity: { size: changes.density } } : {},
|
|
14577
15103
|
...(0, import_service_utils.hasOwnDefined)(changes, "quickEdit") ? { quickEdit: { editable: changes.quickEdit } } : {},
|
|
15104
|
+
...(0, import_service_utils.hasOwnDefined)(changes, "enableRowSelection") ? { enableRowSelection: { enableRowSelection: changes.enableRowSelection } } : {},
|
|
14578
15105
|
...(0, import_service_utils.hasOwnDefined)(changes, "showRowNumbers") ? { showRowNumbers: { showIndex: changes.showRowNumbers } } : {},
|
|
14579
15106
|
...(0, import_service_utils.hasOwnDefined)(changes, "sorting") ? {
|
|
14580
15107
|
defaultSorting: {
|
|
@@ -15952,6 +16479,7 @@ class FlowSurfacesService {
|
|
|
15952
16479
|
);
|
|
15953
16480
|
}
|
|
15954
16481
|
async configureJSColumn(target, changes, options) {
|
|
16482
|
+
assertNoJsDeclarativeOpenView("jsColumn", changes, "JSColumnModel");
|
|
15955
16483
|
const allowedKeys = (0, import_configure_options.getConfigureOptionKeysForUse)("JSColumnModel");
|
|
15956
16484
|
(0, import_service_utils.assertSupportedSimpleChanges)("jsColumn", changes, allowedKeys);
|
|
15957
16485
|
return this.updateSettings(
|
|
@@ -15985,6 +16513,8 @@ class FlowSurfacesService {
|
|
|
15985
16513
|
);
|
|
15986
16514
|
}
|
|
15987
16515
|
async configureJSItem(target, changes, options) {
|
|
16516
|
+
const { currentUse = "JSItemModel", ...updateOptions } = options;
|
|
16517
|
+
assertNoJsDeclarativeOpenView("jsItem", changes, currentUse);
|
|
15988
16518
|
const allowedKeys = (0, import_configure_options.getConfigureOptionKeysForUse)("JSItemModel");
|
|
15989
16519
|
(0, import_service_utils.assertSupportedSimpleChanges)("jsItem", changes, allowedKeys);
|
|
15990
16520
|
return this.updateSettings(
|
|
@@ -16009,7 +16539,7 @@ class FlowSurfacesService {
|
|
|
16009
16539
|
}
|
|
16010
16540
|
} : void 0
|
|
16011
16541
|
},
|
|
16012
|
-
|
|
16542
|
+
updateOptions
|
|
16013
16543
|
);
|
|
16014
16544
|
}
|
|
16015
16545
|
async configureDividerItem(target, changes, options) {
|
|
@@ -16060,6 +16590,7 @@ class FlowSurfacesService {
|
|
|
16060
16590
|
transaction: options.transaction,
|
|
16061
16591
|
includeAsyncNode: true
|
|
16062
16592
|
}) : null;
|
|
16593
|
+
assertNoJsDeclarativeOpenView("field", changes, innerField == null ? void 0 : innerField.use);
|
|
16063
16594
|
const currentFieldInit = ((_e = (_d = current == null ? void 0 : current.stepParams) == null ? void 0 : _d.fieldSettings) == null ? void 0 : _e.init) || ((_g = (_f = innerField == null ? void 0 : innerField.stepParams) == null ? void 0 : _f.fieldSettings) == null ? void 0 : _g.init) || {};
|
|
16064
16595
|
const bindingChange = (0, import_service_utils.hasDefinedValue)(wrapperChanges, ["fieldPath", "associationPathName"]);
|
|
16065
16596
|
const normalizedBinding = bindingChange ? this.normalizeDisplayFieldBinding({
|
|
@@ -16271,6 +16802,8 @@ class FlowSurfacesService {
|
|
|
16271
16802
|
const enabledPackages = await this.resolveEnabledPluginPackages(options);
|
|
16272
16803
|
const resolved = await this.locator.resolve(target, options);
|
|
16273
16804
|
const current = await this.loadResolvedNode(resolved, options.transaction);
|
|
16805
|
+
const isJsFieldNode = ["JSFieldModel", "JSEditableFieldModel"].includes((current == null ? void 0 : current.use) || "");
|
|
16806
|
+
assertNoJsDeclarativeOpenView("field", changes, current == null ? void 0 : current.use);
|
|
16274
16807
|
(0, import_service_utils.assertSupportedSimpleChanges)(
|
|
16275
16808
|
"field",
|
|
16276
16809
|
changes,
|
|
@@ -16281,7 +16814,6 @@ class FlowSurfacesService {
|
|
|
16281
16814
|
transaction: options.transaction,
|
|
16282
16815
|
includeAsyncNode: true
|
|
16283
16816
|
}) : null;
|
|
16284
|
-
const isJsFieldNode = ["JSFieldModel", "JSEditableFieldModel"].includes((current == null ? void 0 : current.use) || "");
|
|
16285
16817
|
if ((0, import_service_utils.hasDefinedValue)(changes, ["code", "version"]) && !isJsFieldNode) {
|
|
16286
16818
|
(0, import_errors.throwBadRequest)(`flowSurfaces configure field '${current == null ? void 0 : current.use}' does not support code/version`);
|
|
16287
16819
|
}
|
|
@@ -16486,6 +17018,93 @@ class FlowSurfacesService {
|
|
|
16486
17018
|
isAIEmployeeActionUse(use) {
|
|
16487
17019
|
return String(use || "").trim() === AI_EMPLOYEE_ACTION_USE;
|
|
16488
17020
|
}
|
|
17021
|
+
stableSerializeAIEmployeeValue(value) {
|
|
17022
|
+
if (Array.isArray(value)) {
|
|
17023
|
+
return `[${value.map((item) => this.stableSerializeAIEmployeeValue(item)).join(",")}]`;
|
|
17024
|
+
}
|
|
17025
|
+
if (import_lodash.default.isPlainObject(value)) {
|
|
17026
|
+
return `{${Object.keys(value).sort().map((key) => `${JSON.stringify(key)}:${this.stableSerializeAIEmployeeValue(value[key])}`).join(",")}}`;
|
|
17027
|
+
}
|
|
17028
|
+
return JSON.stringify(value);
|
|
17029
|
+
}
|
|
17030
|
+
buildAIEmployeeActionDedupIdentity(values) {
|
|
17031
|
+
var _a, _b, _c, _d, _e, _f;
|
|
17032
|
+
const username = String(((_b = (_a = values == null ? void 0 : values.props) == null ? void 0 : _a.aiEmployee) == null ? void 0 : _b.username) || "").trim();
|
|
17033
|
+
if (!username) {
|
|
17034
|
+
return "";
|
|
17035
|
+
}
|
|
17036
|
+
return this.stableSerializeAIEmployeeValue({
|
|
17037
|
+
username,
|
|
17038
|
+
auto: typeof ((_c = values == null ? void 0 : values.props) == null ? void 0 : _c.auto) === "boolean" ? values.props.auto : false,
|
|
17039
|
+
workContext: this.normalizeAIEmployeeWorkContextForDedupIdentity((_e = (_d = values == null ? void 0 : values.props) == null ? void 0 : _d.context) == null ? void 0 : _e.workContext),
|
|
17040
|
+
tasks: this.normalizeAIEmployeeTasksForDedupIdentity(
|
|
17041
|
+
import_lodash.default.get(values, ["stepParams", ...AI_EMPLOYEE_TASK_STEP_PARAMS_PATH])
|
|
17042
|
+
),
|
|
17043
|
+
style: {
|
|
17044
|
+
...AI_EMPLOYEE_DEFAULT_STYLE,
|
|
17045
|
+
...import_lodash.default.isPlainObject((_f = values == null ? void 0 : values.props) == null ? void 0 : _f.style) ? import_lodash.default.pick(values.props.style, AI_EMPLOYEE_STYLE_PUBLIC_KEYS) : {}
|
|
17046
|
+
}
|
|
17047
|
+
});
|
|
17048
|
+
}
|
|
17049
|
+
normalizeAIEmployeeWorkContextForDedupIdentity(value) {
|
|
17050
|
+
return import_lodash.default.castArray(value || []).map(
|
|
17051
|
+
(item) => import_lodash.default.isPlainObject(item) ? import_lodash.default.pick(item, AI_EMPLOYEE_WORK_CONTEXT_PUBLIC_KEYS) : item
|
|
17052
|
+
);
|
|
17053
|
+
}
|
|
17054
|
+
normalizeAIEmployeeTasksForDedupIdentity(value) {
|
|
17055
|
+
return import_lodash.default.castArray(value || []).map((task) => {
|
|
17056
|
+
if (!import_lodash.default.isPlainObject(task)) {
|
|
17057
|
+
return task;
|
|
17058
|
+
}
|
|
17059
|
+
const output = import_lodash.default.pick(task, AI_EMPLOYEE_TASK_PUBLIC_SETTING_KEYS);
|
|
17060
|
+
if (import_lodash.default.isPlainObject(output.message)) {
|
|
17061
|
+
output.message = import_lodash.default.pick(output.message, AI_EMPLOYEE_TASK_MESSAGE_PUBLIC_KEYS);
|
|
17062
|
+
if (Object.prototype.hasOwnProperty.call(output.message, "workContext")) {
|
|
17063
|
+
output.message.workContext = this.normalizeAIEmployeeWorkContextForDedupIdentity(output.message.workContext);
|
|
17064
|
+
}
|
|
17065
|
+
}
|
|
17066
|
+
if (import_lodash.default.isPlainObject(output.model)) {
|
|
17067
|
+
output.model = import_lodash.default.pick(output.model, AI_EMPLOYEE_TASK_MODEL_PUBLIC_KEYS);
|
|
17068
|
+
}
|
|
17069
|
+
if (import_lodash.default.isPlainObject(output.skillSettings)) {
|
|
17070
|
+
output.skillSettings = import_lodash.default.pick(output.skillSettings, AI_EMPLOYEE_SKILL_SETTINGS_PUBLIC_KEYS);
|
|
17071
|
+
}
|
|
17072
|
+
return output;
|
|
17073
|
+
});
|
|
17074
|
+
}
|
|
17075
|
+
async assertNoDuplicateAIEmployeeAction(actionName, parentUid, values, transaction) {
|
|
17076
|
+
var _a;
|
|
17077
|
+
const identity = this.buildAIEmployeeActionDedupIdentity(values);
|
|
17078
|
+
if (!identity) {
|
|
17079
|
+
return;
|
|
17080
|
+
}
|
|
17081
|
+
const parentNode = await this.repository.findModelById(parentUid, {
|
|
17082
|
+
transaction,
|
|
17083
|
+
includeAsyncNode: true
|
|
17084
|
+
});
|
|
17085
|
+
const duplicate = import_lodash.default.castArray(((_a = parentNode == null ? void 0 : parentNode.subModels) == null ? void 0 : _a.actions) || []).find((action) => {
|
|
17086
|
+
if (!this.isAIEmployeeActionUse(action == null ? void 0 : action.use)) {
|
|
17087
|
+
return false;
|
|
17088
|
+
}
|
|
17089
|
+
return this.buildAIEmployeeActionDedupIdentity({
|
|
17090
|
+
props: action.props,
|
|
17091
|
+
stepParams: action.stepParams
|
|
17092
|
+
}) === identity;
|
|
17093
|
+
});
|
|
17094
|
+
if (!(duplicate == null ? void 0 : duplicate.uid)) {
|
|
17095
|
+
return;
|
|
17096
|
+
}
|
|
17097
|
+
(0, import_errors.throwBadRequest)(
|
|
17098
|
+
`flowSurfaces ${actionName} duplicates an existing AI employee action in the same action container; reuse or update the existing button instead of appending another identical AI employee action`,
|
|
17099
|
+
{
|
|
17100
|
+
ruleId: "duplicate-ai-employee-action",
|
|
17101
|
+
details: {
|
|
17102
|
+
existingUid: duplicate.uid,
|
|
17103
|
+
repairHint: "Remove the duplicate aiEmployee action, or change username, task title/key, or workContext if this is a genuinely different AI employee action."
|
|
17104
|
+
}
|
|
17105
|
+
}
|
|
17106
|
+
);
|
|
17107
|
+
}
|
|
16489
17108
|
hasAIEmployeePublicSettings(settings) {
|
|
16490
17109
|
return import_lodash.default.isPlainObject(settings) && AI_EMPLOYEE_PUBLIC_SETTING_KEYS.some((key) => Object.prototype.hasOwnProperty.call(settings, key));
|
|
16491
17110
|
}
|
|
@@ -16493,16 +17112,31 @@ class FlowSurfacesService {
|
|
|
16493
17112
|
const unsupportedKeys = Object.keys(settings || {}).filter((key) => !AI_EMPLOYEE_PUBLIC_SETTING_KEYS.includes(key));
|
|
16494
17113
|
if (unsupportedKeys.length) {
|
|
16495
17114
|
(0, import_errors.throwBadRequest)(
|
|
16496
|
-
`flowSurfaces ${actionName} AI employee settings do not support keys: ${unsupportedKeys.join(
|
|
17115
|
+
`flowSurfaces ${actionName} AI employee settings do not support keys: ${unsupportedKeys.join(
|
|
17116
|
+
", "
|
|
17117
|
+
)}; allowed keys: ${AI_EMPLOYEE_PUBLIC_SETTING_KEYS.join(
|
|
17118
|
+
", "
|
|
17119
|
+
)}; repairHint: use top-level username, auto, workContext, tasks, or style instead of raw props/stepParams`
|
|
16497
17120
|
);
|
|
16498
17121
|
}
|
|
16499
17122
|
}
|
|
17123
|
+
aiEmployeeNestedRepairHint(path) {
|
|
17124
|
+
if (path.includes("workContext")) {
|
|
17125
|
+
return AI_EMPLOYEE_WORK_CONTEXT_REPAIR_HINT;
|
|
17126
|
+
}
|
|
17127
|
+
if (path.includes("tasks")) {
|
|
17128
|
+
return AI_EMPLOYEE_TASK_REPAIR_HINT;
|
|
17129
|
+
}
|
|
17130
|
+
return "Use only the documented public AI employee settings keys for this nested object.";
|
|
17131
|
+
}
|
|
16500
17132
|
assertOnlyAIEmployeeNestedPublicSettings(actionName, path, value, allowedKeys) {
|
|
16501
17133
|
const unsupportedKeys = Object.keys(value || {}).filter((key) => !allowedKeys.includes(key));
|
|
16502
17134
|
if (!unsupportedKeys.length) {
|
|
16503
17135
|
return;
|
|
16504
17136
|
}
|
|
16505
|
-
(0, import_errors.throwBadRequest)(
|
|
17137
|
+
(0, import_errors.throwBadRequest)(
|
|
17138
|
+
`flowSurfaces ${actionName} ${path} does not support key '${unsupportedKeys[0]}'; allowed keys: ${allowedKeys.join(", ")}; repairHint: ${this.aiEmployeeNestedRepairHint(path)}`
|
|
17139
|
+
);
|
|
16506
17140
|
}
|
|
16507
17141
|
assertNoAIEmployeeInternalPropSettings(actionName, values) {
|
|
16508
17142
|
const props = values == null ? void 0 : values.props;
|
|
@@ -16665,8 +17299,13 @@ class FlowSurfacesService {
|
|
|
16665
17299
|
return username;
|
|
16666
17300
|
}
|
|
16667
17301
|
assertAIEmployeeWorkContextType(actionName, itemPath, item) {
|
|
17302
|
+
if (!Object.prototype.hasOwnProperty.call(item, "type") || import_lodash.default.isUndefined(item.type) || item.type === null) {
|
|
17303
|
+
return;
|
|
17304
|
+
}
|
|
16668
17305
|
if (String(item.type || "").trim() !== "flow-model") {
|
|
16669
|
-
(0, import_errors.throwBadRequest)(
|
|
17306
|
+
(0, import_errors.throwBadRequest)(
|
|
17307
|
+
`flowSurfaces ${actionName} ${itemPath}.type only supports 'flow-model'; omit type to use the default flow-model context. repairHint: ${AI_EMPLOYEE_WORK_CONTEXT_REPAIR_HINT}`
|
|
17308
|
+
);
|
|
16670
17309
|
}
|
|
16671
17310
|
}
|
|
16672
17311
|
normalizeAIEmployeeWorkContext(actionName, value, options) {
|
|
@@ -17099,9 +17738,18 @@ ${AI_EMPLOYEE_CURRENT_RECORD_PROMPT_VARIABLE}` : AI_EMPLOYEE_CURRENT_RECORD_PROM
|
|
|
17099
17738
|
(0, import_errors.throwBadRequest)(`flowSurfaces ${actionName} ${options.path} must be an object`);
|
|
17100
17739
|
}
|
|
17101
17740
|
const next = import_lodash.default.pick(import_lodash.default.isPlainObject(existing) ? import_lodash.default.cloneDeep(existing) : {}, AI_EMPLOYEE_TASK_PUBLIC_SETTING_KEYS);
|
|
17741
|
+
if (Object.prototype.hasOwnProperty.call(patch, "prompt") && import_lodash.default.isPlainObject(patch.message) && Object.prototype.hasOwnProperty.call(patch.message, "user")) {
|
|
17742
|
+
(0, import_errors.throwBadRequest)(
|
|
17743
|
+
`flowSurfaces ${actionName} ${options.path} cannot set both prompt and message.user; prompt is an alias for message.user. repairHint: keep only one of ${options.path}.prompt or ${options.path}.message.user`
|
|
17744
|
+
);
|
|
17745
|
+
}
|
|
17102
17746
|
Object.entries(patch).forEach(([key, value]) => {
|
|
17103
|
-
if (!
|
|
17104
|
-
(0, import_errors.throwBadRequest)(
|
|
17747
|
+
if (!AI_EMPLOYEE_TASK_PATCH_PUBLIC_SETTING_KEYS.includes(key)) {
|
|
17748
|
+
(0, import_errors.throwBadRequest)(
|
|
17749
|
+
`flowSurfaces ${actionName} ${options.path} does not support key '${key}'; allowed keys: ${AI_EMPLOYEE_TASK_PATCH_PUBLIC_SETTING_KEYS.join(
|
|
17750
|
+
", "
|
|
17751
|
+
)}; repairHint: ${AI_EMPLOYEE_TASK_REPAIR_HINT}`
|
|
17752
|
+
);
|
|
17105
17753
|
}
|
|
17106
17754
|
if (key === "message") {
|
|
17107
17755
|
next.message = this.normalizeAIEmployeeTaskMessage(actionName, `${options.path}.message`, value, next.message, {
|
|
@@ -17110,6 +17758,18 @@ ${AI_EMPLOYEE_CURRENT_RECORD_PROMPT_VARIABLE}` : AI_EMPLOYEE_CURRENT_RECORD_PROM
|
|
|
17110
17758
|
});
|
|
17111
17759
|
return;
|
|
17112
17760
|
}
|
|
17761
|
+
if (key === "prompt") {
|
|
17762
|
+
if (typeof value !== "string") {
|
|
17763
|
+
(0, import_errors.throwBadRequest)(
|
|
17764
|
+
`flowSurfaces ${actionName} ${options.path}.prompt must be a string; repairHint: ${AI_EMPLOYEE_TASK_REPAIR_HINT}`
|
|
17765
|
+
);
|
|
17766
|
+
}
|
|
17767
|
+
next.message = {
|
|
17768
|
+
...import_lodash.default.isPlainObject(next.message) ? import_lodash.default.cloneDeep(next.message) : {},
|
|
17769
|
+
user: value
|
|
17770
|
+
};
|
|
17771
|
+
return;
|
|
17772
|
+
}
|
|
17113
17773
|
if (key === "title") {
|
|
17114
17774
|
if (typeof value !== "string") {
|
|
17115
17775
|
(0, import_errors.throwBadRequest)(`flowSurfaces ${actionName} ${options.path}.title must be a string`);
|
|
@@ -17324,6 +17984,9 @@ ${AI_EMPLOYEE_CURRENT_RECORD_PROMPT_VARIABLE}` : AI_EMPLOYEE_CURRENT_RECORD_PROM
|
|
|
17324
17984
|
}) : null);
|
|
17325
17985
|
changes = await this.normalizeActionPanelActionChanges(changes, options);
|
|
17326
17986
|
const allowedKeys = (0, import_configure_options.getConfigureOptionKeysForUse)(use);
|
|
17987
|
+
if ((0, import_service_utils.hasOwnDefined)(changes, "openView") && !allowedKeys.includes("openView") && JS_POPUP_GUIDANCE_USES.has(use)) {
|
|
17988
|
+
(0, import_errors.throwBadRequest)(withJsPopupGuidance(`flowSurfaces configure action '${use}' does not support openView`, use));
|
|
17989
|
+
}
|
|
17327
17990
|
(0, import_service_utils.assertSupportedSimpleChanges)("action", changes, allowedKeys);
|
|
17328
17991
|
if (this.isAIEmployeeActionUse(use)) {
|
|
17329
17992
|
const aiEmployeeSettingsPayload = await this.normalizeAIEmployeeActionPublicSettings(
|
|
@@ -17417,7 +18080,7 @@ ${AI_EMPLOYEE_CURRENT_RECORD_PROMPT_VARIABLE}` : AI_EMPLOYEE_CURRENT_RECORD_PROM
|
|
|
17417
18080
|
openView: import_lodash.default.cloneDeep(changes.openView)
|
|
17418
18081
|
};
|
|
17419
18082
|
} else if (!POPUP_ACTION_USES.has(use)) {
|
|
17420
|
-
(0, import_errors.throwBadRequest)(`flowSurfaces configure action '${use}' does not support openView
|
|
18083
|
+
(0, import_errors.throwBadRequest)(withJsPopupGuidance(`flowSurfaces configure action '${use}' does not support openView`, use));
|
|
17421
18084
|
} else {
|
|
17422
18085
|
let openView = import_lodash.default.cloneDeep(changes.openView);
|
|
17423
18086
|
if (use === "AddChildActionModel") {
|