@nocobase/plugin-flow-engine 2.1.0-beta.36 → 2.1.0-beta.38
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 +17 -4
- 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 +19 -8
- package/dist/server/flow-surfaces/locator.js +16 -2
- package/dist/server/flow-surfaces/runjs-authoring/ctx-libs-member-mismatch-stop/index.js +1 -1
- package/dist/server/flow-surfaces/runjs-authoring/index.js +6224 -2119
- 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 +67 -14
- package/dist/server/flow-surfaces/service.js +1316 -122
- package/dist/server/flow-surfaces/template-service-utils.d.ts +1 -0
- package/dist/swagger/flow-surfaces.d.ts +5 -2
- package/dist/swagger/flow-surfaces.examples.d.ts +11 -37
- package/dist/swagger/flow-surfaces.examples.js +6 -6
- package/dist/swagger/flow-surfaces.js +6 -3
- package/dist/swagger/index.d.ts +5 -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,16 +537,25 @@ 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"];
|
|
463
544
|
const AI_EMPLOYEE_INTERNAL_PROP_KEYS = ["aiEmployee", "context", "auto", "tasks", "style"];
|
|
545
|
+
const AI_EMPLOYEE_TASK_STEP_PARAMS_PATH = ["shortcutSettings", "editTasks", "tasks"];
|
|
464
546
|
const AI_EMPLOYEE_WORK_CONTEXT_PUBLIC_KEYS = ["type", "uid", "target"];
|
|
465
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"];
|
|
466
549
|
const AI_EMPLOYEE_TASK_MESSAGE_PUBLIC_KEYS = ["system", "user", "workContext"];
|
|
467
550
|
const AI_EMPLOYEE_TASK_MODEL_PUBLIC_KEYS = ["llmService", "model"];
|
|
468
551
|
const AI_EMPLOYEE_SKILL_SETTINGS_PUBLIC_KEYS = ["skills", "tools", "skillsVersion", "toolsVersion"];
|
|
469
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.";
|
|
555
|
+
const AI_EMPLOYEE_PROMPT_CONTEXT_MAX_DEPTH = 8;
|
|
556
|
+
const AI_EMPLOYEE_PROMPT_VARIABLE_INVALID = "FLOW_SURFACE_AI_EMPLOYEE_PROMPT_VARIABLE_INVALID";
|
|
557
|
+
const AI_EMPLOYEE_CURRENT_RECORD_PROMPT_VARIABLE = "{{ ctx.record }}";
|
|
558
|
+
const AI_EMPLOYEE_CURRENT_RECORD_PROMPT_VARIABLE_RE = /\{\{\s*ctx\.record\s*\}\}/;
|
|
470
559
|
const AI_EMPLOYEE_DEFAULT_STYLE = {
|
|
471
560
|
size: 40,
|
|
472
561
|
mask: false
|
|
@@ -710,10 +799,16 @@ class FlowSurfacesService {
|
|
|
710
799
|
);
|
|
711
800
|
}
|
|
712
801
|
async loadEnabledPluginPackages(transaction) {
|
|
713
|
-
|
|
802
|
+
var _a;
|
|
803
|
+
const db = this.db;
|
|
804
|
+
if (!((_a = db == null ? void 0 : db.getCollection) == null ? void 0 : _a.call(db, "applicationPlugins")) || !(db == null ? void 0 : db.getRepository)) {
|
|
805
|
+
return /* @__PURE__ */ new Set();
|
|
806
|
+
}
|
|
807
|
+
const repository = db.getRepository("applicationPlugins");
|
|
808
|
+
if (!(repository == null ? void 0 : repository.find)) {
|
|
714
809
|
return /* @__PURE__ */ new Set();
|
|
715
810
|
}
|
|
716
|
-
const plugins = await
|
|
811
|
+
const plugins = await repository.find({
|
|
717
812
|
fields: ["packageName"],
|
|
718
813
|
filter: {
|
|
719
814
|
enabled: true
|
|
@@ -721,8 +816,8 @@ class FlowSurfacesService {
|
|
|
721
816
|
transaction
|
|
722
817
|
});
|
|
723
818
|
const packageNames = plugins.map((plugin) => {
|
|
724
|
-
var
|
|
725
|
-
return ((
|
|
819
|
+
var _a2;
|
|
820
|
+
return ((_a2 = plugin == null ? void 0 : plugin.get) == null ? void 0 : _a2.call(plugin, "packageName")) || (plugin == null ? void 0 : plugin.packageName);
|
|
726
821
|
}).filter((packageName) => typeof packageName === "string" && !!packageName.trim()).map((packageName) => packageName.trim());
|
|
727
822
|
return new Set(packageNames);
|
|
728
823
|
}
|
|
@@ -762,6 +857,18 @@ class FlowSurfacesService {
|
|
|
762
857
|
})
|
|
763
858
|
);
|
|
764
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
|
+
}
|
|
765
872
|
async findFlowPageRoutesByParentIdAndTitle(parentId, title, transaction) {
|
|
766
873
|
const normalizedTitle = String(title || "").trim();
|
|
767
874
|
const normalizedParentId = String(parentId ?? "").trim();
|
|
@@ -843,20 +950,97 @@ class FlowSurfacesService {
|
|
|
843
950
|
...extras
|
|
844
951
|
};
|
|
845
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
|
+
}
|
|
846
1005
|
async createFlowMenuGroup(values, transaction) {
|
|
847
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);
|
|
848
1032
|
const schemaUid = values.schemaUid || (0, import_utils.uid)();
|
|
849
1033
|
const desktopRoutes = this.db.getRepository("desktopRoutes");
|
|
850
1034
|
await desktopRoutes.create({
|
|
851
1035
|
values: {
|
|
852
1036
|
type: "group",
|
|
853
1037
|
sort: this.allocateRouteSortValue(),
|
|
854
|
-
title
|
|
1038
|
+
title,
|
|
855
1039
|
icon: values.icon,
|
|
856
1040
|
tooltip: values.tooltip,
|
|
857
1041
|
schemaUid,
|
|
858
1042
|
hideInMenu: !!values.hideInMenu,
|
|
859
|
-
parentId
|
|
1043
|
+
parentId
|
|
860
1044
|
},
|
|
861
1045
|
transaction
|
|
862
1046
|
});
|
|
@@ -869,6 +1053,7 @@ class FlowSurfacesService {
|
|
|
869
1053
|
async createFlowMenuItem(values, transaction) {
|
|
870
1054
|
var _a;
|
|
871
1055
|
const parentRoute = await this.assertMenuParentIsGroup(values.parentMenuRouteId, transaction);
|
|
1056
|
+
this.assertVisibleNavigationIcon("createMenu", "values", values);
|
|
872
1057
|
const pageSchemaUid = values.pageSchemaUid || (0, import_utils.uid)();
|
|
873
1058
|
const pageUid = values.pageUid || (0, import_utils.uid)();
|
|
874
1059
|
const tabSchemaUid = values.tabSchemaUid || (0, import_utils.uid)();
|
|
@@ -2596,6 +2781,10 @@ class FlowSurfacesService {
|
|
|
2596
2781
|
),
|
|
2597
2782
|
options.transaction
|
|
2598
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
|
+
}
|
|
2599
2788
|
const publicNode = this.stripInternalSurfaceMetaFromNodeTree(import_lodash.default.cloneDeep(rawNode));
|
|
2600
2789
|
return this.buildSurfaceReadPayload(target, resolved, publicNode, options);
|
|
2601
2790
|
}
|
|
@@ -2767,13 +2956,13 @@ class FlowSurfacesService {
|
|
|
2767
2956
|
if (!groupTitle) {
|
|
2768
2957
|
return document;
|
|
2769
2958
|
}
|
|
2770
|
-
const matchedRoutes = await this.
|
|
2959
|
+
const matchedRoutes = await this.findMenuGroupRoutesByParentIdAndTitle(null, groupTitle, transaction);
|
|
2771
2960
|
if (!matchedRoutes.length) {
|
|
2772
2961
|
return document;
|
|
2773
2962
|
}
|
|
2774
2963
|
if (matchedRoutes.length > 1) {
|
|
2775
2964
|
(0, import_errors.throwBadRequest)(
|
|
2776
|
-
`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`
|
|
2777
2966
|
);
|
|
2778
2967
|
}
|
|
2779
2968
|
const routeId = this.readRouteField(matchedRoutes[0], "id");
|
|
@@ -2843,6 +3032,22 @@ class FlowSurfacesService {
|
|
|
2843
3032
|
getCollection: (dataSourceKey, collectionName) => this.getCollection(dataSourceKey || "main", collectionName || "")
|
|
2844
3033
|
});
|
|
2845
3034
|
}
|
|
3035
|
+
async prevalidateApplyBlueprintChartAssets(document, transaction) {
|
|
3036
|
+
var _a;
|
|
3037
|
+
const chartAssets = import_lodash.default.isPlainObject((_a = document.assets) == null ? void 0 : _a.charts) ? document.assets.charts : {};
|
|
3038
|
+
for (const [chartKey, chartAsset] of Object.entries(chartAssets)) {
|
|
3039
|
+
if (!import_lodash.default.isPlainObject(chartAsset)) {
|
|
3040
|
+
continue;
|
|
3041
|
+
}
|
|
3042
|
+
(0, import_service_utils.assertSupportedSimpleChanges)("chart", chartAsset, (0, import_configure_options.getConfigureOptionKeysForUse)("ChartBlockModel"));
|
|
3043
|
+
const nextConfigure = (0, import_chart_config.buildChartConfigureFromSemanticChanges)(void 0, chartAsset);
|
|
3044
|
+
await this.validateChartConfigureForRuntime(
|
|
3045
|
+
`applyBlueprint assets.charts.${chartKey}`,
|
|
3046
|
+
nextConfigure,
|
|
3047
|
+
transaction
|
|
3048
|
+
);
|
|
3049
|
+
}
|
|
3050
|
+
}
|
|
2846
3051
|
getApplyBlueprintKanbanBlockResourceObject(block) {
|
|
2847
3052
|
return import_lodash.default.isPlainObject(block == null ? void 0 : block.resource) ? block.resource : {};
|
|
2848
3053
|
}
|
|
@@ -3231,25 +3436,48 @@ class FlowSurfacesService {
|
|
|
3231
3436
|
}
|
|
3232
3437
|
if (!options.transaction) {
|
|
3233
3438
|
const createdKanbanSortFields = [];
|
|
3234
|
-
|
|
3235
|
-
|
|
3236
|
-
|
|
3237
|
-
|
|
3238
|
-
|
|
3239
|
-
|
|
3240
|
-
|
|
3241
|
-
|
|
3242
|
-
|
|
3243
|
-
|
|
3439
|
+
const mutationResult = await this.applyBlueprintMutationWithoutExternalTransaction(
|
|
3440
|
+
values,
|
|
3441
|
+
options,
|
|
3442
|
+
createdKanbanSortFields
|
|
3443
|
+
);
|
|
3444
|
+
const surface = await this.get(mutationResult.pageLocator, { currentRoles: options.currentRoles });
|
|
3445
|
+
return this.buildApplyBlueprintResponse(mutationResult.mode, mutationResult.pageLocator, surface);
|
|
3446
|
+
}
|
|
3447
|
+
}
|
|
3448
|
+
async applyBlueprintMutationWithoutExternalTransaction(values, options = {}, createdKanbanSortFields) {
|
|
3449
|
+
try {
|
|
3450
|
+
await this.assertApplyBlueprintAuthoringPayload(values, options);
|
|
3451
|
+
const document = (0, import_blueprint.prepareFlowSurfaceApplyBlueprintDocument)(values);
|
|
3452
|
+
await this.prevalidateApplyBlueprintChartAssets(document);
|
|
3453
|
+
if (document.mode === "create") {
|
|
3454
|
+
return await this.applyBlueprintWithTransaction(
|
|
3455
|
+
values,
|
|
3456
|
+
{ ...options, skipAuthoringValidation: true },
|
|
3457
|
+
createdKanbanSortFields,
|
|
3458
|
+
{
|
|
3459
|
+
readSurface: false
|
|
3460
|
+
}
|
|
3244
3461
|
);
|
|
3245
|
-
} catch (error) {
|
|
3246
|
-
await this.cleanupApplyBlueprintKanbanSortFields(createdKanbanSortFields);
|
|
3247
|
-
throw error;
|
|
3248
3462
|
}
|
|
3463
|
+
return await this.transaction(
|
|
3464
|
+
(transaction) => this.applyBlueprintWithTransaction(
|
|
3465
|
+
values,
|
|
3466
|
+
{
|
|
3467
|
+
...options,
|
|
3468
|
+
transaction,
|
|
3469
|
+
skipAuthoringValidation: true
|
|
3470
|
+
},
|
|
3471
|
+
createdKanbanSortFields,
|
|
3472
|
+
{ readSurface: false }
|
|
3473
|
+
)
|
|
3474
|
+
);
|
|
3475
|
+
} catch (error) {
|
|
3476
|
+
await this.cleanupApplyBlueprintKanbanSortFields(createdKanbanSortFields);
|
|
3477
|
+
throw error;
|
|
3249
3478
|
}
|
|
3250
3479
|
}
|
|
3251
|
-
async
|
|
3252
|
-
var _a;
|
|
3480
|
+
async assertApplyBlueprintAuthoringPayload(values, options = {}) {
|
|
3253
3481
|
const enabledPackages = await this.resolveEnabledPluginPackages(options);
|
|
3254
3482
|
await (0, import_authoring_validation.assertFlowSurfaceAuthoringPayload)("applyBlueprint", values, {
|
|
3255
3483
|
transaction: options.transaction,
|
|
@@ -3257,6 +3485,11 @@ class FlowSurfacesService {
|
|
|
3257
3485
|
findMenuGroupRoutesByTitle: (title, transaction) => this.findMenuGroupRoutesByTitle(title, transaction),
|
|
3258
3486
|
getCollection: (dataSourceKey, collectionName) => this.getCollection(dataSourceKey || "main", collectionName || "")
|
|
3259
3487
|
});
|
|
3488
|
+
}
|
|
3489
|
+
async applyBlueprintWithTransaction(values, options = {}, createdKanbanSortFields, resultOptions = {}) {
|
|
3490
|
+
if (options.skipAuthoringValidation !== true) {
|
|
3491
|
+
await this.assertApplyBlueprintAuthoringPayload(values, options);
|
|
3492
|
+
}
|
|
3260
3493
|
const prepared = await this.prepareApplyBlueprintRequest(values, options.transaction, createdKanbanSortFields);
|
|
3261
3494
|
const popupTemplateAliasSession = this.createPopupTemplateAliasSession();
|
|
3262
3495
|
const popupTemplateTreeCache = /* @__PURE__ */ new Map();
|
|
@@ -3277,10 +3510,27 @@ class FlowSurfacesService {
|
|
|
3277
3510
|
options
|
|
3278
3511
|
);
|
|
3279
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
|
+
});
|
|
3519
|
+
if (resultOptions.readSurface === false) {
|
|
3520
|
+
return {
|
|
3521
|
+
version: "1",
|
|
3522
|
+
mode: prepared.document.mode,
|
|
3523
|
+
pageLocator
|
|
3524
|
+
};
|
|
3525
|
+
}
|
|
3280
3526
|
const surface = await this.get(pageLocator, options);
|
|
3527
|
+
return this.buildApplyBlueprintResponse(prepared.document.mode, pageLocator, surface);
|
|
3528
|
+
}
|
|
3529
|
+
buildApplyBlueprintResponse(mode, pageLocator, surface) {
|
|
3530
|
+
var _a;
|
|
3281
3531
|
return {
|
|
3282
3532
|
version: "1",
|
|
3283
|
-
mode
|
|
3533
|
+
mode,
|
|
3284
3534
|
target: (0, import_service_utils.buildDefinedPayload)({
|
|
3285
3535
|
pageSchemaUid: pageLocator.pageSchemaUid,
|
|
3286
3536
|
pageUid: (_a = surface == null ? void 0 : surface.target) == null ? void 0 : _a.uid
|
|
@@ -3942,8 +4192,8 @@ class FlowSurfacesService {
|
|
|
3942
4192
|
stepParams: (0, import_template_service_utils.buildFlowTemplateReferenceBlockStepParams)(template, templateTargetUid, init)
|
|
3943
4193
|
};
|
|
3944
4194
|
}
|
|
3945
|
-
buildPopupTemplateReferenceOpenView(template, templateTargetUid) {
|
|
3946
|
-
return this.buildPopupTemplateOpenView(template, "reference", templateTargetUid);
|
|
4195
|
+
buildPopupTemplateReferenceOpenView(template, templateTargetUid, options = {}) {
|
|
4196
|
+
return this.buildPopupTemplateOpenView(template, "reference", templateTargetUid, options);
|
|
3947
4197
|
}
|
|
3948
4198
|
shouldHydrateDetachedPopupTemplateBlockResourceContext(blockNode, context) {
|
|
3949
4199
|
if (!this.isCollectionBlockUse(blockNode == null ? void 0 : blockNode.use) || !context.associationName || !context.sourceId) {
|
|
@@ -4293,15 +4543,35 @@ class FlowSurfacesService {
|
|
|
4293
4543
|
}
|
|
4294
4544
|
const nextStepParams = import_lodash.default.cloneDeep(sourceNode.stepParams || {});
|
|
4295
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
|
+
}
|
|
4296
4569
|
let nextOpenView = {
|
|
4297
|
-
...
|
|
4298
|
-
|
|
4299
|
-
|
|
4300
|
-
|
|
4301
|
-
|
|
4302
|
-
"popupTemplateHasSourceId"
|
|
4303
|
-
]),
|
|
4304
|
-
...this.buildPopupTemplateReferenceOpenView(template, templateTargetUid)
|
|
4570
|
+
...currentOpenView,
|
|
4571
|
+
...this.buildPopupTemplateReferenceOpenView(template, templateTargetUid, {
|
|
4572
|
+
filterTargetKey,
|
|
4573
|
+
useRuntimeRecordFilterByTk
|
|
4574
|
+
})
|
|
4305
4575
|
};
|
|
4306
4576
|
if (String(sourceNode.use || "").trim() === "AddChildActionModel") {
|
|
4307
4577
|
nextOpenView = await this.normalizeAddChildOpenViewForAction(sourceNode, nextOpenView, transaction);
|
|
@@ -5043,6 +5313,13 @@ class FlowSurfacesService {
|
|
|
5043
5313
|
});
|
|
5044
5314
|
for (const [blockIndex, block] of result.blocks.entries()) {
|
|
5045
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
|
+
}
|
|
5046
5323
|
if ((blockSpec == null ? void 0 : blockSpec.type) === "table") {
|
|
5047
5324
|
const appliedTreeTableDefaults = await this.applyTreeTableCreatedBlockDefaults(
|
|
5048
5325
|
{
|
|
@@ -5176,7 +5453,7 @@ class FlowSurfacesService {
|
|
|
5176
5453
|
if ((current == null ? void 0 : current.use) === "DividerItemModel") {
|
|
5177
5454
|
return this.configureDividerItem(target, changes, options);
|
|
5178
5455
|
}
|
|
5179
|
-
return this.configureJSItem(target, changes, options);
|
|
5456
|
+
return this.configureJSItem(target, changes, { ...options, currentUse: (current == null ? void 0 : current.use) || "JSItemModel" });
|
|
5180
5457
|
}
|
|
5181
5458
|
if ((0, import_service_utils.isFieldNodeUse)(current == null ? void 0 : current.use)) {
|
|
5182
5459
|
return this.configureFieldNode(target, changes, configureOptions);
|
|
@@ -5251,6 +5528,7 @@ class FlowSurfacesService {
|
|
|
5251
5528
|
if (!this.isBindableMenuRoutePendingInitialization(route, structure)) {
|
|
5252
5529
|
(0, import_errors.throwBadRequest)(`flowSurfaces createPage does not allow re-initializing menu route '${routeId}'`);
|
|
5253
5530
|
}
|
|
5531
|
+
this.assertVisibleNavigationRouteIconUpdate("createPage", "values", route, values);
|
|
5254
5532
|
const existingPage = structure.pageModel;
|
|
5255
5533
|
const enableTabs = !!values.enableTabs;
|
|
5256
5534
|
const displayTitle = values.displayTitle !== false;
|
|
@@ -6330,7 +6608,7 @@ class FlowSurfacesService {
|
|
|
6330
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",
|
|
6331
6609
|
type: catalogItem.key || values.type,
|
|
6332
6610
|
fields: values.fields,
|
|
6333
|
-
fieldsLayout: values.fieldsLayout
|
|
6611
|
+
...Object.prototype.hasOwnProperty.call(values || {}, "fieldsLayout") ? { fieldsLayout: values.fieldsLayout } : {}
|
|
6334
6612
|
},
|
|
6335
6613
|
0,
|
|
6336
6614
|
enabledPackages,
|
|
@@ -6524,6 +6802,8 @@ class FlowSurfacesService {
|
|
|
6524
6802
|
...fieldSpec.popupSize ? { popupSize: fieldSpec.popupSize } : {},
|
|
6525
6803
|
...!import_lodash.default.isUndefined(fieldSpec.pageSize) ? { pageSize: fieldSpec.pageSize } : {},
|
|
6526
6804
|
...!import_lodash.default.isUndefined(fieldSpec.showIndex) ? { showIndex: fieldSpec.showIndex } : {},
|
|
6805
|
+
...fieldSpec.defaultTargetUid ? { defaultTargetUid: fieldSpec.defaultTargetUid } : {},
|
|
6806
|
+
...fieldSpec.targetBlockUid ? { targetBlockUid: fieldSpec.targetBlockUid } : {},
|
|
6527
6807
|
...fieldSpec.popup ? { popup: fieldSpec.popup } : {},
|
|
6528
6808
|
...fieldSpec.__autoPopupForRelationField ? { __autoPopupForRelationField: true } : {},
|
|
6529
6809
|
...fieldSpec[import_defaults.FLOW_SURFACE_APPLY_BLUEPRINT_POPUP_DEFAULTS_KEY] ? {
|
|
@@ -6598,6 +6878,13 @@ class FlowSurfacesService {
|
|
|
6598
6878
|
enabledPackages
|
|
6599
6879
|
}
|
|
6600
6880
|
);
|
|
6881
|
+
if (catalogItem.use === "TableBlockModel" && !options.skipDefaultBlockActions) {
|
|
6882
|
+
await this.ensureTableDefaultActionIntegrity(created, {
|
|
6883
|
+
...options,
|
|
6884
|
+
enabledPackages,
|
|
6885
|
+
popupTemplateTreeCache: options.popupTemplateTreeCache
|
|
6886
|
+
});
|
|
6887
|
+
}
|
|
6601
6888
|
if (!options.deferAutoLayout && (initialGrid == null ? void 0 : initialGrid.uid)) {
|
|
6602
6889
|
const finalGrid = await this.repository.findModelById(parentUid, {
|
|
6603
6890
|
transaction: options.transaction,
|
|
@@ -6665,7 +6952,9 @@ class FlowSurfacesService {
|
|
|
6665
6952
|
(0, import_errors.throwBadRequest)("flowSurfaces fieldType is only supported for relation fields");
|
|
6666
6953
|
}
|
|
6667
6954
|
if (inlinePopup) {
|
|
6668
|
-
(0, import_errors.throwBadRequest)(
|
|
6955
|
+
(0, import_errors.throwBadRequest)(
|
|
6956
|
+
withJsPopupGuidance(`flowSurfaces addField type '${values.type}' does not support popup`, values.type)
|
|
6957
|
+
);
|
|
6669
6958
|
}
|
|
6670
6959
|
if (isFilterFormItem) {
|
|
6671
6960
|
(0, import_errors.throwBadRequest)(`flowSurfaces addField type '${values.type}' is not allowed under filter-form`);
|
|
@@ -6860,9 +7149,18 @@ class FlowSurfacesService {
|
|
|
6860
7149
|
}
|
|
6861
7150
|
}
|
|
6862
7151
|
if (inlinePopup && !this.isPopupFieldHostUse(boundFieldCapability.fieldUse)) {
|
|
6863
|
-
(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
|
+
);
|
|
6864
7158
|
}
|
|
6865
|
-
|
|
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) {
|
|
6866
7164
|
const popupDefaultsMetadata = values[import_defaults.FLOW_SURFACE_APPLY_BLUEPRINT_POPUP_DEFAULTS_KEY];
|
|
6867
7165
|
inlinePopup = this.normalizeInlinePopup("addField", {
|
|
6868
7166
|
tryTemplate: true,
|
|
@@ -6872,9 +7170,19 @@ class FlowSurfacesService {
|
|
|
6872
7170
|
} : {}
|
|
6873
7171
|
});
|
|
6874
7172
|
}
|
|
6875
|
-
|
|
6876
|
-
|
|
6877
|
-
|
|
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) {
|
|
6878
7186
|
(0, import_errors.throwBadRequest)(`flowSurfaces addField popup cannot be combined with external openView.uid`);
|
|
6879
7187
|
}
|
|
6880
7188
|
const defaultFieldState = (0, import_service_utils.buildDefaultFieldState)(
|
|
@@ -7013,7 +7321,12 @@ class FlowSurfacesService {
|
|
|
7013
7321
|
);
|
|
7014
7322
|
}
|
|
7015
7323
|
if (inlinePopup && !POPUP_ACTION_USES.has(actionCatalogItem.use)) {
|
|
7016
|
-
(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
|
+
);
|
|
7017
7330
|
}
|
|
7018
7331
|
await this.assertApprovalActionSingleton(container.parentUid, actionCatalogItem.use, options.transaction);
|
|
7019
7332
|
(0, import_action_scope.assertRequestedActionScope)({
|
|
@@ -7041,20 +7354,42 @@ class FlowSurfacesService {
|
|
|
7041
7354
|
return result2;
|
|
7042
7355
|
}
|
|
7043
7356
|
const resourceContext = container.ownerUid ? await this.locator.resolveCollectionContext(container.ownerUid, options.transaction).catch(() => null) : null;
|
|
7044
|
-
const
|
|
7357
|
+
const aiEmployeeSettingsPayload = this.isAIEmployeeActionUse(actionCatalogItem.use) ? await this.normalizeAIEmployeeActionPublicSettings("addAction", inlineSettings || {}, {
|
|
7045
7358
|
transaction: options.transaction,
|
|
7046
7359
|
enabledPackages,
|
|
7047
7360
|
requireUsername: true,
|
|
7048
7361
|
currentRoles: options.currentRoles,
|
|
7049
|
-
selfUid: container.ownerUid
|
|
7362
|
+
selfUid: container.ownerUid,
|
|
7363
|
+
promptContext: {
|
|
7364
|
+
kind: "container",
|
|
7365
|
+
ownerUid: container.ownerUid,
|
|
7366
|
+
scope: resolvedScope
|
|
7367
|
+
}
|
|
7050
7368
|
}) : void 0;
|
|
7369
|
+
const actionSettingsPayload = {
|
|
7370
|
+
props: values.props,
|
|
7371
|
+
stepParams: values.stepParams
|
|
7372
|
+
};
|
|
7373
|
+
if (aiEmployeeSettingsPayload) {
|
|
7374
|
+
this.mergeAIEmployeeActionSettingsPayload(
|
|
7375
|
+
{ use: actionCatalogItem.use },
|
|
7376
|
+
actionSettingsPayload,
|
|
7377
|
+
aiEmployeeSettingsPayload
|
|
7378
|
+
);
|
|
7379
|
+
await this.assertNoDuplicateAIEmployeeAction(
|
|
7380
|
+
"addAction",
|
|
7381
|
+
container.parentUid,
|
|
7382
|
+
actionSettingsPayload,
|
|
7383
|
+
options.transaction
|
|
7384
|
+
);
|
|
7385
|
+
}
|
|
7051
7386
|
const action = (0, import_builder.buildActionTree)({
|
|
7052
7387
|
use: actionCatalogItem.use,
|
|
7053
7388
|
containerUse: container.ownerUse,
|
|
7054
7389
|
resourceInit: values.resourceInit || (resourceContext == null ? void 0 : resourceContext.resourceInit),
|
|
7055
|
-
props:
|
|
7390
|
+
props: actionSettingsPayload.props,
|
|
7056
7391
|
decoratorProps: values.decoratorProps,
|
|
7057
|
-
stepParams:
|
|
7392
|
+
stepParams: actionSettingsPayload.stepParams,
|
|
7058
7393
|
flowRegistry: values.flowRegistry
|
|
7059
7394
|
});
|
|
7060
7395
|
this.contractGuard.validateNodeTreeAgainstContract(action);
|
|
@@ -7109,7 +7444,12 @@ class FlowSurfacesService {
|
|
|
7109
7444
|
);
|
|
7110
7445
|
const resolvedScope = actionCatalogItem.scope;
|
|
7111
7446
|
if (inlinePopup && !POPUP_ACTION_USES.has(actionCatalogItem.use)) {
|
|
7112
|
-
(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
|
+
);
|
|
7113
7453
|
}
|
|
7114
7454
|
if (this.isAddChildCatalogItem(actionCatalogItem)) {
|
|
7115
7455
|
await this.assertAddChildSupportedForOwnerNode(container.ownerNode, "addRecordAction", options.transaction);
|
|
@@ -7141,20 +7481,42 @@ class FlowSurfacesService {
|
|
|
7141
7481
|
}
|
|
7142
7482
|
const resourceContext = container.ownerUid ? await this.locator.resolveCollectionContext(container.ownerUid, options.transaction).catch(() => null) : null;
|
|
7143
7483
|
const resourceInit = this.isAddChildCatalogItem(actionCatalogItem) ? await this.resolveAddChildResourceInitForOwnerNode(container.ownerNode, options.transaction) : values.resourceInit || (resourceContext == null ? void 0 : resourceContext.resourceInit);
|
|
7144
|
-
const
|
|
7484
|
+
const aiEmployeeSettingsPayload = this.isAIEmployeeActionUse(actionCatalogItem.use) ? await this.normalizeAIEmployeeActionPublicSettings("addRecordAction", inlineSettings || {}, {
|
|
7145
7485
|
transaction: options.transaction,
|
|
7146
7486
|
enabledPackages,
|
|
7147
7487
|
requireUsername: true,
|
|
7148
7488
|
currentRoles: options.currentRoles,
|
|
7149
|
-
selfUid: container.ownerUid
|
|
7489
|
+
selfUid: container.ownerUid,
|
|
7490
|
+
promptContext: {
|
|
7491
|
+
kind: "container",
|
|
7492
|
+
ownerUid: container.ownerUid,
|
|
7493
|
+
scope: resolvedScope
|
|
7494
|
+
}
|
|
7150
7495
|
}) : void 0;
|
|
7496
|
+
const actionSettingsPayload = {
|
|
7497
|
+
props: values.props,
|
|
7498
|
+
stepParams: values.stepParams
|
|
7499
|
+
};
|
|
7500
|
+
if (aiEmployeeSettingsPayload) {
|
|
7501
|
+
this.mergeAIEmployeeActionSettingsPayload(
|
|
7502
|
+
{ use: actionCatalogItem.use },
|
|
7503
|
+
actionSettingsPayload,
|
|
7504
|
+
aiEmployeeSettingsPayload
|
|
7505
|
+
);
|
|
7506
|
+
await this.assertNoDuplicateAIEmployeeAction(
|
|
7507
|
+
"addRecordAction",
|
|
7508
|
+
materializedContainer.parentUid,
|
|
7509
|
+
actionSettingsPayload,
|
|
7510
|
+
options.transaction
|
|
7511
|
+
);
|
|
7512
|
+
}
|
|
7151
7513
|
const action = (0, import_builder.buildActionTree)({
|
|
7152
7514
|
use: actionCatalogItem.use,
|
|
7153
7515
|
containerUse: container.containerUse,
|
|
7154
7516
|
resourceInit,
|
|
7155
|
-
props:
|
|
7517
|
+
props: actionSettingsPayload.props,
|
|
7156
7518
|
decoratorProps: values.decoratorProps,
|
|
7157
|
-
stepParams:
|
|
7519
|
+
stepParams: actionSettingsPayload.stepParams,
|
|
7158
7520
|
flowRegistry: values.flowRegistry
|
|
7159
7521
|
});
|
|
7160
7522
|
this.contractGuard.validateNodeTreeAgainstContract(action);
|
|
@@ -8083,6 +8445,17 @@ class FlowSurfacesService {
|
|
|
8083
8445
|
const { fieldChanges } = (0, import_service_utils.splitComposeFieldChanges)(settings, wrapperUse);
|
|
8084
8446
|
return fieldChanges.openView;
|
|
8085
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
|
+
}
|
|
8086
8459
|
async assertOpenViewUidTarget(actionName, uid2, options = {}) {
|
|
8087
8460
|
const targetNode = await this.repository.findModelById(uid2, {
|
|
8088
8461
|
transaction: options.transaction,
|
|
@@ -8613,15 +8986,71 @@ class FlowSurfacesService {
|
|
|
8613
8986
|
sourceId: String(template.sourceId || "").trim() || void 0
|
|
8614
8987
|
};
|
|
8615
8988
|
}
|
|
8616
|
-
|
|
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 = {}) {
|
|
8617
9045
|
const popupTemplateHasFilterByTk = !!String(template.filterByTk || "").trim();
|
|
8618
9046
|
const popupTemplateHasSourceId = !!String(template.sourceId || "").trim() || !!String(template.associationName || "").trim();
|
|
9047
|
+
const omitRuntimeRecordFilterByTk = options.useRuntimeRecordFilterByTk === true && this.shouldOmitRuntimeRecordFilterByTk(template.filterByTk, { filterTargetKey: options.filterTargetKey });
|
|
8619
9048
|
const base = (0, import_service_utils.buildDefinedPayload)({
|
|
8620
9049
|
uid: uidValue,
|
|
8621
9050
|
dataSourceKey: template.dataSourceKey,
|
|
8622
9051
|
collectionName: template.collectionName,
|
|
8623
9052
|
associationName: template.associationName,
|
|
8624
|
-
...popupTemplateHasFilterByTk ? { filterByTk: template.filterByTk } : {},
|
|
9053
|
+
...popupTemplateHasFilterByTk && !omitRuntimeRecordFilterByTk ? { filterByTk: template.filterByTk } : {},
|
|
8625
9054
|
...popupTemplateHasSourceId && template.sourceId ? { sourceId: template.sourceId } : {},
|
|
8626
9055
|
popupTemplateHasFilterByTk,
|
|
8627
9056
|
popupTemplateHasSourceId,
|
|
@@ -8694,7 +9123,7 @@ class FlowSurfacesService {
|
|
|
8694
9123
|
}
|
|
8695
9124
|
}
|
|
8696
9125
|
async normalizeOpenView(actionName, openView, options = {}) {
|
|
8697
|
-
var _a;
|
|
9126
|
+
var _a, _b, _c, _d;
|
|
8698
9127
|
if (import_lodash.default.isUndefined(openView) || import_lodash.default.isNull(openView)) {
|
|
8699
9128
|
return openView;
|
|
8700
9129
|
}
|
|
@@ -8761,17 +9190,39 @@ class FlowSurfacesService {
|
|
|
8761
9190
|
if (templateRef.mode === "copy") {
|
|
8762
9191
|
await this.ensurePopupSurface(resolvedUid, options.transaction);
|
|
8763
9192
|
}
|
|
8764
|
-
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
|
+
});
|
|
8765
9206
|
Object.keys(normalizedOpenView).forEach((key) => {
|
|
8766
9207
|
if (key === "template" || key === "popupTemplateUid" || key === "popupTemplateMode" || key === "popupTemplateContext" || key === "popupTemplateHasFilterByTk" || key === "popupTemplateHasSourceId") {
|
|
8767
9208
|
delete normalizedOpenView[key];
|
|
8768
9209
|
}
|
|
8769
9210
|
});
|
|
9211
|
+
if (((_d = options.popupActionContext) == null ? void 0 : _d.hasCurrentRecord) === true && this.shouldOmitRuntimeRecordFilterByTk(normalizedOpenView.filterByTk, {
|
|
9212
|
+
filterTargetKey
|
|
9213
|
+
})) {
|
|
9214
|
+
delete normalizedOpenView.filterByTk;
|
|
9215
|
+
}
|
|
8770
9216
|
if (String(options.popupTemplateHostUse || "").trim() === "AddChildActionModel") {
|
|
8771
9217
|
nextTemplateOpenView = import_lodash.default.omit(nextTemplateOpenView, ["sourceId"]);
|
|
8772
9218
|
}
|
|
8773
9219
|
Object.assign(normalizedOpenView, nextTemplateOpenView);
|
|
8774
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
|
+
}
|
|
8775
9226
|
if (!import_lodash.default.isUndefined(normalizedOpenView.uid)) {
|
|
8776
9227
|
const normalizedUid = String(normalizedOpenView.uid || "").trim();
|
|
8777
9228
|
if (!normalizedUid) {
|
|
@@ -8812,7 +9263,8 @@ class FlowSurfacesService {
|
|
|
8812
9263
|
return void 0;
|
|
8813
9264
|
}
|
|
8814
9265
|
return {
|
|
8815
|
-
hasCurrentRecord: true
|
|
9266
|
+
hasCurrentRecord: true,
|
|
9267
|
+
currentRecordFilterTargetKey: await this.resolvePopupHostCurrentRecordFilterTargetKey(current.uid, transaction)
|
|
8816
9268
|
};
|
|
8817
9269
|
}
|
|
8818
9270
|
unsetPayloadPathAndPruneEmptyParents(payload, path) {
|
|
@@ -8970,7 +9422,12 @@ class FlowSurfacesService {
|
|
|
8970
9422
|
return {};
|
|
8971
9423
|
}
|
|
8972
9424
|
if (input.popup && !this.isPopupFieldHostUse(fieldNode.use)) {
|
|
8973
|
-
(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
|
+
);
|
|
8974
9431
|
}
|
|
8975
9432
|
let openView = this.resolvePopupHostOpenView(fieldNode);
|
|
8976
9433
|
if (input.popup && this.isExternalPopupOpenView(openView, fieldHostUid)) {
|
|
@@ -9296,6 +9753,20 @@ class FlowSurfacesService {
|
|
|
9296
9753
|
isEmptyInlinePopupPayload(popup) {
|
|
9297
9754
|
return import_lodash.default.isPlainObject(popup) && Object.keys(popup).length === 0;
|
|
9298
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
|
+
}
|
|
9299
9770
|
shouldAutoCompleteDefaultFieldPopup(fieldNode, popup, wrapperNode) {
|
|
9300
9771
|
if (!import_lodash.default.isPlainObject(popup)) {
|
|
9301
9772
|
return false;
|
|
@@ -9310,7 +9781,7 @@ class FlowSurfacesService {
|
|
|
9310
9781
|
if (!String(fieldContext.collectionName || "").trim()) {
|
|
9311
9782
|
return false;
|
|
9312
9783
|
}
|
|
9313
|
-
return popup.tryTemplate === true || !import_lodash.default.isUndefined(popup.defaultType) ||
|
|
9784
|
+
return popup.tryTemplate === true || !import_lodash.default.isUndefined(popup.defaultType) || this.isInlineFieldPopupDefaultShell(popup);
|
|
9314
9785
|
}
|
|
9315
9786
|
isInlineFieldPopupBlockMissingResource(block) {
|
|
9316
9787
|
if (!import_lodash.default.isPlainObject(block) || !import_lodash.default.isUndefined(block.template)) {
|
|
@@ -10372,14 +10843,21 @@ class FlowSurfacesService {
|
|
|
10372
10843
|
actionNode,
|
|
10373
10844
|
options.transaction
|
|
10374
10845
|
).catch(() => null);
|
|
10375
|
-
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;
|
|
10376
10854
|
const defaultFilterByTk = this.resolvePopupCurrentRecordResourceFilterByTk(popupProfile);
|
|
10377
10855
|
const currentFilterByTk = import_lodash.default.isString(currentOpenView.filterByTk) ? currentOpenView.filterByTk.trim() : "";
|
|
10378
|
-
const preserveCustomFilterByTk = currentFilterByTk &&
|
|
10856
|
+
const preserveCustomFilterByTk = currentFilterByTk && !this.shouldOmitRuntimeRecordFilterByTk(currentOpenView.filterByTk, { filterTargetKey: filterTargetKey || "" });
|
|
10379
10857
|
const nextOpenView = (0, import_service_utils.buildDefinedPayload)({
|
|
10380
|
-
...currentOpenView,
|
|
10858
|
+
...useRuntimeRecordFilterByTk && !preserveCustomFilterByTk ? import_lodash.default.omit(currentOpenView, ["filterByTk"]) : currentOpenView,
|
|
10381
10859
|
title: openViewTitle,
|
|
10382
|
-
filterByTk: preserveCustomFilterByTk ? currentOpenView.filterByTk : defaultFilterByTk || currentOpenView.filterByTk
|
|
10860
|
+
filterByTk: useRuntimeRecordFilterByTk ? preserveCustomFilterByTk ? currentOpenView.filterByTk : void 0 : preserveCustomFilterByTk ? currentOpenView.filterByTk : defaultFilterByTk || currentOpenView.filterByTk
|
|
10383
10861
|
});
|
|
10384
10862
|
if (import_lodash.default.isEqual(nextOpenView, currentOpenView)) {
|
|
10385
10863
|
return;
|
|
@@ -10641,7 +11119,7 @@ class FlowSurfacesService {
|
|
|
10641
11119
|
}
|
|
10642
11120
|
if (this.isAIEmployeeActionUse(current == null ? void 0 : current.use) && this.hasAIEmployeePublicSettings(normalizedValues)) {
|
|
10643
11121
|
const enabledPackages = await this.resolveEnabledPluginPackages(options);
|
|
10644
|
-
const
|
|
11122
|
+
const aiEmployeeSettingsPayload = await this.normalizeAIEmployeeActionPublicSettings(
|
|
10645
11123
|
"updateSettings",
|
|
10646
11124
|
import_lodash.default.pick(normalizedValues, AI_EMPLOYEE_PUBLIC_SETTING_KEYS),
|
|
10647
11125
|
{
|
|
@@ -10649,13 +11127,17 @@ class FlowSurfacesService {
|
|
|
10649
11127
|
enabledPackages,
|
|
10650
11128
|
current,
|
|
10651
11129
|
currentRoles: options.currentRoles,
|
|
10652
|
-
selfUid: await this.resolveAIEmployeeActionSelfUid(current, options.transaction)
|
|
11130
|
+
selfUid: await this.resolveAIEmployeeActionSelfUid(current, options.transaction),
|
|
11131
|
+
promptContext: {
|
|
11132
|
+
kind: "target",
|
|
11133
|
+
targetUid: (current == null ? void 0 : current.uid) || writeTarget.uid
|
|
11134
|
+
}
|
|
10653
11135
|
}
|
|
10654
11136
|
);
|
|
10655
11137
|
AI_EMPLOYEE_PUBLIC_SETTING_KEYS.forEach((key) => {
|
|
10656
11138
|
delete normalizedValues[key];
|
|
10657
11139
|
});
|
|
10658
|
-
|
|
11140
|
+
this.mergeAIEmployeeActionSettingsPayload(current, normalizedValues, aiEmployeeSettingsPayload);
|
|
10659
11141
|
}
|
|
10660
11142
|
assertNoFlowSurfaceIdTitleFieldSettings(normalizedValues, {
|
|
10661
11143
|
action: "updateSettings",
|
|
@@ -10703,6 +11185,14 @@ class FlowSurfacesService {
|
|
|
10703
11185
|
nextPayload,
|
|
10704
11186
|
options.replaceRecordHistorySettings === true
|
|
10705
11187
|
);
|
|
11188
|
+
this.syncAIEmployeeTaskStepParamsForUpdateSettings(current, nextPayload);
|
|
11189
|
+
await this.normalizeAIEmployeeStepParamTasksForUpdateSettings(current, nextPayload, writeTarget, options);
|
|
11190
|
+
await this.assertAIEmployeeStepParamTaskPromptVariablesAllowedForUpdateSettings(
|
|
11191
|
+
current,
|
|
11192
|
+
nextPayload,
|
|
11193
|
+
writeTarget,
|
|
11194
|
+
options
|
|
11195
|
+
);
|
|
10706
11196
|
this.syncCalendarPopupPropsForUpdateSettings(current, normalizedValues, nextPayload);
|
|
10707
11197
|
this.syncKanbanPopupPropsForUpdateSettings(current, normalizedValues, nextPayload);
|
|
10708
11198
|
this.syncDefaultSortingForUpdateSettings(current, normalizedValues, nextPayload);
|
|
@@ -11590,7 +12080,12 @@ class FlowSurfacesService {
|
|
|
11590
12080
|
}
|
|
11591
12081
|
if (!((_c = sqlPreview.queryOutputs) == null ? void 0 : _c.length)) {
|
|
11592
12082
|
(0, import_errors.throwBadRequest)(
|
|
11593
|
-
|
|
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
|
+
}
|
|
11594
12089
|
);
|
|
11595
12090
|
}
|
|
11596
12091
|
const supportedOutputs = new Set(
|
|
@@ -11599,7 +12094,14 @@ class FlowSurfacesService {
|
|
|
11599
12094
|
for (const mappingField of (0, import_chart_config.getChartVisualMappingAliases)(state.visual)) {
|
|
11600
12095
|
if (!supportedOutputs.has(mappingField)) {
|
|
11601
12096
|
(0, import_errors.throwBadRequest)(
|
|
11602
|
-
|
|
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
|
+
}
|
|
11603
12105
|
);
|
|
11604
12106
|
}
|
|
11605
12107
|
}
|
|
@@ -11648,13 +12150,32 @@ class FlowSurfacesService {
|
|
|
11648
12150
|
continue;
|
|
11649
12151
|
}
|
|
11650
12152
|
(0, import_errors.throwBadRequest)(
|
|
11651
|
-
|
|
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
|
+
}
|
|
11652
12163
|
);
|
|
11653
12164
|
}
|
|
11654
12165
|
if (!fieldPath.includes(".") && (0, import_service_helpers.isAssociationField)(field)) {
|
|
11655
12166
|
const suggestion = this.resolveBuilderChartAssociationSubfieldSuggestion(fieldPath, field, dataSourceKey);
|
|
11656
12167
|
(0, import_errors.throwBadRequest)(
|
|
11657
|
-
|
|
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
|
+
}
|
|
11658
12179
|
);
|
|
11659
12180
|
}
|
|
11660
12181
|
}
|
|
@@ -11679,23 +12200,65 @@ class FlowSurfacesService {
|
|
|
11679
12200
|
suggestedFieldPath: `${fieldPath}.<field>`
|
|
11680
12201
|
};
|
|
11681
12202
|
}
|
|
11682
|
-
|
|
11683
|
-
|
|
11684
|
-
|
|
11685
|
-
|
|
11686
|
-
|
|
11687
|
-
|
|
11688
|
-
|
|
11689
|
-
|
|
11690
|
-
|
|
12203
|
+
async validateChartConfigureForRuntime(actionName, configure, transaction) {
|
|
12204
|
+
var _a, _b, _c;
|
|
12205
|
+
if (!import_lodash.default.isPlainObject(configure)) {
|
|
12206
|
+
return;
|
|
12207
|
+
}
|
|
12208
|
+
this.validateBuilderChartFieldsForRuntime(actionName, configure);
|
|
12209
|
+
const state = (0, import_chart_config.deriveChartSemanticState)(configure);
|
|
12210
|
+
if (((_a = state.query) == null ? void 0 : _a.mode) !== "sql") {
|
|
12211
|
+
return;
|
|
12212
|
+
}
|
|
12213
|
+
const sqlPreview = await this.resolveSqlChartPreview(state.query, transaction);
|
|
12214
|
+
if (((_b = state.visual) == null ? void 0 : _b.mode) !== "basic") {
|
|
12215
|
+
return;
|
|
12216
|
+
}
|
|
12217
|
+
if (!((_c = sqlPreview.queryOutputs) == null ? void 0 : _c.length)) {
|
|
12218
|
+
(0, import_errors.throwBadRequest)(
|
|
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
|
+
}
|
|
12225
|
+
);
|
|
12226
|
+
}
|
|
12227
|
+
const supportedOutputs = new Set(
|
|
12228
|
+
sqlPreview.queryOutputs.map((output) => String((output == null ? void 0 : output.alias) || "").trim()).filter(Boolean)
|
|
12229
|
+
);
|
|
12230
|
+
for (const mappingField of (0, import_chart_config.getChartVisualMappingAliases)(state.visual)) {
|
|
12231
|
+
if (!supportedOutputs.has(mappingField)) {
|
|
12232
|
+
(0, import_errors.throwBadRequest)(
|
|
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
|
+
}
|
|
12241
|
+
);
|
|
12242
|
+
}
|
|
12243
|
+
}
|
|
12244
|
+
}
|
|
12245
|
+
stripChartSqlForInspection(sql) {
|
|
12246
|
+
return sql.replace(/\/\*[\s\S]*?\*\//g, " ").replace(/--[^\r\n]*/g, " ").replace(/'(?:''|[^'])*'/g, "''").replace(/"(?:[""]|[^"])*"/g, '""');
|
|
12247
|
+
}
|
|
12248
|
+
normalizeReadOnlyChartSql(sql) {
|
|
12249
|
+
const normalized = (typeof sql === "string" ? sql : "").trim();
|
|
12250
|
+
const inspected = this.stripChartSqlForInspection(normalized).replace(/;+\s*$/, "").trim();
|
|
12251
|
+
if (!inspected) {
|
|
12252
|
+
throwChartRepairBadRequest("chart query.sql cannot be empty");
|
|
12253
|
+
}
|
|
11691
12254
|
if (inspected.includes(";")) {
|
|
11692
|
-
(
|
|
12255
|
+
throwChartRepairBadRequest("chart query.sql must be a single read-only SELECT statement");
|
|
11693
12256
|
}
|
|
11694
12257
|
if (!/^(with|select)\b/i.test(inspected)) {
|
|
11695
|
-
(
|
|
12258
|
+
throwChartRepairBadRequest("chart query.sql must start with SELECT or WITH");
|
|
11696
12259
|
}
|
|
11697
12260
|
if (/\b(insert|update|delete|drop|alter|truncate|create|replace|grant|revoke|merge|call|execute)\b/i.test(inspected)) {
|
|
11698
|
-
(
|
|
12261
|
+
throwChartRepairBadRequest("chart query.sql must be read-only");
|
|
11699
12262
|
}
|
|
11700
12263
|
return normalized.replace(/;+\s*$/, "").trim();
|
|
11701
12264
|
}
|
|
@@ -11713,7 +12276,7 @@ class FlowSurfacesService {
|
|
|
11713
12276
|
if ((_a = db == null ? void 0 : db.sequelize) == null ? void 0 : _a.query) {
|
|
11714
12277
|
return db.sequelize.query(sql, { bind, transaction });
|
|
11715
12278
|
}
|
|
11716
|
-
(
|
|
12279
|
+
throwChartRepairBadRequest("chart SQL preview is unavailable for the target data source");
|
|
11717
12280
|
}
|
|
11718
12281
|
extractSqlChartPreviewAliases(metadata) {
|
|
11719
12282
|
const pickName = (field) => {
|
|
@@ -11751,7 +12314,13 @@ class FlowSurfacesService {
|
|
|
11751
12314
|
async resolveSqlChartPreview(query, _transaction) {
|
|
11752
12315
|
var _a, _b;
|
|
11753
12316
|
const normalizedSql = this.normalizeReadOnlyChartSql(query == null ? void 0 : query.sql);
|
|
11754
|
-
|
|
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
|
+
}
|
|
11755
12324
|
const riskyHints = [];
|
|
11756
12325
|
const hasRuntimeContext = Object.keys((transformed == null ? void 0 : transformed.bind) || {}).length > 0 || Object.keys((transformed == null ? void 0 : transformed.liquidContext) || {}).length > 0;
|
|
11757
12326
|
if (hasRuntimeContext) {
|
|
@@ -11807,7 +12376,7 @@ class FlowSurfacesService {
|
|
|
11807
12376
|
}
|
|
11808
12377
|
const outputAliases = Object.keys(firstRow);
|
|
11809
12378
|
if (!outputAliases.length) {
|
|
11810
|
-
(
|
|
12379
|
+
throwChartRepairBadRequest("chart query.sql must expose at least one output column");
|
|
11811
12380
|
}
|
|
11812
12381
|
return {
|
|
11813
12382
|
queryOutputs: outputAliases.map((alias) => ({
|
|
@@ -11818,8 +12387,11 @@ class FlowSurfacesService {
|
|
|
11818
12387
|
riskyHints
|
|
11819
12388
|
};
|
|
11820
12389
|
} catch (error) {
|
|
12390
|
+
if (isFlowSurfaceChartRepairError(error)) {
|
|
12391
|
+
throw error;
|
|
12392
|
+
}
|
|
11821
12393
|
const message = (error == null ? void 0 : error.message) || String(error);
|
|
11822
|
-
(
|
|
12394
|
+
throwChartRepairBadRequest(`chart query.sql is invalid: ${message}`);
|
|
11823
12395
|
}
|
|
11824
12396
|
}
|
|
11825
12397
|
syncChartCardRuntimeStepParamsForUpdateSettings(current, nextPayload, replacementCardSettings) {
|
|
@@ -13827,6 +14399,97 @@ class FlowSurfacesService {
|
|
|
13827
14399
|
}
|
|
13828
14400
|
}
|
|
13829
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
|
+
}
|
|
13830
14493
|
async resolveReusableSingletonAction(input) {
|
|
13831
14494
|
var _a, _b, _c;
|
|
13832
14495
|
if (AUTO_SUBMIT_FORM_BLOCK_USES.has(input.ownerUse || "") && input.actionUse === "FormSubmitActionModel") {
|
|
@@ -13990,8 +14653,10 @@ class FlowSurfacesService {
|
|
|
13990
14653
|
if (blockCatalogItem) {
|
|
13991
14654
|
this.validateComposeActionGroups(blockCatalogItem.use, actions, recordActions, enabledPackages);
|
|
13992
14655
|
}
|
|
13993
|
-
const actionKeys = new Set(actions.map((item) => item.key).filter(Boolean));
|
|
13994
|
-
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
|
+
);
|
|
13995
14660
|
const blockDescriptor = this.describeComposeBlock({
|
|
13996
14661
|
index: index + 1,
|
|
13997
14662
|
key,
|
|
@@ -14422,6 +15087,7 @@ class FlowSurfacesService {
|
|
|
14422
15087
|
...(0, import_service_utils.hasDefinedValue)(changes, [
|
|
14423
15088
|
"pageSize",
|
|
14424
15089
|
"density",
|
|
15090
|
+
"enableRowSelection",
|
|
14425
15091
|
"showRowNumbers",
|
|
14426
15092
|
"sorting",
|
|
14427
15093
|
"dataScope",
|
|
@@ -14435,6 +15101,7 @@ class FlowSurfacesService {
|
|
|
14435
15101
|
...(0, import_service_utils.hasOwnDefined)(changes, "pageSize") ? { pageSize: { pageSize: changes.pageSize } } : {},
|
|
14436
15102
|
...(0, import_service_utils.hasOwnDefined)(changes, "density") ? { tableDensity: { size: changes.density } } : {},
|
|
14437
15103
|
...(0, import_service_utils.hasOwnDefined)(changes, "quickEdit") ? { quickEdit: { editable: changes.quickEdit } } : {},
|
|
15104
|
+
...(0, import_service_utils.hasOwnDefined)(changes, "enableRowSelection") ? { enableRowSelection: { enableRowSelection: changes.enableRowSelection } } : {},
|
|
14438
15105
|
...(0, import_service_utils.hasOwnDefined)(changes, "showRowNumbers") ? { showRowNumbers: { showIndex: changes.showRowNumbers } } : {},
|
|
14439
15106
|
...(0, import_service_utils.hasOwnDefined)(changes, "sorting") ? {
|
|
14440
15107
|
defaultSorting: {
|
|
@@ -15812,6 +16479,7 @@ class FlowSurfacesService {
|
|
|
15812
16479
|
);
|
|
15813
16480
|
}
|
|
15814
16481
|
async configureJSColumn(target, changes, options) {
|
|
16482
|
+
assertNoJsDeclarativeOpenView("jsColumn", changes, "JSColumnModel");
|
|
15815
16483
|
const allowedKeys = (0, import_configure_options.getConfigureOptionKeysForUse)("JSColumnModel");
|
|
15816
16484
|
(0, import_service_utils.assertSupportedSimpleChanges)("jsColumn", changes, allowedKeys);
|
|
15817
16485
|
return this.updateSettings(
|
|
@@ -15845,6 +16513,8 @@ class FlowSurfacesService {
|
|
|
15845
16513
|
);
|
|
15846
16514
|
}
|
|
15847
16515
|
async configureJSItem(target, changes, options) {
|
|
16516
|
+
const { currentUse = "JSItemModel", ...updateOptions } = options;
|
|
16517
|
+
assertNoJsDeclarativeOpenView("jsItem", changes, currentUse);
|
|
15848
16518
|
const allowedKeys = (0, import_configure_options.getConfigureOptionKeysForUse)("JSItemModel");
|
|
15849
16519
|
(0, import_service_utils.assertSupportedSimpleChanges)("jsItem", changes, allowedKeys);
|
|
15850
16520
|
return this.updateSettings(
|
|
@@ -15869,7 +16539,7 @@ class FlowSurfacesService {
|
|
|
15869
16539
|
}
|
|
15870
16540
|
} : void 0
|
|
15871
16541
|
},
|
|
15872
|
-
|
|
16542
|
+
updateOptions
|
|
15873
16543
|
);
|
|
15874
16544
|
}
|
|
15875
16545
|
async configureDividerItem(target, changes, options) {
|
|
@@ -15920,6 +16590,7 @@ class FlowSurfacesService {
|
|
|
15920
16590
|
transaction: options.transaction,
|
|
15921
16591
|
includeAsyncNode: true
|
|
15922
16592
|
}) : null;
|
|
16593
|
+
assertNoJsDeclarativeOpenView("field", changes, innerField == null ? void 0 : innerField.use);
|
|
15923
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) || {};
|
|
15924
16595
|
const bindingChange = (0, import_service_utils.hasDefinedValue)(wrapperChanges, ["fieldPath", "associationPathName"]);
|
|
15925
16596
|
const normalizedBinding = bindingChange ? this.normalizeDisplayFieldBinding({
|
|
@@ -16131,6 +16802,8 @@ class FlowSurfacesService {
|
|
|
16131
16802
|
const enabledPackages = await this.resolveEnabledPluginPackages(options);
|
|
16132
16803
|
const resolved = await this.locator.resolve(target, options);
|
|
16133
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);
|
|
16134
16807
|
(0, import_service_utils.assertSupportedSimpleChanges)(
|
|
16135
16808
|
"field",
|
|
16136
16809
|
changes,
|
|
@@ -16141,7 +16814,6 @@ class FlowSurfacesService {
|
|
|
16141
16814
|
transaction: options.transaction,
|
|
16142
16815
|
includeAsyncNode: true
|
|
16143
16816
|
}) : null;
|
|
16144
|
-
const isJsFieldNode = ["JSFieldModel", "JSEditableFieldModel"].includes((current == null ? void 0 : current.use) || "");
|
|
16145
16817
|
if ((0, import_service_utils.hasDefinedValue)(changes, ["code", "version"]) && !isJsFieldNode) {
|
|
16146
16818
|
(0, import_errors.throwBadRequest)(`flowSurfaces configure field '${current == null ? void 0 : current.use}' does not support code/version`);
|
|
16147
16819
|
}
|
|
@@ -16346,6 +17018,93 @@ class FlowSurfacesService {
|
|
|
16346
17018
|
isAIEmployeeActionUse(use) {
|
|
16347
17019
|
return String(use || "").trim() === AI_EMPLOYEE_ACTION_USE;
|
|
16348
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
|
+
}
|
|
16349
17108
|
hasAIEmployeePublicSettings(settings) {
|
|
16350
17109
|
return import_lodash.default.isPlainObject(settings) && AI_EMPLOYEE_PUBLIC_SETTING_KEYS.some((key) => Object.prototype.hasOwnProperty.call(settings, key));
|
|
16351
17110
|
}
|
|
@@ -16353,16 +17112,31 @@ class FlowSurfacesService {
|
|
|
16353
17112
|
const unsupportedKeys = Object.keys(settings || {}).filter((key) => !AI_EMPLOYEE_PUBLIC_SETTING_KEYS.includes(key));
|
|
16354
17113
|
if (unsupportedKeys.length) {
|
|
16355
17114
|
(0, import_errors.throwBadRequest)(
|
|
16356
|
-
`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`
|
|
16357
17120
|
);
|
|
16358
17121
|
}
|
|
16359
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
|
+
}
|
|
16360
17132
|
assertOnlyAIEmployeeNestedPublicSettings(actionName, path, value, allowedKeys) {
|
|
16361
17133
|
const unsupportedKeys = Object.keys(value || {}).filter((key) => !allowedKeys.includes(key));
|
|
16362
17134
|
if (!unsupportedKeys.length) {
|
|
16363
17135
|
return;
|
|
16364
17136
|
}
|
|
16365
|
-
(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
|
+
);
|
|
16366
17140
|
}
|
|
16367
17141
|
assertNoAIEmployeeInternalPropSettings(actionName, values) {
|
|
16368
17142
|
const props = values == null ? void 0 : values.props;
|
|
@@ -16381,6 +17155,67 @@ class FlowSurfacesService {
|
|
|
16381
17155
|
)}; use top-level username, auto, workContext, tasks or style instead`
|
|
16382
17156
|
);
|
|
16383
17157
|
}
|
|
17158
|
+
readAIEmployeePersistedTasks(current) {
|
|
17159
|
+
var _a;
|
|
17160
|
+
const stepTasks = import_lodash.default.get(current, ["stepParams", ...AI_EMPLOYEE_TASK_STEP_PARAMS_PATH]);
|
|
17161
|
+
if (Array.isArray(stepTasks)) {
|
|
17162
|
+
return stepTasks;
|
|
17163
|
+
}
|
|
17164
|
+
const legacyPropsTasks = (_a = current == null ? void 0 : current.props) == null ? void 0 : _a.tasks;
|
|
17165
|
+
return Array.isArray(legacyPropsTasks) ? legacyPropsTasks : [];
|
|
17166
|
+
}
|
|
17167
|
+
buildAIEmployeeTaskStepParams(tasks) {
|
|
17168
|
+
const stepParams = {};
|
|
17169
|
+
import_lodash.default.set(stepParams, AI_EMPLOYEE_TASK_STEP_PARAMS_PATH, import_lodash.default.cloneDeep(tasks));
|
|
17170
|
+
return stepParams;
|
|
17171
|
+
}
|
|
17172
|
+
mergeAIEmployeeActionSettingsPayload(current, values, payload) {
|
|
17173
|
+
if (Object.keys(payload.props).length) {
|
|
17174
|
+
values.props = import_lodash.default.merge({}, values.props || {}, payload.props);
|
|
17175
|
+
}
|
|
17176
|
+
if (Object.keys(payload.stepParams).length) {
|
|
17177
|
+
values.stepParams = import_lodash.default.mergeWith({}, values.stepParams || {}, payload.stepParams, (_currentValue, nextValue) => {
|
|
17178
|
+
if (Array.isArray(nextValue)) {
|
|
17179
|
+
return import_lodash.default.cloneDeep(nextValue);
|
|
17180
|
+
}
|
|
17181
|
+
return void 0;
|
|
17182
|
+
});
|
|
17183
|
+
}
|
|
17184
|
+
if (import_lodash.default.has(payload.stepParams, AI_EMPLOYEE_TASK_STEP_PARAMS_PATH) && this.isAIEmployeeActionUse(current == null ? void 0 : current.use)) {
|
|
17185
|
+
if (import_lodash.default.isPlainObject(values.props)) {
|
|
17186
|
+
delete values.props.tasks;
|
|
17187
|
+
}
|
|
17188
|
+
}
|
|
17189
|
+
}
|
|
17190
|
+
syncAIEmployeeTaskStepParamsForUpdateSettings(current, nextPayload) {
|
|
17191
|
+
var _a;
|
|
17192
|
+
if (!this.isAIEmployeeActionUse(current == null ? void 0 : current.use)) {
|
|
17193
|
+
return;
|
|
17194
|
+
}
|
|
17195
|
+
const legacyPropsTasks = (_a = current == null ? void 0 : current.props) == null ? void 0 : _a.tasks;
|
|
17196
|
+
const hasLegacyPropsTasks = Array.isArray(legacyPropsTasks);
|
|
17197
|
+
const hasNextStepTasks = import_lodash.default.has(nextPayload, ["stepParams", ...AI_EMPLOYEE_TASK_STEP_PARAMS_PATH]);
|
|
17198
|
+
const currentStepTasks = import_lodash.default.get(current, ["stepParams", ...AI_EMPLOYEE_TASK_STEP_PARAMS_PATH]);
|
|
17199
|
+
if (!hasNextStepTasks && hasLegacyPropsTasks && !Array.isArray(currentStepTasks)) {
|
|
17200
|
+
nextPayload.stepParams = import_lodash.default.mergeWith(
|
|
17201
|
+
{},
|
|
17202
|
+
(current == null ? void 0 : current.stepParams) || {},
|
|
17203
|
+
this.buildAIEmployeeTaskStepParams(legacyPropsTasks),
|
|
17204
|
+
(_currentValue, nextValue) => {
|
|
17205
|
+
if (Array.isArray(nextValue)) {
|
|
17206
|
+
return import_lodash.default.cloneDeep(nextValue);
|
|
17207
|
+
}
|
|
17208
|
+
return void 0;
|
|
17209
|
+
}
|
|
17210
|
+
);
|
|
17211
|
+
}
|
|
17212
|
+
if (!hasLegacyPropsTasks && !import_lodash.default.has(nextPayload, ["props", "tasks"])) {
|
|
17213
|
+
return;
|
|
17214
|
+
}
|
|
17215
|
+
const nextProps = import_lodash.default.cloneDeep(nextPayload.props ?? (current == null ? void 0 : current.props) ?? {});
|
|
17216
|
+
delete nextProps.tasks;
|
|
17217
|
+
nextPayload.props = nextProps;
|
|
17218
|
+
}
|
|
16384
17219
|
assertAIEmployeePluginEnabled(actionName, enabledPackages) {
|
|
16385
17220
|
if (!enabledPackages.has(AI_EMPLOYEE_OWNER_PLUGIN)) {
|
|
16386
17221
|
(0, import_errors.throwBadRequest)(
|
|
@@ -16464,8 +17299,13 @@ class FlowSurfacesService {
|
|
|
16464
17299
|
return username;
|
|
16465
17300
|
}
|
|
16466
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
|
+
}
|
|
16467
17305
|
if (String(item.type || "").trim() !== "flow-model") {
|
|
16468
|
-
(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
|
+
);
|
|
16469
17309
|
}
|
|
16470
17310
|
}
|
|
16471
17311
|
normalizeAIEmployeeWorkContext(actionName, value, options) {
|
|
@@ -16574,8 +17414,290 @@ class FlowSurfacesService {
|
|
|
16574
17414
|
if (Object.prototype.hasOwnProperty.call(next, "toolsVersion") && typeof next.toolsVersion !== "number") {
|
|
16575
17415
|
(0, import_errors.throwBadRequest)(`flowSurfaces ${actionName} ${path}.toolsVersion must be a number`);
|
|
16576
17416
|
}
|
|
17417
|
+
const hasSkills = Object.prototype.hasOwnProperty.call(next, "skills");
|
|
17418
|
+
const hasTools = Object.prototype.hasOwnProperty.call(next, "tools");
|
|
17419
|
+
const hasSkillsVersion = Object.prototype.hasOwnProperty.call(next, "skillsVersion");
|
|
17420
|
+
const hasToolsVersion = Object.prototype.hasOwnProperty.call(next, "toolsVersion");
|
|
17421
|
+
if (hasSkills && hasTools && !hasSkillsVersion && !hasToolsVersion && Array.isArray(next.skills) && Array.isArray(next.tools) && next.skills.length === 0 && next.tools.length === 0) {
|
|
17422
|
+
return null;
|
|
17423
|
+
}
|
|
17424
|
+
if (hasSkills && !hasSkillsVersion) {
|
|
17425
|
+
next.skillsVersion = 2;
|
|
17426
|
+
}
|
|
17427
|
+
if (hasTools && !hasToolsVersion) {
|
|
17428
|
+
next.toolsVersion = 2;
|
|
17429
|
+
}
|
|
16577
17430
|
return next;
|
|
16578
17431
|
}
|
|
17432
|
+
collectAIEmployeePromptVariables(value) {
|
|
17433
|
+
if (!value.includes("{{")) {
|
|
17434
|
+
return [];
|
|
17435
|
+
}
|
|
17436
|
+
return [...value.matchAll(/\{\{\s*([\s\S]+?)\s*\}\}/g)].map(([raw, inner]) => ({
|
|
17437
|
+
raw,
|
|
17438
|
+
inner: String(inner || "").trim()
|
|
17439
|
+
}));
|
|
17440
|
+
}
|
|
17441
|
+
hasAIEmployeePromptVariables(tasks) {
|
|
17442
|
+
return import_lodash.default.castArray(tasks || []).some((task) => {
|
|
17443
|
+
const message = task == null ? void 0 : task.message;
|
|
17444
|
+
return typeof (message == null ? void 0 : message.system) === "string" && this.collectAIEmployeePromptVariables(message.system).length > 0 || typeof (message == null ? void 0 : message.user) === "string" && this.collectAIEmployeePromptVariables(message.user).length > 0;
|
|
17445
|
+
});
|
|
17446
|
+
}
|
|
17447
|
+
collectAIEmployeeContextPathEntries(context) {
|
|
17448
|
+
const result = /* @__PURE__ */ new Map();
|
|
17449
|
+
const visit = (prefix, info) => {
|
|
17450
|
+
if (!prefix || !info) {
|
|
17451
|
+
return;
|
|
17452
|
+
}
|
|
17453
|
+
result.set(prefix, info);
|
|
17454
|
+
if (info.dynamicProperties) {
|
|
17455
|
+
result.set(`${prefix}.*`, info.dynamicProperties);
|
|
17456
|
+
}
|
|
17457
|
+
for (const [childKey, childInfo] of Object.entries(info.properties || {})) {
|
|
17458
|
+
visit(`${prefix}.${childKey}`, childInfo);
|
|
17459
|
+
}
|
|
17460
|
+
};
|
|
17461
|
+
for (const [key, info] of Object.entries((context == null ? void 0 : context.vars) || {})) {
|
|
17462
|
+
visit(key, info);
|
|
17463
|
+
}
|
|
17464
|
+
return result;
|
|
17465
|
+
}
|
|
17466
|
+
isAIEmployeeContextInfoPathAllowed(info, segments) {
|
|
17467
|
+
var _a;
|
|
17468
|
+
if (!info) {
|
|
17469
|
+
return false;
|
|
17470
|
+
}
|
|
17471
|
+
if (!segments.length) {
|
|
17472
|
+
return true;
|
|
17473
|
+
}
|
|
17474
|
+
const [segment, ...rest] = segments;
|
|
17475
|
+
const staticChild = (_a = info.properties) == null ? void 0 : _a[segment];
|
|
17476
|
+
if (staticChild) {
|
|
17477
|
+
return this.isAIEmployeeContextInfoPathAllowed(staticChild, rest);
|
|
17478
|
+
}
|
|
17479
|
+
if (info.dynamicProperties) {
|
|
17480
|
+
return this.isAIEmployeeContextInfoPathAllowed(info.dynamicProperties, rest);
|
|
17481
|
+
}
|
|
17482
|
+
return false;
|
|
17483
|
+
}
|
|
17484
|
+
canResolveAIEmployeeContextPath(path, semantic) {
|
|
17485
|
+
var _a;
|
|
17486
|
+
return !!((_a = (0, import_context.buildFlowSurfaceContextResponse)({
|
|
17487
|
+
semantic,
|
|
17488
|
+
path,
|
|
17489
|
+
maxDepth: 1
|
|
17490
|
+
}).vars) == null ? void 0 : _a[path]);
|
|
17491
|
+
}
|
|
17492
|
+
isAIEmployeeContextPathAllowed(path, validation) {
|
|
17493
|
+
if (validation.contextPaths.has(path)) {
|
|
17494
|
+
return true;
|
|
17495
|
+
}
|
|
17496
|
+
for (const [allowedPath, info] of validation.contextPaths) {
|
|
17497
|
+
if (!allowedPath.endsWith(".*")) {
|
|
17498
|
+
continue;
|
|
17499
|
+
}
|
|
17500
|
+
const prefix = allowedPath.slice(0, -2);
|
|
17501
|
+
if (!path.startsWith(`${prefix}.`)) {
|
|
17502
|
+
continue;
|
|
17503
|
+
}
|
|
17504
|
+
const dynamicSegments = path.slice(prefix.length + 1).split(".").filter(Boolean);
|
|
17505
|
+
if (dynamicSegments.length && this.isAIEmployeeContextInfoPathAllowed(info, dynamicSegments.slice(1))) {
|
|
17506
|
+
return true;
|
|
17507
|
+
}
|
|
17508
|
+
}
|
|
17509
|
+
return this.canResolveAIEmployeeContextPath(path, validation.semantic);
|
|
17510
|
+
}
|
|
17511
|
+
extractAIEmployeePromptContextPath(expression) {
|
|
17512
|
+
const normalized = String(expression || "").trim();
|
|
17513
|
+
if (normalized === "ctx") {
|
|
17514
|
+
return "";
|
|
17515
|
+
}
|
|
17516
|
+
if (!normalized.startsWith("ctx.")) {
|
|
17517
|
+
return null;
|
|
17518
|
+
}
|
|
17519
|
+
const path = normalized.slice(4).trim();
|
|
17520
|
+
return (0, import_context.isBareFlowContextPath)(path) ? path : null;
|
|
17521
|
+
}
|
|
17522
|
+
buildAIEmployeePromptVariableHint(targetUid) {
|
|
17523
|
+
return `Call flowSurfaces:context${targetUid ? ` with target.uid "${targetUid}"` : ""} to inspect available ctx paths before writing prompt variables.`;
|
|
17524
|
+
}
|
|
17525
|
+
throwAIEmployeePromptVariableInvalid(input) {
|
|
17526
|
+
(0, import_errors.throwBadRequest)(
|
|
17527
|
+
`flowSurfaces ${input.actionName} ${input.fieldPath} variable "${input.variable}" is not allowed: ${input.reason}. Use a concrete ctx path such as "{{ ctx.record.id }}" only when that path is available. ${this.buildAIEmployeePromptVariableHint(
|
|
17528
|
+
input.targetUid
|
|
17529
|
+
)}`,
|
|
17530
|
+
AI_EMPLOYEE_PROMPT_VARIABLE_INVALID,
|
|
17531
|
+
{
|
|
17532
|
+
path: input.fieldPath,
|
|
17533
|
+
details: (0, import_service_utils.buildDefinedPayload)({
|
|
17534
|
+
variable: input.variable,
|
|
17535
|
+
contextPath: input.path,
|
|
17536
|
+
targetUid: input.targetUid
|
|
17537
|
+
})
|
|
17538
|
+
}
|
|
17539
|
+
);
|
|
17540
|
+
}
|
|
17541
|
+
assertAIEmployeePromptVariablesAllowed(actionName, fieldPath, value, validation) {
|
|
17542
|
+
for (const variable of this.collectAIEmployeePromptVariables(value)) {
|
|
17543
|
+
const path = this.extractAIEmployeePromptContextPath(variable.inner);
|
|
17544
|
+
if (path === "") {
|
|
17545
|
+
this.throwAIEmployeePromptVariableInvalid({
|
|
17546
|
+
actionName,
|
|
17547
|
+
fieldPath,
|
|
17548
|
+
variable: variable.raw,
|
|
17549
|
+
targetUid: validation.targetUid,
|
|
17550
|
+
reason: "the whole ctx object is not a valid prompt variable; use a concrete ctx path"
|
|
17551
|
+
});
|
|
17552
|
+
}
|
|
17553
|
+
if (!path) {
|
|
17554
|
+
this.throwAIEmployeePromptVariableInvalid({
|
|
17555
|
+
actionName,
|
|
17556
|
+
fieldPath,
|
|
17557
|
+
variable: variable.raw,
|
|
17558
|
+
targetUid: validation.targetUid,
|
|
17559
|
+
reason: 'only simple ctx dot paths like "{{ ctx.record.id }}" are supported'
|
|
17560
|
+
});
|
|
17561
|
+
}
|
|
17562
|
+
if (!this.isAIEmployeeContextPathAllowed(path, validation)) {
|
|
17563
|
+
this.throwAIEmployeePromptVariableInvalid({
|
|
17564
|
+
actionName,
|
|
17565
|
+
fieldPath,
|
|
17566
|
+
variable: variable.raw,
|
|
17567
|
+
targetUid: validation.targetUid,
|
|
17568
|
+
path,
|
|
17569
|
+
reason: `path "${path}" is not available in the current Flow Surface context`
|
|
17570
|
+
});
|
|
17571
|
+
}
|
|
17572
|
+
}
|
|
17573
|
+
}
|
|
17574
|
+
assertAIEmployeeTaskPromptVariablesAllowed(actionName, tasks, validation, path = "settings.tasks") {
|
|
17575
|
+
if (!validation) {
|
|
17576
|
+
return;
|
|
17577
|
+
}
|
|
17578
|
+
tasks.forEach((task, index) => {
|
|
17579
|
+
const message = task == null ? void 0 : task.message;
|
|
17580
|
+
if (typeof (message == null ? void 0 : message.system) === "string") {
|
|
17581
|
+
this.assertAIEmployeePromptVariablesAllowed(
|
|
17582
|
+
actionName,
|
|
17583
|
+
`${path}[${index}].message.system`,
|
|
17584
|
+
message.system,
|
|
17585
|
+
validation
|
|
17586
|
+
);
|
|
17587
|
+
}
|
|
17588
|
+
if (typeof (message == null ? void 0 : message.user) === "string") {
|
|
17589
|
+
this.assertAIEmployeePromptVariablesAllowed(
|
|
17590
|
+
actionName,
|
|
17591
|
+
`${path}[${index}].message.user`,
|
|
17592
|
+
message.user,
|
|
17593
|
+
validation
|
|
17594
|
+
);
|
|
17595
|
+
}
|
|
17596
|
+
});
|
|
17597
|
+
}
|
|
17598
|
+
appendAIEmployeeCurrentRecordPromptVariable(value) {
|
|
17599
|
+
if (AI_EMPLOYEE_CURRENT_RECORD_PROMPT_VARIABLE_RE.test(value)) {
|
|
17600
|
+
return value;
|
|
17601
|
+
}
|
|
17602
|
+
return value ? `${value}
|
|
17603
|
+
${AI_EMPLOYEE_CURRENT_RECORD_PROMPT_VARIABLE}` : AI_EMPLOYEE_CURRENT_RECORD_PROMPT_VARIABLE;
|
|
17604
|
+
}
|
|
17605
|
+
async resolveAIEmployeePromptActionTargetUid(context, transaction) {
|
|
17606
|
+
if (!context) {
|
|
17607
|
+
return void 0;
|
|
17608
|
+
}
|
|
17609
|
+
if (context.kind === "target") {
|
|
17610
|
+
return String(context.targetUid || "").trim() || void 0;
|
|
17611
|
+
}
|
|
17612
|
+
return String(context.ownerUid || "").trim() || void 0;
|
|
17613
|
+
}
|
|
17614
|
+
async buildAIEmployeePromptValidationContext(actionName, tasks, options) {
|
|
17615
|
+
var _a, _b;
|
|
17616
|
+
if (!this.hasAIEmployeePromptVariables(tasks)) {
|
|
17617
|
+
return void 0;
|
|
17618
|
+
}
|
|
17619
|
+
const targetUid = await this.resolveAIEmployeePromptActionTargetUid(options.promptContext, options.transaction);
|
|
17620
|
+
if (!targetUid) {
|
|
17621
|
+
(0, import_errors.throwBadRequest)(
|
|
17622
|
+
`flowSurfaces ${actionName} AI employee prompt variables require a resolvable Flow Surface context. ${this.buildAIEmployeePromptVariableHint()}`,
|
|
17623
|
+
AI_EMPLOYEE_PROMPT_VARIABLE_INVALID
|
|
17624
|
+
);
|
|
17625
|
+
}
|
|
17626
|
+
const target = { uid: targetUid };
|
|
17627
|
+
const resolved = await this.locator.resolve(target, { transaction: options.transaction });
|
|
17628
|
+
let semantic = await this.resolveContextSemantic(((_a = resolved == null ? void 0 : resolved.node) == null ? void 0 : _a.uid) || target.uid, resolved, options.transaction);
|
|
17629
|
+
if (((_b = options.promptContext) == null ? void 0 : _b.kind) === "container" && options.promptContext.scope === "record") {
|
|
17630
|
+
semantic = {
|
|
17631
|
+
...semantic,
|
|
17632
|
+
recordCollection: semantic.recordCollection || semantic.collection || await this.resolveContextOwnerCollection(targetUid, options.transaction).catch(() => null)
|
|
17633
|
+
};
|
|
17634
|
+
}
|
|
17635
|
+
const context = (0, import_context.buildFlowSurfaceContextResponse)({
|
|
17636
|
+
semantic,
|
|
17637
|
+
maxDepth: AI_EMPLOYEE_PROMPT_CONTEXT_MAX_DEPTH
|
|
17638
|
+
});
|
|
17639
|
+
return {
|
|
17640
|
+
targetUid,
|
|
17641
|
+
semantic,
|
|
17642
|
+
contextPaths: this.collectAIEmployeeContextPathEntries(context)
|
|
17643
|
+
};
|
|
17644
|
+
}
|
|
17645
|
+
appendAIEmployeeCurrentRecordPromptVariableToTasks(tasks, validation) {
|
|
17646
|
+
if (!tasks.length || !validation || !this.isAIEmployeeContextPathAllowed("record", validation)) {
|
|
17647
|
+
return tasks;
|
|
17648
|
+
}
|
|
17649
|
+
return tasks.map((task) => {
|
|
17650
|
+
var _a;
|
|
17651
|
+
if (typeof ((_a = task == null ? void 0 : task.message) == null ? void 0 : _a.user) !== "string") {
|
|
17652
|
+
return task;
|
|
17653
|
+
}
|
|
17654
|
+
const next = import_lodash.default.cloneDeep(task);
|
|
17655
|
+
next.message.user = this.appendAIEmployeeCurrentRecordPromptVariable(next.message.user);
|
|
17656
|
+
return next;
|
|
17657
|
+
});
|
|
17658
|
+
}
|
|
17659
|
+
async assertAIEmployeeStepParamTaskPromptVariablesAllowedForUpdateSettings(current, nextPayload, writeTarget, options) {
|
|
17660
|
+
if (!this.isAIEmployeeActionUse(current == null ? void 0 : current.use) || !import_lodash.default.has(nextPayload, ["stepParams", ...AI_EMPLOYEE_TASK_STEP_PARAMS_PATH])) {
|
|
17661
|
+
return;
|
|
17662
|
+
}
|
|
17663
|
+
const tasks = import_lodash.default.get(nextPayload, ["stepParams", ...AI_EMPLOYEE_TASK_STEP_PARAMS_PATH]);
|
|
17664
|
+
if (!Array.isArray(tasks)) {
|
|
17665
|
+
return;
|
|
17666
|
+
}
|
|
17667
|
+
const actionName = options.openViewActionName || "updateSettings";
|
|
17668
|
+
this.assertAIEmployeeTaskPromptVariablesAllowed(
|
|
17669
|
+
actionName,
|
|
17670
|
+
tasks,
|
|
17671
|
+
await this.buildAIEmployeePromptValidationContext(actionName, tasks, {
|
|
17672
|
+
transaction: options.transaction,
|
|
17673
|
+
promptContext: {
|
|
17674
|
+
kind: "target",
|
|
17675
|
+
targetUid: (current == null ? void 0 : current.uid) || writeTarget.uid
|
|
17676
|
+
}
|
|
17677
|
+
}),
|
|
17678
|
+
"stepParams.shortcutSettings.editTasks.tasks"
|
|
17679
|
+
);
|
|
17680
|
+
}
|
|
17681
|
+
async normalizeAIEmployeeStepParamTasksForUpdateSettings(current, nextPayload, writeTarget, options) {
|
|
17682
|
+
if (!this.isAIEmployeeActionUse(current == null ? void 0 : current.use) || !import_lodash.default.has(nextPayload, ["stepParams", ...AI_EMPLOYEE_TASK_STEP_PARAMS_PATH])) {
|
|
17683
|
+
return;
|
|
17684
|
+
}
|
|
17685
|
+
const tasks = import_lodash.default.get(nextPayload, ["stepParams", ...AI_EMPLOYEE_TASK_STEP_PARAMS_PATH]);
|
|
17686
|
+
if (!Array.isArray(tasks)) {
|
|
17687
|
+
return;
|
|
17688
|
+
}
|
|
17689
|
+
const actionName = options.openViewActionName || "updateSettings";
|
|
17690
|
+
const normalizedTasks = this.normalizeAIEmployeeTasks(
|
|
17691
|
+
actionName,
|
|
17692
|
+
tasks,
|
|
17693
|
+
this.readAIEmployeePersistedTasks(current),
|
|
17694
|
+
{
|
|
17695
|
+
selfUid: await this.resolveAIEmployeeActionSelfUid(current || { uid: writeTarget.uid }, options.transaction),
|
|
17696
|
+
path: "stepParams.shortcutSettings.editTasks.tasks"
|
|
17697
|
+
}
|
|
17698
|
+
);
|
|
17699
|
+
import_lodash.default.set(nextPayload, ["stepParams", ...AI_EMPLOYEE_TASK_STEP_PARAMS_PATH], normalizedTasks);
|
|
17700
|
+
}
|
|
16579
17701
|
normalizeAIEmployeeTaskMessage(actionName, path, value, existing, options) {
|
|
16580
17702
|
if (!import_lodash.default.isPlainObject(value)) {
|
|
16581
17703
|
(0, import_errors.throwBadRequest)(`flowSurfaces ${actionName} ${path} must be an object`);
|
|
@@ -16616,9 +17738,18 @@ class FlowSurfacesService {
|
|
|
16616
17738
|
(0, import_errors.throwBadRequest)(`flowSurfaces ${actionName} ${options.path} must be an object`);
|
|
16617
17739
|
}
|
|
16618
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
|
+
}
|
|
16619
17746
|
Object.entries(patch).forEach(([key, value]) => {
|
|
16620
|
-
if (!
|
|
16621
|
-
(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
|
+
);
|
|
16622
17753
|
}
|
|
16623
17754
|
if (key === "message") {
|
|
16624
17755
|
next.message = this.normalizeAIEmployeeTaskMessage(actionName, `${options.path}.message`, value, next.message, {
|
|
@@ -16627,6 +17758,18 @@ class FlowSurfacesService {
|
|
|
16627
17758
|
});
|
|
16628
17759
|
return;
|
|
16629
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
|
+
}
|
|
16630
17773
|
if (key === "title") {
|
|
16631
17774
|
if (typeof value !== "string") {
|
|
16632
17775
|
(0, import_errors.throwBadRequest)(`flowSurfaces ${actionName} ${options.path}.title must be a string`);
|
|
@@ -16661,6 +17804,14 @@ class FlowSurfacesService {
|
|
|
16661
17804
|
if (!import_lodash.default.isPlainObject(next.message)) {
|
|
16662
17805
|
next.message = {};
|
|
16663
17806
|
}
|
|
17807
|
+
if (import_lodash.default.isPlainObject(next.skillSettings)) {
|
|
17808
|
+
if (Array.isArray(next.skillSettings.skills) && !Object.prototype.hasOwnProperty.call(next.skillSettings, "skillsVersion")) {
|
|
17809
|
+
next.skillSettings.skillsVersion = 2;
|
|
17810
|
+
}
|
|
17811
|
+
if (Array.isArray(next.skillSettings.tools) && !Object.prototype.hasOwnProperty.call(next.skillSettings, "toolsVersion")) {
|
|
17812
|
+
next.skillSettings.toolsVersion = 2;
|
|
17813
|
+
}
|
|
17814
|
+
}
|
|
16664
17815
|
return next;
|
|
16665
17816
|
}
|
|
16666
17817
|
normalizeAIEmployeeTasks(actionName, value, currentTasks, options) {
|
|
@@ -16723,6 +17874,7 @@ class FlowSurfacesService {
|
|
|
16723
17874
|
});
|
|
16724
17875
|
}
|
|
16725
17876
|
const props = {};
|
|
17877
|
+
const stepParams = {};
|
|
16726
17878
|
if (effectiveUsername && (hasUsername || options.requireUsername)) {
|
|
16727
17879
|
props.aiEmployee = {
|
|
16728
17880
|
...import_lodash.default.isPlainObject(currentProps.aiEmployee) ? import_lodash.default.cloneDeep(currentProps.aiEmployee) : {},
|
|
@@ -16748,11 +17900,36 @@ class FlowSurfacesService {
|
|
|
16748
17900
|
};
|
|
16749
17901
|
}
|
|
16750
17902
|
if (Object.prototype.hasOwnProperty.call(settings, "tasks")) {
|
|
16751
|
-
|
|
16752
|
-
|
|
16753
|
-
|
|
16754
|
-
|
|
17903
|
+
const normalizedTasks = this.normalizeAIEmployeeTasks(
|
|
17904
|
+
actionName,
|
|
17905
|
+
settings.tasks,
|
|
17906
|
+
this.readAIEmployeePersistedTasks(options.current),
|
|
17907
|
+
{
|
|
17908
|
+
selfUid: options.selfUid,
|
|
17909
|
+
keyMap: options.keyMap,
|
|
17910
|
+
path: "settings.tasks"
|
|
17911
|
+
}
|
|
17912
|
+
);
|
|
17913
|
+
const validation = options.promptContext && normalizedTasks.length ? await this.buildAIEmployeePromptValidationContext(
|
|
17914
|
+
actionName,
|
|
17915
|
+
[
|
|
17916
|
+
{
|
|
17917
|
+
message: {
|
|
17918
|
+
user: AI_EMPLOYEE_CURRENT_RECORD_PROMPT_VARIABLE
|
|
17919
|
+
}
|
|
17920
|
+
}
|
|
17921
|
+
],
|
|
17922
|
+
{
|
|
17923
|
+
transaction: options.transaction,
|
|
17924
|
+
promptContext: options.promptContext
|
|
17925
|
+
}
|
|
17926
|
+
) : await this.buildAIEmployeePromptValidationContext(actionName, normalizedTasks, {
|
|
17927
|
+
transaction: options.transaction,
|
|
17928
|
+
promptContext: options.promptContext
|
|
16755
17929
|
});
|
|
17930
|
+
const tasks = this.appendAIEmployeeCurrentRecordPromptVariableToTasks(normalizedTasks, validation);
|
|
17931
|
+
this.assertAIEmployeeTaskPromptVariablesAllowed(actionName, tasks, validation);
|
|
17932
|
+
import_lodash.default.merge(stepParams, this.buildAIEmployeeTaskStepParams(tasks));
|
|
16756
17933
|
}
|
|
16757
17934
|
if (Object.prototype.hasOwnProperty.call(settings, "style") || options.requireUsername) {
|
|
16758
17935
|
const style = Object.prototype.hasOwnProperty.call(settings, "style") ? settings.style : {};
|
|
@@ -16780,7 +17957,10 @@ class FlowSurfacesService {
|
|
|
16780
17957
|
import_lodash.default.isPlainObject(style) ? import_lodash.default.pick(import_lodash.default.cloneDeep(style), AI_EMPLOYEE_STYLE_PUBLIC_KEYS) : {}
|
|
16781
17958
|
);
|
|
16782
17959
|
}
|
|
16783
|
-
return
|
|
17960
|
+
return {
|
|
17961
|
+
props,
|
|
17962
|
+
stepParams
|
|
17963
|
+
};
|
|
16784
17964
|
}
|
|
16785
17965
|
async resolveAIEmployeeActionSelfUid(actionNode, transaction) {
|
|
16786
17966
|
const parentUid = String((actionNode == null ? void 0 : actionNode.parentId) || "").trim() || ((actionNode == null ? void 0 : actionNode.uid) ? await this.locator.findParentUid(actionNode.uid, transaction).catch(() => "") : "");
|
|
@@ -16804,27 +17984,39 @@ class FlowSurfacesService {
|
|
|
16804
17984
|
}) : null);
|
|
16805
17985
|
changes = await this.normalizeActionPanelActionChanges(changes, options);
|
|
16806
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
|
+
}
|
|
16807
17990
|
(0, import_service_utils.assertSupportedSimpleChanges)("action", changes, allowedKeys);
|
|
16808
17991
|
if (this.isAIEmployeeActionUse(use)) {
|
|
16809
|
-
const
|
|
16810
|
-
|
|
16811
|
-
|
|
16812
|
-
current: currentNode,
|
|
16813
|
-
currentRoles: options.currentRoles,
|
|
16814
|
-
selfUid: await this.resolveAIEmployeeActionSelfUid(currentNode, options.transaction)
|
|
16815
|
-
});
|
|
16816
|
-
return this.updateSettings(
|
|
16817
|
-
{
|
|
16818
|
-
target,
|
|
16819
|
-
props: props2
|
|
16820
|
-
},
|
|
17992
|
+
const aiEmployeeSettingsPayload = await this.normalizeAIEmployeeActionPublicSettings(
|
|
17993
|
+
"configure action",
|
|
17994
|
+
changes,
|
|
16821
17995
|
{
|
|
16822
|
-
|
|
16823
|
-
|
|
16824
|
-
|
|
16825
|
-
|
|
17996
|
+
transaction: options.transaction,
|
|
17997
|
+
enabledPackages: options.enabledPackages || await this.resolveEnabledPluginPackages(options),
|
|
17998
|
+
current: currentNode,
|
|
17999
|
+
currentRoles: options.currentRoles,
|
|
18000
|
+
selfUid: await this.resolveAIEmployeeActionSelfUid(currentNode, options.transaction),
|
|
18001
|
+
promptContext: {
|
|
18002
|
+
kind: "target",
|
|
18003
|
+
targetUid: (currentNode == null ? void 0 : currentNode.uid) || target.uid
|
|
18004
|
+
}
|
|
16826
18005
|
}
|
|
16827
18006
|
);
|
|
18007
|
+
const settingsValues = { target };
|
|
18008
|
+
if (Object.keys(aiEmployeeSettingsPayload.props).length) {
|
|
18009
|
+
settingsValues.props = aiEmployeeSettingsPayload.props;
|
|
18010
|
+
}
|
|
18011
|
+
if (Object.keys(aiEmployeeSettingsPayload.stepParams).length) {
|
|
18012
|
+
settingsValues.stepParams = aiEmployeeSettingsPayload.stepParams;
|
|
18013
|
+
}
|
|
18014
|
+
return this.updateSettings(settingsValues, {
|
|
18015
|
+
...options,
|
|
18016
|
+
openViewActionName: options.openViewActionName || "configure action",
|
|
18017
|
+
popupTemplateHostUid: target.uid,
|
|
18018
|
+
allowAIEmployeeInternalProps: true
|
|
18019
|
+
});
|
|
16828
18020
|
}
|
|
16829
18021
|
const normalizedDefaultFilter = (0, import_service_utils.hasOwnDefined)(changes, "defaultFilter") ? this.normalizeFilterActionDefaultFilterValue(changes.defaultFilter) : void 0;
|
|
16830
18022
|
const stepParams = {};
|
|
@@ -16888,7 +18080,7 @@ class FlowSurfacesService {
|
|
|
16888
18080
|
openView: import_lodash.default.cloneDeep(changes.openView)
|
|
16889
18081
|
};
|
|
16890
18082
|
} else if (!POPUP_ACTION_USES.has(use)) {
|
|
16891
|
-
(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));
|
|
16892
18084
|
} else {
|
|
16893
18085
|
let openView = import_lodash.default.cloneDeep(changes.openView);
|
|
16894
18086
|
if (use === "AddChildActionModel") {
|
|
@@ -18117,7 +19309,8 @@ class FlowSurfacesService {
|
|
|
18117
19309
|
}
|
|
18118
19310
|
resolveRecordActionContextOwner(ancestors) {
|
|
18119
19311
|
const currentNode = ancestors[0];
|
|
18120
|
-
|
|
19312
|
+
const currentUse = String((currentNode == null ? void 0 : currentNode.use) || "").trim();
|
|
19313
|
+
if (!currentUse.endsWith("ActionModel") && !import_node_use_sets.ACTION_BUTTON_USES.has(currentUse)) {
|
|
18121
19314
|
return null;
|
|
18122
19315
|
}
|
|
18123
19316
|
return ancestors.slice(1).find((node) => (0, import_action_scope.getActionContainerScope)(node == null ? void 0 : node.use) === "record") || null;
|
|
@@ -18368,11 +19561,12 @@ class FlowSurfacesService {
|
|
|
18368
19561
|
};
|
|
18369
19562
|
}
|
|
18370
19563
|
getCollection(dataSourceKey, collectionName) {
|
|
18371
|
-
var _a, _b, _c, _d, _e;
|
|
19564
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
18372
19565
|
const normalizedDataSourceKey = dataSourceKey || "main";
|
|
18373
|
-
const
|
|
18374
|
-
const
|
|
18375
|
-
|
|
19566
|
+
const app = (_a = this.plugin) == null ? void 0 : _a.app;
|
|
19567
|
+
const dataSourceManager = app == null ? void 0 : app.dataSourceManager;
|
|
19568
|
+
const dataSource = (_b = dataSourceManager == null ? void 0 : dataSourceManager.get) == null ? void 0 : _b.call(dataSourceManager, normalizedDataSourceKey);
|
|
19569
|
+
return ((_d = (_c = dataSource == null ? void 0 : dataSource.collectionManager) == null ? void 0 : _c.getCollection) == null ? void 0 : _d.call(_c, collectionName)) || ((_f = (_e = app == null ? void 0 : app.db) == null ? void 0 : _e.getCollection) == null ? void 0 : _f.call(_e, collectionName)) || ((_h = (_g = this.db) == null ? void 0 : _g.getCollection) == null ? void 0 : _h.call(_g, collectionName));
|
|
18376
19570
|
}
|
|
18377
19571
|
normalizeKanbanFieldNameInput(value, context, options = {}) {
|
|
18378
19572
|
if (import_lodash.default.isUndefined(value)) {
|