@nocobase/plugin-flow-engine 2.1.0-alpha.40 → 2.1.0-alpha.46
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/client/index.js +1 -1
- 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 +28 -14
- package/dist/server/flow-surfaces/apply/matching.js +2 -0
- package/dist/server/flow-surfaces/authoring-validation.d.ts +1 -0
- package/dist/server/flow-surfaces/authoring-validation.js +1453 -151
- 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/blueprint/normalize-document.js +5 -1
- package/dist/server/flow-surfaces/catalog.js +26 -9
- package/dist/server/flow-surfaces/chart-config.js +231 -14
- 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/contract-guard.js +40 -6
- package/dist/server/flow-surfaces/default-block-actions.js +2 -0
- package/dist/server/flow-surfaces/errors.d.ts +15 -0
- package/dist/server/flow-surfaces/errors.js +49 -3
- package/dist/server/flow-surfaces/event-flow-normalizer.d.ts +19 -0
- package/dist/server/flow-surfaces/event-flow-normalizer.js +128 -0
- package/dist/server/flow-surfaces/filter-group.d.ts +9 -1
- package/dist/server/flow-surfaces/filter-group.js +402 -3
- package/dist/server/flow-surfaces/locator.js +16 -2
- package/dist/server/flow-surfaces/public-data-surface-default-filter.js +2 -1
- package/dist/server/flow-surfaces/route-sync.js +19 -2
- package/dist/server/flow-surfaces/runjs-authoring/ast/bindings.d.ts +66 -0
- package/dist/server/flow-surfaces/runjs-authoring/ast/bindings.js +661 -0
- package/dist/server/flow-surfaces/runjs-authoring/ast/execution.d.ts +20 -0
- package/dist/server/flow-surfaces/runjs-authoring/ast/execution.js +275 -0
- package/dist/server/flow-surfaces/runjs-authoring/ast/parser.d.ts +16 -0
- package/dist/server/flow-surfaces/runjs-authoring/ast/parser.js +130 -0
- package/dist/server/flow-surfaces/runjs-authoring/ast/react-values.d.ts +20 -0
- package/dist/server/flow-surfaces/runjs-authoring/ast/react-values.js +401 -0
- package/dist/server/flow-surfaces/runjs-authoring/ast/request-config.d.ts +21 -0
- package/dist/server/flow-surfaces/runjs-authoring/ast/request-config.js +199 -0
- package/dist/server/flow-surfaces/runjs-authoring/ast/source.d.ts +70 -0
- package/dist/server/flow-surfaces/runjs-authoring/ast/source.js +895 -0
- package/dist/server/flow-surfaces/runjs-authoring/ast/static-bindings.d.ts +23 -0
- package/dist/server/flow-surfaces/runjs-authoring/ast/static-bindings.js +618 -0
- package/dist/server/flow-surfaces/runjs-authoring/ast/static-values.d.ts +196 -0
- package/dist/server/flow-surfaces/runjs-authoring/ast/static-values.js +1777 -0
- package/dist/server/flow-surfaces/runjs-authoring/ast/walk.d.ts +10 -0
- package/dist/server/flow-surfaces/runjs-authoring/ast/walk.js +55 -0
- package/dist/server/flow-surfaces/runjs-authoring/collectors.d.ts +12 -0
- package/dist/server/flow-surfaces/runjs-authoring/collectors.js +589 -0
- package/dist/server/flow-surfaces/runjs-authoring/ctx-libs-member-mismatch-stop/index.js +1 -1
- package/dist/server/flow-surfaces/runjs-authoring/index.d.ts +2 -25
- package/dist/server/flow-surfaces/runjs-authoring/index.js +5 -7033
- package/dist/server/flow-surfaces/runjs-authoring/inspect.d.ts +13 -0
- package/dist/server/flow-surfaces/runjs-authoring/inspect.js +149 -0
- package/dist/server/flow-surfaces/runjs-authoring/internal-types.d.ts +333 -0
- package/dist/server/flow-surfaces/runjs-authoring/internal-types.js +36 -0
- package/dist/server/flow-surfaces/runjs-authoring/rules.js +2 -0
- package/dist/server/flow-surfaces/runjs-authoring/runtime/constants.d.ts +67 -0
- package/dist/server/flow-surfaces/runjs-authoring/runtime/constants.js +757 -0
- package/dist/server/flow-surfaces/runjs-authoring/runtime/errors.d.ts +22 -0
- package/dist/server/flow-surfaces/runjs-authoring/runtime/errors.js +91 -0
- package/dist/server/flow-surfaces/runjs-authoring/runtime/source-budget.d.ts +16 -0
- package/dist/server/flow-surfaces/runjs-authoring/runtime/source-budget.js +115 -0
- package/dist/server/flow-surfaces/runjs-authoring/runtime/surface.d.ts +19 -0
- package/dist/server/flow-surfaces/runjs-authoring/runtime/surface.js +140 -0
- package/dist/server/flow-surfaces/runjs-authoring/runtime/types.d.ts +91 -0
- package/dist/server/flow-surfaces/runjs-authoring/runtime/types.js +24 -0
- package/dist/server/flow-surfaces/runjs-authoring/scan/ctx-api.d.ts +138 -0
- package/dist/server/flow-surfaces/runjs-authoring/scan/ctx-api.js +1779 -0
- package/dist/server/flow-surfaces/runjs-authoring/scan/filter.d.ts +10 -0
- package/dist/server/flow-surfaces/runjs-authoring/scan/filter.js +1583 -0
- package/dist/server/flow-surfaces/runjs-authoring/scan/index.d.ts +195 -0
- package/dist/server/flow-surfaces/runjs-authoring/scan/index.js +463 -0
- package/dist/server/flow-surfaces/runjs-authoring/scan/react-render.d.ts +48 -0
- package/dist/server/flow-surfaces/runjs-authoring/scan/react-render.js +379 -0
- package/dist/server/flow-surfaces/runjs-authoring/scan/react.d.ts +26 -0
- package/dist/server/flow-surfaces/runjs-authoring/scan/react.js +1441 -0
- package/dist/server/flow-surfaces/runjs-authoring/scan/resource.d.ts +23 -0
- package/dist/server/flow-surfaces/runjs-authoring/scan/resource.js +1427 -0
- package/dist/server/flow-surfaces/runjs-authoring/scan/source-patterns.d.ts +91 -0
- package/dist/server/flow-surfaces/runjs-authoring/scan/source-patterns.js +889 -0
- package/dist/server/flow-surfaces/runjs-authoring/types.d.ts +1 -1
- package/dist/server/flow-surfaces/runjs-authoring/unknown-global-stop/index.d.ts +10 -0
- package/dist/server/flow-surfaces/runjs-authoring/unknown-global-stop/index.js +40 -0
- package/dist/server/flow-surfaces/runjs-authoring/validators/index.d.ts +12 -0
- package/dist/server/flow-surfaces/runjs-authoring/validators/index.js +887 -0
- package/dist/server/flow-surfaces/service-helpers.d.ts +29 -0
- package/dist/server/flow-surfaces/service-helpers.js +105 -0
- package/dist/server/flow-surfaces/service-utils.d.ts +17 -3
- package/dist/server/flow-surfaces/service-utils.js +14 -5
- package/dist/server/flow-surfaces/service.d.ts +74 -15
- package/dist/server/flow-surfaces/service.js +1781 -193
- package/dist/server/flow-surfaces/template-service-utils.d.ts +1 -0
- package/dist/server/flow-surfaces/types.d.ts +3 -0
- package/dist/server/repository.d.ts +12 -1
- package/dist/server/repository.js +195 -23
- package/dist/swagger/flow-surfaces.d.ts +180 -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 +136 -54
- package/dist/swagger/index.d.ts +180 -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");
|
|
@@ -80,6 +81,7 @@ var import_placement = require("./placement");
|
|
|
80
81
|
var import_route_sync = require("./route-sync");
|
|
81
82
|
var import_surface_context = require("./surface-context");
|
|
82
83
|
var import_context = require("./context");
|
|
84
|
+
var import_event_flow_normalizer = require("./event-flow-normalizer");
|
|
83
85
|
var import_configure_options = require("./configure-options");
|
|
84
86
|
var import_public_compatibility = require("./public-compatibility");
|
|
85
87
|
var import_support_matrix = require("./support-matrix");
|
|
@@ -102,6 +104,131 @@ var import_template_service_utils = require("./template-service-utils");
|
|
|
102
104
|
var import_hidden_popup_contract = require("./hidden-popup-contract");
|
|
103
105
|
var import_hidden_popup_calendar = require("./hidden-popup-calendar");
|
|
104
106
|
var import_hidden_popup_kanban = require("./hidden-popup-kanban");
|
|
107
|
+
const FLOW_SURFACE_CHART_REPAIR_HINT = "This is a chart payload shape problem. Keep using chart and 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.";
|
|
108
|
+
const FLOW_SURFACE_CHART_REPAIR_STEPS = [
|
|
109
|
+
"Keep the block type as chart.",
|
|
110
|
+
"Define assets.charts.<key>.query and assets.charts.<key>.visual, or fill localized settings.query and settings.visual on the existing chart block.",
|
|
111
|
+
"Reference the asset from the chart block with block.chart = <key> when using assets.charts.",
|
|
112
|
+
"Retry the chart payload instead of replacing the chart with another block type, omitting it, or deferring it."
|
|
113
|
+
];
|
|
114
|
+
const FLOW_SURFACE_CHART_EXPECTED_SHAPE = {
|
|
115
|
+
settings: {
|
|
116
|
+
query: {
|
|
117
|
+
mode: "builder",
|
|
118
|
+
resource: {
|
|
119
|
+
dataSourceKey: "main",
|
|
120
|
+
collectionName: "employees"
|
|
121
|
+
},
|
|
122
|
+
measures: [
|
|
123
|
+
{
|
|
124
|
+
field: "id",
|
|
125
|
+
aggregation: "count",
|
|
126
|
+
alias: "employeeCount"
|
|
127
|
+
}
|
|
128
|
+
]
|
|
129
|
+
},
|
|
130
|
+
visual: {
|
|
131
|
+
mode: "basic",
|
|
132
|
+
type: "bar",
|
|
133
|
+
mappings: {
|
|
134
|
+
x: "status",
|
|
135
|
+
y: "employeeCount"
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
},
|
|
139
|
+
assets: {
|
|
140
|
+
charts: {
|
|
141
|
+
chartKey: {
|
|
142
|
+
query: "builder/sql query configuration",
|
|
143
|
+
visual: "basic/custom visual configuration"
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
},
|
|
147
|
+
block: {
|
|
148
|
+
type: "chart",
|
|
149
|
+
chart: "chartKey"
|
|
150
|
+
}
|
|
151
|
+
};
|
|
152
|
+
const FLOW_SURFACE_CHART_FORBIDDEN_FALLBACKS = [
|
|
153
|
+
"table",
|
|
154
|
+
"list",
|
|
155
|
+
"jsBlock",
|
|
156
|
+
"actionPanel",
|
|
157
|
+
"gridCard",
|
|
158
|
+
"markdown",
|
|
159
|
+
"drop chart",
|
|
160
|
+
"defer chart"
|
|
161
|
+
];
|
|
162
|
+
const FLOW_SURFACE_CHART_REPAIR_EXAMPLE = {
|
|
163
|
+
settings: {
|
|
164
|
+
query: {
|
|
165
|
+
mode: "builder",
|
|
166
|
+
resource: {
|
|
167
|
+
dataSourceKey: "main",
|
|
168
|
+
collectionName: "<collectionName>"
|
|
169
|
+
},
|
|
170
|
+
measures: [
|
|
171
|
+
{
|
|
172
|
+
field: "id",
|
|
173
|
+
aggregation: "count",
|
|
174
|
+
alias: "recordCount"
|
|
175
|
+
}
|
|
176
|
+
],
|
|
177
|
+
dimensions: [
|
|
178
|
+
{
|
|
179
|
+
field: "<dimensionField>"
|
|
180
|
+
}
|
|
181
|
+
]
|
|
182
|
+
},
|
|
183
|
+
visual: {
|
|
184
|
+
mode: "basic",
|
|
185
|
+
type: "bar",
|
|
186
|
+
mappings: {
|
|
187
|
+
x: "<dimensionField>",
|
|
188
|
+
y: "recordCount"
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
};
|
|
193
|
+
function withChartRepairMessage(message) {
|
|
194
|
+
return `${message}. ${FLOW_SURFACE_CHART_REPAIR_HINT}`;
|
|
195
|
+
}
|
|
196
|
+
function withFlowSurfaceChartRepairDetails(details = {}) {
|
|
197
|
+
return {
|
|
198
|
+
...details,
|
|
199
|
+
requiredBlockType: "chart",
|
|
200
|
+
fixStrategy: "repair_same_block_type",
|
|
201
|
+
repairHint: FLOW_SURFACE_CHART_REPAIR_HINT,
|
|
202
|
+
repairSteps: FLOW_SURFACE_CHART_REPAIR_STEPS,
|
|
203
|
+
expectedShape: FLOW_SURFACE_CHART_EXPECTED_SHAPE,
|
|
204
|
+
repairExample: FLOW_SURFACE_CHART_REPAIR_EXAMPLE,
|
|
205
|
+
forbiddenFallbacks: FLOW_SURFACE_CHART_FORBIDDEN_FALLBACKS
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
function throwChartRepairBadRequest(message, options = {}) {
|
|
209
|
+
const details = import_lodash.default.isPlainObject(options.details) ? options.details : {};
|
|
210
|
+
(0, import_errors.throwBadRequest)(withChartRepairMessage(message), {
|
|
211
|
+
...options,
|
|
212
|
+
details: withFlowSurfaceChartRepairDetails(details)
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
function isChartConfigureBadRequestError(error) {
|
|
216
|
+
return error instanceof import_errors.FlowSurfaceBadRequestError && String(error.message || "").startsWith("chart ");
|
|
217
|
+
}
|
|
218
|
+
function buildChartConfigureFromSemanticChangesWithRepair(currentConfigure, changes) {
|
|
219
|
+
try {
|
|
220
|
+
return (0, import_chart_config.buildChartConfigureFromSemanticChanges)(currentConfigure, changes);
|
|
221
|
+
} catch (error) {
|
|
222
|
+
if (isChartConfigureBadRequestError(error)) {
|
|
223
|
+
throwChartRepairBadRequest(error.message, error.options);
|
|
224
|
+
}
|
|
225
|
+
throw error;
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
function isFlowSurfaceChartRepairError(error) {
|
|
229
|
+
var _a, _b;
|
|
230
|
+
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;
|
|
231
|
+
}
|
|
105
232
|
const FORM_BLOCK_USES = /* @__PURE__ */ new Set(["FormBlockModel", "CreateFormModel", "EditFormModel", ...import_approval.APPROVAL_FORM_BLOCK_USES]);
|
|
106
233
|
const AUTO_SUBMIT_FORM_BLOCK_USES = /* @__PURE__ */ new Set(["CreateFormModel", "EditFormModel"]);
|
|
107
234
|
const FLOW_SURFACE_DEFAULT_ACTION_SETTINGS_KEYS = /* @__PURE__ */ new Set(["filter"]);
|
|
@@ -251,6 +378,17 @@ const JS_ACTION_USES = /* @__PURE__ */ new Set([
|
|
|
251
378
|
"JSActionModel"
|
|
252
379
|
]);
|
|
253
380
|
const JS_ITEM_ACTION_USES = /* @__PURE__ */ new Set(["JSItemActionModel"]);
|
|
381
|
+
const JS_POPUP_GUIDANCE_MESSAGE = "should use ctx.openView to open popup";
|
|
382
|
+
const JS_POPUP_GUIDANCE_USES = /* @__PURE__ */ new Set([
|
|
383
|
+
...JS_ACTION_USES,
|
|
384
|
+
...JS_ITEM_ACTION_USES,
|
|
385
|
+
"JSColumnModel",
|
|
386
|
+
"JSItemModel",
|
|
387
|
+
"JSFieldModel",
|
|
388
|
+
"JSEditableFieldModel",
|
|
389
|
+
"FormJSFieldItemModel"
|
|
390
|
+
]);
|
|
391
|
+
const JS_POPUP_GUIDANCE_PUBLIC_KEYS = /* @__PURE__ */ new Set(["js", "jsColumn", "jsItem"]);
|
|
254
392
|
const POPUP_ACTION_USES = /* @__PURE__ */ new Set([
|
|
255
393
|
"AddNewActionModel",
|
|
256
394
|
"ViewActionModel",
|
|
@@ -264,6 +402,24 @@ const POPUP_ACTION_USES = /* @__PURE__ */ new Set([
|
|
|
264
402
|
"AddChildActionModel",
|
|
265
403
|
"MailSendActionModel"
|
|
266
404
|
]);
|
|
405
|
+
function withJsPopupGuidance(message, value) {
|
|
406
|
+
const normalizedValue = String(value || "").trim();
|
|
407
|
+
if (JS_POPUP_GUIDANCE_USES.has(normalizedValue) || JS_POPUP_GUIDANCE_PUBLIC_KEYS.has(normalizedValue)) {
|
|
408
|
+
return `${message}; ${JS_POPUP_GUIDANCE_MESSAGE}`;
|
|
409
|
+
}
|
|
410
|
+
return message;
|
|
411
|
+
}
|
|
412
|
+
function assertNoJsDeclarativeOpenView(context, changes, use) {
|
|
413
|
+
const normalizedUse = String(use || "").trim();
|
|
414
|
+
if ((0, import_service_utils.hasOwnDefined)(changes, "openView") && JS_POPUP_GUIDANCE_USES.has(normalizedUse)) {
|
|
415
|
+
(0, import_errors.throwBadRequest)(
|
|
416
|
+
withJsPopupGuidance(
|
|
417
|
+
`flowSurfaces configure ${context} '${normalizedUse}' does not support openView`,
|
|
418
|
+
normalizedUse
|
|
419
|
+
)
|
|
420
|
+
);
|
|
421
|
+
}
|
|
422
|
+
}
|
|
267
423
|
const POPUP_HOST_DEFAULT_RECORD_CONTEXT_ACTION_USES = /* @__PURE__ */ new Set([
|
|
268
424
|
"ViewActionModel",
|
|
269
425
|
"EditActionModel",
|
|
@@ -457,16 +613,25 @@ const UPDATE_SETTINGS_STEP_PARAM_MIRRORS_BY_USE = {
|
|
|
457
613
|
DividerItemModel: DIVIDER_ITEM_STEP_PARAM_MIRRORS
|
|
458
614
|
};
|
|
459
615
|
const FLOW_SURFACE_MENU_BINDABLE_OPTION_KEY = "flowSurfaceMenuBindable";
|
|
616
|
+
const ANT_DESIGN_ICON_NAMES = new Set(Object.keys(antDesignIconAsn || {}));
|
|
460
617
|
const AI_EMPLOYEE_ACTION_USE = "AIEmployeeButtonModel";
|
|
461
618
|
const AI_EMPLOYEE_OWNER_PLUGIN = "@nocobase/plugin-ai";
|
|
462
619
|
const AI_EMPLOYEE_PUBLIC_SETTING_KEYS = ["username", "auto", "workContext", "tasks", "style"];
|
|
463
620
|
const AI_EMPLOYEE_INTERNAL_PROP_KEYS = ["aiEmployee", "context", "auto", "tasks", "style"];
|
|
621
|
+
const AI_EMPLOYEE_TASK_STEP_PARAMS_PATH = ["shortcutSettings", "editTasks", "tasks"];
|
|
464
622
|
const AI_EMPLOYEE_WORK_CONTEXT_PUBLIC_KEYS = ["type", "uid", "target"];
|
|
465
623
|
const AI_EMPLOYEE_TASK_PUBLIC_SETTING_KEYS = ["title", "message", "autoSend", "skillSettings", "model", "webSearch"];
|
|
624
|
+
const AI_EMPLOYEE_TASK_PATCH_PUBLIC_SETTING_KEYS = [...AI_EMPLOYEE_TASK_PUBLIC_SETTING_KEYS, "prompt"];
|
|
466
625
|
const AI_EMPLOYEE_TASK_MESSAGE_PUBLIC_KEYS = ["system", "user", "workContext"];
|
|
467
626
|
const AI_EMPLOYEE_TASK_MODEL_PUBLIC_KEYS = ["llmService", "model"];
|
|
468
627
|
const AI_EMPLOYEE_SKILL_SETTINGS_PUBLIC_KEYS = ["skills", "tools", "skillsVersion", "toolsVersion"];
|
|
469
628
|
const AI_EMPLOYEE_STYLE_PUBLIC_KEYS = ["size", "mask"];
|
|
629
|
+
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.';
|
|
630
|
+
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.";
|
|
631
|
+
const AI_EMPLOYEE_PROMPT_CONTEXT_MAX_DEPTH = 8;
|
|
632
|
+
const AI_EMPLOYEE_PROMPT_VARIABLE_INVALID = "FLOW_SURFACE_AI_EMPLOYEE_PROMPT_VARIABLE_INVALID";
|
|
633
|
+
const AI_EMPLOYEE_CURRENT_RECORD_PROMPT_VARIABLE = "{{ ctx.record }}";
|
|
634
|
+
const AI_EMPLOYEE_CURRENT_RECORD_PROMPT_VARIABLE_RE = /\{\{\s*ctx\.record\s*\}\}/;
|
|
470
635
|
const AI_EMPLOYEE_DEFAULT_STYLE = {
|
|
471
636
|
size: 40,
|
|
472
637
|
mask: false
|
|
@@ -710,10 +875,16 @@ class FlowSurfacesService {
|
|
|
710
875
|
);
|
|
711
876
|
}
|
|
712
877
|
async loadEnabledPluginPackages(transaction) {
|
|
713
|
-
|
|
878
|
+
var _a;
|
|
879
|
+
const db = this.db;
|
|
880
|
+
if (!((_a = db == null ? void 0 : db.getCollection) == null ? void 0 : _a.call(db, "applicationPlugins")) || !(db == null ? void 0 : db.getRepository)) {
|
|
881
|
+
return /* @__PURE__ */ new Set();
|
|
882
|
+
}
|
|
883
|
+
const repository = db.getRepository("applicationPlugins");
|
|
884
|
+
if (!(repository == null ? void 0 : repository.find)) {
|
|
714
885
|
return /* @__PURE__ */ new Set();
|
|
715
886
|
}
|
|
716
|
-
const plugins = await
|
|
887
|
+
const plugins = await repository.find({
|
|
717
888
|
fields: ["packageName"],
|
|
718
889
|
filter: {
|
|
719
890
|
enabled: true
|
|
@@ -721,8 +892,8 @@ class FlowSurfacesService {
|
|
|
721
892
|
transaction
|
|
722
893
|
});
|
|
723
894
|
const packageNames = plugins.map((plugin) => {
|
|
724
|
-
var
|
|
725
|
-
return ((
|
|
895
|
+
var _a2;
|
|
896
|
+
return ((_a2 = plugin == null ? void 0 : plugin.get) == null ? void 0 : _a2.call(plugin, "packageName")) || (plugin == null ? void 0 : plugin.packageName);
|
|
726
897
|
}).filter((packageName) => typeof packageName === "string" && !!packageName.trim()).map((packageName) => packageName.trim());
|
|
727
898
|
return new Set(packageNames);
|
|
728
899
|
}
|
|
@@ -762,6 +933,18 @@ class FlowSurfacesService {
|
|
|
762
933
|
})
|
|
763
934
|
);
|
|
764
935
|
}
|
|
936
|
+
routeParentIdMatches(routeParentId, parentId) {
|
|
937
|
+
if (import_lodash.default.isNil(routeParentId) && import_lodash.default.isNil(parentId)) {
|
|
938
|
+
return true;
|
|
939
|
+
}
|
|
940
|
+
return String(routeParentId ?? "") === String(parentId ?? "");
|
|
941
|
+
}
|
|
942
|
+
async findMenuGroupRoutesByParentIdAndTitle(parentId, title, transaction) {
|
|
943
|
+
const routes = await this.findMenuGroupRoutesByTitle(title, transaction);
|
|
944
|
+
return routes.filter(
|
|
945
|
+
(route) => this.routeParentIdMatches(this.readRouteField(route, "parentId") ?? null, parentId)
|
|
946
|
+
);
|
|
947
|
+
}
|
|
765
948
|
async findFlowPageRoutesByParentIdAndTitle(parentId, title, transaction) {
|
|
766
949
|
const normalizedTitle = String(title || "").trim();
|
|
767
950
|
const normalizedParentId = String(parentId ?? "").trim();
|
|
@@ -843,20 +1026,97 @@ class FlowSurfacesService {
|
|
|
843
1026
|
...extras
|
|
844
1027
|
};
|
|
845
1028
|
}
|
|
1029
|
+
isValidMenuIconName(value) {
|
|
1030
|
+
const normalized = String(value || "").trim();
|
|
1031
|
+
return !!normalized && ANT_DESIGN_ICON_NAMES.has(normalized);
|
|
1032
|
+
}
|
|
1033
|
+
assertVisibleNavigationIcon(actionName, path, values) {
|
|
1034
|
+
if (values.hideInMenu === true) {
|
|
1035
|
+
return;
|
|
1036
|
+
}
|
|
1037
|
+
const icon = String(values.icon || "").trim();
|
|
1038
|
+
if (!icon) {
|
|
1039
|
+
(0, import_errors.throwBadRequest)(`flowSurfaces ${actionName} ${path}.icon is required when creating a visible menu route`, {
|
|
1040
|
+
ruleId: "navigation-icon-required",
|
|
1041
|
+
path: `${path}.icon`,
|
|
1042
|
+
details: {
|
|
1043
|
+
repairHint: "Pass a valid Ant Design icon name such as AppstoreOutlined, DashboardOutlined, or FolderOpenOutlined."
|
|
1044
|
+
}
|
|
1045
|
+
});
|
|
1046
|
+
}
|
|
1047
|
+
if (!this.isValidMenuIconName(icon)) {
|
|
1048
|
+
(0, import_errors.throwBadRequest)(`flowSurfaces ${actionName} ${path}.icon must be a valid Ant Design icon name`, {
|
|
1049
|
+
ruleId: "navigation-icon-unknown",
|
|
1050
|
+
path: `${path}.icon`,
|
|
1051
|
+
details: {
|
|
1052
|
+
icon
|
|
1053
|
+
}
|
|
1054
|
+
});
|
|
1055
|
+
}
|
|
1056
|
+
}
|
|
1057
|
+
assertVisibleNavigationRouteIconUpdate(actionName, path, route, values) {
|
|
1058
|
+
if (!Object.prototype.hasOwnProperty.call(values, "icon") || this.readRouteField(route, "hideInMenu") === true) {
|
|
1059
|
+
return;
|
|
1060
|
+
}
|
|
1061
|
+
const icon = String(values.icon || "").trim();
|
|
1062
|
+
if (!icon) {
|
|
1063
|
+
(0, import_errors.throwBadRequest)(`flowSurfaces ${actionName} ${path}.icon cannot be empty for a visible menu route`, {
|
|
1064
|
+
ruleId: "navigation-icon-required",
|
|
1065
|
+
path: `${path}.icon`,
|
|
1066
|
+
details: {
|
|
1067
|
+
repairHint: "Pass a valid Ant Design icon name such as AppstoreOutlined, DashboardOutlined, or FolderOpenOutlined."
|
|
1068
|
+
}
|
|
1069
|
+
});
|
|
1070
|
+
}
|
|
1071
|
+
if (!this.isValidMenuIconName(icon)) {
|
|
1072
|
+
(0, import_errors.throwBadRequest)(`flowSurfaces ${actionName} ${path}.icon must be a valid Ant Design icon name`, {
|
|
1073
|
+
ruleId: "navigation-icon-unknown",
|
|
1074
|
+
path: `${path}.icon`,
|
|
1075
|
+
details: {
|
|
1076
|
+
icon
|
|
1077
|
+
}
|
|
1078
|
+
});
|
|
1079
|
+
}
|
|
1080
|
+
}
|
|
846
1081
|
async createFlowMenuGroup(values, transaction) {
|
|
847
1082
|
const parentRoute = await this.assertMenuParentIsGroup(values.parentMenuRouteId, transaction);
|
|
1083
|
+
const parentId = this.readRouteField(parentRoute, "id") ?? null;
|
|
1084
|
+
const title = String(values.title || "").trim();
|
|
1085
|
+
const existingGroups = await this.findMenuGroupRoutesByParentIdAndTitle(parentId, title, transaction);
|
|
1086
|
+
if (existingGroups.length === 1) {
|
|
1087
|
+
return this.buildMenuResult(existingGroups[0]);
|
|
1088
|
+
}
|
|
1089
|
+
if (existingGroups.length > 1) {
|
|
1090
|
+
(0, import_errors.throwBadRequest)(
|
|
1091
|
+
`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`,
|
|
1092
|
+
{
|
|
1093
|
+
ruleId: "menu-group-title-ambiguous-under-parent",
|
|
1094
|
+
details: {
|
|
1095
|
+
title,
|
|
1096
|
+
parentMenuRouteId: values.parentMenuRouteId ?? null,
|
|
1097
|
+
matches: existingGroups.map((route2) => ({
|
|
1098
|
+
routeId: this.readRouteField(route2, "id"),
|
|
1099
|
+
parentMenuRouteId: this.readRouteField(route2, "parentId") ?? null,
|
|
1100
|
+
type: this.readRouteField(route2, "type"),
|
|
1101
|
+
schemaUid: this.readRouteField(route2, "schemaUid") ?? null
|
|
1102
|
+
}))
|
|
1103
|
+
}
|
|
1104
|
+
}
|
|
1105
|
+
);
|
|
1106
|
+
}
|
|
1107
|
+
this.assertVisibleNavigationIcon("createMenu", "values", values);
|
|
848
1108
|
const schemaUid = values.schemaUid || (0, import_utils.uid)();
|
|
849
1109
|
const desktopRoutes = this.db.getRepository("desktopRoutes");
|
|
850
1110
|
await desktopRoutes.create({
|
|
851
1111
|
values: {
|
|
852
1112
|
type: "group",
|
|
853
1113
|
sort: this.allocateRouteSortValue(),
|
|
854
|
-
title
|
|
1114
|
+
title,
|
|
855
1115
|
icon: values.icon,
|
|
856
1116
|
tooltip: values.tooltip,
|
|
857
1117
|
schemaUid,
|
|
858
1118
|
hideInMenu: !!values.hideInMenu,
|
|
859
|
-
parentId
|
|
1119
|
+
parentId
|
|
860
1120
|
},
|
|
861
1121
|
transaction
|
|
862
1122
|
});
|
|
@@ -869,6 +1129,7 @@ class FlowSurfacesService {
|
|
|
869
1129
|
async createFlowMenuItem(values, transaction) {
|
|
870
1130
|
var _a;
|
|
871
1131
|
const parentRoute = await this.assertMenuParentIsGroup(values.parentMenuRouteId, transaction);
|
|
1132
|
+
this.assertVisibleNavigationIcon("createMenu", "values", values);
|
|
872
1133
|
const pageSchemaUid = values.pageSchemaUid || (0, import_utils.uid)();
|
|
873
1134
|
const pageUid = values.pageUid || (0, import_utils.uid)();
|
|
874
1135
|
const tabSchemaUid = values.tabSchemaUid || (0, import_utils.uid)();
|
|
@@ -903,7 +1164,7 @@ class FlowSurfacesService {
|
|
|
903
1164
|
parentId: null,
|
|
904
1165
|
options: {
|
|
905
1166
|
documentTitle: values.tabDocumentTitle,
|
|
906
|
-
flowRegistry: values.tabFlowRegistry || {}
|
|
1167
|
+
flowRegistry: this.normalizeEventFlowRegistry("createMenu", values.tabFlowRegistry || {})
|
|
907
1168
|
}
|
|
908
1169
|
}
|
|
909
1170
|
]
|
|
@@ -2596,6 +2857,10 @@ class FlowSurfacesService {
|
|
|
2596
2857
|
),
|
|
2597
2858
|
options.transaction
|
|
2598
2859
|
);
|
|
2860
|
+
if (!(rawNode == null ? void 0 : rawNode.uid)) {
|
|
2861
|
+
const resolvedUid = String((resolved == null ? void 0 : resolved.uid) || "").trim() || String(target.uid || target.tabSchemaUid || target.pageSchemaUid || target.routeId || "").trim() || "unknown";
|
|
2862
|
+
(0, import_errors.throwBadRequest)(`flowSurfaces:get target '${resolvedUid}' could not resolve a readable surface tree`);
|
|
2863
|
+
}
|
|
2599
2864
|
const publicNode = this.stripInternalSurfaceMetaFromNodeTree(import_lodash.default.cloneDeep(rawNode));
|
|
2600
2865
|
return this.buildSurfaceReadPayload(target, resolved, publicNode, options);
|
|
2601
2866
|
}
|
|
@@ -2630,7 +2895,7 @@ class FlowSurfacesService {
|
|
|
2630
2895
|
use: "RootPageTabModel",
|
|
2631
2896
|
props: import_lodash.default.omit(import_lodash.default.cloneDeep((currentNode == null ? void 0 : currentNode.props) || {}), ["route"]),
|
|
2632
2897
|
decoratorProps: import_lodash.default.cloneDeep((currentNode == null ? void 0 : currentNode.decoratorProps) || {}),
|
|
2633
|
-
flowRegistry:
|
|
2898
|
+
flowRegistry: this.getEventFlowRegistry(currentNode),
|
|
2634
2899
|
stepParams: import_lodash.default.cloneDeep((values == null ? void 0 : values.stepParams) || (currentNode == null ? void 0 : currentNode.stepParams) || {})
|
|
2635
2900
|
}),
|
|
2636
2901
|
{ transaction: options == null ? void 0 : options.transaction }
|
|
@@ -2767,13 +3032,13 @@ class FlowSurfacesService {
|
|
|
2767
3032
|
if (!groupTitle) {
|
|
2768
3033
|
return document;
|
|
2769
3034
|
}
|
|
2770
|
-
const matchedRoutes = await this.
|
|
3035
|
+
const matchedRoutes = await this.findMenuGroupRoutesByParentIdAndTitle(null, groupTitle, transaction);
|
|
2771
3036
|
if (!matchedRoutes.length) {
|
|
2772
3037
|
return document;
|
|
2773
3038
|
}
|
|
2774
3039
|
if (matchedRoutes.length > 1) {
|
|
2775
3040
|
(0, import_errors.throwBadRequest)(
|
|
2776
|
-
`flowSurfaces applyBlueprint navigation.group.title '${groupTitle}' matches ${matchedRoutes.length} existing menu groups; pass navigation.group.routeId explicitly`
|
|
3041
|
+
`flowSurfaces applyBlueprint navigation.group.title '${groupTitle}' matches ${matchedRoutes.length} existing root menu groups; pass navigation.group.routeId explicitly`
|
|
2777
3042
|
);
|
|
2778
3043
|
}
|
|
2779
3044
|
const routeId = this.readRouteField(matchedRoutes[0], "id");
|
|
@@ -2843,6 +3108,225 @@ class FlowSurfacesService {
|
|
|
2843
3108
|
getCollection: (dataSourceKey, collectionName) => this.getCollection(dataSourceKey || "main", collectionName || "")
|
|
2844
3109
|
});
|
|
2845
3110
|
}
|
|
3111
|
+
async prevalidateApplyBlueprintChartAssets(document, transaction) {
|
|
3112
|
+
var _a;
|
|
3113
|
+
const chartAssets = import_lodash.default.isPlainObject((_a = document.assets) == null ? void 0 : _a.charts) ? document.assets.charts : {};
|
|
3114
|
+
for (const [chartKey, chartAsset] of Object.entries(chartAssets)) {
|
|
3115
|
+
if (!import_lodash.default.isPlainObject(chartAsset)) {
|
|
3116
|
+
continue;
|
|
3117
|
+
}
|
|
3118
|
+
(0, import_service_utils.assertSupportedSimpleChanges)("chart", chartAsset, (0, import_configure_options.getConfigureOptionKeysForUse)("ChartBlockModel"));
|
|
3119
|
+
const nextConfigure = buildChartConfigureFromSemanticChangesWithRepair(void 0, chartAsset);
|
|
3120
|
+
await this.validateChartConfigureForRuntime(
|
|
3121
|
+
`applyBlueprint assets.charts.${chartKey}`,
|
|
3122
|
+
nextConfigure,
|
|
3123
|
+
transaction
|
|
3124
|
+
);
|
|
3125
|
+
}
|
|
3126
|
+
}
|
|
3127
|
+
composeChartBlockHasInlineConfig(block) {
|
|
3128
|
+
const settings = import_lodash.default.isPlainObject(block.settings) ? block.settings : {};
|
|
3129
|
+
return ["configure", "query", "visual", "events"].some(
|
|
3130
|
+
(key) => Object.prototype.hasOwnProperty.call(settings, key)
|
|
3131
|
+
);
|
|
3132
|
+
}
|
|
3133
|
+
prepareComposeChartAssetNestedPopupBlocks(input, path, chartAssets) {
|
|
3134
|
+
if (!import_lodash.default.isPlainObject(input)) {
|
|
3135
|
+
return { value: input, didResolveChartAsset: false };
|
|
3136
|
+
}
|
|
3137
|
+
let didResolveChartAsset = false;
|
|
3138
|
+
let nextInput = input;
|
|
3139
|
+
const ensureNextInput = () => {
|
|
3140
|
+
if (nextInput === input) {
|
|
3141
|
+
nextInput = { ...input };
|
|
3142
|
+
}
|
|
3143
|
+
return nextInput;
|
|
3144
|
+
};
|
|
3145
|
+
const preparePopupBlocks = (key) => {
|
|
3146
|
+
const popup = input[key];
|
|
3147
|
+
if (!import_lodash.default.isPlainObject(popup) || !Array.isArray(popup.blocks)) {
|
|
3148
|
+
return;
|
|
3149
|
+
}
|
|
3150
|
+
const prepared = this.prepareComposeChartAssetBlockList(popup.blocks, `${path}.${key}.blocks`, chartAssets);
|
|
3151
|
+
if (!prepared.didResolveChartAsset) {
|
|
3152
|
+
return;
|
|
3153
|
+
}
|
|
3154
|
+
ensureNextInput()[key] = {
|
|
3155
|
+
...popup,
|
|
3156
|
+
blocks: prepared.blocks
|
|
3157
|
+
};
|
|
3158
|
+
didResolveChartAsset = true;
|
|
3159
|
+
};
|
|
3160
|
+
preparePopupBlocks("popup");
|
|
3161
|
+
preparePopupBlocks("openView");
|
|
3162
|
+
return {
|
|
3163
|
+
value: nextInput,
|
|
3164
|
+
didResolveChartAsset
|
|
3165
|
+
};
|
|
3166
|
+
}
|
|
3167
|
+
prepareComposeChartAssetBlockList(blocks, path, chartAssets) {
|
|
3168
|
+
const rawBlocks = import_lodash.default.castArray(blocks || []);
|
|
3169
|
+
if (!rawBlocks.length) {
|
|
3170
|
+
return { blocks: rawBlocks, didResolveChartAsset: false };
|
|
3171
|
+
}
|
|
3172
|
+
let didResolveChartAsset = false;
|
|
3173
|
+
const hiddenPopupKeys = [
|
|
3174
|
+
"quickCreatePopup",
|
|
3175
|
+
"eventPopup",
|
|
3176
|
+
"cardPopup",
|
|
3177
|
+
"quickCreatePopupSettings",
|
|
3178
|
+
"eventPopupSettings",
|
|
3179
|
+
"cardPopupSettings"
|
|
3180
|
+
];
|
|
3181
|
+
const nextBlocks = rawBlocks.map((block, index) => {
|
|
3182
|
+
if (!import_lodash.default.isPlainObject(block)) {
|
|
3183
|
+
return block;
|
|
3184
|
+
}
|
|
3185
|
+
const blockPath = `${path}[${index}]`;
|
|
3186
|
+
let nextBlock = block;
|
|
3187
|
+
const ensureNextBlock = () => {
|
|
3188
|
+
if (nextBlock === block) {
|
|
3189
|
+
nextBlock = { ...block };
|
|
3190
|
+
}
|
|
3191
|
+
return nextBlock;
|
|
3192
|
+
};
|
|
3193
|
+
if (Array.isArray(block.blocks)) {
|
|
3194
|
+
const prepared = this.prepareComposeChartAssetBlockList(block.blocks, `${blockPath}.blocks`, chartAssets);
|
|
3195
|
+
if (prepared.didResolveChartAsset) {
|
|
3196
|
+
ensureNextBlock().blocks = prepared.blocks;
|
|
3197
|
+
didResolveChartAsset = true;
|
|
3198
|
+
}
|
|
3199
|
+
}
|
|
3200
|
+
for (const slot of ["actions", "recordActions", "fields"]) {
|
|
3201
|
+
if (!Array.isArray(block[slot])) {
|
|
3202
|
+
continue;
|
|
3203
|
+
}
|
|
3204
|
+
let didPrepareSlot = false;
|
|
3205
|
+
const nextItems = block[slot].map((item, itemIndex) => {
|
|
3206
|
+
const prepared = this.prepareComposeChartAssetNestedPopupBlocks(
|
|
3207
|
+
item,
|
|
3208
|
+
`${blockPath}.${slot}[${itemIndex}]`,
|
|
3209
|
+
chartAssets
|
|
3210
|
+
);
|
|
3211
|
+
didPrepareSlot = didPrepareSlot || prepared.didResolveChartAsset;
|
|
3212
|
+
return prepared.value;
|
|
3213
|
+
});
|
|
3214
|
+
if (didPrepareSlot) {
|
|
3215
|
+
ensureNextBlock()[slot] = nextItems;
|
|
3216
|
+
didResolveChartAsset = true;
|
|
3217
|
+
}
|
|
3218
|
+
}
|
|
3219
|
+
if (Array.isArray(block.fieldGroups)) {
|
|
3220
|
+
let didPrepareFieldGroups = false;
|
|
3221
|
+
const nextFieldGroups = block.fieldGroups.map((group, groupIndex) => {
|
|
3222
|
+
if (!import_lodash.default.isPlainObject(group) || !Array.isArray(group.fields)) {
|
|
3223
|
+
return group;
|
|
3224
|
+
}
|
|
3225
|
+
let didPrepareGroupFields = false;
|
|
3226
|
+
const nextFields = group.fields.map((field, fieldIndex) => {
|
|
3227
|
+
const prepared = this.prepareComposeChartAssetNestedPopupBlocks(
|
|
3228
|
+
field,
|
|
3229
|
+
`${blockPath}.fieldGroups[${groupIndex}].fields[${fieldIndex}]`,
|
|
3230
|
+
chartAssets
|
|
3231
|
+
);
|
|
3232
|
+
didPrepareGroupFields = didPrepareGroupFields || prepared.didResolveChartAsset;
|
|
3233
|
+
return prepared.value;
|
|
3234
|
+
});
|
|
3235
|
+
if (!didPrepareGroupFields) {
|
|
3236
|
+
return group;
|
|
3237
|
+
}
|
|
3238
|
+
didPrepareFieldGroups = true;
|
|
3239
|
+
return {
|
|
3240
|
+
...group,
|
|
3241
|
+
fields: nextFields
|
|
3242
|
+
};
|
|
3243
|
+
});
|
|
3244
|
+
if (didPrepareFieldGroups) {
|
|
3245
|
+
ensureNextBlock().fieldGroups = nextFieldGroups;
|
|
3246
|
+
didResolveChartAsset = true;
|
|
3247
|
+
}
|
|
3248
|
+
}
|
|
3249
|
+
if (import_lodash.default.isPlainObject(block.popup) && Array.isArray(block.popup.blocks)) {
|
|
3250
|
+
const prepared = this.prepareComposeChartAssetBlockList(
|
|
3251
|
+
block.popup.blocks,
|
|
3252
|
+
`${blockPath}.popup.blocks`,
|
|
3253
|
+
chartAssets
|
|
3254
|
+
);
|
|
3255
|
+
if (prepared.didResolveChartAsset) {
|
|
3256
|
+
ensureNextBlock().popup = {
|
|
3257
|
+
...block.popup,
|
|
3258
|
+
blocks: prepared.blocks
|
|
3259
|
+
};
|
|
3260
|
+
didResolveChartAsset = true;
|
|
3261
|
+
}
|
|
3262
|
+
}
|
|
3263
|
+
if (import_lodash.default.isPlainObject(block.settings)) {
|
|
3264
|
+
for (const key of hiddenPopupKeys) {
|
|
3265
|
+
const popup = block.settings[key];
|
|
3266
|
+
if (!import_lodash.default.isPlainObject(popup) || !Array.isArray(popup.blocks)) {
|
|
3267
|
+
continue;
|
|
3268
|
+
}
|
|
3269
|
+
const prepared = this.prepareComposeChartAssetBlockList(
|
|
3270
|
+
popup.blocks,
|
|
3271
|
+
`${blockPath}.settings.${key}.blocks`,
|
|
3272
|
+
chartAssets
|
|
3273
|
+
);
|
|
3274
|
+
if (!prepared.didResolveChartAsset) {
|
|
3275
|
+
continue;
|
|
3276
|
+
}
|
|
3277
|
+
ensureNextBlock().settings = {
|
|
3278
|
+
...nextBlock.settings || {},
|
|
3279
|
+
[key]: {
|
|
3280
|
+
...popup,
|
|
3281
|
+
blocks: prepared.blocks
|
|
3282
|
+
}
|
|
3283
|
+
};
|
|
3284
|
+
didResolveChartAsset = true;
|
|
3285
|
+
}
|
|
3286
|
+
}
|
|
3287
|
+
if (String(nextBlock.type || "").trim() !== "chart" || !Object.prototype.hasOwnProperty.call(nextBlock, "chart") || this.composeChartBlockHasInlineConfig(nextBlock)) {
|
|
3288
|
+
return nextBlock;
|
|
3289
|
+
}
|
|
3290
|
+
const chartKey = String(nextBlock.chart || "").trim();
|
|
3291
|
+
if (!chartKey) {
|
|
3292
|
+
throwChartRepairBadRequest(`${blockPath}.chart must reference one key from assets.charts`, {
|
|
3293
|
+
path: `${blockPath}.chart`,
|
|
3294
|
+
ruleId: "chart-block-asset-reference-required"
|
|
3295
|
+
});
|
|
3296
|
+
}
|
|
3297
|
+
const chartAsset = chartAssets[chartKey];
|
|
3298
|
+
if (!import_lodash.default.isPlainObject(chartAsset)) {
|
|
3299
|
+
throwChartRepairBadRequest(`${blockPath}.chart references missing chart asset '${chartKey}'`, {
|
|
3300
|
+
path: `${blockPath}.chart`,
|
|
3301
|
+
ruleId: "chart-block-asset-reference-missing",
|
|
3302
|
+
details: {
|
|
3303
|
+
chartKey
|
|
3304
|
+
}
|
|
3305
|
+
});
|
|
3306
|
+
}
|
|
3307
|
+
if (!import_lodash.default.isUndefined(nextBlock.settings) && !import_lodash.default.isPlainObject(nextBlock.settings)) {
|
|
3308
|
+
return nextBlock;
|
|
3309
|
+
}
|
|
3310
|
+
didResolveChartAsset = true;
|
|
3311
|
+
return {
|
|
3312
|
+
...nextBlock,
|
|
3313
|
+
settings: import_lodash.default.merge({}, import_lodash.default.cloneDeep(nextBlock.settings || {}), import_lodash.default.cloneDeep(chartAsset))
|
|
3314
|
+
};
|
|
3315
|
+
});
|
|
3316
|
+
return {
|
|
3317
|
+
blocks: nextBlocks,
|
|
3318
|
+
didResolveChartAsset
|
|
3319
|
+
};
|
|
3320
|
+
}
|
|
3321
|
+
prepareComposeChartAssetSettings(values) {
|
|
3322
|
+
var _a;
|
|
3323
|
+
const chartAssets = import_lodash.default.isPlainObject((_a = values == null ? void 0 : values.assets) == null ? void 0 : _a.charts) ? values.assets.charts : {};
|
|
3324
|
+
const prepared = this.prepareComposeChartAssetBlockList(values == null ? void 0 : values.blocks, "$.blocks", chartAssets);
|
|
3325
|
+
return prepared.didResolveChartAsset ? {
|
|
3326
|
+
...values,
|
|
3327
|
+
blocks: prepared.blocks
|
|
3328
|
+
} : values;
|
|
3329
|
+
}
|
|
2846
3330
|
getApplyBlueprintKanbanBlockResourceObject(block) {
|
|
2847
3331
|
return import_lodash.default.isPlainObject(block == null ? void 0 : block.resource) ? block.resource : {};
|
|
2848
3332
|
}
|
|
@@ -3231,25 +3715,38 @@ class FlowSurfacesService {
|
|
|
3231
3715
|
}
|
|
3232
3716
|
if (!options.transaction) {
|
|
3233
3717
|
const createdKanbanSortFields = [];
|
|
3234
|
-
|
|
3235
|
-
|
|
3236
|
-
|
|
3237
|
-
|
|
3238
|
-
|
|
3239
|
-
|
|
3240
|
-
|
|
3241
|
-
},
|
|
3242
|
-
createdKanbanSortFields
|
|
3243
|
-
)
|
|
3244
|
-
);
|
|
3245
|
-
} catch (error) {
|
|
3246
|
-
await this.cleanupApplyBlueprintKanbanSortFields(createdKanbanSortFields);
|
|
3247
|
-
throw error;
|
|
3248
|
-
}
|
|
3718
|
+
const mutationResult = await this.applyBlueprintMutationWithoutExternalTransaction(
|
|
3719
|
+
values,
|
|
3720
|
+
options,
|
|
3721
|
+
createdKanbanSortFields
|
|
3722
|
+
);
|
|
3723
|
+
const surface = await this.get(mutationResult.pageLocator, { currentRoles: options.currentRoles });
|
|
3724
|
+
return this.buildApplyBlueprintResponse(mutationResult.mode, mutationResult.pageLocator, surface);
|
|
3249
3725
|
}
|
|
3250
3726
|
}
|
|
3251
|
-
async
|
|
3252
|
-
|
|
3727
|
+
async applyBlueprintMutationWithoutExternalTransaction(values, options = {}, createdKanbanSortFields) {
|
|
3728
|
+
try {
|
|
3729
|
+
await this.assertApplyBlueprintAuthoringPayload(values, options);
|
|
3730
|
+
const document = (0, import_blueprint.prepareFlowSurfaceApplyBlueprintDocument)(values);
|
|
3731
|
+
await this.prevalidateApplyBlueprintChartAssets(document);
|
|
3732
|
+
return await this.transaction(
|
|
3733
|
+
(transaction) => this.applyBlueprintWithTransaction(
|
|
3734
|
+
values,
|
|
3735
|
+
{
|
|
3736
|
+
...options,
|
|
3737
|
+
transaction,
|
|
3738
|
+
skipAuthoringValidation: true
|
|
3739
|
+
},
|
|
3740
|
+
createdKanbanSortFields,
|
|
3741
|
+
{ readSurface: false }
|
|
3742
|
+
)
|
|
3743
|
+
);
|
|
3744
|
+
} catch (error) {
|
|
3745
|
+
await this.cleanupApplyBlueprintKanbanSortFields(createdKanbanSortFields);
|
|
3746
|
+
throw error;
|
|
3747
|
+
}
|
|
3748
|
+
}
|
|
3749
|
+
async assertApplyBlueprintAuthoringPayload(values, options = {}) {
|
|
3253
3750
|
const enabledPackages = await this.resolveEnabledPluginPackages(options);
|
|
3254
3751
|
await (0, import_authoring_validation.assertFlowSurfaceAuthoringPayload)("applyBlueprint", values, {
|
|
3255
3752
|
transaction: options.transaction,
|
|
@@ -3257,6 +3754,11 @@ class FlowSurfacesService {
|
|
|
3257
3754
|
findMenuGroupRoutesByTitle: (title, transaction) => this.findMenuGroupRoutesByTitle(title, transaction),
|
|
3258
3755
|
getCollection: (dataSourceKey, collectionName) => this.getCollection(dataSourceKey || "main", collectionName || "")
|
|
3259
3756
|
});
|
|
3757
|
+
}
|
|
3758
|
+
async applyBlueprintWithTransaction(values, options = {}, createdKanbanSortFields, resultOptions = {}) {
|
|
3759
|
+
if (options.skipAuthoringValidation !== true) {
|
|
3760
|
+
await this.assertApplyBlueprintAuthoringPayload(values, options);
|
|
3761
|
+
}
|
|
3260
3762
|
const prepared = await this.prepareApplyBlueprintRequest(values, options.transaction, createdKanbanSortFields);
|
|
3261
3763
|
const popupTemplateAliasSession = this.createPopupTemplateAliasSession();
|
|
3262
3764
|
const popupTemplateTreeCache = /* @__PURE__ */ new Map();
|
|
@@ -3277,10 +3779,27 @@ class FlowSurfacesService {
|
|
|
3277
3779
|
options
|
|
3278
3780
|
);
|
|
3279
3781
|
const pageLocator = (0, import_blueprint.resolveApplyBlueprintPageLocator)(prepared, result);
|
|
3782
|
+
await this.ensureSurfaceTableDefaultActionIntegrity(pageLocator, {
|
|
3783
|
+
...options,
|
|
3784
|
+
enabledPackages: await this.resolveEnabledPluginPackages(options),
|
|
3785
|
+
popupTemplateAliasSession,
|
|
3786
|
+
popupTemplateTreeCache
|
|
3787
|
+
});
|
|
3788
|
+
if (resultOptions.readSurface === false) {
|
|
3789
|
+
return {
|
|
3790
|
+
version: "1",
|
|
3791
|
+
mode: prepared.document.mode,
|
|
3792
|
+
pageLocator
|
|
3793
|
+
};
|
|
3794
|
+
}
|
|
3280
3795
|
const surface = await this.get(pageLocator, options);
|
|
3796
|
+
return this.buildApplyBlueprintResponse(prepared.document.mode, pageLocator, surface);
|
|
3797
|
+
}
|
|
3798
|
+
buildApplyBlueprintResponse(mode, pageLocator, surface) {
|
|
3799
|
+
var _a;
|
|
3281
3800
|
return {
|
|
3282
3801
|
version: "1",
|
|
3283
|
-
mode
|
|
3802
|
+
mode,
|
|
3284
3803
|
target: (0, import_service_utils.buildDefinedPayload)({
|
|
3285
3804
|
pageSchemaUid: pageLocator.pageSchemaUid,
|
|
3286
3805
|
pageUid: (_a = surface == null ? void 0 : surface.target) == null ? void 0 : _a.uid
|
|
@@ -3942,8 +4461,8 @@ class FlowSurfacesService {
|
|
|
3942
4461
|
stepParams: (0, import_template_service_utils.buildFlowTemplateReferenceBlockStepParams)(template, templateTargetUid, init)
|
|
3943
4462
|
};
|
|
3944
4463
|
}
|
|
3945
|
-
buildPopupTemplateReferenceOpenView(template, templateTargetUid) {
|
|
3946
|
-
return this.buildPopupTemplateOpenView(template, "reference", templateTargetUid);
|
|
4464
|
+
buildPopupTemplateReferenceOpenView(template, templateTargetUid, options = {}) {
|
|
4465
|
+
return this.buildPopupTemplateOpenView(template, "reference", templateTargetUid, options);
|
|
3947
4466
|
}
|
|
3948
4467
|
shouldHydrateDetachedPopupTemplateBlockResourceContext(blockNode, context) {
|
|
3949
4468
|
if (!this.isCollectionBlockUse(blockNode == null ? void 0 : blockNode.use) || !context.associationName || !context.sourceId) {
|
|
@@ -4293,15 +4812,35 @@ class FlowSurfacesService {
|
|
|
4293
4812
|
}
|
|
4294
4813
|
const nextStepParams = import_lodash.default.cloneDeep(sourceNode.stepParams || {});
|
|
4295
4814
|
const currentGroup = import_lodash.default.isPlainObject(nextStepParams[openViewStep.flowKey]) ? import_lodash.default.cloneDeep(nextStepParams[openViewStep.flowKey]) : {};
|
|
4815
|
+
const popupProfile = await this.resolvePopupBlockProfile(sourceNode.uid, null, sourceNode, transaction).catch(
|
|
4816
|
+
() => null
|
|
4817
|
+
);
|
|
4818
|
+
const useRuntimeRecordFilterByTk = (popupProfile == null ? void 0 : popupProfile.hasCurrentRecord) === true;
|
|
4819
|
+
const filterTargetKey = useRuntimeRecordFilterByTk ? await this.resolveOpenViewRuntimeRecordFilterTargetKey(openViewStep.openView, template, {
|
|
4820
|
+
transaction,
|
|
4821
|
+
popupTemplateHostUid: sourceNode.uid,
|
|
4822
|
+
popupActionContext: {
|
|
4823
|
+
hasCurrentRecord: true
|
|
4824
|
+
}
|
|
4825
|
+
}) : void 0;
|
|
4826
|
+
const currentOpenView = import_lodash.default.omit(openViewStep.openView || {}, [
|
|
4827
|
+
"popupTemplateUid",
|
|
4828
|
+
"popupTemplateMode",
|
|
4829
|
+
"popupTemplateContext",
|
|
4830
|
+
"popupTemplateHasFilterByTk",
|
|
4831
|
+
"popupTemplateHasSourceId"
|
|
4832
|
+
]);
|
|
4833
|
+
if (useRuntimeRecordFilterByTk && this.shouldOmitRuntimeRecordFilterByTk(currentOpenView.filterByTk, {
|
|
4834
|
+
filterTargetKey
|
|
4835
|
+
})) {
|
|
4836
|
+
delete currentOpenView.filterByTk;
|
|
4837
|
+
}
|
|
4296
4838
|
let nextOpenView = {
|
|
4297
|
-
...
|
|
4298
|
-
|
|
4299
|
-
|
|
4300
|
-
|
|
4301
|
-
|
|
4302
|
-
"popupTemplateHasSourceId"
|
|
4303
|
-
]),
|
|
4304
|
-
...this.buildPopupTemplateReferenceOpenView(template, templateTargetUid)
|
|
4839
|
+
...currentOpenView,
|
|
4840
|
+
...this.buildPopupTemplateReferenceOpenView(template, templateTargetUid, {
|
|
4841
|
+
filterTargetKey,
|
|
4842
|
+
useRuntimeRecordFilterByTk
|
|
4843
|
+
})
|
|
4305
4844
|
};
|
|
4306
4845
|
if (String(sourceNode.use || "").trim() === "AddChildActionModel") {
|
|
4307
4846
|
nextOpenView = await this.normalizeAddChildOpenViewForAction(sourceNode, nextOpenView, transaction);
|
|
@@ -4862,12 +5401,13 @@ class FlowSurfacesService {
|
|
|
4862
5401
|
async compose(values, options = {}) {
|
|
4863
5402
|
var _a, _b, _c;
|
|
4864
5403
|
const enabledPackages = await this.resolveEnabledPluginPackages(options);
|
|
4865
|
-
const
|
|
5404
|
+
const composeValues = this.prepareComposeChartAssetSettings(values);
|
|
5405
|
+
const target = await this.prepareWriteTarget("compose", composeValues == null ? void 0 : composeValues.target, composeValues, options);
|
|
4866
5406
|
const authoringContext = await this.buildTargetAuthoringContext({
|
|
4867
5407
|
target,
|
|
4868
5408
|
transaction: options.transaction
|
|
4869
5409
|
});
|
|
4870
|
-
await (0, import_authoring_validation.assertFlowSurfaceAuthoringPayload)("compose",
|
|
5410
|
+
await (0, import_authoring_validation.assertFlowSurfaceAuthoringPayload)("compose", composeValues, {
|
|
4871
5411
|
transaction: options.transaction,
|
|
4872
5412
|
enabledPackages,
|
|
4873
5413
|
skipGeneratedLayoutSingleColumnErrors: options.skipGeneratedLayoutSingleColumnErrors === true,
|
|
@@ -4880,12 +5420,17 @@ class FlowSurfacesService {
|
|
|
4880
5420
|
...options,
|
|
4881
5421
|
popupTemplateTreeCache
|
|
4882
5422
|
};
|
|
4883
|
-
const mode = this.assertComposeMode(
|
|
4884
|
-
const popupDefaultsMetadata = this.buildPopupDefaultsMetadata(
|
|
4885
|
-
const normalizedBlocks = this.normalizeComposeBlocks(
|
|
4886
|
-
|
|
4887
|
-
|
|
4888
|
-
|
|
5423
|
+
const mode = this.assertComposeMode(composeValues == null ? void 0 : composeValues.mode);
|
|
5424
|
+
const popupDefaultsMetadata = this.buildPopupDefaultsMetadata(composeValues == null ? void 0 : composeValues.defaults);
|
|
5425
|
+
const normalizedBlocks = this.normalizeComposeBlocks(
|
|
5426
|
+
composeValues == null ? void 0 : composeValues.blocks,
|
|
5427
|
+
enabledPackages,
|
|
5428
|
+
popupDefaultsMetadata,
|
|
5429
|
+
{
|
|
5430
|
+
dataSourceKey: authoringContext.currentDataSourceKey,
|
|
5431
|
+
collectionName: authoringContext.currentCollectionName
|
|
5432
|
+
}
|
|
5433
|
+
);
|
|
4889
5434
|
this.validateComposePopupTemplateAliases(normalizedBlocks, popupTemplateAliasSession);
|
|
4890
5435
|
const blockParent = await this.surfaceContext.resolveBlockParent(target, options.transaction);
|
|
4891
5436
|
const gridUid = blockParent.parentUid;
|
|
@@ -4911,7 +5456,7 @@ class FlowSurfacesService {
|
|
|
4911
5456
|
mode,
|
|
4912
5457
|
normalizedBlocks,
|
|
4913
5458
|
existingItemUids: existingItems.map((item) => item.uid),
|
|
4914
|
-
layout:
|
|
5459
|
+
layout: composeValues.layout
|
|
4915
5460
|
});
|
|
4916
5461
|
const generatedDefaultFilterByComposeBlockUid = /* @__PURE__ */ new Map();
|
|
4917
5462
|
const result = await (0, import_compose_runtime.executeComposeRuntime)(plan, {
|
|
@@ -4946,7 +5491,7 @@ class FlowSurfacesService {
|
|
|
4946
5491
|
{
|
|
4947
5492
|
...payload,
|
|
4948
5493
|
...Object.keys(hiddenPopupSettings).length ? { settings: hiddenPopupSettings } : {},
|
|
4949
|
-
...
|
|
5494
|
+
...composeValues.defaults ? { defaults: composeValues.defaults } : {}
|
|
4950
5495
|
},
|
|
4951
5496
|
{
|
|
4952
5497
|
...runtimeOptions,
|
|
@@ -5043,6 +5588,13 @@ class FlowSurfacesService {
|
|
|
5043
5588
|
});
|
|
5044
5589
|
for (const [blockIndex, block] of result.blocks.entries()) {
|
|
5045
5590
|
const blockSpec = normalizedBlocks.find((item) => item.key === block.key);
|
|
5591
|
+
if ((blockSpec == null ? void 0 : blockSpec.type) === "table") {
|
|
5592
|
+
await this.ensureTableDefaultActionIntegrity(block.uid, {
|
|
5593
|
+
...runtimeOptions,
|
|
5594
|
+
enabledPackages,
|
|
5595
|
+
popupTemplateAliasSession
|
|
5596
|
+
});
|
|
5597
|
+
}
|
|
5046
5598
|
if ((blockSpec == null ? void 0 : blockSpec.type) === "table") {
|
|
5047
5599
|
const appliedTreeTableDefaults = await this.applyTreeTableCreatedBlockDefaults(
|
|
5048
5600
|
{
|
|
@@ -5176,7 +5728,7 @@ class FlowSurfacesService {
|
|
|
5176
5728
|
if ((current == null ? void 0 : current.use) === "DividerItemModel") {
|
|
5177
5729
|
return this.configureDividerItem(target, changes, options);
|
|
5178
5730
|
}
|
|
5179
|
-
return this.configureJSItem(target, changes, options);
|
|
5731
|
+
return this.configureJSItem(target, changes, { ...options, currentUse: (current == null ? void 0 : current.use) || "JSItemModel" });
|
|
5180
5732
|
}
|
|
5181
5733
|
if ((0, import_service_utils.isFieldNodeUse)(current == null ? void 0 : current.use)) {
|
|
5182
5734
|
return this.configureFieldNode(target, changes, configureOptions);
|
|
@@ -5251,6 +5803,7 @@ class FlowSurfacesService {
|
|
|
5251
5803
|
if (!this.isBindableMenuRoutePendingInitialization(route, structure)) {
|
|
5252
5804
|
(0, import_errors.throwBadRequest)(`flowSurfaces createPage does not allow re-initializing menu route '${routeId}'`);
|
|
5253
5805
|
}
|
|
5806
|
+
this.assertVisibleNavigationRouteIconUpdate("createPage", "values", route, values);
|
|
5254
5807
|
const existingPage = structure.pageModel;
|
|
5255
5808
|
const enableTabs = !!values.enableTabs;
|
|
5256
5809
|
const displayTitle = values.displayTitle !== false;
|
|
@@ -5275,7 +5828,7 @@ class FlowSurfacesService {
|
|
|
5275
5828
|
parentId: routeId,
|
|
5276
5829
|
options: {
|
|
5277
5830
|
documentTitle: values.tabDocumentTitle,
|
|
5278
|
-
flowRegistry: values.tabFlowRegistry || {}
|
|
5831
|
+
flowRegistry: this.normalizeEventFlowRegistry("createPage", values.tabFlowRegistry || {})
|
|
5279
5832
|
}
|
|
5280
5833
|
},
|
|
5281
5834
|
transaction
|
|
@@ -5294,7 +5847,10 @@ class FlowSurfacesService {
|
|
|
5294
5847
|
options: {
|
|
5295
5848
|
...this.readRouteOptions(tabRoute),
|
|
5296
5849
|
documentTitle: values.tabDocumentTitle ?? this.readRouteOptions(tabRoute).documentTitle,
|
|
5297
|
-
flowRegistry:
|
|
5850
|
+
flowRegistry: this.normalizeEventFlowRegistry(
|
|
5851
|
+
"createPage",
|
|
5852
|
+
values.tabFlowRegistry || this.readRouteOptions(tabRoute).flowRegistry || {}
|
|
5853
|
+
)
|
|
5298
5854
|
}
|
|
5299
5855
|
},
|
|
5300
5856
|
transaction
|
|
@@ -5436,7 +5992,7 @@ class FlowSurfacesService {
|
|
|
5436
5992
|
hidden: !pageRoute.get("enableTabs"),
|
|
5437
5993
|
options: {
|
|
5438
5994
|
documentTitle: values.documentTitle,
|
|
5439
|
-
flowRegistry: values.flowRegistry || {}
|
|
5995
|
+
flowRegistry: this.normalizeEventFlowRegistry("addTab", values.flowRegistry || {})
|
|
5440
5996
|
}
|
|
5441
5997
|
},
|
|
5442
5998
|
transaction: options.transaction
|
|
@@ -5484,7 +6040,7 @@ class FlowSurfacesService {
|
|
|
5484
6040
|
)
|
|
5485
6041
|
}
|
|
5486
6042
|
} : void 0,
|
|
5487
|
-
flowRegistry: !import_lodash.default.isUndefined(values.flowRegistry) ? values.flowRegistry : void 0
|
|
6043
|
+
flowRegistry: !import_lodash.default.isUndefined(values.flowRegistry) ? this.normalizeEventFlowRegistry("updateTab", values.flowRegistry) : void 0
|
|
5488
6044
|
});
|
|
5489
6045
|
await this.routeSync.persistTabSettings(target, current, nextPayload, options.transaction);
|
|
5490
6046
|
return {
|
|
@@ -5600,7 +6156,7 @@ class FlowSurfacesService {
|
|
|
5600
6156
|
title: values.title,
|
|
5601
6157
|
icon: values.icon,
|
|
5602
6158
|
documentTitle: values.documentTitle,
|
|
5603
|
-
flowRegistry: values.flowRegistry
|
|
6159
|
+
flowRegistry: this.normalizeEventFlowRegistry("addPopupTab", values.flowRegistry)
|
|
5604
6160
|
});
|
|
5605
6161
|
await this.repository.upsertModel(
|
|
5606
6162
|
{
|
|
@@ -5655,7 +6211,7 @@ class FlowSurfacesService {
|
|
|
5655
6211
|
}
|
|
5656
6212
|
}
|
|
5657
6213
|
} : void 0,
|
|
5658
|
-
flowRegistry: !import_lodash.default.isUndefined(values.flowRegistry) ? values.flowRegistry : void 0
|
|
6214
|
+
flowRegistry: !import_lodash.default.isUndefined(values.flowRegistry) ? this.normalizeEventFlowRegistry("updatePopupTab", values.flowRegistry) : void 0
|
|
5659
6215
|
});
|
|
5660
6216
|
if (Object.keys(nextPayload).length === 1) {
|
|
5661
6217
|
return { uid: popupTab.uid };
|
|
@@ -5856,7 +6412,7 @@ class FlowSurfacesService {
|
|
|
5856
6412
|
use: "ReferenceFormGridModel",
|
|
5857
6413
|
props: currentGrid.props,
|
|
5858
6414
|
decoratorProps: currentGrid.decoratorProps,
|
|
5859
|
-
flowRegistry: currentGrid
|
|
6415
|
+
flowRegistry: this.getEventFlowRegistry(currentGrid),
|
|
5860
6416
|
sortIndex: currentGrid.sortIndex,
|
|
5861
6417
|
parentId: blockUid,
|
|
5862
6418
|
subKey: "grid",
|
|
@@ -6102,7 +6658,8 @@ class FlowSurfacesService {
|
|
|
6102
6658
|
if ((0, import_service_utils.hasOwnDefined)(normalizedSettings, "defaultFilter")) {
|
|
6103
6659
|
normalizedSettings.defaultFilter = (0, import_filter_group.normalizeFlowSurfaceFilterGroupValue)(
|
|
6104
6660
|
normalizedSettings.defaultFilter,
|
|
6105
|
-
`flowSurfaces ${actionName} defaultActionSettings.filter.defaultFilter expects FilterGroup like ${import_filter_group.FLOW_SURFACE_FILTER_GROUP_EXAMPLE}
|
|
6661
|
+
`flowSurfaces ${actionName} defaultActionSettings.filter.defaultFilter expects FilterGroup like ${import_filter_group.FLOW_SURFACE_FILTER_GROUP_EXAMPLE}`,
|
|
6662
|
+
{ strictDateValues: true }
|
|
6106
6663
|
);
|
|
6107
6664
|
normalizedSettings.defaultFilter = this.normalizeEffectivePublicDataSurfaceDefaultFilter(
|
|
6108
6665
|
normalizedSettings.defaultFilter,
|
|
@@ -6330,7 +6887,7 @@ class FlowSurfacesService {
|
|
|
6330
6887
|
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
6888
|
type: catalogItem.key || values.type,
|
|
6332
6889
|
fields: values.fields,
|
|
6333
|
-
fieldsLayout: values.fieldsLayout
|
|
6890
|
+
...Object.prototype.hasOwnProperty.call(values || {}, "fieldsLayout") ? { fieldsLayout: values.fieldsLayout } : {}
|
|
6334
6891
|
},
|
|
6335
6892
|
0,
|
|
6336
6893
|
enabledPackages,
|
|
@@ -6524,6 +7081,8 @@ class FlowSurfacesService {
|
|
|
6524
7081
|
...fieldSpec.popupSize ? { popupSize: fieldSpec.popupSize } : {},
|
|
6525
7082
|
...!import_lodash.default.isUndefined(fieldSpec.pageSize) ? { pageSize: fieldSpec.pageSize } : {},
|
|
6526
7083
|
...!import_lodash.default.isUndefined(fieldSpec.showIndex) ? { showIndex: fieldSpec.showIndex } : {},
|
|
7084
|
+
...fieldSpec.defaultTargetUid ? { defaultTargetUid: fieldSpec.defaultTargetUid } : {},
|
|
7085
|
+
...fieldSpec.targetBlockUid ? { targetBlockUid: fieldSpec.targetBlockUid } : {},
|
|
6527
7086
|
...fieldSpec.popup ? { popup: fieldSpec.popup } : {},
|
|
6528
7087
|
...fieldSpec.__autoPopupForRelationField ? { __autoPopupForRelationField: true } : {},
|
|
6529
7088
|
...fieldSpec[import_defaults.FLOW_SURFACE_APPLY_BLUEPRINT_POPUP_DEFAULTS_KEY] ? {
|
|
@@ -6598,6 +7157,13 @@ class FlowSurfacesService {
|
|
|
6598
7157
|
enabledPackages
|
|
6599
7158
|
}
|
|
6600
7159
|
);
|
|
7160
|
+
if (catalogItem.use === "TableBlockModel" && !options.skipDefaultBlockActions) {
|
|
7161
|
+
await this.ensureTableDefaultActionIntegrity(created, {
|
|
7162
|
+
...options,
|
|
7163
|
+
enabledPackages,
|
|
7164
|
+
popupTemplateTreeCache: options.popupTemplateTreeCache
|
|
7165
|
+
});
|
|
7166
|
+
}
|
|
6601
7167
|
if (!options.deferAutoLayout && (initialGrid == null ? void 0 : initialGrid.uid)) {
|
|
6602
7168
|
const finalGrid = await this.repository.findModelById(parentUid, {
|
|
6603
7169
|
transaction: options.transaction,
|
|
@@ -6665,7 +7231,9 @@ class FlowSurfacesService {
|
|
|
6665
7231
|
(0, import_errors.throwBadRequest)("flowSurfaces fieldType is only supported for relation fields");
|
|
6666
7232
|
}
|
|
6667
7233
|
if (inlinePopup) {
|
|
6668
|
-
(0, import_errors.throwBadRequest)(
|
|
7234
|
+
(0, import_errors.throwBadRequest)(
|
|
7235
|
+
withJsPopupGuidance(`flowSurfaces addField type '${values.type}' does not support popup`, values.type)
|
|
7236
|
+
);
|
|
6669
7237
|
}
|
|
6670
7238
|
if (isFilterFormItem) {
|
|
6671
7239
|
(0, import_errors.throwBadRequest)(`flowSurfaces addField type '${values.type}' is not allowed under filter-form`);
|
|
@@ -6860,9 +7428,18 @@ class FlowSurfacesService {
|
|
|
6860
7428
|
}
|
|
6861
7429
|
}
|
|
6862
7430
|
if (inlinePopup && !this.isPopupFieldHostUse(boundFieldCapability.fieldUse)) {
|
|
6863
|
-
(0, import_errors.throwBadRequest)(
|
|
7431
|
+
(0, import_errors.throwBadRequest)(
|
|
7432
|
+
withJsPopupGuidance(
|
|
7433
|
+
`flowSurfaces addField field '${boundFieldCapability.fieldUse}' does not support popup`,
|
|
7434
|
+
boundFieldCapability.fieldUse
|
|
7435
|
+
)
|
|
7436
|
+
);
|
|
6864
7437
|
}
|
|
6865
|
-
|
|
7438
|
+
const inlineSettingsOpenView = this.peekInlineFieldSettingsOpenView(
|
|
7439
|
+
inlineSettings,
|
|
7440
|
+
boundFieldCapability.wrapperUse
|
|
7441
|
+
);
|
|
7442
|
+
if (values.__autoPopupForRelationField === true && !inlinePopup && this.isPopupFieldHostUse(boundFieldCapability.fieldUse) && ((0, import_service_helpers.isAssociationField)(resolvedField.field) || !!normalizedFieldBinding.associationPathName) && !inlineSettingsOpenView) {
|
|
6866
7443
|
const popupDefaultsMetadata = values[import_defaults.FLOW_SURFACE_APPLY_BLUEPRINT_POPUP_DEFAULTS_KEY];
|
|
6867
7444
|
inlinePopup = this.normalizeInlinePopup("addField", {
|
|
6868
7445
|
tryTemplate: true,
|
|
@@ -6872,9 +7449,19 @@ class FlowSurfacesService {
|
|
|
6872
7449
|
} : {}
|
|
6873
7450
|
});
|
|
6874
7451
|
}
|
|
6875
|
-
|
|
6876
|
-
|
|
6877
|
-
|
|
7452
|
+
const hasExternalInlineSettingsOpenView = this.isExternalPopupOpenView(inlineSettingsOpenView);
|
|
7453
|
+
if (!inlinePopup && this.isPopupFieldHostUse(boundFieldCapability.fieldUse) && !hasExternalInlineSettingsOpenView && (this.isInlineFieldClickToOpenEnabled(inlineSettings, boundFieldCapability.wrapperUse) || import_lodash.default.isPlainObject(inlineSettingsOpenView))) {
|
|
7454
|
+
const popupDefaultsMetadata = values[import_defaults.FLOW_SURFACE_APPLY_BLUEPRINT_POPUP_DEFAULTS_KEY];
|
|
7455
|
+
inlinePopup = this.normalizeInlinePopup("addField", {
|
|
7456
|
+
tryTemplate: true,
|
|
7457
|
+
defaultType: "view",
|
|
7458
|
+
...import_lodash.default.isPlainObject(inlineSettingsOpenView) ? { openView: import_lodash.default.cloneDeep(inlineSettingsOpenView) } : {},
|
|
7459
|
+
...popupDefaultsMetadata ? {
|
|
7460
|
+
[import_defaults.FLOW_SURFACE_APPLY_BLUEPRINT_POPUP_DEFAULTS_KEY]: popupDefaultsMetadata
|
|
7461
|
+
} : {}
|
|
7462
|
+
});
|
|
7463
|
+
}
|
|
7464
|
+
if (inlinePopup && hasExternalInlineSettingsOpenView) {
|
|
6878
7465
|
(0, import_errors.throwBadRequest)(`flowSurfaces addField popup cannot be combined with external openView.uid`);
|
|
6879
7466
|
}
|
|
6880
7467
|
const defaultFieldState = (0, import_service_utils.buildDefaultFieldState)(
|
|
@@ -7013,7 +7600,12 @@ class FlowSurfacesService {
|
|
|
7013
7600
|
);
|
|
7014
7601
|
}
|
|
7015
7602
|
if (inlinePopup && !POPUP_ACTION_USES.has(actionCatalogItem.use)) {
|
|
7016
|
-
(0, import_errors.throwBadRequest)(
|
|
7603
|
+
(0, import_errors.throwBadRequest)(
|
|
7604
|
+
withJsPopupGuidance(
|
|
7605
|
+
`flowSurfaces addAction type '${actionCatalogItem.key}' does not support popup`,
|
|
7606
|
+
actionCatalogItem.key
|
|
7607
|
+
)
|
|
7608
|
+
);
|
|
7017
7609
|
}
|
|
7018
7610
|
await this.assertApprovalActionSingleton(container.parentUid, actionCatalogItem.use, options.transaction);
|
|
7019
7611
|
(0, import_action_scope.assertRequestedActionScope)({
|
|
@@ -7041,21 +7633,43 @@ class FlowSurfacesService {
|
|
|
7041
7633
|
return result2;
|
|
7042
7634
|
}
|
|
7043
7635
|
const resourceContext = container.ownerUid ? await this.locator.resolveCollectionContext(container.ownerUid, options.transaction).catch(() => null) : null;
|
|
7044
|
-
const
|
|
7636
|
+
const aiEmployeeSettingsPayload = this.isAIEmployeeActionUse(actionCatalogItem.use) ? await this.normalizeAIEmployeeActionPublicSettings("addAction", inlineSettings || {}, {
|
|
7045
7637
|
transaction: options.transaction,
|
|
7046
7638
|
enabledPackages,
|
|
7047
7639
|
requireUsername: true,
|
|
7048
7640
|
currentRoles: options.currentRoles,
|
|
7049
|
-
selfUid: container.ownerUid
|
|
7641
|
+
selfUid: container.ownerUid,
|
|
7642
|
+
promptContext: {
|
|
7643
|
+
kind: "container",
|
|
7644
|
+
ownerUid: container.ownerUid,
|
|
7645
|
+
scope: resolvedScope
|
|
7646
|
+
}
|
|
7050
7647
|
}) : void 0;
|
|
7648
|
+
const actionSettingsPayload = {
|
|
7649
|
+
props: values.props,
|
|
7650
|
+
stepParams: values.stepParams
|
|
7651
|
+
};
|
|
7652
|
+
if (aiEmployeeSettingsPayload) {
|
|
7653
|
+
this.mergeAIEmployeeActionSettingsPayload(
|
|
7654
|
+
{ use: actionCatalogItem.use },
|
|
7655
|
+
actionSettingsPayload,
|
|
7656
|
+
aiEmployeeSettingsPayload
|
|
7657
|
+
);
|
|
7658
|
+
await this.assertNoDuplicateAIEmployeeAction(
|
|
7659
|
+
"addAction",
|
|
7660
|
+
container.parentUid,
|
|
7661
|
+
actionSettingsPayload,
|
|
7662
|
+
options.transaction
|
|
7663
|
+
);
|
|
7664
|
+
}
|
|
7051
7665
|
const action = (0, import_builder.buildActionTree)({
|
|
7052
7666
|
use: actionCatalogItem.use,
|
|
7053
7667
|
containerUse: container.ownerUse,
|
|
7054
7668
|
resourceInit: values.resourceInit || (resourceContext == null ? void 0 : resourceContext.resourceInit),
|
|
7055
|
-
props:
|
|
7669
|
+
props: actionSettingsPayload.props,
|
|
7056
7670
|
decoratorProps: values.decoratorProps,
|
|
7057
|
-
stepParams:
|
|
7058
|
-
flowRegistry: values.flowRegistry
|
|
7671
|
+
stepParams: actionSettingsPayload.stepParams,
|
|
7672
|
+
flowRegistry: this.normalizeEventFlowRegistry("addAction", values.flowRegistry)
|
|
7059
7673
|
});
|
|
7060
7674
|
this.contractGuard.validateNodeTreeAgainstContract(action);
|
|
7061
7675
|
const created = await this.repository.upsertModel(
|
|
@@ -7109,8 +7723,13 @@ class FlowSurfacesService {
|
|
|
7109
7723
|
);
|
|
7110
7724
|
const resolvedScope = actionCatalogItem.scope;
|
|
7111
7725
|
if (inlinePopup && !POPUP_ACTION_USES.has(actionCatalogItem.use)) {
|
|
7112
|
-
(0, import_errors.throwBadRequest)(
|
|
7113
|
-
|
|
7726
|
+
(0, import_errors.throwBadRequest)(
|
|
7727
|
+
withJsPopupGuidance(
|
|
7728
|
+
`flowSurfaces addRecordAction type '${actionCatalogItem.key}' does not support popup`,
|
|
7729
|
+
actionCatalogItem.key
|
|
7730
|
+
)
|
|
7731
|
+
);
|
|
7732
|
+
}
|
|
7114
7733
|
if (this.isAddChildCatalogItem(actionCatalogItem)) {
|
|
7115
7734
|
await this.assertAddChildSupportedForOwnerNode(container.ownerNode, "addRecordAction", options.transaction);
|
|
7116
7735
|
}
|
|
@@ -7141,21 +7760,43 @@ class FlowSurfacesService {
|
|
|
7141
7760
|
}
|
|
7142
7761
|
const resourceContext = container.ownerUid ? await this.locator.resolveCollectionContext(container.ownerUid, options.transaction).catch(() => null) : null;
|
|
7143
7762
|
const resourceInit = this.isAddChildCatalogItem(actionCatalogItem) ? await this.resolveAddChildResourceInitForOwnerNode(container.ownerNode, options.transaction) : values.resourceInit || (resourceContext == null ? void 0 : resourceContext.resourceInit);
|
|
7144
|
-
const
|
|
7763
|
+
const aiEmployeeSettingsPayload = this.isAIEmployeeActionUse(actionCatalogItem.use) ? await this.normalizeAIEmployeeActionPublicSettings("addRecordAction", inlineSettings || {}, {
|
|
7145
7764
|
transaction: options.transaction,
|
|
7146
7765
|
enabledPackages,
|
|
7147
7766
|
requireUsername: true,
|
|
7148
7767
|
currentRoles: options.currentRoles,
|
|
7149
|
-
selfUid: container.ownerUid
|
|
7768
|
+
selfUid: container.ownerUid,
|
|
7769
|
+
promptContext: {
|
|
7770
|
+
kind: "container",
|
|
7771
|
+
ownerUid: container.ownerUid,
|
|
7772
|
+
scope: resolvedScope
|
|
7773
|
+
}
|
|
7150
7774
|
}) : void 0;
|
|
7775
|
+
const actionSettingsPayload = {
|
|
7776
|
+
props: values.props,
|
|
7777
|
+
stepParams: values.stepParams
|
|
7778
|
+
};
|
|
7779
|
+
if (aiEmployeeSettingsPayload) {
|
|
7780
|
+
this.mergeAIEmployeeActionSettingsPayload(
|
|
7781
|
+
{ use: actionCatalogItem.use },
|
|
7782
|
+
actionSettingsPayload,
|
|
7783
|
+
aiEmployeeSettingsPayload
|
|
7784
|
+
);
|
|
7785
|
+
await this.assertNoDuplicateAIEmployeeAction(
|
|
7786
|
+
"addRecordAction",
|
|
7787
|
+
materializedContainer.parentUid,
|
|
7788
|
+
actionSettingsPayload,
|
|
7789
|
+
options.transaction
|
|
7790
|
+
);
|
|
7791
|
+
}
|
|
7151
7792
|
const action = (0, import_builder.buildActionTree)({
|
|
7152
7793
|
use: actionCatalogItem.use,
|
|
7153
7794
|
containerUse: container.containerUse,
|
|
7154
7795
|
resourceInit,
|
|
7155
|
-
props:
|
|
7796
|
+
props: actionSettingsPayload.props,
|
|
7156
7797
|
decoratorProps: values.decoratorProps,
|
|
7157
|
-
stepParams:
|
|
7158
|
-
flowRegistry: values.flowRegistry
|
|
7798
|
+
stepParams: actionSettingsPayload.stepParams,
|
|
7799
|
+
flowRegistry: this.normalizeEventFlowRegistry("addRecordAction", values.flowRegistry)
|
|
7159
7800
|
});
|
|
7160
7801
|
this.contractGuard.validateNodeTreeAgainstContract(action);
|
|
7161
7802
|
const created = await this.repository.upsertModel(
|
|
@@ -7207,7 +7848,8 @@ class FlowSurfacesService {
|
|
|
7207
7848
|
},
|
|
7208
7849
|
{
|
|
7209
7850
|
...options,
|
|
7210
|
-
preserveSingleScopeDataBlockTitle
|
|
7851
|
+
preserveSingleScopeDataBlockTitle,
|
|
7852
|
+
skipAuthoringValidation: true
|
|
7211
7853
|
}
|
|
7212
7854
|
)
|
|
7213
7855
|
});
|
|
@@ -8083,6 +8725,17 @@ class FlowSurfacesService {
|
|
|
8083
8725
|
const { fieldChanges } = (0, import_service_utils.splitComposeFieldChanges)(settings, wrapperUse);
|
|
8084
8726
|
return fieldChanges.openView;
|
|
8085
8727
|
}
|
|
8728
|
+
isInlineFieldClickToOpenEnabled(settings, wrapperUse) {
|
|
8729
|
+
if (!settings || !Object.keys(settings).length) {
|
|
8730
|
+
return false;
|
|
8731
|
+
}
|
|
8732
|
+
const { fieldChanges } = (0, import_service_utils.splitComposeFieldChanges)(settings, wrapperUse);
|
|
8733
|
+
if (!Object.prototype.hasOwnProperty.call(fieldChanges, "clickToOpen")) {
|
|
8734
|
+
return false;
|
|
8735
|
+
}
|
|
8736
|
+
const value = fieldChanges.clickToOpen;
|
|
8737
|
+
return value === true || import_lodash.default.isPlainObject(value) && value.clickToOpen === true;
|
|
8738
|
+
}
|
|
8086
8739
|
async assertOpenViewUidTarget(actionName, uid2, options = {}) {
|
|
8087
8740
|
const targetNode = await this.repository.findModelById(uid2, {
|
|
8088
8741
|
transaction: options.transaction,
|
|
@@ -8613,15 +9266,71 @@ class FlowSurfacesService {
|
|
|
8613
9266
|
sourceId: String(template.sourceId || "").trim() || void 0
|
|
8614
9267
|
};
|
|
8615
9268
|
}
|
|
8616
|
-
|
|
9269
|
+
shouldUseRuntimeRecordFilterByTkForOpenView(openView, options = {}) {
|
|
9270
|
+
var _a;
|
|
9271
|
+
return !!String((openView == null ? void 0 : openView.popupTemplateUid) || "").trim() && ((_a = options.popupActionContext) == null ? void 0 : _a.hasCurrentRecord) === true;
|
|
9272
|
+
}
|
|
9273
|
+
resolveOpenViewFilterTargetKey(openView, template) {
|
|
9274
|
+
const dataSourceKey = String((openView == null ? void 0 : openView.dataSourceKey) || (template == null ? void 0 : template.dataSourceKey) || "main").trim() || "main";
|
|
9275
|
+
const collectionName = String((openView == null ? void 0 : openView.collectionName) || (template == null ? void 0 : template.collectionName) || "").trim();
|
|
9276
|
+
const collection = collectionName ? this.getCollection(dataSourceKey, collectionName) : null;
|
|
9277
|
+
return this.getCollectionFilterTargetKey(collection);
|
|
9278
|
+
}
|
|
9279
|
+
async resolvePopupHostCurrentRecordFilterTargetKey(hostUid, transaction) {
|
|
9280
|
+
var _a, _b, _c;
|
|
9281
|
+
const normalizedHostUid = String(hostUid || "").trim();
|
|
9282
|
+
if (!normalizedHostUid) {
|
|
9283
|
+
return void 0;
|
|
9284
|
+
}
|
|
9285
|
+
const hostNode = await this.repository.findModelById(normalizedHostUid, {
|
|
9286
|
+
transaction,
|
|
9287
|
+
includeAsyncNode: true
|
|
9288
|
+
}).catch(() => null);
|
|
9289
|
+
if (!(hostNode == null ? void 0 : hostNode.uid)) {
|
|
9290
|
+
return void 0;
|
|
9291
|
+
}
|
|
9292
|
+
const hostContext = await this.resolvePopupHostProfileContext(hostNode, transaction).catch(() => null);
|
|
9293
|
+
const ownerResourceInit = ((_a = hostContext == null ? void 0 : hostContext.resourceContext) == null ? void 0 : _a.resourceInit) || {};
|
|
9294
|
+
const dataSourceKey = String(((_b = hostContext == null ? void 0 : hostContext.associationContext) == null ? void 0 : _b.dataSourceKey) || ownerResourceInit.dataSourceKey || "main").trim() || "main";
|
|
9295
|
+
const collectionName = String(
|
|
9296
|
+
((_c = hostContext == null ? void 0 : hostContext.associationContext) == null ? void 0 : _c.collectionName) || ownerResourceInit.collectionName || ""
|
|
9297
|
+
).trim();
|
|
9298
|
+
const collection = collectionName ? this.getCollection(dataSourceKey, collectionName) : null;
|
|
9299
|
+
return collection ? this.getCollectionFilterTargetKey(collection) : void 0;
|
|
9300
|
+
}
|
|
9301
|
+
async resolveOpenViewRuntimeRecordFilterTargetKey(openView, template, options = {}) {
|
|
9302
|
+
var _a;
|
|
9303
|
+
const contextKey = String(((_a = options.popupActionContext) == null ? void 0 : _a.currentRecordFilterTargetKey) || "").trim();
|
|
9304
|
+
if (contextKey) {
|
|
9305
|
+
return contextKey;
|
|
9306
|
+
}
|
|
9307
|
+
const hostKey = await this.resolvePopupHostCurrentRecordFilterTargetKey(
|
|
9308
|
+
options.popupTemplateHostUid,
|
|
9309
|
+
options.transaction
|
|
9310
|
+
);
|
|
9311
|
+
return hostKey || this.resolveOpenViewFilterTargetKey(openView, template);
|
|
9312
|
+
}
|
|
9313
|
+
shouldOmitRuntimeRecordFilterByTk(value, options = {}) {
|
|
9314
|
+
const normalized = this.normalizeFlowContextTemplateValue(value);
|
|
9315
|
+
if (!normalized) {
|
|
9316
|
+
return false;
|
|
9317
|
+
}
|
|
9318
|
+
if (normalized === "{{ctx.view.inputArgs.filterByTk}}") {
|
|
9319
|
+
return true;
|
|
9320
|
+
}
|
|
9321
|
+
const filterTargetKey = String(options.filterTargetKey || "").trim();
|
|
9322
|
+
return !!filterTargetKey && normalized === `{{ctx.record.${filterTargetKey}}}`;
|
|
9323
|
+
}
|
|
9324
|
+
buildPopupTemplateOpenView(template, mode, uidValue, options = {}) {
|
|
8617
9325
|
const popupTemplateHasFilterByTk = !!String(template.filterByTk || "").trim();
|
|
8618
9326
|
const popupTemplateHasSourceId = !!String(template.sourceId || "").trim() || !!String(template.associationName || "").trim();
|
|
9327
|
+
const omitRuntimeRecordFilterByTk = options.useRuntimeRecordFilterByTk === true && this.shouldOmitRuntimeRecordFilterByTk(template.filterByTk, { filterTargetKey: options.filterTargetKey });
|
|
8619
9328
|
const base = (0, import_service_utils.buildDefinedPayload)({
|
|
8620
9329
|
uid: uidValue,
|
|
8621
9330
|
dataSourceKey: template.dataSourceKey,
|
|
8622
9331
|
collectionName: template.collectionName,
|
|
8623
9332
|
associationName: template.associationName,
|
|
8624
|
-
...popupTemplateHasFilterByTk ? { filterByTk: template.filterByTk } : {},
|
|
9333
|
+
...popupTemplateHasFilterByTk && !omitRuntimeRecordFilterByTk ? { filterByTk: template.filterByTk } : {},
|
|
8625
9334
|
...popupTemplateHasSourceId && template.sourceId ? { sourceId: template.sourceId } : {},
|
|
8626
9335
|
popupTemplateHasFilterByTk,
|
|
8627
9336
|
popupTemplateHasSourceId,
|
|
@@ -8694,7 +9403,7 @@ class FlowSurfacesService {
|
|
|
8694
9403
|
}
|
|
8695
9404
|
}
|
|
8696
9405
|
async normalizeOpenView(actionName, openView, options = {}) {
|
|
8697
|
-
var _a;
|
|
9406
|
+
var _a, _b, _c, _d;
|
|
8698
9407
|
if (import_lodash.default.isUndefined(openView) || import_lodash.default.isNull(openView)) {
|
|
8699
9408
|
return openView;
|
|
8700
9409
|
}
|
|
@@ -8761,17 +9470,39 @@ class FlowSurfacesService {
|
|
|
8761
9470
|
if (templateRef.mode === "copy") {
|
|
8762
9471
|
await this.ensurePopupSurface(resolvedUid, options.transaction);
|
|
8763
9472
|
}
|
|
8764
|
-
let
|
|
9473
|
+
let runtimeRecordFilterTargetKey;
|
|
9474
|
+
if (((_b = options.popupActionContext) == null ? void 0 : _b.hasCurrentRecord) === true) {
|
|
9475
|
+
runtimeRecordFilterTargetKey = await this.resolveOpenViewRuntimeRecordFilterTargetKey(
|
|
9476
|
+
normalizedOpenView,
|
|
9477
|
+
template,
|
|
9478
|
+
options
|
|
9479
|
+
);
|
|
9480
|
+
}
|
|
9481
|
+
const filterTargetKey = runtimeRecordFilterTargetKey || this.resolveOpenViewFilterTargetKey(normalizedOpenView, template);
|
|
9482
|
+
let nextTemplateOpenView = this.buildPopupTemplateOpenView(template, templateRef.mode, resolvedUid, {
|
|
9483
|
+
filterTargetKey,
|
|
9484
|
+
useRuntimeRecordFilterByTk: ((_c = options.popupActionContext) == null ? void 0 : _c.hasCurrentRecord) === true
|
|
9485
|
+
});
|
|
8765
9486
|
Object.keys(normalizedOpenView).forEach((key) => {
|
|
8766
9487
|
if (key === "template" || key === "popupTemplateUid" || key === "popupTemplateMode" || key === "popupTemplateContext" || key === "popupTemplateHasFilterByTk" || key === "popupTemplateHasSourceId") {
|
|
8767
9488
|
delete normalizedOpenView[key];
|
|
8768
9489
|
}
|
|
8769
9490
|
});
|
|
9491
|
+
if (((_d = options.popupActionContext) == null ? void 0 : _d.hasCurrentRecord) === true && this.shouldOmitRuntimeRecordFilterByTk(normalizedOpenView.filterByTk, {
|
|
9492
|
+
filterTargetKey
|
|
9493
|
+
})) {
|
|
9494
|
+
delete normalizedOpenView.filterByTk;
|
|
9495
|
+
}
|
|
8770
9496
|
if (String(options.popupTemplateHostUse || "").trim() === "AddChildActionModel") {
|
|
8771
9497
|
nextTemplateOpenView = import_lodash.default.omit(nextTemplateOpenView, ["sourceId"]);
|
|
8772
9498
|
}
|
|
8773
9499
|
Object.assign(normalizedOpenView, nextTemplateOpenView);
|
|
8774
9500
|
}
|
|
9501
|
+
if (this.shouldUseRuntimeRecordFilterByTkForOpenView(normalizedOpenView, options) && this.shouldOmitRuntimeRecordFilterByTk(normalizedOpenView.filterByTk, {
|
|
9502
|
+
filterTargetKey: await this.resolveOpenViewRuntimeRecordFilterTargetKey(normalizedOpenView, void 0, options)
|
|
9503
|
+
})) {
|
|
9504
|
+
delete normalizedOpenView.filterByTk;
|
|
9505
|
+
}
|
|
8775
9506
|
if (!import_lodash.default.isUndefined(normalizedOpenView.uid)) {
|
|
8776
9507
|
const normalizedUid = String(normalizedOpenView.uid || "").trim();
|
|
8777
9508
|
if (!normalizedUid) {
|
|
@@ -8812,7 +9543,8 @@ class FlowSurfacesService {
|
|
|
8812
9543
|
return void 0;
|
|
8813
9544
|
}
|
|
8814
9545
|
return {
|
|
8815
|
-
hasCurrentRecord: true
|
|
9546
|
+
hasCurrentRecord: true,
|
|
9547
|
+
currentRecordFilterTargetKey: await this.resolvePopupHostCurrentRecordFilterTargetKey(current.uid, transaction)
|
|
8816
9548
|
};
|
|
8817
9549
|
}
|
|
8818
9550
|
unsetPayloadPathAndPruneEmptyParents(payload, path) {
|
|
@@ -8970,7 +9702,12 @@ class FlowSurfacesService {
|
|
|
8970
9702
|
return {};
|
|
8971
9703
|
}
|
|
8972
9704
|
if (input.popup && !this.isPopupFieldHostUse(fieldNode.use)) {
|
|
8973
|
-
(0, import_errors.throwBadRequest)(
|
|
9705
|
+
(0, import_errors.throwBadRequest)(
|
|
9706
|
+
withJsPopupGuidance(
|
|
9707
|
+
`flowSurfaces ${actionName} field '${fieldNode.use}' does not support popup`,
|
|
9708
|
+
fieldNode.use
|
|
9709
|
+
)
|
|
9710
|
+
);
|
|
8974
9711
|
}
|
|
8975
9712
|
let openView = this.resolvePopupHostOpenView(fieldNode);
|
|
8976
9713
|
if (input.popup && this.isExternalPopupOpenView(openView, fieldHostUid)) {
|
|
@@ -9296,6 +10033,20 @@ class FlowSurfacesService {
|
|
|
9296
10033
|
isEmptyInlinePopupPayload(popup) {
|
|
9297
10034
|
return import_lodash.default.isPlainObject(popup) && Object.keys(popup).length === 0;
|
|
9298
10035
|
}
|
|
10036
|
+
isInlineFieldPopupDefaultShell(popup) {
|
|
10037
|
+
if (!import_lodash.default.isPlainObject(popup)) {
|
|
10038
|
+
return false;
|
|
10039
|
+
}
|
|
10040
|
+
const shellOnlyKeys = /* @__PURE__ */ new Set([
|
|
10041
|
+
"title",
|
|
10042
|
+
"mode",
|
|
10043
|
+
"openView",
|
|
10044
|
+
"tryTemplate",
|
|
10045
|
+
"defaultType",
|
|
10046
|
+
import_defaults.FLOW_SURFACE_APPLY_BLUEPRINT_POPUP_DEFAULTS_KEY
|
|
10047
|
+
]);
|
|
10048
|
+
return Object.keys(popup).every((key) => shellOnlyKeys.has(key));
|
|
10049
|
+
}
|
|
9299
10050
|
shouldAutoCompleteDefaultFieldPopup(fieldNode, popup, wrapperNode) {
|
|
9300
10051
|
if (!import_lodash.default.isPlainObject(popup)) {
|
|
9301
10052
|
return false;
|
|
@@ -9310,7 +10061,7 @@ class FlowSurfacesService {
|
|
|
9310
10061
|
if (!String(fieldContext.collectionName || "").trim()) {
|
|
9311
10062
|
return false;
|
|
9312
10063
|
}
|
|
9313
|
-
return popup.tryTemplate === true || !import_lodash.default.isUndefined(popup.defaultType) ||
|
|
10064
|
+
return popup.tryTemplate === true || !import_lodash.default.isUndefined(popup.defaultType) || this.isInlineFieldPopupDefaultShell(popup);
|
|
9314
10065
|
}
|
|
9315
10066
|
isInlineFieldPopupBlockMissingResource(block) {
|
|
9316
10067
|
if (!import_lodash.default.isPlainObject(block) || !import_lodash.default.isUndefined(block.template)) {
|
|
@@ -10372,14 +11123,21 @@ class FlowSurfacesService {
|
|
|
10372
11123
|
actionNode,
|
|
10373
11124
|
options.transaction
|
|
10374
11125
|
).catch(() => null);
|
|
10375
|
-
const
|
|
11126
|
+
const useRuntimeRecordFilterByTk = this.isReferencedPopupTemplateOpenView(currentOpenView, actionNode.uid);
|
|
11127
|
+
const filterTargetKey = useRuntimeRecordFilterByTk ? await this.resolveOpenViewRuntimeRecordFilterTargetKey(currentOpenView, void 0, {
|
|
11128
|
+
transaction: options.transaction,
|
|
11129
|
+
popupTemplateHostUid: actionNode.uid,
|
|
11130
|
+
popupActionContext: {
|
|
11131
|
+
hasCurrentRecord: true
|
|
11132
|
+
}
|
|
11133
|
+
}) : (popupProfile == null ? void 0 : popupProfile.currentCollection) ? this.getCollectionFilterTargetKey(popupProfile.currentCollection) : null;
|
|
10376
11134
|
const defaultFilterByTk = this.resolvePopupCurrentRecordResourceFilterByTk(popupProfile);
|
|
10377
11135
|
const currentFilterByTk = import_lodash.default.isString(currentOpenView.filterByTk) ? currentOpenView.filterByTk.trim() : "";
|
|
10378
|
-
const preserveCustomFilterByTk = currentFilterByTk &&
|
|
11136
|
+
const preserveCustomFilterByTk = currentFilterByTk && !this.shouldOmitRuntimeRecordFilterByTk(currentOpenView.filterByTk, { filterTargetKey: filterTargetKey || "" });
|
|
10379
11137
|
const nextOpenView = (0, import_service_utils.buildDefinedPayload)({
|
|
10380
|
-
...currentOpenView,
|
|
11138
|
+
...useRuntimeRecordFilterByTk && !preserveCustomFilterByTk ? import_lodash.default.omit(currentOpenView, ["filterByTk"]) : currentOpenView,
|
|
10381
11139
|
title: openViewTitle,
|
|
10382
|
-
filterByTk: preserveCustomFilterByTk ? currentOpenView.filterByTk : defaultFilterByTk || currentOpenView.filterByTk
|
|
11140
|
+
filterByTk: useRuntimeRecordFilterByTk ? preserveCustomFilterByTk ? currentOpenView.filterByTk : void 0 : preserveCustomFilterByTk ? currentOpenView.filterByTk : defaultFilterByTk || currentOpenView.filterByTk
|
|
10383
11141
|
});
|
|
10384
11142
|
if (import_lodash.default.isEqual(nextOpenView, currentOpenView)) {
|
|
10385
11143
|
return;
|
|
@@ -10641,7 +11399,7 @@ class FlowSurfacesService {
|
|
|
10641
11399
|
}
|
|
10642
11400
|
if (this.isAIEmployeeActionUse(current == null ? void 0 : current.use) && this.hasAIEmployeePublicSettings(normalizedValues)) {
|
|
10643
11401
|
const enabledPackages = await this.resolveEnabledPluginPackages(options);
|
|
10644
|
-
const
|
|
11402
|
+
const aiEmployeeSettingsPayload = await this.normalizeAIEmployeeActionPublicSettings(
|
|
10645
11403
|
"updateSettings",
|
|
10646
11404
|
import_lodash.default.pick(normalizedValues, AI_EMPLOYEE_PUBLIC_SETTING_KEYS),
|
|
10647
11405
|
{
|
|
@@ -10649,13 +11407,17 @@ class FlowSurfacesService {
|
|
|
10649
11407
|
enabledPackages,
|
|
10650
11408
|
current,
|
|
10651
11409
|
currentRoles: options.currentRoles,
|
|
10652
|
-
selfUid: await this.resolveAIEmployeeActionSelfUid(current, options.transaction)
|
|
11410
|
+
selfUid: await this.resolveAIEmployeeActionSelfUid(current, options.transaction),
|
|
11411
|
+
promptContext: {
|
|
11412
|
+
kind: "target",
|
|
11413
|
+
targetUid: (current == null ? void 0 : current.uid) || writeTarget.uid
|
|
11414
|
+
}
|
|
10653
11415
|
}
|
|
10654
11416
|
);
|
|
10655
11417
|
AI_EMPLOYEE_PUBLIC_SETTING_KEYS.forEach((key) => {
|
|
10656
11418
|
delete normalizedValues[key];
|
|
10657
11419
|
});
|
|
10658
|
-
|
|
11420
|
+
this.mergeAIEmployeeActionSettingsPayload(current, normalizedValues, aiEmployeeSettingsPayload);
|
|
10659
11421
|
}
|
|
10660
11422
|
assertNoFlowSurfaceIdTitleFieldSettings(normalizedValues, {
|
|
10661
11423
|
action: "updateSettings",
|
|
@@ -10675,6 +11437,7 @@ class FlowSurfacesService {
|
|
|
10675
11437
|
}
|
|
10676
11438
|
if (domain === "flowRegistry") {
|
|
10677
11439
|
this.assertNoTreeConnectFieldsFlowRegistry(current, normalizedValues[domain], "updateSettings");
|
|
11440
|
+
normalizedValues[domain] = this.normalizeEventFlowRegistry("updateSettings", normalizedValues[domain]);
|
|
10678
11441
|
}
|
|
10679
11442
|
if (!contract.editableDomains.includes(domain)) {
|
|
10680
11443
|
(0, import_errors.throwBadRequest)(`flowSurfaces updateSettings domain '${domain}' is not editable`);
|
|
@@ -10691,6 +11454,9 @@ class FlowSurfacesService {
|
|
|
10691
11454
|
current.use
|
|
10692
11455
|
);
|
|
10693
11456
|
});
|
|
11457
|
+
if (!import_lodash.default.isUndefined(nextPayload.flowRegistry)) {
|
|
11458
|
+
nextPayload.flowRegistry = this.normalizeEventFlowRegistry("updateSettings", nextPayload.flowRegistry);
|
|
11459
|
+
}
|
|
10694
11460
|
this.replaceExplicitPopupStepParamSubtreesForUpdateSettings(
|
|
10695
11461
|
current,
|
|
10696
11462
|
normalizedValues,
|
|
@@ -10703,6 +11469,14 @@ class FlowSurfacesService {
|
|
|
10703
11469
|
nextPayload,
|
|
10704
11470
|
options.replaceRecordHistorySettings === true
|
|
10705
11471
|
);
|
|
11472
|
+
this.syncAIEmployeeTaskStepParamsForUpdateSettings(current, nextPayload);
|
|
11473
|
+
await this.normalizeAIEmployeeStepParamTasksForUpdateSettings(current, nextPayload, writeTarget, options);
|
|
11474
|
+
await this.assertAIEmployeeStepParamTaskPromptVariablesAllowedForUpdateSettings(
|
|
11475
|
+
current,
|
|
11476
|
+
nextPayload,
|
|
11477
|
+
writeTarget,
|
|
11478
|
+
options
|
|
11479
|
+
);
|
|
10706
11480
|
this.syncCalendarPopupPropsForUpdateSettings(current, normalizedValues, nextPayload);
|
|
10707
11481
|
this.syncKanbanPopupPropsForUpdateSettings(current, normalizedValues, nextPayload);
|
|
10708
11482
|
this.syncDefaultSortingForUpdateSettings(current, normalizedValues, nextPayload);
|
|
@@ -10749,7 +11523,7 @@ class FlowSurfacesService {
|
|
|
10749
11523
|
props: nextPayload.props ?? current.props,
|
|
10750
11524
|
decoratorProps: nextPayload.decoratorProps ?? current.decoratorProps,
|
|
10751
11525
|
stepParams: nextPayload.stepParams ?? current.stepParams,
|
|
10752
|
-
flowRegistry: nextPayload.flowRegistry ?? current
|
|
11526
|
+
flowRegistry: nextPayload.flowRegistry ?? this.getEventFlowRegistry(current)
|
|
10753
11527
|
};
|
|
10754
11528
|
const shouldValidateFlowRegistry = !import_lodash.default.isUndefined(nextPayload.flowRegistry) || !import_lodash.default.isUndefined(nextPayload.stepParams);
|
|
10755
11529
|
assertNoFlowSurfaceIdTitleFieldSettings(import_lodash.default.pick(effectiveNode, ["props", "stepParams"]), {
|
|
@@ -11174,12 +11948,12 @@ class FlowSurfacesService {
|
|
|
11174
11948
|
"flowSurfaces updateSettings filter action values 'props.defaultFilterValue/filterValue' and 'stepParams.filterSettings.defaultFilter.defaultFilter' must match"
|
|
11175
11949
|
);
|
|
11176
11950
|
}
|
|
11177
|
-
const
|
|
11178
|
-
hasStepDefaultFilter ? nextStepFilter : nextPropFilter
|
|
11179
|
-
{
|
|
11180
|
-
requiredFieldCount: options.requiredFieldCount
|
|
11181
|
-
}
|
|
11951
|
+
const normalizedFilterValue = this.normalizeFilterActionDefaultFilterValue(
|
|
11952
|
+
hasStepDefaultFilter ? nextStepFilter : nextPropFilter
|
|
11182
11953
|
);
|
|
11954
|
+
const filterValue = this.normalizeEffectivePublicDataSurfaceDefaultFilter(normalizedFilterValue, {
|
|
11955
|
+
requiredFieldCount: options.requiredFieldCount
|
|
11956
|
+
});
|
|
11183
11957
|
if (!hasPropsFilterableFieldNames && !hasStepFilterableFieldNames) {
|
|
11184
11958
|
const filterableFieldNames = (0, import_public_data_surface_default_filter.resolveFlowSurfaceDefaultFilterFieldNames)(filterValue);
|
|
11185
11959
|
if (filterableFieldNames.length) {
|
|
@@ -11590,7 +12364,12 @@ class FlowSurfacesService {
|
|
|
11590
12364
|
}
|
|
11591
12365
|
if (!((_c = sqlPreview.queryOutputs) == null ? void 0 : _c.length)) {
|
|
11592
12366
|
(0, import_errors.throwBadRequest)(
|
|
11593
|
-
|
|
12367
|
+
withChartRepairMessage(
|
|
12368
|
+
"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"
|
|
12369
|
+
),
|
|
12370
|
+
{
|
|
12371
|
+
details: withFlowSurfaceChartRepairDetails()
|
|
12372
|
+
}
|
|
11594
12373
|
);
|
|
11595
12374
|
}
|
|
11596
12375
|
const supportedOutputs = new Set(
|
|
@@ -11599,7 +12378,14 @@ class FlowSurfacesService {
|
|
|
11599
12378
|
for (const mappingField of (0, import_chart_config.getChartVisualMappingAliases)(state.visual)) {
|
|
11600
12379
|
if (!supportedOutputs.has(mappingField)) {
|
|
11601
12380
|
(0, import_errors.throwBadRequest)(
|
|
11602
|
-
|
|
12381
|
+
withChartRepairMessage(
|
|
12382
|
+
`chart visual mappings only support SQL query output fields: ${Array.from(supportedOutputs).join(", ")}`
|
|
12383
|
+
),
|
|
12384
|
+
{
|
|
12385
|
+
details: withFlowSurfaceChartRepairDetails({
|
|
12386
|
+
supportedOutputs: Array.from(supportedOutputs)
|
|
12387
|
+
})
|
|
12388
|
+
}
|
|
11603
12389
|
);
|
|
11604
12390
|
}
|
|
11605
12391
|
}
|
|
@@ -11611,7 +12397,7 @@ class FlowSurfacesService {
|
|
|
11611
12397
|
return String(input || "").trim();
|
|
11612
12398
|
}
|
|
11613
12399
|
validateBuilderChartFieldsForRuntime(actionName, configure) {
|
|
11614
|
-
var _a, _b;
|
|
12400
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
11615
12401
|
const resourceInit = (0, import_chart_config.getChartBuilderResourceInit)(configure);
|
|
11616
12402
|
if (!(resourceInit == null ? void 0 : resourceInit.collectionName)) {
|
|
11617
12403
|
return;
|
|
@@ -11629,10 +12415,12 @@ class FlowSurfacesService {
|
|
|
11629
12415
|
const selections = [
|
|
11630
12416
|
...import_lodash.default.castArray(state.query.measures || []).map((selection, index) => ({
|
|
11631
12417
|
selection,
|
|
12418
|
+
kind: "measure",
|
|
11632
12419
|
path: `chart query.measures[${index}].field`
|
|
11633
12420
|
})),
|
|
11634
12421
|
...import_lodash.default.castArray(state.query.dimensions || []).map((selection, index) => ({
|
|
11635
12422
|
selection,
|
|
12423
|
+
kind: "dimension",
|
|
11636
12424
|
path: `chart query.dimensions[${index}].field`
|
|
11637
12425
|
}))
|
|
11638
12426
|
];
|
|
@@ -11641,20 +12429,153 @@ class FlowSurfacesService {
|
|
|
11641
12429
|
if (!fieldPath) {
|
|
11642
12430
|
continue;
|
|
11643
12431
|
}
|
|
12432
|
+
const fieldPathParts = fieldPath.split(".").filter(Boolean);
|
|
12433
|
+
const isCountMeasureSelection = item.kind === "measure" && String(((_c = item.selection) == null ? void 0 : _c.aggregation) || "").trim() === "count" && !((_d = item.selection) == null ? void 0 : _d.distinct);
|
|
12434
|
+
if (fieldPathParts.length > 1 && !isCountMeasureSelection) {
|
|
12435
|
+
const directAssociationPath = fieldPathParts[0];
|
|
12436
|
+
const directAssociationField = (0, import_service_helpers.resolveFieldFromCollection)(collection, directAssociationPath);
|
|
12437
|
+
const directAssociationTargetCollection = directAssociationField && (0, import_service_helpers.isAssociationField)(directAssociationField) ? (0, import_service_helpers.resolveFieldTargetCollection)(
|
|
12438
|
+
directAssociationField,
|
|
12439
|
+
dataSourceKey,
|
|
12440
|
+
(resolvedDataSourceKey, targetCollection) => this.getCollection(resolvedDataSourceKey, targetCollection)
|
|
12441
|
+
) : null;
|
|
12442
|
+
const invalidDirectSubfield = directAssociationTargetCollection ? (0, import_service_helpers.getInvalidChartBuilderRelationDirectSubfieldDetails)({
|
|
12443
|
+
associationPathName: directAssociationPath,
|
|
12444
|
+
selectedSubfieldPath: fieldPathParts.slice(1).join("."),
|
|
12445
|
+
targetCollection: directAssociationTargetCollection
|
|
12446
|
+
}) : null;
|
|
12447
|
+
if (invalidDirectSubfield) {
|
|
12448
|
+
(0, import_errors.throwBadRequest)(
|
|
12449
|
+
withChartRepairMessage(
|
|
12450
|
+
`flowSurfaces ${actionName} ${item.path} '${fieldPath}' must reference a direct scalar child field under relation '${invalidDirectSubfield.associationPath}'. ${(0, import_service_helpers.formatChartBuilderSupportedRelationSubfields)(
|
|
12451
|
+
invalidDirectSubfield.associationPath,
|
|
12452
|
+
invalidDirectSubfield.supportedFields
|
|
12453
|
+
)}`
|
|
12454
|
+
),
|
|
12455
|
+
{
|
|
12456
|
+
path: item.path,
|
|
12457
|
+
ruleId: "chart-builder-query-relation-direct-subfield-required",
|
|
12458
|
+
details: withFlowSurfaceChartRepairDetails({
|
|
12459
|
+
fieldPath,
|
|
12460
|
+
dataSourceKey,
|
|
12461
|
+
collectionName,
|
|
12462
|
+
...invalidDirectSubfield
|
|
12463
|
+
})
|
|
12464
|
+
}
|
|
12465
|
+
);
|
|
12466
|
+
}
|
|
12467
|
+
}
|
|
11644
12468
|
const parsed = this.parseFieldPath(collection, fieldPath, void 0, dataSourceKey, collectionName);
|
|
12469
|
+
if (parsed.associationPathName) {
|
|
12470
|
+
const associationField = parsed.associationField;
|
|
12471
|
+
const associationTargetCollection = associationField && (0, import_service_helpers.isAssociationField)(associationField) ? (0, import_service_helpers.resolveFieldTargetCollection)(
|
|
12472
|
+
associationField,
|
|
12473
|
+
dataSourceKey,
|
|
12474
|
+
(resolvedDataSourceKey, targetCollection) => this.getCollection(resolvedDataSourceKey, targetCollection)
|
|
12475
|
+
) : null;
|
|
12476
|
+
if (!associationField || !(0, import_service_helpers.isAssociationField)(associationField) || !associationTargetCollection) {
|
|
12477
|
+
(0, import_errors.throwBadRequest)(
|
|
12478
|
+
withChartRepairMessage(
|
|
12479
|
+
`flowSurfaces ${actionName} ${item.path} '${fieldPath}' uses invalid association path '${parsed.associationPathName}' for builder charts`
|
|
12480
|
+
),
|
|
12481
|
+
{
|
|
12482
|
+
path: item.path,
|
|
12483
|
+
ruleId: "chart-builder-query-association-path-invalid",
|
|
12484
|
+
details: withFlowSurfaceChartRepairDetails({
|
|
12485
|
+
fieldPath,
|
|
12486
|
+
associationPath: parsed.associationPathName,
|
|
12487
|
+
dataSourceKey,
|
|
12488
|
+
collectionName
|
|
12489
|
+
})
|
|
12490
|
+
}
|
|
12491
|
+
);
|
|
12492
|
+
}
|
|
12493
|
+
}
|
|
11645
12494
|
const field = (0, import_service_helpers.resolveFieldFromCollection)(parsed.leafCollection, parsed.leafFieldPath);
|
|
12495
|
+
const leafModelAttributes = (0, import_service_helpers.getCollectionModelAttributes)(parsed.leafCollection);
|
|
12496
|
+
const hasLeafModelAttribute = Object.prototype.hasOwnProperty.call(leafModelAttributes, parsed.leafFieldPath);
|
|
12497
|
+
const isCountMeasureRelationSubfield = item.kind === "measure" && String(((_e = item.selection) == null ? void 0 : _e.aggregation) || "").trim() === "count" && !((_f = item.selection) == null ? void 0 : _f.distinct) && parsed.associationField && (0, import_service_helpers.isAssociationField)(parsed.associationField);
|
|
12498
|
+
const unsupportedRelationSubfield = parsed.associationField && (0, import_service_helpers.isAssociationField)(parsed.associationField) ? (0, import_service_helpers.getUnsupportedChartBuilderRelationSubfieldDetails)({
|
|
12499
|
+
associationPathName: parsed.associationPathName,
|
|
12500
|
+
leafFieldName: parsed.leafFieldPath,
|
|
12501
|
+
leafField: field,
|
|
12502
|
+
targetCollection: parsed.leafCollection
|
|
12503
|
+
}) : null;
|
|
11646
12504
|
if (!field) {
|
|
11647
|
-
|
|
11648
|
-
|
|
12505
|
+
const hasConcreteField = hasLeafModelAttribute || this.collectionHasConcreteField(parsed.leafCollection, parsed.leafFieldPath);
|
|
12506
|
+
if (!hasConcreteField) {
|
|
12507
|
+
(0, import_errors.throwBadRequest)(
|
|
12508
|
+
withChartRepairMessage(
|
|
12509
|
+
`flowSurfaces ${actionName} ${item.path} '${fieldPath}' does not exist on collection '${dataSourceKey}.${collectionName}'`
|
|
12510
|
+
),
|
|
12511
|
+
{
|
|
12512
|
+
details: withFlowSurfaceChartRepairDetails({
|
|
12513
|
+
fieldPath,
|
|
12514
|
+
dataSourceKey,
|
|
12515
|
+
collectionName
|
|
12516
|
+
})
|
|
12517
|
+
}
|
|
12518
|
+
);
|
|
11649
12519
|
}
|
|
12520
|
+
}
|
|
12521
|
+
if (!fieldPath.includes(".") && field && (0, import_service_helpers.isAssociationField)(field)) {
|
|
12522
|
+
const suggestion = this.resolveBuilderChartAssociationSubfieldSuggestion(fieldPath, field, dataSourceKey);
|
|
11650
12523
|
(0, import_errors.throwBadRequest)(
|
|
11651
|
-
|
|
12524
|
+
withChartRepairMessage(
|
|
12525
|
+
`flowSurfaces ${actionName} ${item.path} '${fieldPath}' references an association field directly; use scalar subfield '${suggestion.suggestedFieldPath}' for builder charts`
|
|
12526
|
+
),
|
|
12527
|
+
{
|
|
12528
|
+
details: withFlowSurfaceChartRepairDetails({
|
|
12529
|
+
fieldPath,
|
|
12530
|
+
dataSourceKey,
|
|
12531
|
+
collectionName,
|
|
12532
|
+
...suggestion
|
|
12533
|
+
})
|
|
12534
|
+
}
|
|
11652
12535
|
);
|
|
11653
12536
|
}
|
|
11654
|
-
if (
|
|
11655
|
-
|
|
12537
|
+
if (isCountMeasureRelationSubfield) {
|
|
12538
|
+
(0, import_errors.throwBadRequest)(
|
|
12539
|
+
withChartRepairMessage(
|
|
12540
|
+
`flowSurfaces ${actionName} ${item.path} '${fieldPath}' counts a relation subfield; count a scalar base field such as 'id' and keep '${fieldPath}' as a dimension`
|
|
12541
|
+
),
|
|
12542
|
+
{
|
|
12543
|
+
path: item.path,
|
|
12544
|
+
ruleId: "chart-builder-query-count-measure-relation-subfield",
|
|
12545
|
+
details: withFlowSurfaceChartRepairDetails({
|
|
12546
|
+
fieldPath,
|
|
12547
|
+
dataSourceKey,
|
|
12548
|
+
collectionName,
|
|
12549
|
+
suggestedMeasure: {
|
|
12550
|
+
field: "id",
|
|
12551
|
+
aggregation: "count",
|
|
12552
|
+
alias: String(((_g = item.selection) == null ? void 0 : _g.alias) || "").trim() || "recordCount"
|
|
12553
|
+
},
|
|
12554
|
+
suggestedDimension: {
|
|
12555
|
+
field: fieldPath
|
|
12556
|
+
}
|
|
12557
|
+
})
|
|
12558
|
+
}
|
|
12559
|
+
);
|
|
12560
|
+
}
|
|
12561
|
+
if (unsupportedRelationSubfield) {
|
|
11656
12562
|
(0, import_errors.throwBadRequest)(
|
|
11657
|
-
|
|
12563
|
+
withChartRepairMessage(
|
|
12564
|
+
`flowSurfaces ${actionName} ${item.path} '${fieldPath}' references relation subfield '${fieldPath}', but current chart builder SQL generation cannot query relation subfield '${unsupportedRelationSubfield.leafFieldName}' because its database column is '${unsupportedRelationSubfield.columnName}'. ${(0, import_service_helpers.formatChartBuilderSupportedRelationSubfields)(
|
|
12565
|
+
unsupportedRelationSubfield.associationPath,
|
|
12566
|
+
unsupportedRelationSubfield.supportedFields
|
|
12567
|
+
)}`
|
|
12568
|
+
),
|
|
12569
|
+
{
|
|
12570
|
+
path: item.path,
|
|
12571
|
+
ruleId: "chart-builder-query-relation-subfield-column-unsupported",
|
|
12572
|
+
details: withFlowSurfaceChartRepairDetails({
|
|
12573
|
+
fieldPath,
|
|
12574
|
+
dataSourceKey,
|
|
12575
|
+
collectionName,
|
|
12576
|
+
...unsupportedRelationSubfield
|
|
12577
|
+
})
|
|
12578
|
+
}
|
|
11658
12579
|
);
|
|
11659
12580
|
}
|
|
11660
12581
|
}
|
|
@@ -11679,6 +12600,48 @@ class FlowSurfacesService {
|
|
|
11679
12600
|
suggestedFieldPath: `${fieldPath}.<field>`
|
|
11680
12601
|
};
|
|
11681
12602
|
}
|
|
12603
|
+
async validateChartConfigureForRuntime(actionName, configure, transaction) {
|
|
12604
|
+
var _a, _b, _c;
|
|
12605
|
+
if (!import_lodash.default.isPlainObject(configure)) {
|
|
12606
|
+
return;
|
|
12607
|
+
}
|
|
12608
|
+
this.validateBuilderChartFieldsForRuntime(actionName, configure);
|
|
12609
|
+
const state = (0, import_chart_config.deriveChartSemanticState)(configure);
|
|
12610
|
+
if (((_a = state.query) == null ? void 0 : _a.mode) !== "sql") {
|
|
12611
|
+
return;
|
|
12612
|
+
}
|
|
12613
|
+
const sqlPreview = await this.resolveSqlChartPreview(state.query, transaction);
|
|
12614
|
+
if (((_b = state.visual) == null ? void 0 : _b.mode) !== "basic") {
|
|
12615
|
+
return;
|
|
12616
|
+
}
|
|
12617
|
+
if (!((_c = sqlPreview.queryOutputs) == null ? void 0 : _c.length)) {
|
|
12618
|
+
(0, import_errors.throwBadRequest)(
|
|
12619
|
+
withChartRepairMessage(
|
|
12620
|
+
"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"
|
|
12621
|
+
),
|
|
12622
|
+
{
|
|
12623
|
+
details: withFlowSurfaceChartRepairDetails()
|
|
12624
|
+
}
|
|
12625
|
+
);
|
|
12626
|
+
}
|
|
12627
|
+
const supportedOutputs = new Set(
|
|
12628
|
+
sqlPreview.queryOutputs.map((output) => String((output == null ? void 0 : output.alias) || "").trim()).filter(Boolean)
|
|
12629
|
+
);
|
|
12630
|
+
for (const mappingField of (0, import_chart_config.getChartVisualMappingAliases)(state.visual)) {
|
|
12631
|
+
if (!supportedOutputs.has(mappingField)) {
|
|
12632
|
+
(0, import_errors.throwBadRequest)(
|
|
12633
|
+
withChartRepairMessage(
|
|
12634
|
+
`chart visual mappings only support SQL query output fields: ${Array.from(supportedOutputs).join(", ")}`
|
|
12635
|
+
),
|
|
12636
|
+
{
|
|
12637
|
+
details: withFlowSurfaceChartRepairDetails({
|
|
12638
|
+
supportedOutputs: Array.from(supportedOutputs)
|
|
12639
|
+
})
|
|
12640
|
+
}
|
|
12641
|
+
);
|
|
12642
|
+
}
|
|
12643
|
+
}
|
|
12644
|
+
}
|
|
11682
12645
|
stripChartSqlForInspection(sql) {
|
|
11683
12646
|
return sql.replace(/\/\*[\s\S]*?\*\//g, " ").replace(/--[^\r\n]*/g, " ").replace(/'(?:''|[^'])*'/g, "''").replace(/"(?:[""]|[^"])*"/g, '""');
|
|
11684
12647
|
}
|
|
@@ -11686,16 +12649,16 @@ class FlowSurfacesService {
|
|
|
11686
12649
|
const normalized = (typeof sql === "string" ? sql : "").trim();
|
|
11687
12650
|
const inspected = this.stripChartSqlForInspection(normalized).replace(/;+\s*$/, "").trim();
|
|
11688
12651
|
if (!inspected) {
|
|
11689
|
-
(
|
|
12652
|
+
throwChartRepairBadRequest("chart query.sql cannot be empty");
|
|
11690
12653
|
}
|
|
11691
12654
|
if (inspected.includes(";")) {
|
|
11692
|
-
(
|
|
12655
|
+
throwChartRepairBadRequest("chart query.sql must be a single read-only SELECT statement");
|
|
11693
12656
|
}
|
|
11694
12657
|
if (!/^(with|select)\b/i.test(inspected)) {
|
|
11695
|
-
(
|
|
12658
|
+
throwChartRepairBadRequest("chart query.sql must start with SELECT or WITH");
|
|
11696
12659
|
}
|
|
11697
12660
|
if (/\b(insert|update|delete|drop|alter|truncate|create|replace|grant|revoke|merge|call|execute)\b/i.test(inspected)) {
|
|
11698
|
-
(
|
|
12661
|
+
throwChartRepairBadRequest("chart query.sql must be read-only");
|
|
11699
12662
|
}
|
|
11700
12663
|
return normalized.replace(/;+\s*$/, "").trim();
|
|
11701
12664
|
}
|
|
@@ -11713,7 +12676,7 @@ class FlowSurfacesService {
|
|
|
11713
12676
|
if ((_a = db == null ? void 0 : db.sequelize) == null ? void 0 : _a.query) {
|
|
11714
12677
|
return db.sequelize.query(sql, { bind, transaction });
|
|
11715
12678
|
}
|
|
11716
|
-
(
|
|
12679
|
+
throwChartRepairBadRequest("chart SQL preview is unavailable for the target data source");
|
|
11717
12680
|
}
|
|
11718
12681
|
extractSqlChartPreviewAliases(metadata) {
|
|
11719
12682
|
const pickName = (field) => {
|
|
@@ -11751,7 +12714,13 @@ class FlowSurfacesService {
|
|
|
11751
12714
|
async resolveSqlChartPreview(query, _transaction) {
|
|
11752
12715
|
var _a, _b;
|
|
11753
12716
|
const normalizedSql = this.normalizeReadOnlyChartSql(query == null ? void 0 : query.sql);
|
|
11754
|
-
|
|
12717
|
+
let transformed;
|
|
12718
|
+
try {
|
|
12719
|
+
transformed = await (0, import_utils.transformSQL)(normalizedSql);
|
|
12720
|
+
} catch (error) {
|
|
12721
|
+
const message = (error == null ? void 0 : error.message) || String(error);
|
|
12722
|
+
throwChartRepairBadRequest(`chart query.sql is invalid: ${message}`);
|
|
12723
|
+
}
|
|
11755
12724
|
const riskyHints = [];
|
|
11756
12725
|
const hasRuntimeContext = Object.keys((transformed == null ? void 0 : transformed.bind) || {}).length > 0 || Object.keys((transformed == null ? void 0 : transformed.liquidContext) || {}).length > 0;
|
|
11757
12726
|
if (hasRuntimeContext) {
|
|
@@ -11807,7 +12776,7 @@ class FlowSurfacesService {
|
|
|
11807
12776
|
}
|
|
11808
12777
|
const outputAliases = Object.keys(firstRow);
|
|
11809
12778
|
if (!outputAliases.length) {
|
|
11810
|
-
(
|
|
12779
|
+
throwChartRepairBadRequest("chart query.sql must expose at least one output column");
|
|
11811
12780
|
}
|
|
11812
12781
|
return {
|
|
11813
12782
|
queryOutputs: outputAliases.map((alias) => ({
|
|
@@ -11818,8 +12787,11 @@ class FlowSurfacesService {
|
|
|
11818
12787
|
riskyHints
|
|
11819
12788
|
};
|
|
11820
12789
|
} catch (error) {
|
|
12790
|
+
if (isFlowSurfaceChartRepairError(error)) {
|
|
12791
|
+
throw error;
|
|
12792
|
+
}
|
|
11821
12793
|
const message = (error == null ? void 0 : error.message) || String(error);
|
|
11822
|
-
(
|
|
12794
|
+
throwChartRepairBadRequest(`chart query.sql is invalid: ${message}`);
|
|
11823
12795
|
}
|
|
11824
12796
|
}
|
|
11825
12797
|
syncChartCardRuntimeStepParamsForUpdateSettings(current, nextPayload, replacementCardSettings) {
|
|
@@ -11876,6 +12848,8 @@ class FlowSurfacesService {
|
|
|
11876
12848
|
options
|
|
11877
12849
|
);
|
|
11878
12850
|
const flowRegistry = this.getEventFlowRegistry(current);
|
|
12851
|
+
const directEvents = import_lodash.default.cloneDeep(((_a = contract.eventCapabilities) == null ? void 0 : _a.direct) || []);
|
|
12852
|
+
const objectEvents = import_lodash.default.uniq([...import_lodash.default.cloneDeep(((_b = contract.eventCapabilities) == null ? void 0 : _b.object) || []), ...directEvents]);
|
|
11879
12853
|
return {
|
|
11880
12854
|
target: {
|
|
11881
12855
|
uid: target.uid,
|
|
@@ -11884,8 +12858,8 @@ class FlowSurfacesService {
|
|
|
11884
12858
|
},
|
|
11885
12859
|
flowRegistry,
|
|
11886
12860
|
events: {
|
|
11887
|
-
direct:
|
|
11888
|
-
object:
|
|
12861
|
+
direct: directEvents,
|
|
12862
|
+
object: objectEvents
|
|
11889
12863
|
},
|
|
11890
12864
|
phases: {
|
|
11891
12865
|
supported: ["beforeAllFlows", "afterAllFlows", "beforeFlow", "afterFlow", "beforeStep", "afterStep"],
|
|
@@ -11920,13 +12894,12 @@ class FlowSurfacesService {
|
|
|
11920
12894
|
if (phase !== "beforeAllFlows") {
|
|
11921
12895
|
(0, import_errors.throwBadRequest)(`flowSurfaces addEventFlow only supports phase 'beforeAllFlows'`);
|
|
11922
12896
|
}
|
|
11923
|
-
const
|
|
11924
|
-
const nextFlowRegistry = {
|
|
12897
|
+
const nextFlowRegistry = this.normalizeEventFlowRegistry("addEventFlow", {
|
|
11925
12898
|
...flowRegistry,
|
|
11926
|
-
[key]:
|
|
11927
|
-
};
|
|
12899
|
+
[key]: this.normalizeAddEventFlowInput(key, values, phase)
|
|
12900
|
+
});
|
|
11928
12901
|
await this.persistEventFlowRegistry("addEventFlow", target, current, nextFlowRegistry, options);
|
|
11929
|
-
return this.buildEventFlowWriteResult(target, key,
|
|
12902
|
+
return this.buildEventFlowWriteResult(target, key, nextFlowRegistry[key], nextFlowRegistry);
|
|
11930
12903
|
}
|
|
11931
12904
|
async setEventFlow(values, options = {}) {
|
|
11932
12905
|
var _a;
|
|
@@ -11940,13 +12913,12 @@ class FlowSurfacesService {
|
|
|
11940
12913
|
const key = this.normalizeEventFlowKey("setEventFlow", (values == null ? void 0 : values.key) ?? ((_a = values == null ? void 0 : values.flow) == null ? void 0 : _a.key));
|
|
11941
12914
|
this.assertEventFlowFingerprint("setEventFlow", values == null ? void 0 : values.expectedFingerprint, flowRegistry);
|
|
11942
12915
|
const flowInput = import_lodash.default.isPlainObject(values == null ? void 0 : values.flow) ? values.flow : values;
|
|
11943
|
-
const
|
|
11944
|
-
const nextFlowRegistry = {
|
|
12916
|
+
const nextFlowRegistry = this.normalizeEventFlowRegistry("setEventFlow", {
|
|
11945
12917
|
...flowRegistry,
|
|
11946
|
-
[key]:
|
|
11947
|
-
};
|
|
12918
|
+
[key]: this.normalizeEventFlowObject("setEventFlow", key, flowInput)
|
|
12919
|
+
});
|
|
11948
12920
|
await this.persistEventFlowRegistry("setEventFlow", target, current, nextFlowRegistry, options);
|
|
11949
|
-
return this.buildEventFlowWriteResult(target, key,
|
|
12921
|
+
return this.buildEventFlowWriteResult(target, key, nextFlowRegistry[key], nextFlowRegistry);
|
|
11950
12922
|
}
|
|
11951
12923
|
async removeEventFlow(values, options = {}) {
|
|
11952
12924
|
(0, import_payload_shape.validateFlowSurfacePayloadShape)("removeEventFlow", values, "values");
|
|
@@ -11961,14 +12933,14 @@ class FlowSurfacesService {
|
|
|
11961
12933
|
(0, import_errors.throwBadRequest)(`flowSurfaces removeEventFlow flow '${key}' does not exist`);
|
|
11962
12934
|
}
|
|
11963
12935
|
this.assertEventFlowFingerprint("removeEventFlow", values == null ? void 0 : values.expectedFingerprint, flowRegistry);
|
|
11964
|
-
const nextFlowRegistry = import_lodash.default.omit(flowRegistry, [key]);
|
|
12936
|
+
const nextFlowRegistry = this.normalizeEventFlowRegistry("removeEventFlow", import_lodash.default.omit(flowRegistry, [key]));
|
|
11965
12937
|
await this.persistEventFlowRegistry("removeEventFlow", target, current, nextFlowRegistry, options);
|
|
11966
12938
|
return this.buildEventFlowWriteResult(target, key, void 0, nextFlowRegistry);
|
|
11967
12939
|
}
|
|
11968
12940
|
async setEventFlows(values, options = {}) {
|
|
11969
12941
|
(0, import_payload_shape.validateFlowSurfacePayloadShape)("setEventFlows", values, "values");
|
|
11970
12942
|
const { target, current } = await this.resolveEventFlowTarget("setEventFlows", values == null ? void 0 : values.target, values, options);
|
|
11971
|
-
const flows = values.flowRegistry || values.flows || {};
|
|
12943
|
+
const flows = this.normalizeEventFlowRegistry("setEventFlows", values.flowRegistry || values.flows || {});
|
|
11972
12944
|
await this.persistEventFlowRegistry("setEventFlows", target, current, flows, options);
|
|
11973
12945
|
return {
|
|
11974
12946
|
uid: target.uid,
|
|
@@ -11994,7 +12966,10 @@ class FlowSurfacesService {
|
|
|
11994
12966
|
};
|
|
11995
12967
|
}
|
|
11996
12968
|
getEventFlowRegistry(node) {
|
|
11997
|
-
return import_lodash.default.isPlainObject(node == null ? void 0 : node.flowRegistry) ?
|
|
12969
|
+
return import_lodash.default.isPlainObject(node == null ? void 0 : node.flowRegistry) ? this.normalizeEventFlowRegistry("getEventFlowRegistry", node.flowRegistry) : {};
|
|
12970
|
+
}
|
|
12971
|
+
normalizeEventFlowRegistry(actionName, flowRegistry) {
|
|
12972
|
+
return (0, import_event_flow_normalizer.normalizeFlowSurfaceEventFlowRegistry)(actionName, flowRegistry);
|
|
11998
12973
|
}
|
|
11999
12974
|
buildEventFlowFingerprint(flowRegistry) {
|
|
12000
12975
|
return this.buildSurfaceFingerprint({
|
|
@@ -12032,7 +13007,9 @@ class FlowSurfacesService {
|
|
|
12032
13007
|
normalizeAddEventFlowInput(key, values, phase) {
|
|
12033
13008
|
var _a, _b, _c;
|
|
12034
13009
|
const flow = import_lodash.default.isPlainObject(values.flow) ? import_lodash.default.cloneDeep(values.flow) : {};
|
|
12035
|
-
const eventName = String(
|
|
13010
|
+
const eventName = String(
|
|
13011
|
+
values.eventName ?? (typeof flow.on === "string" ? flow.on : (_a = flow == null ? void 0 : flow.on) == null ? void 0 : _a.eventName) ?? ""
|
|
13012
|
+
).trim();
|
|
12036
13013
|
if (!eventName) {
|
|
12037
13014
|
(0, import_errors.throwBadRequest)(`flowSurfaces addEventFlow requires eventName`);
|
|
12038
13015
|
}
|
|
@@ -12055,25 +13032,7 @@ class FlowSurfacesService {
|
|
|
12055
13032
|
});
|
|
12056
13033
|
}
|
|
12057
13034
|
normalizeEventFlowObject(actionName, key, flowInput) {
|
|
12058
|
-
|
|
12059
|
-
(0, import_errors.throwBadRequest)(`flowSurfaces ${actionName} flow '${key}' must be an object`);
|
|
12060
|
-
}
|
|
12061
|
-
const flow = import_lodash.default.cloneDeep(flowInput);
|
|
12062
|
-
flow.key = key;
|
|
12063
|
-
if (import_lodash.default.isPlainObject(flow.on)) {
|
|
12064
|
-
const eventName = String(flow.on.eventName || "").trim();
|
|
12065
|
-
if (eventName) {
|
|
12066
|
-
flow.on.eventName = eventName;
|
|
12067
|
-
}
|
|
12068
|
-
const phase = String(flow.on.phase || "").trim();
|
|
12069
|
-
if (phase) {
|
|
12070
|
-
flow.on.phase = phase;
|
|
12071
|
-
}
|
|
12072
|
-
}
|
|
12073
|
-
if (import_lodash.default.isUndefined(flow.steps)) {
|
|
12074
|
-
flow.steps = {};
|
|
12075
|
-
}
|
|
12076
|
-
return flow;
|
|
13035
|
+
return (0, import_event_flow_normalizer.normalizeFlowSurfaceEventFlow)(actionName, key, flowInput);
|
|
12077
13036
|
}
|
|
12078
13037
|
async persistEventFlowRegistry(actionName, target, current, flowRegistry, options = {}) {
|
|
12079
13038
|
this.assertNoTreeConnectFieldsFlowRegistry(current, flowRegistry, actionName);
|
|
@@ -13827,6 +14786,97 @@ class FlowSurfacesService {
|
|
|
13827
14786
|
}
|
|
13828
14787
|
}
|
|
13829
14788
|
}
|
|
14789
|
+
hasActionWithPublicType(actions, type) {
|
|
14790
|
+
return actions.some((action) => import_catalog.ACTION_KEY_BY_USE.get(String((action == null ? void 0 : action.use) || "").trim()) === type);
|
|
14791
|
+
}
|
|
14792
|
+
async ensureTableDefaultActionIntegrity(tableUid, options = {}) {
|
|
14793
|
+
var _a, _b, _c, _d;
|
|
14794
|
+
let table = await this.repository.findModelById(tableUid, {
|
|
14795
|
+
transaction: options.transaction,
|
|
14796
|
+
includeAsyncNode: true
|
|
14797
|
+
});
|
|
14798
|
+
if ((table == null ? void 0 : table.use) !== "TableBlockModel" || this.resolveTreeTableCreationContext(table)) {
|
|
14799
|
+
return;
|
|
14800
|
+
}
|
|
14801
|
+
const descriptors = (0, import_default_block_actions.getFlowSurfaceDefaultBlockActions)({ blockType: "table" });
|
|
14802
|
+
const blockActionDescriptors = descriptors.filter((descriptor) => descriptor.scope === "actions");
|
|
14803
|
+
const recordActionDescriptors = descriptors.filter((descriptor) => descriptor.scope === "recordActions");
|
|
14804
|
+
let blockActions = import_lodash.default.castArray(((_a = table == null ? void 0 : table.subModels) == null ? void 0 : _a.actions) || []);
|
|
14805
|
+
for (const descriptor of blockActionDescriptors) {
|
|
14806
|
+
if (this.hasActionWithPublicType(blockActions, descriptor.type)) {
|
|
14807
|
+
continue;
|
|
14808
|
+
}
|
|
14809
|
+
await this.addAction(
|
|
14810
|
+
{
|
|
14811
|
+
target: { uid: tableUid },
|
|
14812
|
+
type: descriptor.type,
|
|
14813
|
+
...descriptor.popup ? { popup: import_lodash.default.cloneDeep(descriptor.popup) } : {}
|
|
14814
|
+
},
|
|
14815
|
+
options
|
|
14816
|
+
);
|
|
14817
|
+
table = await this.repository.findModelById(tableUid, {
|
|
14818
|
+
transaction: options.transaction,
|
|
14819
|
+
includeAsyncNode: true
|
|
14820
|
+
});
|
|
14821
|
+
blockActions = import_lodash.default.castArray(((_b = table == null ? void 0 : table.subModels) == null ? void 0 : _b.actions) || []);
|
|
14822
|
+
}
|
|
14823
|
+
const actionsColumnUid = await this.ensureTableActionsColumn(tableUid, options.transaction);
|
|
14824
|
+
let actionsColumn = await this.repository.findModelById(actionsColumnUid, {
|
|
14825
|
+
transaction: options.transaction,
|
|
14826
|
+
includeAsyncNode: true
|
|
14827
|
+
});
|
|
14828
|
+
let recordActions = import_lodash.default.castArray(((_c = actionsColumn == null ? void 0 : actionsColumn.subModels) == null ? void 0 : _c.actions) || []);
|
|
14829
|
+
for (const descriptor of recordActionDescriptors) {
|
|
14830
|
+
if (this.hasActionWithPublicType(recordActions, descriptor.type)) {
|
|
14831
|
+
continue;
|
|
14832
|
+
}
|
|
14833
|
+
await this.addRecordAction(
|
|
14834
|
+
{
|
|
14835
|
+
target: { uid: tableUid },
|
|
14836
|
+
type: descriptor.type,
|
|
14837
|
+
...descriptor.popup ? { popup: import_lodash.default.cloneDeep(descriptor.popup) } : {}
|
|
14838
|
+
},
|
|
14839
|
+
options
|
|
14840
|
+
);
|
|
14841
|
+
actionsColumn = await this.repository.findModelById(actionsColumnUid, {
|
|
14842
|
+
transaction: options.transaction,
|
|
14843
|
+
includeAsyncNode: true
|
|
14844
|
+
});
|
|
14845
|
+
recordActions = import_lodash.default.castArray(((_d = actionsColumn == null ? void 0 : actionsColumn.subModels) == null ? void 0 : _d.actions) || []);
|
|
14846
|
+
}
|
|
14847
|
+
const missingRecordActions = recordActionDescriptors.map((descriptor) => descriptor.type).filter((type) => !this.hasActionWithPublicType(recordActions, type));
|
|
14848
|
+
if (missingRecordActions.length) {
|
|
14849
|
+
(0, import_errors.throwBadRequest)(`flowSurfaces table '${tableUid}' is missing required default record actions`, {
|
|
14850
|
+
ruleId: "table-record-actions-required",
|
|
14851
|
+
details: {
|
|
14852
|
+
tableUid,
|
|
14853
|
+
missingRecordActions,
|
|
14854
|
+
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."
|
|
14855
|
+
}
|
|
14856
|
+
});
|
|
14857
|
+
}
|
|
14858
|
+
}
|
|
14859
|
+
collectNodeTreeDescendants(node, predicate, bucket = []) {
|
|
14860
|
+
if (!node || typeof node !== "object") {
|
|
14861
|
+
return bucket;
|
|
14862
|
+
}
|
|
14863
|
+
if (predicate(node)) {
|
|
14864
|
+
bucket.push(node);
|
|
14865
|
+
}
|
|
14866
|
+
Object.values(import_lodash.default.isPlainObject(node.subModels) ? node.subModels : {}).forEach((subModel) => {
|
|
14867
|
+
import_lodash.default.castArray(subModel).forEach((child) => this.collectNodeTreeDescendants(child, predicate, bucket));
|
|
14868
|
+
});
|
|
14869
|
+
return bucket;
|
|
14870
|
+
}
|
|
14871
|
+
async ensureSurfaceTableDefaultActionIntegrity(pageLocator, options = {}) {
|
|
14872
|
+
const surface = await this.get(pageLocator, options);
|
|
14873
|
+
const tables = this.collectNodeTreeDescendants(surface == null ? void 0 : surface.tree, (item) => (item == null ? void 0 : item.use) === "TableBlockModel");
|
|
14874
|
+
for (const table of tables) {
|
|
14875
|
+
if (table == null ? void 0 : table.uid) {
|
|
14876
|
+
await this.ensureTableDefaultActionIntegrity(table.uid, options);
|
|
14877
|
+
}
|
|
14878
|
+
}
|
|
14879
|
+
}
|
|
13830
14880
|
async resolveReusableSingletonAction(input) {
|
|
13831
14881
|
var _a, _b, _c;
|
|
13832
14882
|
if (AUTO_SUBMIT_FORM_BLOCK_USES.has(input.ownerUse || "") && input.actionUse === "FormSubmitActionModel") {
|
|
@@ -13990,8 +15040,10 @@ class FlowSurfacesService {
|
|
|
13990
15040
|
if (blockCatalogItem) {
|
|
13991
15041
|
this.validateComposeActionGroups(blockCatalogItem.use, actions, recordActions, enabledPackages);
|
|
13992
15042
|
}
|
|
13993
|
-
const actionKeys = new Set(actions.map((item) => item.key).filter(Boolean));
|
|
13994
|
-
const recordActionKeys = new Set(
|
|
15043
|
+
const actionKeys = new Set(actions.map((item) => String(item.key || "").trim()).filter(Boolean));
|
|
15044
|
+
const recordActionKeys = new Set(
|
|
15045
|
+
recordActions.map((item) => String(item.key || "").trim()).filter(Boolean)
|
|
15046
|
+
);
|
|
13995
15047
|
const blockDescriptor = this.describeComposeBlock({
|
|
13996
15048
|
index: index + 1,
|
|
13997
15049
|
key,
|
|
@@ -14422,6 +15474,7 @@ class FlowSurfacesService {
|
|
|
14422
15474
|
...(0, import_service_utils.hasDefinedValue)(changes, [
|
|
14423
15475
|
"pageSize",
|
|
14424
15476
|
"density",
|
|
15477
|
+
"enableRowSelection",
|
|
14425
15478
|
"showRowNumbers",
|
|
14426
15479
|
"sorting",
|
|
14427
15480
|
"dataScope",
|
|
@@ -14435,6 +15488,7 @@ class FlowSurfacesService {
|
|
|
14435
15488
|
...(0, import_service_utils.hasOwnDefined)(changes, "pageSize") ? { pageSize: { pageSize: changes.pageSize } } : {},
|
|
14436
15489
|
...(0, import_service_utils.hasOwnDefined)(changes, "density") ? { tableDensity: { size: changes.density } } : {},
|
|
14437
15490
|
...(0, import_service_utils.hasOwnDefined)(changes, "quickEdit") ? { quickEdit: { editable: changes.quickEdit } } : {},
|
|
15491
|
+
...(0, import_service_utils.hasOwnDefined)(changes, "enableRowSelection") ? { enableRowSelection: { enableRowSelection: changes.enableRowSelection } } : {},
|
|
14438
15492
|
...(0, import_service_utils.hasOwnDefined)(changes, "showRowNumbers") ? { showRowNumbers: { showIndex: changes.showRowNumbers } } : {},
|
|
14439
15493
|
...(0, import_service_utils.hasOwnDefined)(changes, "sorting") ? {
|
|
14440
15494
|
defaultSorting: {
|
|
@@ -15370,7 +16424,10 @@ class FlowSurfacesService {
|
|
|
15370
16424
|
const shouldLoadCurrent = shouldUpdateConfigure || shouldUpdateCardSettings;
|
|
15371
16425
|
const resolved = shouldLoadCurrent ? await this.locator.resolve(target, options) : null;
|
|
15372
16426
|
const current = resolved ? await this.loadResolvedNode(resolved, options.transaction) : null;
|
|
15373
|
-
let nextConfigure = shouldUpdateConfigure ? (
|
|
16427
|
+
let nextConfigure = shouldUpdateConfigure ? buildChartConfigureFromSemanticChangesWithRepair(
|
|
16428
|
+
import_lodash.default.get(current, ["stepParams", "chartSettings", "configure"]),
|
|
16429
|
+
changes
|
|
16430
|
+
) : void 0;
|
|
15374
16431
|
if (shouldUpdateConfigure) {
|
|
15375
16432
|
nextConfigure = await this.stripBasicSqlVisualWhenPreviewUnavailable(nextConfigure, changes, options.transaction);
|
|
15376
16433
|
}
|
|
@@ -15498,18 +16555,18 @@ class FlowSurfacesService {
|
|
|
15498
16555
|
return String(raw || "").trim();
|
|
15499
16556
|
}
|
|
15500
16557
|
collectionHasConcreteField(collection, fieldName) {
|
|
15501
|
-
var _a, _b, _c
|
|
16558
|
+
var _a, _b, _c;
|
|
15502
16559
|
const normalized = String(fieldName || "").trim();
|
|
15503
16560
|
if (!normalized) {
|
|
15504
16561
|
return false;
|
|
15505
16562
|
}
|
|
15506
|
-
const modelAttributes = (
|
|
16563
|
+
const modelAttributes = (0, import_service_helpers.getCollectionModelAttributes)(collection);
|
|
15507
16564
|
const primaryKeyAttributes = import_lodash.default.castArray(
|
|
15508
|
-
((
|
|
16565
|
+
((_a = collection == null ? void 0 : collection.model) == null ? void 0 : _a.primaryKeyAttributes) || ((_b = collection == null ? void 0 : collection.model) == null ? void 0 : _b.primaryKeyAttribute) || []
|
|
15509
16566
|
);
|
|
15510
16567
|
const modelAttribute = modelAttributes == null ? void 0 : modelAttributes[normalized];
|
|
15511
16568
|
const isModelPrimaryKey = primaryKeyAttributes.includes(normalized) || !!(modelAttribute == null ? void 0 : modelAttribute.primaryKey);
|
|
15512
|
-
return !!((0, import_service_helpers.resolveFieldFromCollection)(collection, normalized) || ((
|
|
16569
|
+
return !!((0, import_service_helpers.resolveFieldFromCollection)(collection, normalized) || ((_c = collection == null ? void 0 : collection.getField) == null ? void 0 : _c.call(collection, normalized)) || (0, import_service_helpers.getCollectionFields)(collection).some((field) => (0, import_service_helpers.getFieldName)(field) === normalized) || isModelPrimaryKey);
|
|
15513
16570
|
}
|
|
15514
16571
|
assertInitialBlockResourceCompatible(actionName, blockUse, resourceInit, popupProfile) {
|
|
15515
16572
|
if (blockUse === "CommentsBlockModel") {
|
|
@@ -15812,6 +16869,7 @@ class FlowSurfacesService {
|
|
|
15812
16869
|
);
|
|
15813
16870
|
}
|
|
15814
16871
|
async configureJSColumn(target, changes, options) {
|
|
16872
|
+
assertNoJsDeclarativeOpenView("jsColumn", changes, "JSColumnModel");
|
|
15815
16873
|
const allowedKeys = (0, import_configure_options.getConfigureOptionKeysForUse)("JSColumnModel");
|
|
15816
16874
|
(0, import_service_utils.assertSupportedSimpleChanges)("jsColumn", changes, allowedKeys);
|
|
15817
16875
|
return this.updateSettings(
|
|
@@ -15845,6 +16903,8 @@ class FlowSurfacesService {
|
|
|
15845
16903
|
);
|
|
15846
16904
|
}
|
|
15847
16905
|
async configureJSItem(target, changes, options) {
|
|
16906
|
+
const { currentUse = "JSItemModel", ...updateOptions } = options;
|
|
16907
|
+
assertNoJsDeclarativeOpenView("jsItem", changes, currentUse);
|
|
15848
16908
|
const allowedKeys = (0, import_configure_options.getConfigureOptionKeysForUse)("JSItemModel");
|
|
15849
16909
|
(0, import_service_utils.assertSupportedSimpleChanges)("jsItem", changes, allowedKeys);
|
|
15850
16910
|
return this.updateSettings(
|
|
@@ -15869,7 +16929,7 @@ class FlowSurfacesService {
|
|
|
15869
16929
|
}
|
|
15870
16930
|
} : void 0
|
|
15871
16931
|
},
|
|
15872
|
-
|
|
16932
|
+
updateOptions
|
|
15873
16933
|
);
|
|
15874
16934
|
}
|
|
15875
16935
|
async configureDividerItem(target, changes, options) {
|
|
@@ -15920,6 +16980,7 @@ class FlowSurfacesService {
|
|
|
15920
16980
|
transaction: options.transaction,
|
|
15921
16981
|
includeAsyncNode: true
|
|
15922
16982
|
}) : null;
|
|
16983
|
+
assertNoJsDeclarativeOpenView("field", changes, innerField == null ? void 0 : innerField.use);
|
|
15923
16984
|
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
16985
|
const bindingChange = (0, import_service_utils.hasDefinedValue)(wrapperChanges, ["fieldPath", "associationPathName"]);
|
|
15925
16986
|
const normalizedBinding = bindingChange ? this.normalizeDisplayFieldBinding({
|
|
@@ -16131,6 +17192,8 @@ class FlowSurfacesService {
|
|
|
16131
17192
|
const enabledPackages = await this.resolveEnabledPluginPackages(options);
|
|
16132
17193
|
const resolved = await this.locator.resolve(target, options);
|
|
16133
17194
|
const current = await this.loadResolvedNode(resolved, options.transaction);
|
|
17195
|
+
const isJsFieldNode = ["JSFieldModel", "JSEditableFieldModel"].includes((current == null ? void 0 : current.use) || "");
|
|
17196
|
+
assertNoJsDeclarativeOpenView("field", changes, current == null ? void 0 : current.use);
|
|
16134
17197
|
(0, import_service_utils.assertSupportedSimpleChanges)(
|
|
16135
17198
|
"field",
|
|
16136
17199
|
changes,
|
|
@@ -16141,7 +17204,6 @@ class FlowSurfacesService {
|
|
|
16141
17204
|
transaction: options.transaction,
|
|
16142
17205
|
includeAsyncNode: true
|
|
16143
17206
|
}) : null;
|
|
16144
|
-
const isJsFieldNode = ["JSFieldModel", "JSEditableFieldModel"].includes((current == null ? void 0 : current.use) || "");
|
|
16145
17207
|
if ((0, import_service_utils.hasDefinedValue)(changes, ["code", "version"]) && !isJsFieldNode) {
|
|
16146
17208
|
(0, import_errors.throwBadRequest)(`flowSurfaces configure field '${current == null ? void 0 : current.use}' does not support code/version`);
|
|
16147
17209
|
}
|
|
@@ -16315,7 +17377,11 @@ class FlowSurfacesService {
|
|
|
16315
17377
|
items: []
|
|
16316
17378
|
};
|
|
16317
17379
|
}
|
|
16318
|
-
return
|
|
17380
|
+
return (0, import_filter_group.normalizeFlowSurfaceFilterGroupValue)(
|
|
17381
|
+
value,
|
|
17382
|
+
`flowSurfaces configure action defaultFilter expects FilterGroup like ${import_filter_group.FLOW_SURFACE_FILTER_GROUP_EXAMPLE}`,
|
|
17383
|
+
{ strictDateValues: true }
|
|
17384
|
+
);
|
|
16319
17385
|
}
|
|
16320
17386
|
normalizeActionAssignValues(actionName, value) {
|
|
16321
17387
|
if (!import_lodash.default.isPlainObject(value)) {
|
|
@@ -16346,6 +17412,93 @@ class FlowSurfacesService {
|
|
|
16346
17412
|
isAIEmployeeActionUse(use) {
|
|
16347
17413
|
return String(use || "").trim() === AI_EMPLOYEE_ACTION_USE;
|
|
16348
17414
|
}
|
|
17415
|
+
stableSerializeAIEmployeeValue(value) {
|
|
17416
|
+
if (Array.isArray(value)) {
|
|
17417
|
+
return `[${value.map((item) => this.stableSerializeAIEmployeeValue(item)).join(",")}]`;
|
|
17418
|
+
}
|
|
17419
|
+
if (import_lodash.default.isPlainObject(value)) {
|
|
17420
|
+
return `{${Object.keys(value).sort().map((key) => `${JSON.stringify(key)}:${this.stableSerializeAIEmployeeValue(value[key])}`).join(",")}}`;
|
|
17421
|
+
}
|
|
17422
|
+
return JSON.stringify(value);
|
|
17423
|
+
}
|
|
17424
|
+
buildAIEmployeeActionDedupIdentity(values) {
|
|
17425
|
+
var _a, _b, _c, _d, _e, _f;
|
|
17426
|
+
const username = String(((_b = (_a = values == null ? void 0 : values.props) == null ? void 0 : _a.aiEmployee) == null ? void 0 : _b.username) || "").trim();
|
|
17427
|
+
if (!username) {
|
|
17428
|
+
return "";
|
|
17429
|
+
}
|
|
17430
|
+
return this.stableSerializeAIEmployeeValue({
|
|
17431
|
+
username,
|
|
17432
|
+
auto: typeof ((_c = values == null ? void 0 : values.props) == null ? void 0 : _c.auto) === "boolean" ? values.props.auto : false,
|
|
17433
|
+
workContext: this.normalizeAIEmployeeWorkContextForDedupIdentity((_e = (_d = values == null ? void 0 : values.props) == null ? void 0 : _d.context) == null ? void 0 : _e.workContext),
|
|
17434
|
+
tasks: this.normalizeAIEmployeeTasksForDedupIdentity(
|
|
17435
|
+
import_lodash.default.get(values, ["stepParams", ...AI_EMPLOYEE_TASK_STEP_PARAMS_PATH])
|
|
17436
|
+
),
|
|
17437
|
+
style: {
|
|
17438
|
+
...AI_EMPLOYEE_DEFAULT_STYLE,
|
|
17439
|
+
...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) : {}
|
|
17440
|
+
}
|
|
17441
|
+
});
|
|
17442
|
+
}
|
|
17443
|
+
normalizeAIEmployeeWorkContextForDedupIdentity(value) {
|
|
17444
|
+
return import_lodash.default.castArray(value || []).map(
|
|
17445
|
+
(item) => import_lodash.default.isPlainObject(item) ? import_lodash.default.pick(item, AI_EMPLOYEE_WORK_CONTEXT_PUBLIC_KEYS) : item
|
|
17446
|
+
);
|
|
17447
|
+
}
|
|
17448
|
+
normalizeAIEmployeeTasksForDedupIdentity(value) {
|
|
17449
|
+
return import_lodash.default.castArray(value || []).map((task) => {
|
|
17450
|
+
if (!import_lodash.default.isPlainObject(task)) {
|
|
17451
|
+
return task;
|
|
17452
|
+
}
|
|
17453
|
+
const output = import_lodash.default.pick(task, AI_EMPLOYEE_TASK_PUBLIC_SETTING_KEYS);
|
|
17454
|
+
if (import_lodash.default.isPlainObject(output.message)) {
|
|
17455
|
+
output.message = import_lodash.default.pick(output.message, AI_EMPLOYEE_TASK_MESSAGE_PUBLIC_KEYS);
|
|
17456
|
+
if (Object.prototype.hasOwnProperty.call(output.message, "workContext")) {
|
|
17457
|
+
output.message.workContext = this.normalizeAIEmployeeWorkContextForDedupIdentity(output.message.workContext);
|
|
17458
|
+
}
|
|
17459
|
+
}
|
|
17460
|
+
if (import_lodash.default.isPlainObject(output.model)) {
|
|
17461
|
+
output.model = import_lodash.default.pick(output.model, AI_EMPLOYEE_TASK_MODEL_PUBLIC_KEYS);
|
|
17462
|
+
}
|
|
17463
|
+
if (import_lodash.default.isPlainObject(output.skillSettings)) {
|
|
17464
|
+
output.skillSettings = import_lodash.default.pick(output.skillSettings, AI_EMPLOYEE_SKILL_SETTINGS_PUBLIC_KEYS);
|
|
17465
|
+
}
|
|
17466
|
+
return output;
|
|
17467
|
+
});
|
|
17468
|
+
}
|
|
17469
|
+
async assertNoDuplicateAIEmployeeAction(actionName, parentUid, values, transaction) {
|
|
17470
|
+
var _a;
|
|
17471
|
+
const identity = this.buildAIEmployeeActionDedupIdentity(values);
|
|
17472
|
+
if (!identity) {
|
|
17473
|
+
return;
|
|
17474
|
+
}
|
|
17475
|
+
const parentNode = await this.repository.findModelById(parentUid, {
|
|
17476
|
+
transaction,
|
|
17477
|
+
includeAsyncNode: true
|
|
17478
|
+
});
|
|
17479
|
+
const duplicate = import_lodash.default.castArray(((_a = parentNode == null ? void 0 : parentNode.subModels) == null ? void 0 : _a.actions) || []).find((action) => {
|
|
17480
|
+
if (!this.isAIEmployeeActionUse(action == null ? void 0 : action.use)) {
|
|
17481
|
+
return false;
|
|
17482
|
+
}
|
|
17483
|
+
return this.buildAIEmployeeActionDedupIdentity({
|
|
17484
|
+
props: action.props,
|
|
17485
|
+
stepParams: action.stepParams
|
|
17486
|
+
}) === identity;
|
|
17487
|
+
});
|
|
17488
|
+
if (!(duplicate == null ? void 0 : duplicate.uid)) {
|
|
17489
|
+
return;
|
|
17490
|
+
}
|
|
17491
|
+
(0, import_errors.throwBadRequest)(
|
|
17492
|
+
`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`,
|
|
17493
|
+
{
|
|
17494
|
+
ruleId: "duplicate-ai-employee-action",
|
|
17495
|
+
details: {
|
|
17496
|
+
existingUid: duplicate.uid,
|
|
17497
|
+
repairHint: "Remove the duplicate aiEmployee action, or change username, task title/key, or workContext if this is a genuinely different AI employee action."
|
|
17498
|
+
}
|
|
17499
|
+
}
|
|
17500
|
+
);
|
|
17501
|
+
}
|
|
16349
17502
|
hasAIEmployeePublicSettings(settings) {
|
|
16350
17503
|
return import_lodash.default.isPlainObject(settings) && AI_EMPLOYEE_PUBLIC_SETTING_KEYS.some((key) => Object.prototype.hasOwnProperty.call(settings, key));
|
|
16351
17504
|
}
|
|
@@ -16353,16 +17506,31 @@ class FlowSurfacesService {
|
|
|
16353
17506
|
const unsupportedKeys = Object.keys(settings || {}).filter((key) => !AI_EMPLOYEE_PUBLIC_SETTING_KEYS.includes(key));
|
|
16354
17507
|
if (unsupportedKeys.length) {
|
|
16355
17508
|
(0, import_errors.throwBadRequest)(
|
|
16356
|
-
`flowSurfaces ${actionName} AI employee settings do not support keys: ${unsupportedKeys.join(
|
|
17509
|
+
`flowSurfaces ${actionName} AI employee settings do not support keys: ${unsupportedKeys.join(
|
|
17510
|
+
", "
|
|
17511
|
+
)}; allowed keys: ${AI_EMPLOYEE_PUBLIC_SETTING_KEYS.join(
|
|
17512
|
+
", "
|
|
17513
|
+
)}; repairHint: use top-level username, auto, workContext, tasks, or style instead of raw props/stepParams`
|
|
16357
17514
|
);
|
|
16358
17515
|
}
|
|
16359
17516
|
}
|
|
17517
|
+
aiEmployeeNestedRepairHint(path) {
|
|
17518
|
+
if (path.includes("workContext")) {
|
|
17519
|
+
return AI_EMPLOYEE_WORK_CONTEXT_REPAIR_HINT;
|
|
17520
|
+
}
|
|
17521
|
+
if (path.includes("tasks")) {
|
|
17522
|
+
return AI_EMPLOYEE_TASK_REPAIR_HINT;
|
|
17523
|
+
}
|
|
17524
|
+
return "Use only the documented public AI employee settings keys for this nested object.";
|
|
17525
|
+
}
|
|
16360
17526
|
assertOnlyAIEmployeeNestedPublicSettings(actionName, path, value, allowedKeys) {
|
|
16361
17527
|
const unsupportedKeys = Object.keys(value || {}).filter((key) => !allowedKeys.includes(key));
|
|
16362
17528
|
if (!unsupportedKeys.length) {
|
|
16363
17529
|
return;
|
|
16364
17530
|
}
|
|
16365
|
-
(0, import_errors.throwBadRequest)(
|
|
17531
|
+
(0, import_errors.throwBadRequest)(
|
|
17532
|
+
`flowSurfaces ${actionName} ${path} does not support key '${unsupportedKeys[0]}'; allowed keys: ${allowedKeys.join(", ")}; repairHint: ${this.aiEmployeeNestedRepairHint(path)}`
|
|
17533
|
+
);
|
|
16366
17534
|
}
|
|
16367
17535
|
assertNoAIEmployeeInternalPropSettings(actionName, values) {
|
|
16368
17536
|
const props = values == null ? void 0 : values.props;
|
|
@@ -16381,6 +17549,67 @@ class FlowSurfacesService {
|
|
|
16381
17549
|
)}; use top-level username, auto, workContext, tasks or style instead`
|
|
16382
17550
|
);
|
|
16383
17551
|
}
|
|
17552
|
+
readAIEmployeePersistedTasks(current) {
|
|
17553
|
+
var _a;
|
|
17554
|
+
const stepTasks = import_lodash.default.get(current, ["stepParams", ...AI_EMPLOYEE_TASK_STEP_PARAMS_PATH]);
|
|
17555
|
+
if (Array.isArray(stepTasks)) {
|
|
17556
|
+
return stepTasks;
|
|
17557
|
+
}
|
|
17558
|
+
const legacyPropsTasks = (_a = current == null ? void 0 : current.props) == null ? void 0 : _a.tasks;
|
|
17559
|
+
return Array.isArray(legacyPropsTasks) ? legacyPropsTasks : [];
|
|
17560
|
+
}
|
|
17561
|
+
buildAIEmployeeTaskStepParams(tasks) {
|
|
17562
|
+
const stepParams = {};
|
|
17563
|
+
import_lodash.default.set(stepParams, AI_EMPLOYEE_TASK_STEP_PARAMS_PATH, import_lodash.default.cloneDeep(tasks));
|
|
17564
|
+
return stepParams;
|
|
17565
|
+
}
|
|
17566
|
+
mergeAIEmployeeActionSettingsPayload(current, values, payload) {
|
|
17567
|
+
if (Object.keys(payload.props).length) {
|
|
17568
|
+
values.props = import_lodash.default.merge({}, values.props || {}, payload.props);
|
|
17569
|
+
}
|
|
17570
|
+
if (Object.keys(payload.stepParams).length) {
|
|
17571
|
+
values.stepParams = import_lodash.default.mergeWith({}, values.stepParams || {}, payload.stepParams, (_currentValue, nextValue) => {
|
|
17572
|
+
if (Array.isArray(nextValue)) {
|
|
17573
|
+
return import_lodash.default.cloneDeep(nextValue);
|
|
17574
|
+
}
|
|
17575
|
+
return void 0;
|
|
17576
|
+
});
|
|
17577
|
+
}
|
|
17578
|
+
if (import_lodash.default.has(payload.stepParams, AI_EMPLOYEE_TASK_STEP_PARAMS_PATH) && this.isAIEmployeeActionUse(current == null ? void 0 : current.use)) {
|
|
17579
|
+
if (import_lodash.default.isPlainObject(values.props)) {
|
|
17580
|
+
delete values.props.tasks;
|
|
17581
|
+
}
|
|
17582
|
+
}
|
|
17583
|
+
}
|
|
17584
|
+
syncAIEmployeeTaskStepParamsForUpdateSettings(current, nextPayload) {
|
|
17585
|
+
var _a;
|
|
17586
|
+
if (!this.isAIEmployeeActionUse(current == null ? void 0 : current.use)) {
|
|
17587
|
+
return;
|
|
17588
|
+
}
|
|
17589
|
+
const legacyPropsTasks = (_a = current == null ? void 0 : current.props) == null ? void 0 : _a.tasks;
|
|
17590
|
+
const hasLegacyPropsTasks = Array.isArray(legacyPropsTasks);
|
|
17591
|
+
const hasNextStepTasks = import_lodash.default.has(nextPayload, ["stepParams", ...AI_EMPLOYEE_TASK_STEP_PARAMS_PATH]);
|
|
17592
|
+
const currentStepTasks = import_lodash.default.get(current, ["stepParams", ...AI_EMPLOYEE_TASK_STEP_PARAMS_PATH]);
|
|
17593
|
+
if (!hasNextStepTasks && hasLegacyPropsTasks && !Array.isArray(currentStepTasks)) {
|
|
17594
|
+
nextPayload.stepParams = import_lodash.default.mergeWith(
|
|
17595
|
+
{},
|
|
17596
|
+
(current == null ? void 0 : current.stepParams) || {},
|
|
17597
|
+
this.buildAIEmployeeTaskStepParams(legacyPropsTasks),
|
|
17598
|
+
(_currentValue, nextValue) => {
|
|
17599
|
+
if (Array.isArray(nextValue)) {
|
|
17600
|
+
return import_lodash.default.cloneDeep(nextValue);
|
|
17601
|
+
}
|
|
17602
|
+
return void 0;
|
|
17603
|
+
}
|
|
17604
|
+
);
|
|
17605
|
+
}
|
|
17606
|
+
if (!hasLegacyPropsTasks && !import_lodash.default.has(nextPayload, ["props", "tasks"])) {
|
|
17607
|
+
return;
|
|
17608
|
+
}
|
|
17609
|
+
const nextProps = import_lodash.default.cloneDeep(nextPayload.props ?? (current == null ? void 0 : current.props) ?? {});
|
|
17610
|
+
delete nextProps.tasks;
|
|
17611
|
+
nextPayload.props = nextProps;
|
|
17612
|
+
}
|
|
16384
17613
|
assertAIEmployeePluginEnabled(actionName, enabledPackages) {
|
|
16385
17614
|
if (!enabledPackages.has(AI_EMPLOYEE_OWNER_PLUGIN)) {
|
|
16386
17615
|
(0, import_errors.throwBadRequest)(
|
|
@@ -16464,8 +17693,13 @@ class FlowSurfacesService {
|
|
|
16464
17693
|
return username;
|
|
16465
17694
|
}
|
|
16466
17695
|
assertAIEmployeeWorkContextType(actionName, itemPath, item) {
|
|
17696
|
+
if (!Object.prototype.hasOwnProperty.call(item, "type") || import_lodash.default.isUndefined(item.type) || item.type === null) {
|
|
17697
|
+
return;
|
|
17698
|
+
}
|
|
16467
17699
|
if (String(item.type || "").trim() !== "flow-model") {
|
|
16468
|
-
(0, import_errors.throwBadRequest)(
|
|
17700
|
+
(0, import_errors.throwBadRequest)(
|
|
17701
|
+
`flowSurfaces ${actionName} ${itemPath}.type only supports 'flow-model'; omit type to use the default flow-model context. repairHint: ${AI_EMPLOYEE_WORK_CONTEXT_REPAIR_HINT}`
|
|
17702
|
+
);
|
|
16469
17703
|
}
|
|
16470
17704
|
}
|
|
16471
17705
|
normalizeAIEmployeeWorkContext(actionName, value, options) {
|
|
@@ -16574,8 +17808,290 @@ class FlowSurfacesService {
|
|
|
16574
17808
|
if (Object.prototype.hasOwnProperty.call(next, "toolsVersion") && typeof next.toolsVersion !== "number") {
|
|
16575
17809
|
(0, import_errors.throwBadRequest)(`flowSurfaces ${actionName} ${path}.toolsVersion must be a number`);
|
|
16576
17810
|
}
|
|
17811
|
+
const hasSkills = Object.prototype.hasOwnProperty.call(next, "skills");
|
|
17812
|
+
const hasTools = Object.prototype.hasOwnProperty.call(next, "tools");
|
|
17813
|
+
const hasSkillsVersion = Object.prototype.hasOwnProperty.call(next, "skillsVersion");
|
|
17814
|
+
const hasToolsVersion = Object.prototype.hasOwnProperty.call(next, "toolsVersion");
|
|
17815
|
+
if (hasSkills && hasTools && !hasSkillsVersion && !hasToolsVersion && Array.isArray(next.skills) && Array.isArray(next.tools) && next.skills.length === 0 && next.tools.length === 0) {
|
|
17816
|
+
return null;
|
|
17817
|
+
}
|
|
17818
|
+
if (hasSkills && !hasSkillsVersion) {
|
|
17819
|
+
next.skillsVersion = 2;
|
|
17820
|
+
}
|
|
17821
|
+
if (hasTools && !hasToolsVersion) {
|
|
17822
|
+
next.toolsVersion = 2;
|
|
17823
|
+
}
|
|
16577
17824
|
return next;
|
|
16578
17825
|
}
|
|
17826
|
+
collectAIEmployeePromptVariables(value) {
|
|
17827
|
+
if (!value.includes("{{")) {
|
|
17828
|
+
return [];
|
|
17829
|
+
}
|
|
17830
|
+
return [...value.matchAll(/\{\{\s*([\s\S]+?)\s*\}\}/g)].map(([raw, inner]) => ({
|
|
17831
|
+
raw,
|
|
17832
|
+
inner: String(inner || "").trim()
|
|
17833
|
+
}));
|
|
17834
|
+
}
|
|
17835
|
+
hasAIEmployeePromptVariables(tasks) {
|
|
17836
|
+
return import_lodash.default.castArray(tasks || []).some((task) => {
|
|
17837
|
+
const message = task == null ? void 0 : task.message;
|
|
17838
|
+
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;
|
|
17839
|
+
});
|
|
17840
|
+
}
|
|
17841
|
+
collectAIEmployeeContextPathEntries(context) {
|
|
17842
|
+
const result = /* @__PURE__ */ new Map();
|
|
17843
|
+
const visit = (prefix, info) => {
|
|
17844
|
+
if (!prefix || !info) {
|
|
17845
|
+
return;
|
|
17846
|
+
}
|
|
17847
|
+
result.set(prefix, info);
|
|
17848
|
+
if (info.dynamicProperties) {
|
|
17849
|
+
result.set(`${prefix}.*`, info.dynamicProperties);
|
|
17850
|
+
}
|
|
17851
|
+
for (const [childKey, childInfo] of Object.entries(info.properties || {})) {
|
|
17852
|
+
visit(`${prefix}.${childKey}`, childInfo);
|
|
17853
|
+
}
|
|
17854
|
+
};
|
|
17855
|
+
for (const [key, info] of Object.entries((context == null ? void 0 : context.vars) || {})) {
|
|
17856
|
+
visit(key, info);
|
|
17857
|
+
}
|
|
17858
|
+
return result;
|
|
17859
|
+
}
|
|
17860
|
+
isAIEmployeeContextInfoPathAllowed(info, segments) {
|
|
17861
|
+
var _a;
|
|
17862
|
+
if (!info) {
|
|
17863
|
+
return false;
|
|
17864
|
+
}
|
|
17865
|
+
if (!segments.length) {
|
|
17866
|
+
return true;
|
|
17867
|
+
}
|
|
17868
|
+
const [segment, ...rest] = segments;
|
|
17869
|
+
const staticChild = (_a = info.properties) == null ? void 0 : _a[segment];
|
|
17870
|
+
if (staticChild) {
|
|
17871
|
+
return this.isAIEmployeeContextInfoPathAllowed(staticChild, rest);
|
|
17872
|
+
}
|
|
17873
|
+
if (info.dynamicProperties) {
|
|
17874
|
+
return this.isAIEmployeeContextInfoPathAllowed(info.dynamicProperties, rest);
|
|
17875
|
+
}
|
|
17876
|
+
return false;
|
|
17877
|
+
}
|
|
17878
|
+
canResolveAIEmployeeContextPath(path, semantic) {
|
|
17879
|
+
var _a;
|
|
17880
|
+
return !!((_a = (0, import_context.buildFlowSurfaceContextResponse)({
|
|
17881
|
+
semantic,
|
|
17882
|
+
path,
|
|
17883
|
+
maxDepth: 1
|
|
17884
|
+
}).vars) == null ? void 0 : _a[path]);
|
|
17885
|
+
}
|
|
17886
|
+
isAIEmployeeContextPathAllowed(path, validation) {
|
|
17887
|
+
if (validation.contextPaths.has(path)) {
|
|
17888
|
+
return true;
|
|
17889
|
+
}
|
|
17890
|
+
for (const [allowedPath, info] of validation.contextPaths) {
|
|
17891
|
+
if (!allowedPath.endsWith(".*")) {
|
|
17892
|
+
continue;
|
|
17893
|
+
}
|
|
17894
|
+
const prefix = allowedPath.slice(0, -2);
|
|
17895
|
+
if (!path.startsWith(`${prefix}.`)) {
|
|
17896
|
+
continue;
|
|
17897
|
+
}
|
|
17898
|
+
const dynamicSegments = path.slice(prefix.length + 1).split(".").filter(Boolean);
|
|
17899
|
+
if (dynamicSegments.length && this.isAIEmployeeContextInfoPathAllowed(info, dynamicSegments.slice(1))) {
|
|
17900
|
+
return true;
|
|
17901
|
+
}
|
|
17902
|
+
}
|
|
17903
|
+
return this.canResolveAIEmployeeContextPath(path, validation.semantic);
|
|
17904
|
+
}
|
|
17905
|
+
extractAIEmployeePromptContextPath(expression) {
|
|
17906
|
+
const normalized = String(expression || "").trim();
|
|
17907
|
+
if (normalized === "ctx") {
|
|
17908
|
+
return "";
|
|
17909
|
+
}
|
|
17910
|
+
if (!normalized.startsWith("ctx.")) {
|
|
17911
|
+
return null;
|
|
17912
|
+
}
|
|
17913
|
+
const path = normalized.slice(4).trim();
|
|
17914
|
+
return (0, import_context.isBareFlowContextPath)(path) ? path : null;
|
|
17915
|
+
}
|
|
17916
|
+
buildAIEmployeePromptVariableHint(targetUid) {
|
|
17917
|
+
return `Call flowSurfaces:context${targetUid ? ` with target.uid "${targetUid}"` : ""} to inspect available ctx paths before writing prompt variables.`;
|
|
17918
|
+
}
|
|
17919
|
+
throwAIEmployeePromptVariableInvalid(input) {
|
|
17920
|
+
(0, import_errors.throwBadRequest)(
|
|
17921
|
+
`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(
|
|
17922
|
+
input.targetUid
|
|
17923
|
+
)}`,
|
|
17924
|
+
AI_EMPLOYEE_PROMPT_VARIABLE_INVALID,
|
|
17925
|
+
{
|
|
17926
|
+
path: input.fieldPath,
|
|
17927
|
+
details: (0, import_service_utils.buildDefinedPayload)({
|
|
17928
|
+
variable: input.variable,
|
|
17929
|
+
contextPath: input.path,
|
|
17930
|
+
targetUid: input.targetUid
|
|
17931
|
+
})
|
|
17932
|
+
}
|
|
17933
|
+
);
|
|
17934
|
+
}
|
|
17935
|
+
assertAIEmployeePromptVariablesAllowed(actionName, fieldPath, value, validation) {
|
|
17936
|
+
for (const variable of this.collectAIEmployeePromptVariables(value)) {
|
|
17937
|
+
const path = this.extractAIEmployeePromptContextPath(variable.inner);
|
|
17938
|
+
if (path === "") {
|
|
17939
|
+
this.throwAIEmployeePromptVariableInvalid({
|
|
17940
|
+
actionName,
|
|
17941
|
+
fieldPath,
|
|
17942
|
+
variable: variable.raw,
|
|
17943
|
+
targetUid: validation.targetUid,
|
|
17944
|
+
reason: "the whole ctx object is not a valid prompt variable; use a concrete ctx path"
|
|
17945
|
+
});
|
|
17946
|
+
}
|
|
17947
|
+
if (!path) {
|
|
17948
|
+
this.throwAIEmployeePromptVariableInvalid({
|
|
17949
|
+
actionName,
|
|
17950
|
+
fieldPath,
|
|
17951
|
+
variable: variable.raw,
|
|
17952
|
+
targetUid: validation.targetUid,
|
|
17953
|
+
reason: 'only simple ctx dot paths like "{{ ctx.record.id }}" are supported'
|
|
17954
|
+
});
|
|
17955
|
+
}
|
|
17956
|
+
if (!this.isAIEmployeeContextPathAllowed(path, validation)) {
|
|
17957
|
+
this.throwAIEmployeePromptVariableInvalid({
|
|
17958
|
+
actionName,
|
|
17959
|
+
fieldPath,
|
|
17960
|
+
variable: variable.raw,
|
|
17961
|
+
targetUid: validation.targetUid,
|
|
17962
|
+
path,
|
|
17963
|
+
reason: `path "${path}" is not available in the current Flow Surface context`
|
|
17964
|
+
});
|
|
17965
|
+
}
|
|
17966
|
+
}
|
|
17967
|
+
}
|
|
17968
|
+
assertAIEmployeeTaskPromptVariablesAllowed(actionName, tasks, validation, path = "settings.tasks") {
|
|
17969
|
+
if (!validation) {
|
|
17970
|
+
return;
|
|
17971
|
+
}
|
|
17972
|
+
tasks.forEach((task, index) => {
|
|
17973
|
+
const message = task == null ? void 0 : task.message;
|
|
17974
|
+
if (typeof (message == null ? void 0 : message.system) === "string") {
|
|
17975
|
+
this.assertAIEmployeePromptVariablesAllowed(
|
|
17976
|
+
actionName,
|
|
17977
|
+
`${path}[${index}].message.system`,
|
|
17978
|
+
message.system,
|
|
17979
|
+
validation
|
|
17980
|
+
);
|
|
17981
|
+
}
|
|
17982
|
+
if (typeof (message == null ? void 0 : message.user) === "string") {
|
|
17983
|
+
this.assertAIEmployeePromptVariablesAllowed(
|
|
17984
|
+
actionName,
|
|
17985
|
+
`${path}[${index}].message.user`,
|
|
17986
|
+
message.user,
|
|
17987
|
+
validation
|
|
17988
|
+
);
|
|
17989
|
+
}
|
|
17990
|
+
});
|
|
17991
|
+
}
|
|
17992
|
+
appendAIEmployeeCurrentRecordPromptVariable(value) {
|
|
17993
|
+
if (AI_EMPLOYEE_CURRENT_RECORD_PROMPT_VARIABLE_RE.test(value)) {
|
|
17994
|
+
return value;
|
|
17995
|
+
}
|
|
17996
|
+
return value ? `${value}
|
|
17997
|
+
${AI_EMPLOYEE_CURRENT_RECORD_PROMPT_VARIABLE}` : AI_EMPLOYEE_CURRENT_RECORD_PROMPT_VARIABLE;
|
|
17998
|
+
}
|
|
17999
|
+
async resolveAIEmployeePromptActionTargetUid(context, transaction) {
|
|
18000
|
+
if (!context) {
|
|
18001
|
+
return void 0;
|
|
18002
|
+
}
|
|
18003
|
+
if (context.kind === "target") {
|
|
18004
|
+
return String(context.targetUid || "").trim() || void 0;
|
|
18005
|
+
}
|
|
18006
|
+
return String(context.ownerUid || "").trim() || void 0;
|
|
18007
|
+
}
|
|
18008
|
+
async buildAIEmployeePromptValidationContext(actionName, tasks, options) {
|
|
18009
|
+
var _a, _b;
|
|
18010
|
+
if (!this.hasAIEmployeePromptVariables(tasks)) {
|
|
18011
|
+
return void 0;
|
|
18012
|
+
}
|
|
18013
|
+
const targetUid = await this.resolveAIEmployeePromptActionTargetUid(options.promptContext, options.transaction);
|
|
18014
|
+
if (!targetUid) {
|
|
18015
|
+
(0, import_errors.throwBadRequest)(
|
|
18016
|
+
`flowSurfaces ${actionName} AI employee prompt variables require a resolvable Flow Surface context. ${this.buildAIEmployeePromptVariableHint()}`,
|
|
18017
|
+
AI_EMPLOYEE_PROMPT_VARIABLE_INVALID
|
|
18018
|
+
);
|
|
18019
|
+
}
|
|
18020
|
+
const target = { uid: targetUid };
|
|
18021
|
+
const resolved = await this.locator.resolve(target, { transaction: options.transaction });
|
|
18022
|
+
let semantic = await this.resolveContextSemantic(((_a = resolved == null ? void 0 : resolved.node) == null ? void 0 : _a.uid) || target.uid, resolved, options.transaction);
|
|
18023
|
+
if (((_b = options.promptContext) == null ? void 0 : _b.kind) === "container" && options.promptContext.scope === "record") {
|
|
18024
|
+
semantic = {
|
|
18025
|
+
...semantic,
|
|
18026
|
+
recordCollection: semantic.recordCollection || semantic.collection || await this.resolveContextOwnerCollection(targetUid, options.transaction).catch(() => null)
|
|
18027
|
+
};
|
|
18028
|
+
}
|
|
18029
|
+
const context = (0, import_context.buildFlowSurfaceContextResponse)({
|
|
18030
|
+
semantic,
|
|
18031
|
+
maxDepth: AI_EMPLOYEE_PROMPT_CONTEXT_MAX_DEPTH
|
|
18032
|
+
});
|
|
18033
|
+
return {
|
|
18034
|
+
targetUid,
|
|
18035
|
+
semantic,
|
|
18036
|
+
contextPaths: this.collectAIEmployeeContextPathEntries(context)
|
|
18037
|
+
};
|
|
18038
|
+
}
|
|
18039
|
+
appendAIEmployeeCurrentRecordPromptVariableToTasks(tasks, validation) {
|
|
18040
|
+
if (!tasks.length || !validation || !this.isAIEmployeeContextPathAllowed("record", validation)) {
|
|
18041
|
+
return tasks;
|
|
18042
|
+
}
|
|
18043
|
+
return tasks.map((task) => {
|
|
18044
|
+
var _a;
|
|
18045
|
+
if (typeof ((_a = task == null ? void 0 : task.message) == null ? void 0 : _a.user) !== "string") {
|
|
18046
|
+
return task;
|
|
18047
|
+
}
|
|
18048
|
+
const next = import_lodash.default.cloneDeep(task);
|
|
18049
|
+
next.message.user = this.appendAIEmployeeCurrentRecordPromptVariable(next.message.user);
|
|
18050
|
+
return next;
|
|
18051
|
+
});
|
|
18052
|
+
}
|
|
18053
|
+
async assertAIEmployeeStepParamTaskPromptVariablesAllowedForUpdateSettings(current, nextPayload, writeTarget, options) {
|
|
18054
|
+
if (!this.isAIEmployeeActionUse(current == null ? void 0 : current.use) || !import_lodash.default.has(nextPayload, ["stepParams", ...AI_EMPLOYEE_TASK_STEP_PARAMS_PATH])) {
|
|
18055
|
+
return;
|
|
18056
|
+
}
|
|
18057
|
+
const tasks = import_lodash.default.get(nextPayload, ["stepParams", ...AI_EMPLOYEE_TASK_STEP_PARAMS_PATH]);
|
|
18058
|
+
if (!Array.isArray(tasks)) {
|
|
18059
|
+
return;
|
|
18060
|
+
}
|
|
18061
|
+
const actionName = options.openViewActionName || "updateSettings";
|
|
18062
|
+
this.assertAIEmployeeTaskPromptVariablesAllowed(
|
|
18063
|
+
actionName,
|
|
18064
|
+
tasks,
|
|
18065
|
+
await this.buildAIEmployeePromptValidationContext(actionName, tasks, {
|
|
18066
|
+
transaction: options.transaction,
|
|
18067
|
+
promptContext: {
|
|
18068
|
+
kind: "target",
|
|
18069
|
+
targetUid: (current == null ? void 0 : current.uid) || writeTarget.uid
|
|
18070
|
+
}
|
|
18071
|
+
}),
|
|
18072
|
+
"stepParams.shortcutSettings.editTasks.tasks"
|
|
18073
|
+
);
|
|
18074
|
+
}
|
|
18075
|
+
async normalizeAIEmployeeStepParamTasksForUpdateSettings(current, nextPayload, writeTarget, options) {
|
|
18076
|
+
if (!this.isAIEmployeeActionUse(current == null ? void 0 : current.use) || !import_lodash.default.has(nextPayload, ["stepParams", ...AI_EMPLOYEE_TASK_STEP_PARAMS_PATH])) {
|
|
18077
|
+
return;
|
|
18078
|
+
}
|
|
18079
|
+
const tasks = import_lodash.default.get(nextPayload, ["stepParams", ...AI_EMPLOYEE_TASK_STEP_PARAMS_PATH]);
|
|
18080
|
+
if (!Array.isArray(tasks)) {
|
|
18081
|
+
return;
|
|
18082
|
+
}
|
|
18083
|
+
const actionName = options.openViewActionName || "updateSettings";
|
|
18084
|
+
const normalizedTasks = this.normalizeAIEmployeeTasks(
|
|
18085
|
+
actionName,
|
|
18086
|
+
tasks,
|
|
18087
|
+
this.readAIEmployeePersistedTasks(current),
|
|
18088
|
+
{
|
|
18089
|
+
selfUid: await this.resolveAIEmployeeActionSelfUid(current || { uid: writeTarget.uid }, options.transaction),
|
|
18090
|
+
path: "stepParams.shortcutSettings.editTasks.tasks"
|
|
18091
|
+
}
|
|
18092
|
+
);
|
|
18093
|
+
import_lodash.default.set(nextPayload, ["stepParams", ...AI_EMPLOYEE_TASK_STEP_PARAMS_PATH], normalizedTasks);
|
|
18094
|
+
}
|
|
16579
18095
|
normalizeAIEmployeeTaskMessage(actionName, path, value, existing, options) {
|
|
16580
18096
|
if (!import_lodash.default.isPlainObject(value)) {
|
|
16581
18097
|
(0, import_errors.throwBadRequest)(`flowSurfaces ${actionName} ${path} must be an object`);
|
|
@@ -16616,9 +18132,18 @@ class FlowSurfacesService {
|
|
|
16616
18132
|
(0, import_errors.throwBadRequest)(`flowSurfaces ${actionName} ${options.path} must be an object`);
|
|
16617
18133
|
}
|
|
16618
18134
|
const next = import_lodash.default.pick(import_lodash.default.isPlainObject(existing) ? import_lodash.default.cloneDeep(existing) : {}, AI_EMPLOYEE_TASK_PUBLIC_SETTING_KEYS);
|
|
18135
|
+
if (Object.prototype.hasOwnProperty.call(patch, "prompt") && import_lodash.default.isPlainObject(patch.message) && Object.prototype.hasOwnProperty.call(patch.message, "user")) {
|
|
18136
|
+
(0, import_errors.throwBadRequest)(
|
|
18137
|
+
`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`
|
|
18138
|
+
);
|
|
18139
|
+
}
|
|
16619
18140
|
Object.entries(patch).forEach(([key, value]) => {
|
|
16620
|
-
if (!
|
|
16621
|
-
(0, import_errors.throwBadRequest)(
|
|
18141
|
+
if (!AI_EMPLOYEE_TASK_PATCH_PUBLIC_SETTING_KEYS.includes(key)) {
|
|
18142
|
+
(0, import_errors.throwBadRequest)(
|
|
18143
|
+
`flowSurfaces ${actionName} ${options.path} does not support key '${key}'; allowed keys: ${AI_EMPLOYEE_TASK_PATCH_PUBLIC_SETTING_KEYS.join(
|
|
18144
|
+
", "
|
|
18145
|
+
)}; repairHint: ${AI_EMPLOYEE_TASK_REPAIR_HINT}`
|
|
18146
|
+
);
|
|
16622
18147
|
}
|
|
16623
18148
|
if (key === "message") {
|
|
16624
18149
|
next.message = this.normalizeAIEmployeeTaskMessage(actionName, `${options.path}.message`, value, next.message, {
|
|
@@ -16627,6 +18152,18 @@ class FlowSurfacesService {
|
|
|
16627
18152
|
});
|
|
16628
18153
|
return;
|
|
16629
18154
|
}
|
|
18155
|
+
if (key === "prompt") {
|
|
18156
|
+
if (typeof value !== "string") {
|
|
18157
|
+
(0, import_errors.throwBadRequest)(
|
|
18158
|
+
`flowSurfaces ${actionName} ${options.path}.prompt must be a string; repairHint: ${AI_EMPLOYEE_TASK_REPAIR_HINT}`
|
|
18159
|
+
);
|
|
18160
|
+
}
|
|
18161
|
+
next.message = {
|
|
18162
|
+
...import_lodash.default.isPlainObject(next.message) ? import_lodash.default.cloneDeep(next.message) : {},
|
|
18163
|
+
user: value
|
|
18164
|
+
};
|
|
18165
|
+
return;
|
|
18166
|
+
}
|
|
16630
18167
|
if (key === "title") {
|
|
16631
18168
|
if (typeof value !== "string") {
|
|
16632
18169
|
(0, import_errors.throwBadRequest)(`flowSurfaces ${actionName} ${options.path}.title must be a string`);
|
|
@@ -16661,6 +18198,14 @@ class FlowSurfacesService {
|
|
|
16661
18198
|
if (!import_lodash.default.isPlainObject(next.message)) {
|
|
16662
18199
|
next.message = {};
|
|
16663
18200
|
}
|
|
18201
|
+
if (import_lodash.default.isPlainObject(next.skillSettings)) {
|
|
18202
|
+
if (Array.isArray(next.skillSettings.skills) && !Object.prototype.hasOwnProperty.call(next.skillSettings, "skillsVersion")) {
|
|
18203
|
+
next.skillSettings.skillsVersion = 2;
|
|
18204
|
+
}
|
|
18205
|
+
if (Array.isArray(next.skillSettings.tools) && !Object.prototype.hasOwnProperty.call(next.skillSettings, "toolsVersion")) {
|
|
18206
|
+
next.skillSettings.toolsVersion = 2;
|
|
18207
|
+
}
|
|
18208
|
+
}
|
|
16664
18209
|
return next;
|
|
16665
18210
|
}
|
|
16666
18211
|
normalizeAIEmployeeTasks(actionName, value, currentTasks, options) {
|
|
@@ -16723,6 +18268,7 @@ class FlowSurfacesService {
|
|
|
16723
18268
|
});
|
|
16724
18269
|
}
|
|
16725
18270
|
const props = {};
|
|
18271
|
+
const stepParams = {};
|
|
16726
18272
|
if (effectiveUsername && (hasUsername || options.requireUsername)) {
|
|
16727
18273
|
props.aiEmployee = {
|
|
16728
18274
|
...import_lodash.default.isPlainObject(currentProps.aiEmployee) ? import_lodash.default.cloneDeep(currentProps.aiEmployee) : {},
|
|
@@ -16748,11 +18294,36 @@ class FlowSurfacesService {
|
|
|
16748
18294
|
};
|
|
16749
18295
|
}
|
|
16750
18296
|
if (Object.prototype.hasOwnProperty.call(settings, "tasks")) {
|
|
16751
|
-
|
|
16752
|
-
|
|
16753
|
-
|
|
16754
|
-
|
|
18297
|
+
const normalizedTasks = this.normalizeAIEmployeeTasks(
|
|
18298
|
+
actionName,
|
|
18299
|
+
settings.tasks,
|
|
18300
|
+
this.readAIEmployeePersistedTasks(options.current),
|
|
18301
|
+
{
|
|
18302
|
+
selfUid: options.selfUid,
|
|
18303
|
+
keyMap: options.keyMap,
|
|
18304
|
+
path: "settings.tasks"
|
|
18305
|
+
}
|
|
18306
|
+
);
|
|
18307
|
+
const validation = options.promptContext && normalizedTasks.length ? await this.buildAIEmployeePromptValidationContext(
|
|
18308
|
+
actionName,
|
|
18309
|
+
[
|
|
18310
|
+
{
|
|
18311
|
+
message: {
|
|
18312
|
+
user: AI_EMPLOYEE_CURRENT_RECORD_PROMPT_VARIABLE
|
|
18313
|
+
}
|
|
18314
|
+
}
|
|
18315
|
+
],
|
|
18316
|
+
{
|
|
18317
|
+
transaction: options.transaction,
|
|
18318
|
+
promptContext: options.promptContext
|
|
18319
|
+
}
|
|
18320
|
+
) : await this.buildAIEmployeePromptValidationContext(actionName, normalizedTasks, {
|
|
18321
|
+
transaction: options.transaction,
|
|
18322
|
+
promptContext: options.promptContext
|
|
16755
18323
|
});
|
|
18324
|
+
const tasks = this.appendAIEmployeeCurrentRecordPromptVariableToTasks(normalizedTasks, validation);
|
|
18325
|
+
this.assertAIEmployeeTaskPromptVariablesAllowed(actionName, tasks, validation);
|
|
18326
|
+
import_lodash.default.merge(stepParams, this.buildAIEmployeeTaskStepParams(tasks));
|
|
16756
18327
|
}
|
|
16757
18328
|
if (Object.prototype.hasOwnProperty.call(settings, "style") || options.requireUsername) {
|
|
16758
18329
|
const style = Object.prototype.hasOwnProperty.call(settings, "style") ? settings.style : {};
|
|
@@ -16780,7 +18351,10 @@ class FlowSurfacesService {
|
|
|
16780
18351
|
import_lodash.default.isPlainObject(style) ? import_lodash.default.pick(import_lodash.default.cloneDeep(style), AI_EMPLOYEE_STYLE_PUBLIC_KEYS) : {}
|
|
16781
18352
|
);
|
|
16782
18353
|
}
|
|
16783
|
-
return
|
|
18354
|
+
return {
|
|
18355
|
+
props,
|
|
18356
|
+
stepParams
|
|
18357
|
+
};
|
|
16784
18358
|
}
|
|
16785
18359
|
async resolveAIEmployeeActionSelfUid(actionNode, transaction) {
|
|
16786
18360
|
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 +18378,39 @@ class FlowSurfacesService {
|
|
|
16804
18378
|
}) : null);
|
|
16805
18379
|
changes = await this.normalizeActionPanelActionChanges(changes, options);
|
|
16806
18380
|
const allowedKeys = (0, import_configure_options.getConfigureOptionKeysForUse)(use);
|
|
18381
|
+
if ((0, import_service_utils.hasOwnDefined)(changes, "openView") && !allowedKeys.includes("openView") && JS_POPUP_GUIDANCE_USES.has(use)) {
|
|
18382
|
+
(0, import_errors.throwBadRequest)(withJsPopupGuidance(`flowSurfaces configure action '${use}' does not support openView`, use));
|
|
18383
|
+
}
|
|
16807
18384
|
(0, import_service_utils.assertSupportedSimpleChanges)("action", changes, allowedKeys);
|
|
16808
18385
|
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
|
-
},
|
|
18386
|
+
const aiEmployeeSettingsPayload = await this.normalizeAIEmployeeActionPublicSettings(
|
|
18387
|
+
"configure action",
|
|
18388
|
+
changes,
|
|
16821
18389
|
{
|
|
16822
|
-
|
|
16823
|
-
|
|
16824
|
-
|
|
16825
|
-
|
|
18390
|
+
transaction: options.transaction,
|
|
18391
|
+
enabledPackages: options.enabledPackages || await this.resolveEnabledPluginPackages(options),
|
|
18392
|
+
current: currentNode,
|
|
18393
|
+
currentRoles: options.currentRoles,
|
|
18394
|
+
selfUid: await this.resolveAIEmployeeActionSelfUid(currentNode, options.transaction),
|
|
18395
|
+
promptContext: {
|
|
18396
|
+
kind: "target",
|
|
18397
|
+
targetUid: (currentNode == null ? void 0 : currentNode.uid) || target.uid
|
|
18398
|
+
}
|
|
16826
18399
|
}
|
|
16827
18400
|
);
|
|
18401
|
+
const settingsValues = { target };
|
|
18402
|
+
if (Object.keys(aiEmployeeSettingsPayload.props).length) {
|
|
18403
|
+
settingsValues.props = aiEmployeeSettingsPayload.props;
|
|
18404
|
+
}
|
|
18405
|
+
if (Object.keys(aiEmployeeSettingsPayload.stepParams).length) {
|
|
18406
|
+
settingsValues.stepParams = aiEmployeeSettingsPayload.stepParams;
|
|
18407
|
+
}
|
|
18408
|
+
return this.updateSettings(settingsValues, {
|
|
18409
|
+
...options,
|
|
18410
|
+
openViewActionName: options.openViewActionName || "configure action",
|
|
18411
|
+
popupTemplateHostUid: target.uid,
|
|
18412
|
+
allowAIEmployeeInternalProps: true
|
|
18413
|
+
});
|
|
16828
18414
|
}
|
|
16829
18415
|
const normalizedDefaultFilter = (0, import_service_utils.hasOwnDefined)(changes, "defaultFilter") ? this.normalizeFilterActionDefaultFilterValue(changes.defaultFilter) : void 0;
|
|
16830
18416
|
const stepParams = {};
|
|
@@ -16888,7 +18474,7 @@ class FlowSurfacesService {
|
|
|
16888
18474
|
openView: import_lodash.default.cloneDeep(changes.openView)
|
|
16889
18475
|
};
|
|
16890
18476
|
} else if (!POPUP_ACTION_USES.has(use)) {
|
|
16891
|
-
(0, import_errors.throwBadRequest)(`flowSurfaces configure action '${use}' does not support openView
|
|
18477
|
+
(0, import_errors.throwBadRequest)(withJsPopupGuidance(`flowSurfaces configure action '${use}' does not support openView`, use));
|
|
16892
18478
|
} else {
|
|
16893
18479
|
let openView = import_lodash.default.cloneDeep(changes.openView);
|
|
16894
18480
|
if (use === "AddChildActionModel") {
|
|
@@ -18117,7 +19703,8 @@ class FlowSurfacesService {
|
|
|
18117
19703
|
}
|
|
18118
19704
|
resolveRecordActionContextOwner(ancestors) {
|
|
18119
19705
|
const currentNode = ancestors[0];
|
|
18120
|
-
|
|
19706
|
+
const currentUse = String((currentNode == null ? void 0 : currentNode.use) || "").trim();
|
|
19707
|
+
if (!currentUse.endsWith("ActionModel") && !import_node_use_sets.ACTION_BUTTON_USES.has(currentUse)) {
|
|
18121
19708
|
return null;
|
|
18122
19709
|
}
|
|
18123
19710
|
return ancestors.slice(1).find((node) => (0, import_action_scope.getActionContainerScope)(node == null ? void 0 : node.use) === "record") || null;
|
|
@@ -18368,11 +19955,12 @@ class FlowSurfacesService {
|
|
|
18368
19955
|
};
|
|
18369
19956
|
}
|
|
18370
19957
|
getCollection(dataSourceKey, collectionName) {
|
|
18371
|
-
var _a, _b, _c, _d, _e;
|
|
19958
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
18372
19959
|
const normalizedDataSourceKey = dataSourceKey || "main";
|
|
18373
|
-
const
|
|
18374
|
-
const
|
|
18375
|
-
|
|
19960
|
+
const app = (_a = this.plugin) == null ? void 0 : _a.app;
|
|
19961
|
+
const dataSourceManager = app == null ? void 0 : app.dataSourceManager;
|
|
19962
|
+
const dataSource = (_b = dataSourceManager == null ? void 0 : dataSourceManager.get) == null ? void 0 : _b.call(dataSourceManager, normalizedDataSourceKey);
|
|
19963
|
+
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
19964
|
}
|
|
18377
19965
|
normalizeKanbanFieldNameInput(value, context, options = {}) {
|
|
18378
19966
|
if (import_lodash.default.isUndefined(value)) {
|
|
@@ -20443,7 +22031,7 @@ class FlowSurfacesService {
|
|
|
20443
22031
|
(value) => !import_lodash.default.isUndefined(value)
|
|
20444
22032
|
),
|
|
20445
22033
|
decoratorProps: import_lodash.default.cloneDeep(innerField.decoratorProps || {}),
|
|
20446
|
-
flowRegistry:
|
|
22034
|
+
flowRegistry: this.getEventFlowRegistry(innerField),
|
|
20447
22035
|
stepParams: import_lodash.default.merge({}, innerField.stepParams || {}, {
|
|
20448
22036
|
fieldBinding: {
|
|
20449
22037
|
use: normalizedTargetUse
|