n8n-editor-ui 1.93.0 → 1.94.0
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/assets/{AnimatedSpinner-hbTZDd93.js → AnimatedSpinner-CY5xYI5m.js} +1 -1
- package/dist/assets/{AnnotationTagsDropdown.ee.vue_vue_type_script_setup_true_lang-CYzc5StE.js → AnnotationTagsDropdown.ee.vue_vue_type_script_setup_true_lang-BOrzkwPH.js} +1 -1
- package/dist/assets/{AuthView-8SLMP0H_.js → AuthView-BTzGYAnY.js} +2 -2
- package/dist/assets/{CanvasChatSwitch-Dt8TgNJg.js → CanvasChatSwitch-CwpjFCL0.js} +17 -18
- package/dist/assets/{ChangePasswordView-DIRyDp89.js → ChangePasswordView-BKR2UFVI.js} +3 -3
- package/dist/assets/CollectionParameter-BJtiV9En.js +4 -0
- package/dist/assets/{CredentialsView-B6-VxAJ6.js → CredentialsView-DVgxfnNi.js} +7 -7
- package/dist/assets/{DemoFooter-CIHwH5PG.js → DemoFooter-C1T3Q0NX.js} +7 -8
- package/dist/assets/{ErrorView-C7i0TZwT.js → ErrorView-Cf2Yb8Ea.js} +1 -1
- package/dist/assets/{ExecutionsTime.vue_vue_type_script_setup_true_lang--2G21NNR.js → ExecutionsTime.vue_vue_type_script_setup_true_lang-DUu0UMcW.js} +2 -2
- package/dist/assets/{ExecutionsView-C_YtciAr.js → ExecutionsView-DjNkfnDh.js} +19 -18
- package/dist/assets/{FileSaver.min-bgn7Q9Gt.js → FileSaver.min-C1p9Eies.js} +1 -1
- package/dist/assets/{FixedCollectionParameter-BPCJ5aaq.js → FixedCollectionParameter-DN_uJhpe.js} +1 -1
- package/dist/assets/{ForgotMyPasswordView-DyUaGd6Z.js → ForgotMyPasswordView-BMQBDIrq.js} +3 -3
- package/dist/assets/{InsightsChartAverageRuntime-BB2I2vpV.js → InsightsChartAverageRuntime-JzBkV6Rc.js} +4 -4
- package/dist/assets/{InsightsChartFailed-CN_Rl3Bl.js → InsightsChartFailed-DMD3c7zM.js} +4 -4
- package/dist/assets/{InsightsChartFailureRate-CHKlg6tg.js → InsightsChartFailureRate-D_qeZo4f.js} +4 -4
- package/dist/assets/{InsightsChartTimeSaved-Cd05cM8q.js → InsightsChartTimeSaved-Cw2T-Wvp.js} +4 -4
- package/dist/assets/{InsightsChartTotal-ChAO7myf.js → InsightsChartTotal-DlF47gob.js} +4 -4
- package/dist/assets/{InsightsDashboard-Bx4vx9gz.css → InsightsDashboard-BSrakbzr.css} +42 -8
- package/dist/assets/{InsightsDashboard-BeCfBVUz.js → InsightsDashboard-CxQ9H296.js} +40 -41
- package/dist/assets/{InsightsPaywall-Chz8CDc3.js → InsightsPaywall-hRkAfeHz.js} +1 -1
- package/dist/assets/InsightsSummary-BcXd-3nU.js +209 -0
- package/dist/assets/{InsightsSummary-CdlaUpAt.css → InsightsSummary-DzGQpM5h.css} +27 -24
- package/dist/assets/{InsightsTableWorkflows-Blv_GPUj.css → InsightsTableWorkflows-DfTZQkWL.css} +3 -4
- package/dist/assets/{InsightsTableWorkflows-5rpYY7YT.js → InsightsTableWorkflows-ybloXdDn.js} +5 -6
- package/dist/assets/{Logo-DUDCllkm.js → Logo-BGe7-2Vd.js} +1 -1
- package/dist/assets/{LogsPanel-D9r5AcQH.js → LogsPanel-DtTp6kY0.js} +331 -336
- package/dist/assets/{MainHeader-CEMGASqv.css → MainHeader-Y95RcfHb.css} +18 -18
- package/dist/assets/{MainHeader-DkKOOZ_D.js → MainHeader-h2DV-VuD.js} +13 -13
- package/dist/assets/{MainSidebar-ZUBIWeXm.js → MainSidebar-AAHHRXFA.js} +2 -2
- package/dist/assets/{NodeCreation-DCfAFuL5.js → NodeCreation-nHiG-Lhi.js} +3 -4
- package/dist/assets/{NodeCreator-a0YVv1IE.js → NodeCreator-weAzsmlU.js} +2 -3
- package/dist/assets/{NodeDetailsView-C5_hVJzj.js → NodeDetailsView-BsXbcyfb.js} +20 -11
- package/dist/assets/{NodeDetailsView-pYP-34nS.css → NodeDetailsView-DpO8nTmN.css} +16 -16
- package/dist/assets/{NodeView-Bk9h8GYy.js → NodeView-BY1O3wWl.js} +81 -38
- package/dist/assets/{ProjectCardBadge-DRlDZx3d.js → ProjectCardBadge-3xpk5Z4e.js} +1 -1
- package/dist/assets/{ProjectHeader-DNm605Kk.js → ProjectHeader-CpoOisjf.js} +2 -2
- package/dist/assets/{ProjectSettings-Dge_6KaR.js → ProjectSettings-B__3XaPY.js} +14 -4
- package/dist/assets/{PushConnectionTracker.vue_vue_type_script_setup_true_lang-CUf0LkWR.js → PushConnectionTracker.vue_vue_type_script_setup_true_lang-DaoPdG_5.js} +1 -1
- package/dist/assets/{ResourcesListLayout-Bbl-1i4l.js → ResourcesListLayout-DAxou314.js} +2 -2
- package/dist/assets/{RunData-DQeENuzG.css → RunData-CE5FsU6k.css} +2 -2
- package/dist/assets/{RunData-b0RE2JWc.js → RunData-fnd-jejc.js} +233 -92
- package/dist/assets/{RunDataAi-DnWcCR_0.js → RunDataAi-Ck3VGKP_.js} +3 -4
- package/dist/assets/{RunDataJson-CptVuHuA.js → RunDataJson-B80Z4URL.js} +7 -7
- package/dist/assets/{RunDataJsonActions-3jjDztw7.js → RunDataJsonActions-CdZi1Qul.js} +1 -1
- package/dist/assets/{RunDataParsedAiContent-BbXv-NPD.js → RunDataParsedAiContent-BczxQ63H.js} +5 -5
- package/dist/assets/{RunDataSearch-B90wjsDA.js → RunDataSearch-C4KmCz4c.js} +1 -1
- package/dist/assets/{RunDataTable-CpS78GlT.js → RunDataTable-CsLCZIWp.js} +3 -3
- package/dist/assets/{SamlOnboarding-Ch9K5rRW.js → SamlOnboarding-DkhjCrPa.js} +3 -3
- package/dist/assets/{SettingsApiView-9GU5n_rm.js → SettingsApiView-Ci2-rEpm.js} +1 -1
- package/dist/assets/{SettingsCommunityNodesView-CPnVRzNX.js → SettingsCommunityNodesView-_UOppuqS.js} +4 -4
- package/dist/assets/{SettingsExternalSecrets-D7xTMV9h.js → SettingsExternalSecrets-DHIkKr53.js} +1 -1
- package/dist/assets/{SettingsLdapView-OfrjGKkt.js → SettingsLdapView-B8ezgdqP.js} +1 -1
- package/dist/assets/{SettingsLogStreamingView-C_VnOaeX.js → SettingsLogStreamingView-YP6Xy7Fe.js} +1 -1
- package/dist/assets/{SettingsPersonalView-Dm24akPV.js → SettingsPersonalView-BmbFyWPb.js} +1 -1
- package/dist/assets/{SettingsSourceControl-DDCmL82j.js → SettingsSourceControl-DwaOdDke.js} +1 -1
- package/dist/assets/{SettingsSso-BGGQ0Cpg.js → SettingsSso-DOC-P2wt.js} +1 -1
- package/dist/assets/{SettingsUsageAndPlan-BzO_zdkH.js → SettingsUsageAndPlan-DVOLlEkG.js} +1 -1
- package/dist/assets/{SettingsUsersView-DHQUqhqB.js → SettingsUsersView-CN_KLeIm.js} +1 -1
- package/dist/assets/{SettingsView-CbtAqjOX.js → SettingsView-DiAhLyco.js} +1 -1
- package/dist/assets/{SetupView-BME1OE6U.js → SetupView-OE_yCNOU.js} +3 -3
- package/dist/assets/{SetupWorkflowCredentialsButton-DZr4TCPC.js → SetupWorkflowCredentialsButton-Dx1IkZgW.js} +1 -1
- package/dist/assets/{SetupWorkflowFromTemplateView-CPkKEY04.js → SetupWorkflowFromTemplateView-lQXKgIuL.js} +3 -3
- package/dist/assets/{SigninView-DUeRvOiY.js → SigninView-BWSrzbF7.js} +3 -3
- package/dist/assets/{SignoutView-BC7SBunZ.js → SignoutView-DxGgFxt2.js} +1 -1
- package/dist/assets/{SignupView-B5ecYJ2q.js → SignupView-Dtu5bMqF.js} +3 -3
- package/dist/assets/{TemplateDetails-DjanZgC1.js → TemplateDetails-CQ7TYqsP.js} +1 -1
- package/dist/assets/{TemplateList-8TyNGxY-.js → TemplateList-Cxmv-0p-.js} +1 -1
- package/dist/assets/{TemplatesCollectionView-BkH4pJCv.js → TemplatesCollectionView-xvV6FXib.js} +5 -5
- package/dist/assets/{TemplatesSearchView-Bcdhi1SL.js → TemplatesSearchView-CsECyZ52.js} +3 -3
- package/dist/assets/{TemplatesView-De2XB6We.js → TemplatesView-DrEKpZTU.js} +1 -1
- package/dist/assets/{TemplatesWorkflowView-BVnwtrMa.js → TemplatesWorkflowView-iSAL_yol.js} +5 -5
- package/dist/assets/{TestDefinitionEditView-DjmPnrTk.js → TestDefinitionEditView-C3ohfu_r.js} +6 -7
- package/dist/assets/{TestDefinitionListView-BL2s_qBZ.js → TestDefinitionListView-Dwto0jxH.js} +1 -1
- package/dist/assets/{TestDefinitionNewView-B9BqJZST.js → TestDefinitionNewView-9xVUm2ZJ.js} +2 -2
- package/dist/assets/{TestDefinitionRootView-AlWyxbc0.js → TestDefinitionRootView-DLurQ4xl.js} +1 -1
- package/dist/assets/{VariablesView-BZCvPfan.js → VariablesView-Cg2WSt_e.js} +4 -4
- package/dist/assets/{WorkerView-CigxqnWi.js → WorkerView-BG-Dl0Ej.js} +6 -6
- package/dist/assets/{WorkflowActivator-B7jRy4L1.js → WorkflowActivator-e7wvW1kJ.js} +11 -9
- package/dist/assets/{WorkflowExecutionsInfoAccordion-C_ZycbsF.js → WorkflowExecutionsInfoAccordion-CijtfO0l.js} +1 -1
- package/dist/assets/{WorkflowExecutionsLandingPage-DOqrfKlC.js → WorkflowExecutionsLandingPage-Do4y1yOx.js} +2 -2
- package/dist/assets/{WorkflowExecutionsPreview-B4Cj2gXW.js → WorkflowExecutionsPreview-Bqo_3PXl.js} +6 -6
- package/dist/assets/{WorkflowExecutionsView-RXfP7zkJ.js → WorkflowExecutionsView-C1gS45nc.js} +10 -10
- package/dist/assets/{WorkflowHistory-DrXrRwIS.js → WorkflowHistory-CypQw7rC.js} +3 -3
- package/dist/assets/{WorkflowOnboardingView-CXH1vCW2.js → WorkflowOnboardingView-DoKXpaNj.js} +1 -1
- package/dist/assets/{WorkflowPreview-B_MuFEV8.js → WorkflowPreview-Bxs5XzBX.js} +1 -1
- package/dist/assets/{WorkflowsView-D90hfJ35.js → WorkflowsView-BlvgD3xI.js} +9 -9
- package/dist/assets/{chartjs.utils-DalQn9bk.js → chartjs.utils-CuWcgqCr.js} +2 -2
- package/dist/assets/{dateFormatter-BPfJSa6q.js → dateFormatter-LbucaaRt.js} +1 -1
- package/dist/assets/{easyAiWorkflowUtils-kgtpBx2h.js → easyAiWorkflowUtils-_kvYb5hw.js} +1 -1
- package/dist/assets/{global-link-actions-CnWOMvqA.js → global-link-actions-DG0SjhQE.js} +1 -1
- package/dist/assets/{import-curl-BvX_O56D.js → import-curl-DQ6uPzZ1.js} +1 -1
- package/dist/assets/{index-yNaoC3fo.css → index-BA8d2DN9.css} +72 -418
- package/dist/assets/{index-DZ6VpjNj.js → index-hdsPF3tl.js} +60325 -57677
- package/dist/assets/{index-Bb2NNknG.js → index-vIybYvt3.js} +1 -1
- package/dist/assets/{pickBy-B_HGYyxS.js → pickBy-DmKUpB7M.js} +1 -1
- package/dist/assets/{polyfills-CLZ4X0Ad.js → polyfills-J2x06Gdp.js} +157 -224
- package/dist/assets/{templateActions-DQfZ3ni5.js → templateActions-DxoxchKp.js} +1 -1
- package/dist/assets/{typescript.worker-BsxN2afA.js → typescript.worker-B1loTpxy.js} +1 -1
- package/dist/assets/{useBeforeUnload-Cu0LPVWe.js → useBeforeUnload-B7JAQiE8.js} +1 -1
- package/dist/assets/{useCanvasMapping-VtpW_QZA.css → useCanvasMapping-CFf4cwnq.css} +6 -6
- package/dist/assets/{useCanvasMapping-CTTq6x8X.js → useCanvasMapping-CvcOHj5p.js} +56 -31
- package/dist/assets/{useClearExecutionButtonVisible-Dwc1_eG9.js → useClearExecutionButtonVisible-DFNEJves.js} +1 -2
- package/dist/assets/{useExecutionDebugging-rc72wLIp.js → useExecutionDebugging-DsRIfE0y.js} +1 -1
- package/dist/assets/{useExecutionHelpers-DqwMonFW.js → useExecutionHelpers-CEOL8_vt.js} +3 -3
- package/dist/assets/{useImportCurlCommand-D_onuFvo.js → useImportCurlCommand-DdIN4YaF.js} +2 -2
- package/dist/assets/{useProjectPages-e8b03-5_.js → useProjectPages-OGc-GAxb.js} +1 -1
- package/dist/assets/{usePushConnection-wm-7Id6Q.js → usePushConnection-DNGIaS0A.js} +16 -111
- package/dist/assets/{useTestDefinitionForm-DlUOnNC0.js → useTestDefinitionForm-Bi6EgFVm.js} +1 -1
- package/dist/assets/{useWorkflowActivate-65xML23U.js → useWorkflowActivate-CJ1hLmv2.js} +1 -1
- package/dist/assets/{useWorkflowSaving-CUel20JA.js → useWorkflowSaving-BuokdhTC.js} +1 -1
- package/dist/index.html +3 -3
- package/package.json +1 -1
- package/tsconfig.json +1 -0
- package/vite.config.mts +4 -0
- package/dist/assets/CollectionParameter-Cj4t6-hd.js +0 -4
- package/dist/assets/InsightsSummary-MECenLJQ.js +0 -207
- package/dist/assets/useCanvasOperations-u8oSDa_u.js +0 -2834
|
@@ -1,2834 +0,0 @@
|
|
|
1
|
-
import { bF as upperFirst, et as toString, eu as createCompounder, ev as SetCache, ew as arrayIncludes, ex as cacheHas, ey as baseRest, ez as isArrayLikeObject, eA as baseFlatten, eB as AI_CATEGORY_DOCUMENT_LOADERS, eC as AI_CATEGORY_LANGUAGE_MODELS, eD as AI_CATEGORY_MEMORY, eE as AI_CATEGORY_OUTPUTPARSER, eF as AI_CATEGORY_RETRIEVERS, eG as AI_CATEGORY_TEXT_SPLITTERS, eH as AI_WORKFLOW_TOOL_LANGCHAIN_NODE_TYPE, eI as AI_CODE_TOOL_LANGCHAIN_NODE_TYPE, c as useI18n, eJ as AI_CATEGORY_TOOLS, e4 as CORE_NODES_CATEGORY, eK as AI_CATEGORY_EMBEDDING, eL as AI_CATEGORY_VECTOR_STORES, eM as AI_UNCATEGORIZED_CATEGORY, eN as AI_OTHERS_NODE_CREATOR_VIEW, bm as NodeConnectionTypes, bz as useNodeTypesStore, aN as useTemplatesStore, p as useSettingsStore, eO as AI_TRANSFORM_NODE_TYPE, eP as AI_NODE_CREATOR_VIEW, eQ as RSS_READ_NODE_TYPE, eR as EMAIL_SEND_NODE_TYPE, eS as DEFAULT_SUBCATEGORY, eT as SET_NODE_TYPE, eU as CODE_NODE_TYPE, eV as DATETIME_NODE_TYPE, eW as FILTER_NODE_TYPE, eX as REMOVE_DUPLICATES_NODE_TYPE, eY as SPLIT_OUT_NODE_TYPE, eZ as LIMIT_NODE_TYPE, e_ as SUMMARIZE_NODE_TYPE, e$ as AGGREGATE_NODE_TYPE, f0 as MERGE_NODE_TYPE, ec as HTML_NODE_TYPE, f1 as MARKDOWN_NODE_TYPE, f2 as XML_NODE_TYPE, f3 as CRYPTO_NODE_TYPE, f4 as EXTRACT_FROM_FILE_NODE_TYPE, f5 as CONVERT_TO_FILE_NODE_TYPE, f6 as COMPRESSION_NODE_TYPE, f7 as EDIT_IMAGE_NODE_TYPE, f8 as TRANSFORM_DATA_SUBCATEGORY, f9 as IF_NODE_TYPE, fa as SPLIT_IN_BATCHES_NODE_TYPE, fb as FLOWS_CONTROL_SUBCATEGORY, fc as HTTP_REQUEST_NODE_TYPE, fd as WEBHOOK_NODE_TYPE, fe as HELPERS_SUBCATEGORY, ff as HITL_SUBCATEGORY, fg as HUMAN_IN_THE_LOOP_CATEGORY, bs as AI_SUBCATEGORY, fh as TRIGGER_NODE_CREATOR_VIEW, fi as REGULAR_NODE_CREATOR_VIEW, fj as MANUAL_TRIGGER_NODE_TYPE, fk as EMAIL_IMAP_NODE_TYPE, fl as SCHEDULE_TRIGGER_NODE_TYPE, fm as FORM_TRIGGER_NODE_TYPE, dK as EXECUTE_WORKFLOW_TRIGGER_NODE_TYPE, bk as CHAT_TRIGGER_NODE_TYPE, fn as OTHER_TRIGGER_NODES_SUBCATEGORY, bt as AI_CATEGORY_AGENTS, bu as AI_CATEGORY_CHAINS, O as defineStore, r as ref, q as computed, fo as extendItemsWithUUID, $ as useCanvasStore, fp as flattenCreateElements, fq as searchNodes, fr as transformNodeType, fs as subcategorizeItems, ft as isAINode, fu as AI_CATEGORY_ROOT_NODES, fv as AI_CATEGORY_MCP_NODES, fw as groupItemsInSections, z as nextTick, fx as getThemedValue, H as useUIStore, bn as v4, bv as AI_CODE_NODE_TYPE, fy as AI_TRANSFORM_NODE_TYPE$1, fz as sortNodeCreateElements, fA as isValidCanvasConnectionMode, c9 as CanvasConnectionMode, c8 as isValidNodeConnectionType, Q as useWorkflowsStore, as as useNDVStore, aP as useExternalHooks, fB as isVueFlowConnection, bw as getNodeInputs, fC as CUSTOM_API_CALL_KEY, T as STORES, cc as NODE_CREATOR_OPEN_SOURCES, ag as useTelemetry, Z as useRootStore, bS as useCredentialsStore, bV as useHistoryStore, E as useTagsStore, at as useExecutionsStore, a1 as useProjectsStore, a as useToast, a5 as useWorkflowHelpers, bA as useNodeHelpers, bf as useClipboard, fD as getSubworkflowId, fE as MCP_TRIGGER_NODE_TYPE, fF as UPDATE_WEBHOOK_ID_NODE_TYPES, dA as generateNodesGraph, fG as getNewNodePosition, fH as AddConnectionCommand, ay as STICKY_NODE_TYPE, by as getNodeOutputs, fI as RemoveConnectionCommand, aa as EnterpriseEditionFeature, cn as deepCopy, el as isPresent, fJ as RemoveNodeCommand, fK as RenameNodeCommand, bq as usePinnedData, fL as useDataSchema, fM as MoveNodeCommand, fN as DEFAULT_NODE_SIZE, fO as CONFIGURATION_NODE_SIZE, bx as getConnectionTypes, fP as generateOffsets, fQ as CONFIGURABLE_NODE_SIZE, fR as PUSH_NODES_OFFSET, fS as AddNodeCommand, fT as NODE_SIZE, fU as GRID_SIZE, fV as getNodeParameters } from "./index-DZ6VpjNj.js";
|
|
2
|
-
function capitalize(string) {
|
|
3
|
-
return upperFirst(toString(string).toLowerCase());
|
|
4
|
-
}
|
|
5
|
-
var camelCase = createCompounder(function(result, word, index) {
|
|
6
|
-
word = word.toLowerCase();
|
|
7
|
-
return result + (index ? capitalize(word) : word);
|
|
8
|
-
});
|
|
9
|
-
var LARGE_ARRAY_SIZE = 200;
|
|
10
|
-
function baseDifference(array, values, iteratee, comparator) {
|
|
11
|
-
var index = -1, includes = arrayIncludes, isCommon = true, length = array.length, result = [], valuesLength = values.length;
|
|
12
|
-
if (!length) {
|
|
13
|
-
return result;
|
|
14
|
-
}
|
|
15
|
-
if (values.length >= LARGE_ARRAY_SIZE) {
|
|
16
|
-
includes = cacheHas;
|
|
17
|
-
isCommon = false;
|
|
18
|
-
values = new SetCache(values);
|
|
19
|
-
}
|
|
20
|
-
outer:
|
|
21
|
-
while (++index < length) {
|
|
22
|
-
var value = array[index], computed2 = value;
|
|
23
|
-
value = value !== 0 ? value : 0;
|
|
24
|
-
if (isCommon && computed2 === computed2) {
|
|
25
|
-
var valuesIndex = valuesLength;
|
|
26
|
-
while (valuesIndex--) {
|
|
27
|
-
if (values[valuesIndex] === computed2) {
|
|
28
|
-
continue outer;
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
result.push(value);
|
|
32
|
-
} else if (!includes(values, computed2, comparator)) {
|
|
33
|
-
result.push(value);
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
return result;
|
|
37
|
-
}
|
|
38
|
-
var difference = baseRest(function(array, values) {
|
|
39
|
-
return isArrayLikeObject(array) ? baseDifference(array, baseFlatten(values, 1, isArrayLikeObject, true)) : [];
|
|
40
|
-
});
|
|
41
|
-
function getNodeView(node) {
|
|
42
|
-
return {
|
|
43
|
-
key: node.name,
|
|
44
|
-
type: "node",
|
|
45
|
-
properties: {
|
|
46
|
-
group: [],
|
|
47
|
-
name: node.name,
|
|
48
|
-
displayName: node.displayName,
|
|
49
|
-
title: node.displayName,
|
|
50
|
-
description: node.description,
|
|
51
|
-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
52
|
-
icon: node.icon,
|
|
53
|
-
iconUrl: node.iconUrl
|
|
54
|
-
}
|
|
55
|
-
};
|
|
56
|
-
}
|
|
57
|
-
function getAiNodesBySubcategory(nodes, subcategory) {
|
|
58
|
-
return nodes.filter(
|
|
59
|
-
(node) => !node.hidden && node.codex?.subcategories?.[AI_SUBCATEGORY]?.includes(subcategory)
|
|
60
|
-
).map(getNodeView).sort((a, b) => a.properties.displayName.localeCompare(b.properties.displayName));
|
|
61
|
-
}
|
|
62
|
-
function AIView(_nodes) {
|
|
63
|
-
const i18n = useI18n();
|
|
64
|
-
const nodeTypesStore = useNodeTypesStore();
|
|
65
|
-
const templatesStore = useTemplatesStore();
|
|
66
|
-
const chainNodes = getAiNodesBySubcategory(nodeTypesStore.allLatestNodeTypes, AI_CATEGORY_CHAINS);
|
|
67
|
-
const agentNodes = getAiNodesBySubcategory(nodeTypesStore.allLatestNodeTypes, AI_CATEGORY_AGENTS);
|
|
68
|
-
const websiteCategoryURLParams = templatesStore.websiteTemplateRepositoryParameters;
|
|
69
|
-
websiteCategoryURLParams.append("utm_user_role", "AdvancedAI");
|
|
70
|
-
const websiteCategoryURL = templatesStore.constructTemplateRepositoryURL(websiteCategoryURLParams);
|
|
71
|
-
const askAiEnabled = useSettingsStore().isAskAiEnabled;
|
|
72
|
-
const aiTransformNode = nodeTypesStore.getNodeType(AI_TRANSFORM_NODE_TYPE);
|
|
73
|
-
const transformNode = askAiEnabled && aiTransformNode ? [getNodeView(aiTransformNode)] : [];
|
|
74
|
-
return {
|
|
75
|
-
value: AI_NODE_CREATOR_VIEW,
|
|
76
|
-
title: i18n.baseText("nodeCreator.aiPanel.aiNodes"),
|
|
77
|
-
subtitle: i18n.baseText("nodeCreator.aiPanel.selectAiNode"),
|
|
78
|
-
items: [
|
|
79
|
-
{
|
|
80
|
-
key: "ai_templates_root",
|
|
81
|
-
type: "link",
|
|
82
|
-
properties: {
|
|
83
|
-
title: i18n.baseText("nodeCreator.aiPanel.linkItem.title"),
|
|
84
|
-
icon: "box-open",
|
|
85
|
-
description: i18n.baseText("nodeCreator.aiPanel.linkItem.description"),
|
|
86
|
-
name: "ai_templates_root",
|
|
87
|
-
url: websiteCategoryURL,
|
|
88
|
-
tag: {
|
|
89
|
-
type: "info",
|
|
90
|
-
text: i18n.baseText("nodeCreator.triggerHelperPanel.manualTriggerTag")
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
},
|
|
94
|
-
...agentNodes,
|
|
95
|
-
...chainNodes,
|
|
96
|
-
...transformNode,
|
|
97
|
-
{
|
|
98
|
-
key: AI_OTHERS_NODE_CREATOR_VIEW,
|
|
99
|
-
type: "view",
|
|
100
|
-
properties: {
|
|
101
|
-
title: i18n.baseText("nodeCreator.aiPanel.aiOtherNodes"),
|
|
102
|
-
icon: "robot",
|
|
103
|
-
description: i18n.baseText("nodeCreator.aiPanel.aiOtherNodesDescription")
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
]
|
|
107
|
-
};
|
|
108
|
-
}
|
|
109
|
-
function AINodesView(_nodes) {
|
|
110
|
-
const i18n = useI18n();
|
|
111
|
-
function getAISubcategoryProperties(nodeConnectionType) {
|
|
112
|
-
return {
|
|
113
|
-
connectionType: nodeConnectionType,
|
|
114
|
-
iconProps: {
|
|
115
|
-
color: `var(--node-type-${nodeConnectionType}-color)`
|
|
116
|
-
},
|
|
117
|
-
panelClass: `nodes-list-panel-${nodeConnectionType}`
|
|
118
|
-
};
|
|
119
|
-
}
|
|
120
|
-
function getSubcategoryInfo(subcategory) {
|
|
121
|
-
const localeKey = `nodeCreator.subcategoryInfos.${camelCase(subcategory)}`;
|
|
122
|
-
const info = i18n.baseText(localeKey);
|
|
123
|
-
if (info === localeKey) return void 0;
|
|
124
|
-
return info;
|
|
125
|
-
}
|
|
126
|
-
return {
|
|
127
|
-
value: AI_OTHERS_NODE_CREATOR_VIEW,
|
|
128
|
-
title: i18n.baseText("nodeCreator.aiPanel.aiOtherNodes"),
|
|
129
|
-
subtitle: i18n.baseText("nodeCreator.aiPanel.selectAiNode"),
|
|
130
|
-
items: [
|
|
131
|
-
{
|
|
132
|
-
key: AI_CATEGORY_DOCUMENT_LOADERS,
|
|
133
|
-
type: "subcategory",
|
|
134
|
-
properties: {
|
|
135
|
-
title: AI_CATEGORY_DOCUMENT_LOADERS,
|
|
136
|
-
info: getSubcategoryInfo(AI_CATEGORY_DOCUMENT_LOADERS),
|
|
137
|
-
icon: "file-import",
|
|
138
|
-
...getAISubcategoryProperties(NodeConnectionTypes.AiDocument)
|
|
139
|
-
}
|
|
140
|
-
},
|
|
141
|
-
{
|
|
142
|
-
key: AI_CATEGORY_LANGUAGE_MODELS,
|
|
143
|
-
type: "subcategory",
|
|
144
|
-
properties: {
|
|
145
|
-
title: AI_CATEGORY_LANGUAGE_MODELS,
|
|
146
|
-
info: getSubcategoryInfo(AI_CATEGORY_LANGUAGE_MODELS),
|
|
147
|
-
icon: "language",
|
|
148
|
-
...getAISubcategoryProperties(NodeConnectionTypes.AiLanguageModel)
|
|
149
|
-
}
|
|
150
|
-
},
|
|
151
|
-
{
|
|
152
|
-
key: AI_CATEGORY_MEMORY,
|
|
153
|
-
type: "subcategory",
|
|
154
|
-
properties: {
|
|
155
|
-
title: AI_CATEGORY_MEMORY,
|
|
156
|
-
info: getSubcategoryInfo(AI_CATEGORY_MEMORY),
|
|
157
|
-
icon: "brain",
|
|
158
|
-
...getAISubcategoryProperties(NodeConnectionTypes.AiMemory)
|
|
159
|
-
}
|
|
160
|
-
},
|
|
161
|
-
{
|
|
162
|
-
key: AI_CATEGORY_OUTPUTPARSER,
|
|
163
|
-
type: "subcategory",
|
|
164
|
-
properties: {
|
|
165
|
-
title: AI_CATEGORY_OUTPUTPARSER,
|
|
166
|
-
info: getSubcategoryInfo(AI_CATEGORY_OUTPUTPARSER),
|
|
167
|
-
icon: "list",
|
|
168
|
-
...getAISubcategoryProperties(NodeConnectionTypes.AiOutputParser)
|
|
169
|
-
}
|
|
170
|
-
},
|
|
171
|
-
{
|
|
172
|
-
key: AI_CATEGORY_RETRIEVERS,
|
|
173
|
-
type: "subcategory",
|
|
174
|
-
properties: {
|
|
175
|
-
title: AI_CATEGORY_RETRIEVERS,
|
|
176
|
-
info: getSubcategoryInfo(AI_CATEGORY_RETRIEVERS),
|
|
177
|
-
icon: "search",
|
|
178
|
-
...getAISubcategoryProperties(NodeConnectionTypes.AiRetriever)
|
|
179
|
-
}
|
|
180
|
-
},
|
|
181
|
-
{
|
|
182
|
-
key: AI_CATEGORY_TEXT_SPLITTERS,
|
|
183
|
-
type: "subcategory",
|
|
184
|
-
properties: {
|
|
185
|
-
title: AI_CATEGORY_TEXT_SPLITTERS,
|
|
186
|
-
info: getSubcategoryInfo(AI_CATEGORY_TEXT_SPLITTERS),
|
|
187
|
-
icon: "grip-lines-vertical",
|
|
188
|
-
...getAISubcategoryProperties(NodeConnectionTypes.AiTextSplitter)
|
|
189
|
-
}
|
|
190
|
-
},
|
|
191
|
-
{
|
|
192
|
-
type: "subcategory",
|
|
193
|
-
key: AI_CATEGORY_TOOLS,
|
|
194
|
-
category: CORE_NODES_CATEGORY,
|
|
195
|
-
properties: {
|
|
196
|
-
title: AI_CATEGORY_TOOLS,
|
|
197
|
-
info: getSubcategoryInfo(AI_CATEGORY_TOOLS),
|
|
198
|
-
icon: "tools",
|
|
199
|
-
...getAISubcategoryProperties(NodeConnectionTypes.AiTool),
|
|
200
|
-
sections: [
|
|
201
|
-
{
|
|
202
|
-
key: "popular",
|
|
203
|
-
title: i18n.baseText("nodeCreator.sectionNames.popular"),
|
|
204
|
-
items: [AI_WORKFLOW_TOOL_LANGCHAIN_NODE_TYPE, AI_CODE_TOOL_LANGCHAIN_NODE_TYPE]
|
|
205
|
-
}
|
|
206
|
-
]
|
|
207
|
-
}
|
|
208
|
-
},
|
|
209
|
-
{
|
|
210
|
-
key: AI_CATEGORY_EMBEDDING,
|
|
211
|
-
type: "subcategory",
|
|
212
|
-
properties: {
|
|
213
|
-
title: AI_CATEGORY_EMBEDDING,
|
|
214
|
-
info: getSubcategoryInfo(AI_CATEGORY_EMBEDDING),
|
|
215
|
-
icon: "vector-square",
|
|
216
|
-
...getAISubcategoryProperties(NodeConnectionTypes.AiEmbedding)
|
|
217
|
-
}
|
|
218
|
-
},
|
|
219
|
-
{
|
|
220
|
-
key: AI_CATEGORY_VECTOR_STORES,
|
|
221
|
-
type: "subcategory",
|
|
222
|
-
properties: {
|
|
223
|
-
title: AI_CATEGORY_VECTOR_STORES,
|
|
224
|
-
info: getSubcategoryInfo(AI_CATEGORY_VECTOR_STORES),
|
|
225
|
-
icon: "project-diagram",
|
|
226
|
-
...getAISubcategoryProperties(NodeConnectionTypes.AiVectorStore)
|
|
227
|
-
}
|
|
228
|
-
},
|
|
229
|
-
{
|
|
230
|
-
key: AI_UNCATEGORIZED_CATEGORY,
|
|
231
|
-
type: "subcategory",
|
|
232
|
-
properties: {
|
|
233
|
-
title: AI_UNCATEGORIZED_CATEGORY,
|
|
234
|
-
icon: "code"
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
]
|
|
238
|
-
};
|
|
239
|
-
}
|
|
240
|
-
function TriggerView() {
|
|
241
|
-
const i18n = useI18n();
|
|
242
|
-
const view = {
|
|
243
|
-
value: TRIGGER_NODE_CREATOR_VIEW,
|
|
244
|
-
title: i18n.baseText("nodeCreator.triggerHelperPanel.selectATrigger"),
|
|
245
|
-
subtitle: i18n.baseText("nodeCreator.triggerHelperPanel.selectATriggerDescription"),
|
|
246
|
-
items: [
|
|
247
|
-
{
|
|
248
|
-
key: MANUAL_TRIGGER_NODE_TYPE,
|
|
249
|
-
type: "node",
|
|
250
|
-
category: [CORE_NODES_CATEGORY],
|
|
251
|
-
properties: {
|
|
252
|
-
group: [],
|
|
253
|
-
name: MANUAL_TRIGGER_NODE_TYPE,
|
|
254
|
-
displayName: i18n.baseText("nodeCreator.triggerHelperPanel.manualTriggerDisplayName"),
|
|
255
|
-
description: i18n.baseText("nodeCreator.triggerHelperPanel.manualTriggerDescription"),
|
|
256
|
-
icon: "fa:mouse-pointer"
|
|
257
|
-
}
|
|
258
|
-
},
|
|
259
|
-
{
|
|
260
|
-
key: DEFAULT_SUBCATEGORY,
|
|
261
|
-
type: "subcategory",
|
|
262
|
-
properties: {
|
|
263
|
-
forceIncludeNodes: [WEBHOOK_NODE_TYPE, EMAIL_IMAP_NODE_TYPE],
|
|
264
|
-
title: "App Trigger Nodes",
|
|
265
|
-
icon: "satellite-dish"
|
|
266
|
-
}
|
|
267
|
-
},
|
|
268
|
-
{
|
|
269
|
-
key: SCHEDULE_TRIGGER_NODE_TYPE,
|
|
270
|
-
type: "node",
|
|
271
|
-
category: [CORE_NODES_CATEGORY],
|
|
272
|
-
properties: {
|
|
273
|
-
group: [],
|
|
274
|
-
name: SCHEDULE_TRIGGER_NODE_TYPE,
|
|
275
|
-
displayName: i18n.baseText("nodeCreator.triggerHelperPanel.scheduleTriggerDisplayName"),
|
|
276
|
-
description: i18n.baseText("nodeCreator.triggerHelperPanel.scheduleTriggerDescription"),
|
|
277
|
-
icon: "fa:clock"
|
|
278
|
-
}
|
|
279
|
-
},
|
|
280
|
-
{
|
|
281
|
-
key: WEBHOOK_NODE_TYPE,
|
|
282
|
-
type: "node",
|
|
283
|
-
category: [CORE_NODES_CATEGORY],
|
|
284
|
-
properties: {
|
|
285
|
-
group: [],
|
|
286
|
-
name: WEBHOOK_NODE_TYPE,
|
|
287
|
-
displayName: i18n.baseText("nodeCreator.triggerHelperPanel.webhookTriggerDisplayName"),
|
|
288
|
-
description: i18n.baseText("nodeCreator.triggerHelperPanel.webhookTriggerDescription"),
|
|
289
|
-
iconData: {
|
|
290
|
-
type: "file",
|
|
291
|
-
fileBuffer: "/static/webhook-icon.svg"
|
|
292
|
-
}
|
|
293
|
-
}
|
|
294
|
-
},
|
|
295
|
-
{
|
|
296
|
-
key: FORM_TRIGGER_NODE_TYPE,
|
|
297
|
-
type: "node",
|
|
298
|
-
category: [CORE_NODES_CATEGORY],
|
|
299
|
-
properties: {
|
|
300
|
-
group: [],
|
|
301
|
-
name: FORM_TRIGGER_NODE_TYPE,
|
|
302
|
-
displayName: i18n.baseText("nodeCreator.triggerHelperPanel.formTriggerDisplayName"),
|
|
303
|
-
description: i18n.baseText("nodeCreator.triggerHelperPanel.formTriggerDescription"),
|
|
304
|
-
iconData: {
|
|
305
|
-
type: "file",
|
|
306
|
-
fileBuffer: "/static/form-grey.svg"
|
|
307
|
-
}
|
|
308
|
-
}
|
|
309
|
-
},
|
|
310
|
-
{
|
|
311
|
-
key: EXECUTE_WORKFLOW_TRIGGER_NODE_TYPE,
|
|
312
|
-
type: "node",
|
|
313
|
-
category: [CORE_NODES_CATEGORY],
|
|
314
|
-
properties: {
|
|
315
|
-
group: [],
|
|
316
|
-
name: EXECUTE_WORKFLOW_TRIGGER_NODE_TYPE,
|
|
317
|
-
displayName: i18n.baseText("nodeCreator.triggerHelperPanel.workflowTriggerDisplayName"),
|
|
318
|
-
description: i18n.baseText("nodeCreator.triggerHelperPanel.workflowTriggerDescription"),
|
|
319
|
-
icon: "fa:sign-out-alt"
|
|
320
|
-
}
|
|
321
|
-
},
|
|
322
|
-
{
|
|
323
|
-
key: CHAT_TRIGGER_NODE_TYPE,
|
|
324
|
-
type: "node",
|
|
325
|
-
category: [CORE_NODES_CATEGORY],
|
|
326
|
-
properties: {
|
|
327
|
-
group: [],
|
|
328
|
-
name: CHAT_TRIGGER_NODE_TYPE,
|
|
329
|
-
displayName: i18n.baseText("nodeCreator.triggerHelperPanel.chatTriggerDisplayName"),
|
|
330
|
-
description: i18n.baseText("nodeCreator.triggerHelperPanel.chatTriggerDescription"),
|
|
331
|
-
icon: "fa:comments"
|
|
332
|
-
}
|
|
333
|
-
},
|
|
334
|
-
{
|
|
335
|
-
type: "subcategory",
|
|
336
|
-
key: OTHER_TRIGGER_NODES_SUBCATEGORY,
|
|
337
|
-
category: CORE_NODES_CATEGORY,
|
|
338
|
-
properties: {
|
|
339
|
-
title: OTHER_TRIGGER_NODES_SUBCATEGORY,
|
|
340
|
-
icon: "folder-open"
|
|
341
|
-
}
|
|
342
|
-
}
|
|
343
|
-
]
|
|
344
|
-
};
|
|
345
|
-
return view;
|
|
346
|
-
}
|
|
347
|
-
function RegularView(nodes) {
|
|
348
|
-
const i18n = useI18n();
|
|
349
|
-
const popularItemsSubcategory = [
|
|
350
|
-
SET_NODE_TYPE,
|
|
351
|
-
CODE_NODE_TYPE,
|
|
352
|
-
DATETIME_NODE_TYPE,
|
|
353
|
-
AI_TRANSFORM_NODE_TYPE
|
|
354
|
-
];
|
|
355
|
-
const getSendAndWaitNodes = (nodes2) => {
|
|
356
|
-
return (nodes2 ?? []).filter((node) => node.codex?.categories?.includes(HUMAN_IN_THE_LOOP_CATEGORY)).map((node) => node.name);
|
|
357
|
-
};
|
|
358
|
-
const view = {
|
|
359
|
-
value: REGULAR_NODE_CREATOR_VIEW,
|
|
360
|
-
title: i18n.baseText("nodeCreator.triggerHelperPanel.whatHappensNext"),
|
|
361
|
-
items: [
|
|
362
|
-
{
|
|
363
|
-
key: DEFAULT_SUBCATEGORY,
|
|
364
|
-
type: "subcategory",
|
|
365
|
-
properties: {
|
|
366
|
-
title: "App Regular Nodes",
|
|
367
|
-
icon: "globe",
|
|
368
|
-
forceIncludeNodes: [RSS_READ_NODE_TYPE, EMAIL_SEND_NODE_TYPE]
|
|
369
|
-
}
|
|
370
|
-
},
|
|
371
|
-
{
|
|
372
|
-
type: "subcategory",
|
|
373
|
-
key: TRANSFORM_DATA_SUBCATEGORY,
|
|
374
|
-
category: CORE_NODES_CATEGORY,
|
|
375
|
-
properties: {
|
|
376
|
-
title: TRANSFORM_DATA_SUBCATEGORY,
|
|
377
|
-
icon: "pen",
|
|
378
|
-
sections: [
|
|
379
|
-
{
|
|
380
|
-
key: "popular",
|
|
381
|
-
title: i18n.baseText("nodeCreator.sectionNames.popular"),
|
|
382
|
-
items: popularItemsSubcategory
|
|
383
|
-
},
|
|
384
|
-
{
|
|
385
|
-
key: "addOrRemove",
|
|
386
|
-
title: i18n.baseText("nodeCreator.sectionNames.transform.addOrRemove"),
|
|
387
|
-
items: [
|
|
388
|
-
FILTER_NODE_TYPE,
|
|
389
|
-
REMOVE_DUPLICATES_NODE_TYPE,
|
|
390
|
-
SPLIT_OUT_NODE_TYPE,
|
|
391
|
-
LIMIT_NODE_TYPE
|
|
392
|
-
]
|
|
393
|
-
},
|
|
394
|
-
{
|
|
395
|
-
key: "combine",
|
|
396
|
-
title: i18n.baseText("nodeCreator.sectionNames.transform.combine"),
|
|
397
|
-
items: [SUMMARIZE_NODE_TYPE, AGGREGATE_NODE_TYPE, MERGE_NODE_TYPE]
|
|
398
|
-
},
|
|
399
|
-
{
|
|
400
|
-
key: "convert",
|
|
401
|
-
title: i18n.baseText("nodeCreator.sectionNames.transform.convert"),
|
|
402
|
-
items: [
|
|
403
|
-
HTML_NODE_TYPE,
|
|
404
|
-
MARKDOWN_NODE_TYPE,
|
|
405
|
-
XML_NODE_TYPE,
|
|
406
|
-
CRYPTO_NODE_TYPE,
|
|
407
|
-
EXTRACT_FROM_FILE_NODE_TYPE,
|
|
408
|
-
CONVERT_TO_FILE_NODE_TYPE,
|
|
409
|
-
COMPRESSION_NODE_TYPE,
|
|
410
|
-
EDIT_IMAGE_NODE_TYPE
|
|
411
|
-
]
|
|
412
|
-
}
|
|
413
|
-
]
|
|
414
|
-
}
|
|
415
|
-
},
|
|
416
|
-
{
|
|
417
|
-
type: "subcategory",
|
|
418
|
-
key: FLOWS_CONTROL_SUBCATEGORY,
|
|
419
|
-
category: CORE_NODES_CATEGORY,
|
|
420
|
-
properties: {
|
|
421
|
-
title: FLOWS_CONTROL_SUBCATEGORY,
|
|
422
|
-
icon: "code-branch",
|
|
423
|
-
sections: [
|
|
424
|
-
{
|
|
425
|
-
key: "popular",
|
|
426
|
-
title: i18n.baseText("nodeCreator.sectionNames.popular"),
|
|
427
|
-
items: [FILTER_NODE_TYPE, IF_NODE_TYPE, SPLIT_IN_BATCHES_NODE_TYPE, MERGE_NODE_TYPE]
|
|
428
|
-
}
|
|
429
|
-
]
|
|
430
|
-
}
|
|
431
|
-
},
|
|
432
|
-
{
|
|
433
|
-
type: "subcategory",
|
|
434
|
-
key: HELPERS_SUBCATEGORY,
|
|
435
|
-
category: CORE_NODES_CATEGORY,
|
|
436
|
-
properties: {
|
|
437
|
-
title: HELPERS_SUBCATEGORY,
|
|
438
|
-
icon: "toolbox",
|
|
439
|
-
sections: [
|
|
440
|
-
{
|
|
441
|
-
key: "popular",
|
|
442
|
-
title: i18n.baseText("nodeCreator.sectionNames.popular"),
|
|
443
|
-
items: [HTTP_REQUEST_NODE_TYPE, WEBHOOK_NODE_TYPE, CODE_NODE_TYPE]
|
|
444
|
-
}
|
|
445
|
-
]
|
|
446
|
-
}
|
|
447
|
-
},
|
|
448
|
-
// To add node to this subcategory:
|
|
449
|
-
// - add "HITL" to the "categories" property of the node's codex
|
|
450
|
-
// - add "HITL": ["Human in the Loop"] to the "subcategories" property of the node's codex
|
|
451
|
-
// node has to have the "sendAndWait" operation, if a new operation needs to be included here:
|
|
452
|
-
// - update getHumanInTheLoopActions in packages/frontend/editor-ui/src/components/Node/NodeCreator/Modes/NodesMode.vue
|
|
453
|
-
{
|
|
454
|
-
type: "subcategory",
|
|
455
|
-
key: HITL_SUBCATEGORY,
|
|
456
|
-
category: HUMAN_IN_THE_LOOP_CATEGORY,
|
|
457
|
-
properties: {
|
|
458
|
-
title: HITL_SUBCATEGORY,
|
|
459
|
-
icon: "user-check",
|
|
460
|
-
sections: [
|
|
461
|
-
{
|
|
462
|
-
key: "sendAndWait",
|
|
463
|
-
title: i18n.baseText("nodeCreator.sectionNames.sendAndWait"),
|
|
464
|
-
items: getSendAndWaitNodes(nodes)
|
|
465
|
-
}
|
|
466
|
-
]
|
|
467
|
-
}
|
|
468
|
-
}
|
|
469
|
-
]
|
|
470
|
-
};
|
|
471
|
-
const hasAINodes = (nodes ?? []).some((node) => node.codex?.categories?.includes(AI_SUBCATEGORY));
|
|
472
|
-
if (hasAINodes)
|
|
473
|
-
view.items.unshift({
|
|
474
|
-
key: AI_NODE_CREATOR_VIEW,
|
|
475
|
-
type: "view",
|
|
476
|
-
properties: {
|
|
477
|
-
title: i18n.baseText("nodeCreator.aiPanel.langchainAiNodes"),
|
|
478
|
-
icon: "robot",
|
|
479
|
-
description: i18n.baseText("nodeCreator.aiPanel.nodesForAi"),
|
|
480
|
-
borderless: true
|
|
481
|
-
}
|
|
482
|
-
});
|
|
483
|
-
view.items.push({
|
|
484
|
-
key: TRIGGER_NODE_CREATOR_VIEW,
|
|
485
|
-
type: "view",
|
|
486
|
-
properties: {
|
|
487
|
-
title: i18n.baseText("nodeCreator.triggerHelperPanel.addAnotherTrigger"),
|
|
488
|
-
icon: "bolt",
|
|
489
|
-
description: i18n.baseText("nodeCreator.triggerHelperPanel.addAnotherTriggerDescription")
|
|
490
|
-
}
|
|
491
|
-
});
|
|
492
|
-
return view;
|
|
493
|
-
}
|
|
494
|
-
const KEYBOARD_ID_ATTR = "data-keyboard-nav-id";
|
|
495
|
-
const WATCHED_KEYS = [
|
|
496
|
-
"ArrowUp",
|
|
497
|
-
"ArrowDown",
|
|
498
|
-
"ArrowLeft",
|
|
499
|
-
"ArrowRight",
|
|
500
|
-
"Enter",
|
|
501
|
-
"Escape",
|
|
502
|
-
"Tab"
|
|
503
|
-
];
|
|
504
|
-
const useKeyboardNavigation = defineStore("nodeCreatorKeyboardNavigation", () => {
|
|
505
|
-
const selectableItems = ref([]);
|
|
506
|
-
const activeItemId = ref(null);
|
|
507
|
-
const keysHooks = ref({});
|
|
508
|
-
function getItemType(element) {
|
|
509
|
-
return element?.getAttribute("data-keyboard-nav-type");
|
|
510
|
-
}
|
|
511
|
-
function getElementId(element) {
|
|
512
|
-
return element?.getAttribute(KEYBOARD_ID_ATTR) || void 0;
|
|
513
|
-
}
|
|
514
|
-
async function refreshSelectableItems() {
|
|
515
|
-
return await new Promise((resolve) => {
|
|
516
|
-
cleanupSelectableItems();
|
|
517
|
-
setTimeout(() => {
|
|
518
|
-
selectableItems.value = Array.from(
|
|
519
|
-
document.querySelectorAll("[data-keyboard-nav-type]")
|
|
520
|
-
).map((el) => new WeakRef(el));
|
|
521
|
-
resolve();
|
|
522
|
-
}, 0);
|
|
523
|
-
});
|
|
524
|
-
}
|
|
525
|
-
function executeKeyHooks(keyboardKey, activeItem) {
|
|
526
|
-
const flatHooks = Object.values(keysHooks.value);
|
|
527
|
-
const hooks = flatHooks.filter((hook) => hook.keyboardKeys.includes(keyboardKey));
|
|
528
|
-
hooks.forEach((hook) => {
|
|
529
|
-
if (!activeItemId.value) return;
|
|
530
|
-
const conditionPassed = hook.condition === void 0 || hook.condition(getItemType(activeItem) || "", activeItemId.value);
|
|
531
|
-
if (conditionPassed && activeItemId.value) {
|
|
532
|
-
hook.handler(activeItemId.value, keyboardKey);
|
|
533
|
-
}
|
|
534
|
-
});
|
|
535
|
-
}
|
|
536
|
-
async function onKeyDown(e) {
|
|
537
|
-
if (e.target instanceof Element && e.target.classList.contains("ignore-key-press-node-creator")) {
|
|
538
|
-
return;
|
|
539
|
-
}
|
|
540
|
-
const pressedKey = e.key;
|
|
541
|
-
if (!WATCHED_KEYS.includes(pressedKey)) return;
|
|
542
|
-
e.preventDefault();
|
|
543
|
-
e.stopPropagation();
|
|
544
|
-
await refreshSelectableItems();
|
|
545
|
-
const activeItemIndex = selectableItems.value.findIndex(
|
|
546
|
-
(item) => getElementId(item?.deref()) === activeItemId.value
|
|
547
|
-
);
|
|
548
|
-
const activeItem = selectableItems.value[activeItemIndex]?.deref();
|
|
549
|
-
const isArrowDown = pressedKey === "ArrowDown";
|
|
550
|
-
const isArrowUp = pressedKey === "ArrowUp";
|
|
551
|
-
if (!activeItem) return;
|
|
552
|
-
if (isArrowDown) {
|
|
553
|
-
const nextItemIndex = activeItemIndex < selectableItems.value.length - 1 ? activeItemIndex + 1 : 0;
|
|
554
|
-
setActiveItem(selectableItems.value[nextItemIndex]?.deref());
|
|
555
|
-
}
|
|
556
|
-
if (isArrowUp) {
|
|
557
|
-
const previousIndex = activeItemIndex > 0 ? activeItemIndex - 1 : selectableItems.value.length - 1;
|
|
558
|
-
setActiveItem(selectableItems.value[previousIndex]?.deref());
|
|
559
|
-
}
|
|
560
|
-
executeKeyHooks(pressedKey, activeItem);
|
|
561
|
-
}
|
|
562
|
-
function setActiveItemId(id) {
|
|
563
|
-
activeItemId.value = id;
|
|
564
|
-
}
|
|
565
|
-
function setActiveItem(item) {
|
|
566
|
-
const itemId = getElementId(item);
|
|
567
|
-
if (!itemId) return;
|
|
568
|
-
setActiveItemId(itemId);
|
|
569
|
-
if (item?.scrollIntoView) {
|
|
570
|
-
item?.scrollIntoView({ block: "center" });
|
|
571
|
-
}
|
|
572
|
-
}
|
|
573
|
-
async function setActiveItemIndex(index) {
|
|
574
|
-
await refreshSelectableItems();
|
|
575
|
-
setActiveItem(selectableItems.value[index]?.deref());
|
|
576
|
-
}
|
|
577
|
-
function attachKeydownEvent() {
|
|
578
|
-
document.addEventListener("keydown", onKeyDown, { capture: true });
|
|
579
|
-
}
|
|
580
|
-
function detachKeydownEvent() {
|
|
581
|
-
cleanupSelectableItems();
|
|
582
|
-
document.removeEventListener("keydown", onKeyDown, { capture: true });
|
|
583
|
-
}
|
|
584
|
-
function registerKeyHook(name, hook) {
|
|
585
|
-
hook.keyboardKeys.forEach((keyboardKey) => {
|
|
586
|
-
if (WATCHED_KEYS.includes(keyboardKey)) {
|
|
587
|
-
keysHooks.value = { ...keysHooks.value, [name]: hook };
|
|
588
|
-
} else {
|
|
589
|
-
throw new Error(`Key ${keyboardKey} is not supported`);
|
|
590
|
-
}
|
|
591
|
-
});
|
|
592
|
-
}
|
|
593
|
-
function cleanupSelectableItems() {
|
|
594
|
-
selectableItems.value = [];
|
|
595
|
-
}
|
|
596
|
-
function getActiveItemIndex() {
|
|
597
|
-
return selectableItems.value.findIndex(
|
|
598
|
-
(item) => getElementId(item?.deref()) === activeItemId.value
|
|
599
|
-
);
|
|
600
|
-
}
|
|
601
|
-
return {
|
|
602
|
-
activeItemId,
|
|
603
|
-
attachKeydownEvent,
|
|
604
|
-
refreshSelectableItems,
|
|
605
|
-
detachKeydownEvent,
|
|
606
|
-
registerKeyHook,
|
|
607
|
-
getActiveItemIndex,
|
|
608
|
-
setActiveItemId,
|
|
609
|
-
setActiveItemIndex
|
|
610
|
-
};
|
|
611
|
-
});
|
|
612
|
-
const useViewStacks = defineStore("nodeCreatorViewStacks", () => {
|
|
613
|
-
const nodeCreatorStore = useNodeCreatorStore();
|
|
614
|
-
const { getActiveItemIndex } = useKeyboardNavigation();
|
|
615
|
-
const i18n = useI18n();
|
|
616
|
-
const settingsStore = useSettingsStore();
|
|
617
|
-
const viewStacks = ref([]);
|
|
618
|
-
const activeStackItems = computed(() => {
|
|
619
|
-
const stack = getLastActiveStack();
|
|
620
|
-
if (!stack?.baselineItems) {
|
|
621
|
-
return stack.items ? extendItemsWithUUID(stack.items) : [];
|
|
622
|
-
}
|
|
623
|
-
if (stack.search && searchBaseItems.value) {
|
|
624
|
-
let searchBase = searchBaseItems.value;
|
|
625
|
-
const canvasHasAINodes = useCanvasStore().aiNodes.length > 0;
|
|
626
|
-
if (searchBaseItems.value.length === 0) {
|
|
627
|
-
searchBase = flattenCreateElements(stack.baselineItems ?? []);
|
|
628
|
-
}
|
|
629
|
-
if (
|
|
630
|
-
// Filter-out AI sub-nodes if canvas has no AI nodes and the root view is not AI
|
|
631
|
-
!(isAiRootView(stack) || canvasHasAINodes) || // or if the source is a plus endpoint or a node connection drop and the root view is not AI subcategory
|
|
632
|
-
["plus_endpoint", "node_connection_drop"].includes(nodeCreatorStore.openSource) && !isAiSubcategoryView(stack)
|
|
633
|
-
) {
|
|
634
|
-
searchBase = filterOutAiNodes(searchBase);
|
|
635
|
-
}
|
|
636
|
-
const searchResults = extendItemsWithUUID(searchNodes(stack.search || "", searchBase));
|
|
637
|
-
const groupedNodes = groupIfAiNodes(searchResults, false) ?? searchResults;
|
|
638
|
-
stack.activeIndex = groupedNodes.some((node) => node.type === "section") ? 1 : 0;
|
|
639
|
-
return groupedNodes;
|
|
640
|
-
}
|
|
641
|
-
return extendItemsWithUUID(groupIfAiNodes(stack.baselineItems, true));
|
|
642
|
-
});
|
|
643
|
-
const activeViewStack = computed(() => {
|
|
644
|
-
const stack = getLastActiveStack();
|
|
645
|
-
if (!stack) return {};
|
|
646
|
-
const flatBaselineItems = flattenCreateElements(stack.baselineItems ?? []);
|
|
647
|
-
return {
|
|
648
|
-
...stack,
|
|
649
|
-
items: activeStackItems.value,
|
|
650
|
-
hasSearch: flatBaselineItems.length > 8 || stack?.hasSearch
|
|
651
|
-
};
|
|
652
|
-
});
|
|
653
|
-
const activeViewStackMode = computed(
|
|
654
|
-
() => activeViewStack.value.mode || TRIGGER_NODE_CREATOR_VIEW
|
|
655
|
-
);
|
|
656
|
-
const searchBaseItems = computed(() => {
|
|
657
|
-
const stack = getLastActiveStack();
|
|
658
|
-
if (!stack?.searchItems) return [];
|
|
659
|
-
return stack.searchItems.map((item) => transformNodeType(item, stack.subcategory));
|
|
660
|
-
});
|
|
661
|
-
function isAiSubcategoryView(stack) {
|
|
662
|
-
return stack.rootView === AI_OTHERS_NODE_CREATOR_VIEW;
|
|
663
|
-
}
|
|
664
|
-
function getLastActiveStack() {
|
|
665
|
-
return viewStacks.value[viewStacks.value.length - 1];
|
|
666
|
-
}
|
|
667
|
-
function getAllNodeCreateElements() {
|
|
668
|
-
return nodeCreatorStore.mergedNodes.map(
|
|
669
|
-
(item) => transformNodeType(item)
|
|
670
|
-
);
|
|
671
|
-
}
|
|
672
|
-
const globalSearchItemsDiff = computed(() => {
|
|
673
|
-
const stack = getLastActiveStack();
|
|
674
|
-
if (!stack?.search || isAiSubcategoryView(stack)) return [];
|
|
675
|
-
const allNodes = getAllNodeCreateElements();
|
|
676
|
-
const filteredNodes = isAiRootView(stack) ? allNodes : filterOutAiNodes(allNodes);
|
|
677
|
-
let globalSearchResult = extendItemsWithUUID(
|
|
678
|
-
searchNodes(stack.search || "", filteredNodes)
|
|
679
|
-
);
|
|
680
|
-
if (isAiRootView(stack)) {
|
|
681
|
-
globalSearchResult = groupIfAiNodes(globalSearchResult);
|
|
682
|
-
}
|
|
683
|
-
const filteredItems = globalSearchResult.filter((item) => {
|
|
684
|
-
return !activeStackItems.value.find((activeItem) => {
|
|
685
|
-
if (activeItem.type === "section") {
|
|
686
|
-
const matchingSectionItem = activeItem.children.some(
|
|
687
|
-
(sectionItem) => sectionItem.key === item.key
|
|
688
|
-
);
|
|
689
|
-
return matchingSectionItem;
|
|
690
|
-
}
|
|
691
|
-
return activeItem.key === item.key;
|
|
692
|
-
});
|
|
693
|
-
});
|
|
694
|
-
const filteredSections = filteredItems.filter((item) => {
|
|
695
|
-
if (item.type === "section") {
|
|
696
|
-
const hasVisibleChildren = item.children.some(
|
|
697
|
-
(child) => activeStackItems.value.some((filteredItem) => filteredItem.key === child.key)
|
|
698
|
-
);
|
|
699
|
-
return hasVisibleChildren;
|
|
700
|
-
}
|
|
701
|
-
return true;
|
|
702
|
-
});
|
|
703
|
-
return filteredSections;
|
|
704
|
-
});
|
|
705
|
-
const itemsBySubcategory = computed(() => subcategorizeItems(nodeCreatorStore.mergedNodes));
|
|
706
|
-
function isAiRootView(stack) {
|
|
707
|
-
return stack.rootView === AI_NODE_CREATOR_VIEW;
|
|
708
|
-
}
|
|
709
|
-
function filterAiRootNodes(items) {
|
|
710
|
-
return items.filter((node) => {
|
|
711
|
-
if (node.type !== "node") return false;
|
|
712
|
-
const subcategories = node.properties.codex?.subcategories?.[AI_SUBCATEGORY] ?? [];
|
|
713
|
-
return subcategories.includes(AI_CATEGORY_ROOT_NODES) && !subcategories?.includes(AI_CATEGORY_TOOLS);
|
|
714
|
-
});
|
|
715
|
-
}
|
|
716
|
-
function groupIfAiNodes(items, sortAlphabetically = true) {
|
|
717
|
-
const aiNodes = items.filter((node) => isAINode(node));
|
|
718
|
-
const canvasHasAINodes = useCanvasStore().aiNodes.length > 0;
|
|
719
|
-
if (aiNodes.length > 0 && (canvasHasAINodes || isAiRootView(getLastActiveStack()))) {
|
|
720
|
-
const sectionsMap = /* @__PURE__ */ new Map();
|
|
721
|
-
const aiRootNodes = filterAiRootNodes(aiNodes);
|
|
722
|
-
const aiSubNodes = difference(aiNodes, aiRootNodes);
|
|
723
|
-
aiSubNodes.forEach((node) => {
|
|
724
|
-
const subcategories = node.properties.codex?.subcategories ?? {};
|
|
725
|
-
const section = subcategories[AI_SUBCATEGORY]?.[0];
|
|
726
|
-
if (section) {
|
|
727
|
-
const subSection = subcategories[section]?.[0];
|
|
728
|
-
const sectionKey = subSection ?? section;
|
|
729
|
-
const currentItems = sectionsMap.get(sectionKey)?.items ?? [];
|
|
730
|
-
const isSubnodesSection = !(subcategories[AI_SUBCATEGORY].includes(AI_CATEGORY_ROOT_NODES) || subcategories[AI_SUBCATEGORY].includes(AI_CATEGORY_MCP_NODES));
|
|
731
|
-
let title = section;
|
|
732
|
-
if (isSubnodesSection) {
|
|
733
|
-
title = `${section} (${i18n.baseText("nodeCreator.subnodes")})`;
|
|
734
|
-
}
|
|
735
|
-
if (subSection) {
|
|
736
|
-
title = subSection;
|
|
737
|
-
}
|
|
738
|
-
sectionsMap.set(sectionKey, {
|
|
739
|
-
key: sectionKey,
|
|
740
|
-
title,
|
|
741
|
-
items: [...currentItems, node.key]
|
|
742
|
-
});
|
|
743
|
-
}
|
|
744
|
-
});
|
|
745
|
-
const nonAiNodes = difference(items, aiNodes);
|
|
746
|
-
const sections = Array.from(sectionsMap.values());
|
|
747
|
-
return [
|
|
748
|
-
...nonAiNodes,
|
|
749
|
-
...aiRootNodes,
|
|
750
|
-
...groupItemsInSections(aiSubNodes, sections, sortAlphabetically)
|
|
751
|
-
];
|
|
752
|
-
}
|
|
753
|
-
return items;
|
|
754
|
-
}
|
|
755
|
-
function filterOutAiNodes(items) {
|
|
756
|
-
const filteredSearchBase = items.filter((item) => {
|
|
757
|
-
if (item.type === "node") {
|
|
758
|
-
const isAICategory = item.properties.codex?.categories?.includes(AI_SUBCATEGORY) === true;
|
|
759
|
-
if (!isAICategory) return true;
|
|
760
|
-
const isRootNodeSubcategory = item.properties.codex?.subcategories?.[AI_SUBCATEGORY]?.includes(AI_CATEGORY_ROOT_NODES);
|
|
761
|
-
return isRootNodeSubcategory;
|
|
762
|
-
}
|
|
763
|
-
return true;
|
|
764
|
-
});
|
|
765
|
-
return filteredSearchBase;
|
|
766
|
-
}
|
|
767
|
-
async function gotoCompatibleConnectionView(connectionType, isOutput, filter) {
|
|
768
|
-
let nodesByConnectionType;
|
|
769
|
-
let relatedAIView;
|
|
770
|
-
if (isOutput === true) {
|
|
771
|
-
nodesByConnectionType = useNodeTypesStore().visibleNodeTypesByInputConnectionTypeNames;
|
|
772
|
-
relatedAIView = {
|
|
773
|
-
properties: {
|
|
774
|
-
title: i18n.baseText("nodeCreator.aiPanel.aiNodes"),
|
|
775
|
-
icon: "robot"
|
|
776
|
-
}
|
|
777
|
-
};
|
|
778
|
-
} else {
|
|
779
|
-
nodesByConnectionType = useNodeTypesStore().visibleNodeTypesByOutputConnectionTypeNames;
|
|
780
|
-
relatedAIView = AINodesView().items.find(
|
|
781
|
-
(item) => item.properties.connectionType === connectionType
|
|
782
|
-
);
|
|
783
|
-
}
|
|
784
|
-
let extendedInfo = {};
|
|
785
|
-
if (!filter?.nodes?.length && relatedAIView?.properties.info) {
|
|
786
|
-
extendedInfo = { info: relatedAIView?.properties.info };
|
|
787
|
-
}
|
|
788
|
-
await nextTick();
|
|
789
|
-
const iconName = getThemedValue(relatedAIView?.properties.icon, useUIStore().appliedTheme);
|
|
790
|
-
pushViewStack(
|
|
791
|
-
{
|
|
792
|
-
title: relatedAIView?.properties.title,
|
|
793
|
-
...extendedInfo,
|
|
794
|
-
rootView: AI_OTHERS_NODE_CREATOR_VIEW,
|
|
795
|
-
mode: "nodes",
|
|
796
|
-
items: nodeCreatorStore.allNodeCreatorNodes,
|
|
797
|
-
nodeIcon: iconName ? {
|
|
798
|
-
type: "icon",
|
|
799
|
-
name: iconName,
|
|
800
|
-
color: relatedAIView?.properties.iconProps?.color
|
|
801
|
-
} : void 0,
|
|
802
|
-
panelClass: relatedAIView?.properties.panelClass,
|
|
803
|
-
baseFilter: (i) => {
|
|
804
|
-
if (i.key === AI_CODE_NODE_TYPE) return false;
|
|
805
|
-
const displayNode = nodesByConnectionType[connectionType].includes(i.key);
|
|
806
|
-
if (displayNode && filter?.nodes?.length) {
|
|
807
|
-
return filter.nodes.includes(i.key);
|
|
808
|
-
}
|
|
809
|
-
return displayNode;
|
|
810
|
-
},
|
|
811
|
-
itemsMapper(item) {
|
|
812
|
-
return {
|
|
813
|
-
...item,
|
|
814
|
-
subcategory: connectionType
|
|
815
|
-
};
|
|
816
|
-
},
|
|
817
|
-
actionsFilter: (items) => {
|
|
818
|
-
if (items.some((item) => item.outputConnectionType)) {
|
|
819
|
-
return items.filter((item) => item.outputConnectionType === connectionType);
|
|
820
|
-
}
|
|
821
|
-
return items;
|
|
822
|
-
},
|
|
823
|
-
hideActions: true,
|
|
824
|
-
preventBack: true
|
|
825
|
-
},
|
|
826
|
-
{ resetStacks: true }
|
|
827
|
-
);
|
|
828
|
-
}
|
|
829
|
-
function setStackBaselineItems() {
|
|
830
|
-
const stack = getLastActiveStack();
|
|
831
|
-
if (!stack || !activeViewStack.value.uuid) return;
|
|
832
|
-
let stackItems = stack?.items ?? [];
|
|
833
|
-
if (!stack?.items) {
|
|
834
|
-
const subcategory = stack?.subcategory ?? DEFAULT_SUBCATEGORY;
|
|
835
|
-
let itemsInSubcategory = itemsBySubcategory.value[subcategory];
|
|
836
|
-
const isAskAiEnabled = settingsStore.isAskAiEnabled;
|
|
837
|
-
if (!isAskAiEnabled) {
|
|
838
|
-
itemsInSubcategory = itemsInSubcategory.filter(
|
|
839
|
-
(item) => item.key !== AI_TRANSFORM_NODE_TYPE$1
|
|
840
|
-
);
|
|
841
|
-
}
|
|
842
|
-
const sections = stack.sections;
|
|
843
|
-
if (sections) {
|
|
844
|
-
stackItems = groupItemsInSections(itemsInSubcategory, sections);
|
|
845
|
-
} else {
|
|
846
|
-
stackItems = itemsInSubcategory;
|
|
847
|
-
}
|
|
848
|
-
}
|
|
849
|
-
if ((stack.forceIncludeNodes ?? []).length > 0) {
|
|
850
|
-
const matchedNodes = nodeCreatorStore.mergedNodes.filter((item) => stack.forceIncludeNodes?.includes(item.name)).map((item) => transformNodeType(item, stack.subcategory));
|
|
851
|
-
stackItems.push(...matchedNodes);
|
|
852
|
-
}
|
|
853
|
-
if (stack.baseFilter) {
|
|
854
|
-
stackItems = stackItems.filter(stack.baseFilter);
|
|
855
|
-
}
|
|
856
|
-
if (stack.itemsMapper) {
|
|
857
|
-
stackItems = stackItems.map(stack.itemsMapper);
|
|
858
|
-
}
|
|
859
|
-
if (!stack.items) {
|
|
860
|
-
stackItems = sortNodeCreateElements(stackItems);
|
|
861
|
-
}
|
|
862
|
-
updateCurrentViewStack({ baselineItems: stackItems });
|
|
863
|
-
}
|
|
864
|
-
function pushViewStack(stack, options = {}) {
|
|
865
|
-
if (options.resetStacks) {
|
|
866
|
-
resetViewStacks();
|
|
867
|
-
}
|
|
868
|
-
if (activeViewStack.value.uuid) {
|
|
869
|
-
updateCurrentViewStack({ activeIndex: getActiveItemIndex() });
|
|
870
|
-
}
|
|
871
|
-
const newStackUuid = v4();
|
|
872
|
-
viewStacks.value.push({
|
|
873
|
-
...stack,
|
|
874
|
-
uuid: newStackUuid,
|
|
875
|
-
transitionDirection: options.transitionDirection ?? "in",
|
|
876
|
-
activeIndex: 0
|
|
877
|
-
});
|
|
878
|
-
setStackBaselineItems();
|
|
879
|
-
}
|
|
880
|
-
function popViewStack() {
|
|
881
|
-
if (activeViewStack.value.uuid) {
|
|
882
|
-
viewStacks.value.pop();
|
|
883
|
-
updateCurrentViewStack({ transitionDirection: "out" });
|
|
884
|
-
}
|
|
885
|
-
}
|
|
886
|
-
function updateCurrentViewStack(stack) {
|
|
887
|
-
const currentStack = getLastActiveStack();
|
|
888
|
-
const matchedIndex = viewStacks.value.findIndex((s) => s.uuid === currentStack.uuid);
|
|
889
|
-
if (!currentStack) return;
|
|
890
|
-
Object.keys(stack).forEach((key) => {
|
|
891
|
-
const typedKey = key;
|
|
892
|
-
viewStacks.value[matchedIndex] = {
|
|
893
|
-
...viewStacks.value[matchedIndex],
|
|
894
|
-
[key]: stack[typedKey]
|
|
895
|
-
};
|
|
896
|
-
});
|
|
897
|
-
}
|
|
898
|
-
function resetViewStacks() {
|
|
899
|
-
viewStacks.value = [];
|
|
900
|
-
}
|
|
901
|
-
return {
|
|
902
|
-
viewStacks,
|
|
903
|
-
activeViewStack,
|
|
904
|
-
activeViewStackMode,
|
|
905
|
-
globalSearchItemsDiff,
|
|
906
|
-
isAiSubcategoryView,
|
|
907
|
-
gotoCompatibleConnectionView,
|
|
908
|
-
resetViewStacks,
|
|
909
|
-
updateCurrentViewStack,
|
|
910
|
-
pushViewStack,
|
|
911
|
-
popViewStack,
|
|
912
|
-
getAllNodeCreateElements
|
|
913
|
-
};
|
|
914
|
-
});
|
|
915
|
-
function mapLegacyConnectionsToCanvasConnections(legacyConnections, nodes) {
|
|
916
|
-
const mappedConnections = [];
|
|
917
|
-
Object.keys(legacyConnections).forEach((fromNodeName) => {
|
|
918
|
-
const fromId = nodes.find((node) => node.name === fromNodeName)?.id ?? "";
|
|
919
|
-
const fromConnectionTypes = Object.keys(
|
|
920
|
-
legacyConnections[fromNodeName]
|
|
921
|
-
);
|
|
922
|
-
fromConnectionTypes.forEach((fromConnectionType) => {
|
|
923
|
-
const fromPorts = legacyConnections[fromNodeName][fromConnectionType];
|
|
924
|
-
fromPorts?.forEach((toPorts, fromIndex) => {
|
|
925
|
-
toPorts?.forEach((toPort) => {
|
|
926
|
-
const toNodeName = toPort.node;
|
|
927
|
-
const toId = nodes.find((node) => node.name === toNodeName)?.id ?? "";
|
|
928
|
-
const toConnectionType = toPort.type;
|
|
929
|
-
const toIndex = toPort.index;
|
|
930
|
-
const sourceHandle = createCanvasConnectionHandleString({
|
|
931
|
-
mode: CanvasConnectionMode.Output,
|
|
932
|
-
type: fromConnectionType,
|
|
933
|
-
index: fromIndex
|
|
934
|
-
});
|
|
935
|
-
const targetHandle = createCanvasConnectionHandleString({
|
|
936
|
-
mode: CanvasConnectionMode.Input,
|
|
937
|
-
type: toConnectionType,
|
|
938
|
-
index: toIndex
|
|
939
|
-
});
|
|
940
|
-
const connectionId = createCanvasConnectionId({
|
|
941
|
-
source: fromId,
|
|
942
|
-
sourceHandle,
|
|
943
|
-
target: toId,
|
|
944
|
-
targetHandle
|
|
945
|
-
});
|
|
946
|
-
if (fromId && toId) {
|
|
947
|
-
mappedConnections.push({
|
|
948
|
-
id: connectionId,
|
|
949
|
-
source: fromId,
|
|
950
|
-
target: toId,
|
|
951
|
-
sourceHandle,
|
|
952
|
-
targetHandle,
|
|
953
|
-
data: {
|
|
954
|
-
source: {
|
|
955
|
-
node: fromNodeName,
|
|
956
|
-
index: fromIndex,
|
|
957
|
-
type: fromConnectionType
|
|
958
|
-
},
|
|
959
|
-
target: {
|
|
960
|
-
node: toNodeName,
|
|
961
|
-
index: toIndex,
|
|
962
|
-
type: toConnectionType
|
|
963
|
-
}
|
|
964
|
-
}
|
|
965
|
-
});
|
|
966
|
-
}
|
|
967
|
-
});
|
|
968
|
-
});
|
|
969
|
-
});
|
|
970
|
-
});
|
|
971
|
-
return mappedConnections;
|
|
972
|
-
}
|
|
973
|
-
function mapLegacyConnectionToCanvasConnection(sourceNode, targetNode, legacyConnection) {
|
|
974
|
-
const source = sourceNode.id;
|
|
975
|
-
const sourceHandle = createCanvasConnectionHandleString({
|
|
976
|
-
mode: CanvasConnectionMode.Output,
|
|
977
|
-
type: legacyConnection[0].type,
|
|
978
|
-
index: legacyConnection[0].index
|
|
979
|
-
});
|
|
980
|
-
const target = targetNode.id;
|
|
981
|
-
const targetHandle = createCanvasConnectionHandleString({
|
|
982
|
-
mode: CanvasConnectionMode.Input,
|
|
983
|
-
type: legacyConnection[1].type,
|
|
984
|
-
index: legacyConnection[1].index
|
|
985
|
-
});
|
|
986
|
-
return {
|
|
987
|
-
source,
|
|
988
|
-
sourceHandle,
|
|
989
|
-
target,
|
|
990
|
-
targetHandle
|
|
991
|
-
};
|
|
992
|
-
}
|
|
993
|
-
function parseCanvasConnectionHandleString(handle) {
|
|
994
|
-
const [mode, type, index] = (handle ?? "").split("/");
|
|
995
|
-
const resolvedMode = isValidCanvasConnectionMode(mode) ? mode : CanvasConnectionMode.Output;
|
|
996
|
-
const resolvedType = isValidNodeConnectionType(type) ? type : NodeConnectionTypes.Main;
|
|
997
|
-
let resolvedIndex = parseInt(index, 10);
|
|
998
|
-
if (isNaN(resolvedIndex)) {
|
|
999
|
-
resolvedIndex = 0;
|
|
1000
|
-
}
|
|
1001
|
-
return {
|
|
1002
|
-
mode: resolvedMode,
|
|
1003
|
-
type: resolvedType,
|
|
1004
|
-
index: resolvedIndex
|
|
1005
|
-
};
|
|
1006
|
-
}
|
|
1007
|
-
function createCanvasConnectionHandleString({
|
|
1008
|
-
mode,
|
|
1009
|
-
type = NodeConnectionTypes.Main,
|
|
1010
|
-
index = 0
|
|
1011
|
-
}) {
|
|
1012
|
-
return `${mode}/${type}/${index}`;
|
|
1013
|
-
}
|
|
1014
|
-
function createCanvasConnectionId(connection) {
|
|
1015
|
-
return `[${connection.source}/${connection.sourceHandle}][${connection.target}/${connection.targetHandle}]`;
|
|
1016
|
-
}
|
|
1017
|
-
function mapCanvasConnectionToLegacyConnection(sourceNode, targetNode, connection) {
|
|
1018
|
-
const sourceNodeName = sourceNode?.name ?? "";
|
|
1019
|
-
const { type: sourceType, index: sourceIndex } = parseCanvasConnectionHandleString(
|
|
1020
|
-
connection.sourceHandle
|
|
1021
|
-
);
|
|
1022
|
-
const targetNodeName = targetNode?.name ?? "";
|
|
1023
|
-
const { type: targetType, index: targetIndex } = parseCanvasConnectionHandleString(
|
|
1024
|
-
connection.targetHandle
|
|
1025
|
-
);
|
|
1026
|
-
return [
|
|
1027
|
-
{
|
|
1028
|
-
node: sourceNodeName,
|
|
1029
|
-
type: sourceType,
|
|
1030
|
-
index: sourceIndex
|
|
1031
|
-
},
|
|
1032
|
-
{
|
|
1033
|
-
node: targetNodeName,
|
|
1034
|
-
type: targetType,
|
|
1035
|
-
index: targetIndex
|
|
1036
|
-
}
|
|
1037
|
-
];
|
|
1038
|
-
}
|
|
1039
|
-
function mapLegacyEndpointsToCanvasConnectionPort(endpoints, endpointNames = []) {
|
|
1040
|
-
if (typeof endpoints === "string") {
|
|
1041
|
-
console.warn("Node endpoints have not been evaluated", endpoints);
|
|
1042
|
-
return [];
|
|
1043
|
-
}
|
|
1044
|
-
return endpoints.map((endpoint, endpointIndex) => {
|
|
1045
|
-
const typeValue = typeof endpoint === "string" ? endpoint : endpoint.type;
|
|
1046
|
-
const type = isValidNodeConnectionType(typeValue) ? typeValue : NodeConnectionTypes.Main;
|
|
1047
|
-
const label = typeof endpoint === "string" ? endpointNames[endpointIndex] : endpoint.displayName;
|
|
1048
|
-
const index = endpoints.slice(0, endpointIndex + 1).filter((e) => (typeof e === "string" ? e : e.type) === type).length - 1;
|
|
1049
|
-
const required = typeof endpoint === "string" ? false : endpoint.required;
|
|
1050
|
-
const maxConnections = typeof endpoint === "string" ? void 0 : endpoint.maxConnections;
|
|
1051
|
-
return {
|
|
1052
|
-
type,
|
|
1053
|
-
index,
|
|
1054
|
-
label,
|
|
1055
|
-
...maxConnections ? { maxConnections } : {},
|
|
1056
|
-
...required ? { required } : {}
|
|
1057
|
-
};
|
|
1058
|
-
});
|
|
1059
|
-
}
|
|
1060
|
-
function checkOverlap(node1, node2) {
|
|
1061
|
-
return !// node1 is completely to the left of node2
|
|
1062
|
-
(node1.x + node1.width <= node2.x || // node2 is completely to the left of node1
|
|
1063
|
-
node2.x + node2.width <= node1.x || // node1 is completely above node2
|
|
1064
|
-
node1.y + node1.height <= node2.y || // node2 is completely above node1
|
|
1065
|
-
node2.y + node2.height <= node1.y);
|
|
1066
|
-
}
|
|
1067
|
-
function insertSpacersBetweenEndpoints(endpoints, requiredEndpointsCount = 0, minEndpointsCount = 4) {
|
|
1068
|
-
const endpointsWithSpacers = [...endpoints];
|
|
1069
|
-
const optionalNonMainInputsCount = endpointsWithSpacers.length - requiredEndpointsCount;
|
|
1070
|
-
const spacerCount = minEndpointsCount - requiredEndpointsCount - optionalNonMainInputsCount;
|
|
1071
|
-
if (endpointsWithSpacers.length < minEndpointsCount) {
|
|
1072
|
-
for (let i = 0; i < spacerCount; i++) {
|
|
1073
|
-
endpointsWithSpacers.splice(requiredEndpointsCount + i, 0, null);
|
|
1074
|
-
}
|
|
1075
|
-
}
|
|
1076
|
-
return endpointsWithSpacers;
|
|
1077
|
-
}
|
|
1078
|
-
const useNodeCreatorStore = defineStore(STORES.NODE_CREATOR, () => {
|
|
1079
|
-
const workflowsStore = useWorkflowsStore();
|
|
1080
|
-
const ndvStore = useNDVStore();
|
|
1081
|
-
const uiStore = useUIStore();
|
|
1082
|
-
const nodeTypesStore = useNodeTypesStore();
|
|
1083
|
-
const telemetry = useTelemetry();
|
|
1084
|
-
const externalHooks = useExternalHooks();
|
|
1085
|
-
const selectedView = ref(TRIGGER_NODE_CREATOR_VIEW);
|
|
1086
|
-
const mergedNodes = ref([]);
|
|
1087
|
-
const actions = ref({});
|
|
1088
|
-
const showScrim = ref(false);
|
|
1089
|
-
const openSource = ref("");
|
|
1090
|
-
const isCreateNodeActive = ref(false);
|
|
1091
|
-
const nodePanelSessionId = ref("");
|
|
1092
|
-
const allNodeCreatorNodes = computed(
|
|
1093
|
-
() => Object.values(mergedNodes.value).map((i) => transformNodeType(i))
|
|
1094
|
-
);
|
|
1095
|
-
function setMergeNodes(nodes) {
|
|
1096
|
-
mergedNodes.value = nodes;
|
|
1097
|
-
}
|
|
1098
|
-
function removeNodeFromMergedNodes(nodeName) {
|
|
1099
|
-
mergedNodes.value = mergedNodes.value.filter((n) => n.name !== nodeName);
|
|
1100
|
-
}
|
|
1101
|
-
function setActions(nodes) {
|
|
1102
|
-
actions.value = nodes;
|
|
1103
|
-
}
|
|
1104
|
-
function setShowScrim(isVisible) {
|
|
1105
|
-
showScrim.value = isVisible;
|
|
1106
|
-
}
|
|
1107
|
-
function setSelectedView(view) {
|
|
1108
|
-
selectedView.value = view;
|
|
1109
|
-
}
|
|
1110
|
-
function setOpenSource(view) {
|
|
1111
|
-
openSource.value = view;
|
|
1112
|
-
}
|
|
1113
|
-
function openSelectiveNodeCreator({
|
|
1114
|
-
connectionType,
|
|
1115
|
-
node,
|
|
1116
|
-
creatorView
|
|
1117
|
-
}) {
|
|
1118
|
-
const nodeName = node ?? ndvStore.activeNodeName;
|
|
1119
|
-
const nodeData = nodeName ? workflowsStore.getNodeByName(nodeName) : null;
|
|
1120
|
-
ndvStore.activeNodeName = null;
|
|
1121
|
-
setTimeout(() => {
|
|
1122
|
-
if (creatorView) {
|
|
1123
|
-
setNodeCreatorState({
|
|
1124
|
-
createNodeActive: true,
|
|
1125
|
-
nodeCreatorView: creatorView
|
|
1126
|
-
});
|
|
1127
|
-
} else if (connectionType && nodeData) {
|
|
1128
|
-
openNodeCreatorForConnectingNode({
|
|
1129
|
-
connection: {
|
|
1130
|
-
source: nodeData.id,
|
|
1131
|
-
sourceHandle: createCanvasConnectionHandleString({
|
|
1132
|
-
mode: "inputs",
|
|
1133
|
-
type: connectionType,
|
|
1134
|
-
index: 0
|
|
1135
|
-
})
|
|
1136
|
-
},
|
|
1137
|
-
eventSource: NODE_CREATOR_OPEN_SOURCES.NOTICE_ERROR_MESSAGE
|
|
1138
|
-
});
|
|
1139
|
-
}
|
|
1140
|
-
});
|
|
1141
|
-
}
|
|
1142
|
-
function setNodeCreatorState({
|
|
1143
|
-
source,
|
|
1144
|
-
createNodeActive,
|
|
1145
|
-
nodeCreatorView
|
|
1146
|
-
}) {
|
|
1147
|
-
if (!nodeCreatorView) {
|
|
1148
|
-
nodeCreatorView = workflowsStore.workflowTriggerNodes.length > 0 ? REGULAR_NODE_CREATOR_VIEW : TRIGGER_NODE_CREATOR_VIEW;
|
|
1149
|
-
}
|
|
1150
|
-
setSelectedView(nodeCreatorView);
|
|
1151
|
-
isCreateNodeActive.value = createNodeActive;
|
|
1152
|
-
if (createNodeActive && source) {
|
|
1153
|
-
setOpenSource(source);
|
|
1154
|
-
}
|
|
1155
|
-
void externalHooks.run("nodeView.createNodeActiveChanged", {
|
|
1156
|
-
source,
|
|
1157
|
-
mode: getMode(nodeCreatorView),
|
|
1158
|
-
createNodeActive
|
|
1159
|
-
});
|
|
1160
|
-
if (createNodeActive) {
|
|
1161
|
-
onCreatorOpened({
|
|
1162
|
-
source,
|
|
1163
|
-
mode: getMode(nodeCreatorView),
|
|
1164
|
-
workflow_id: workflowsStore.workflowId
|
|
1165
|
-
});
|
|
1166
|
-
}
|
|
1167
|
-
}
|
|
1168
|
-
function openNodeCreatorForConnectingNode({
|
|
1169
|
-
connection,
|
|
1170
|
-
eventSource,
|
|
1171
|
-
nodeCreatorView
|
|
1172
|
-
}) {
|
|
1173
|
-
const sourceNode = workflowsStore.getNodeById(connection.source);
|
|
1174
|
-
if (!sourceNode) {
|
|
1175
|
-
return;
|
|
1176
|
-
}
|
|
1177
|
-
const { type, index, mode } = parseCanvasConnectionHandleString(connection.sourceHandle);
|
|
1178
|
-
uiStore.lastSelectedNode = sourceNode.name;
|
|
1179
|
-
uiStore.lastSelectedNodeEndpointUuid = connection.sourceHandle ?? null;
|
|
1180
|
-
uiStore.lastSelectedNodeOutputIndex = index;
|
|
1181
|
-
if (isVueFlowConnection(connection)) {
|
|
1182
|
-
uiStore.lastInteractedWithNodeConnection = connection;
|
|
1183
|
-
}
|
|
1184
|
-
uiStore.lastInteractedWithNodeHandle = connection.sourceHandle ?? null;
|
|
1185
|
-
uiStore.lastInteractedWithNodeId = sourceNode.id;
|
|
1186
|
-
const isOutput = mode === CanvasConnectionMode.Output;
|
|
1187
|
-
const isScopedConnection = type !== NodeConnectionTypes.Main;
|
|
1188
|
-
setNodeCreatorState({
|
|
1189
|
-
source: eventSource,
|
|
1190
|
-
createNodeActive: true,
|
|
1191
|
-
nodeCreatorView: isScopedConnection ? AI_UNCATEGORIZED_CATEGORY : nodeCreatorView
|
|
1192
|
-
});
|
|
1193
|
-
if (isScopedConnection) {
|
|
1194
|
-
useViewStacks().gotoCompatibleConnectionView(type, isOutput, getNodeCreatorFilter(sourceNode.name, type)).catch(() => {
|
|
1195
|
-
});
|
|
1196
|
-
}
|
|
1197
|
-
}
|
|
1198
|
-
function openNodeCreatorForTriggerNodes(source) {
|
|
1199
|
-
ndvStore.activeNodeName = null;
|
|
1200
|
-
setSelectedView(TRIGGER_NODE_CREATOR_VIEW);
|
|
1201
|
-
setShowScrim(true);
|
|
1202
|
-
setNodeCreatorState({
|
|
1203
|
-
source,
|
|
1204
|
-
createNodeActive: true,
|
|
1205
|
-
nodeCreatorView: TRIGGER_NODE_CREATOR_VIEW
|
|
1206
|
-
});
|
|
1207
|
-
}
|
|
1208
|
-
function getNodeCreatorFilter(nodeName, outputType) {
|
|
1209
|
-
let filter;
|
|
1210
|
-
const workflow = workflowsStore.getCurrentWorkflow();
|
|
1211
|
-
const workflowNode = workflow.getNode(nodeName);
|
|
1212
|
-
if (!workflowNode) return { nodes: [] };
|
|
1213
|
-
const nodeType = nodeTypesStore.getNodeType(workflowNode?.type, workflowNode.typeVersion);
|
|
1214
|
-
if (nodeType) {
|
|
1215
|
-
const inputs = getNodeInputs(workflow, workflowNode, nodeType);
|
|
1216
|
-
const filterFound = inputs.filter((input) => {
|
|
1217
|
-
if (typeof input === "string" || input.type !== outputType || !input.filter) {
|
|
1218
|
-
return false;
|
|
1219
|
-
}
|
|
1220
|
-
return true;
|
|
1221
|
-
});
|
|
1222
|
-
if (filterFound.length) {
|
|
1223
|
-
filter = filterFound[0].filter;
|
|
1224
|
-
}
|
|
1225
|
-
}
|
|
1226
|
-
return filter;
|
|
1227
|
-
}
|
|
1228
|
-
function resetNodesPanelSession() {
|
|
1229
|
-
nodePanelSessionId.value = `nodes_panel_session_${(/* @__PURE__ */ new Date()).valueOf()}`;
|
|
1230
|
-
}
|
|
1231
|
-
function trackNodeCreatorEvent(event, properties = {}, withPostHog = false) {
|
|
1232
|
-
telemetry.track(
|
|
1233
|
-
event,
|
|
1234
|
-
{
|
|
1235
|
-
...properties,
|
|
1236
|
-
nodes_panel_session_id: nodePanelSessionId.value
|
|
1237
|
-
},
|
|
1238
|
-
{
|
|
1239
|
-
withPostHog
|
|
1240
|
-
}
|
|
1241
|
-
);
|
|
1242
|
-
}
|
|
1243
|
-
function onCreatorOpened({
|
|
1244
|
-
source,
|
|
1245
|
-
mode,
|
|
1246
|
-
workflow_id
|
|
1247
|
-
}) {
|
|
1248
|
-
resetNodesPanelSession();
|
|
1249
|
-
trackNodeCreatorEvent("User opened nodes panel", {
|
|
1250
|
-
source,
|
|
1251
|
-
mode,
|
|
1252
|
-
workflow_id
|
|
1253
|
-
});
|
|
1254
|
-
}
|
|
1255
|
-
function onNodeFilterChanged({
|
|
1256
|
-
newValue,
|
|
1257
|
-
filteredNodes,
|
|
1258
|
-
filterMode,
|
|
1259
|
-
subcategory,
|
|
1260
|
-
title
|
|
1261
|
-
}) {
|
|
1262
|
-
if (!newValue.length) {
|
|
1263
|
-
return;
|
|
1264
|
-
}
|
|
1265
|
-
const { results_count, trigger_count, regular_count } = filteredNodes.reduce(
|
|
1266
|
-
(accu, node) => {
|
|
1267
|
-
if (!("properties" in node)) {
|
|
1268
|
-
return accu;
|
|
1269
|
-
}
|
|
1270
|
-
const isCustomAction = "actionKey" in node.properties && node.properties.actionKey === CUSTOM_API_CALL_KEY;
|
|
1271
|
-
if (isCustomAction) {
|
|
1272
|
-
return accu;
|
|
1273
|
-
}
|
|
1274
|
-
const isTrigger = node.key.includes("Trigger");
|
|
1275
|
-
return {
|
|
1276
|
-
results_count: accu.results_count + 1,
|
|
1277
|
-
trigger_count: accu.trigger_count + (isTrigger ? 1 : 0),
|
|
1278
|
-
regular_count: accu.regular_count + (isTrigger ? 0 : 1)
|
|
1279
|
-
};
|
|
1280
|
-
},
|
|
1281
|
-
{
|
|
1282
|
-
results_count: 0,
|
|
1283
|
-
trigger_count: 0,
|
|
1284
|
-
regular_count: 0
|
|
1285
|
-
}
|
|
1286
|
-
);
|
|
1287
|
-
trackNodeCreatorEvent("User entered nodes panel search term", {
|
|
1288
|
-
search_string: newValue,
|
|
1289
|
-
filter_mode: getMode(filterMode),
|
|
1290
|
-
category_name: subcategory,
|
|
1291
|
-
results_count,
|
|
1292
|
-
trigger_count,
|
|
1293
|
-
regular_count,
|
|
1294
|
-
title
|
|
1295
|
-
});
|
|
1296
|
-
}
|
|
1297
|
-
function onCategoryExpanded(properties) {
|
|
1298
|
-
trackNodeCreatorEvent("User viewed node category", { ...properties, is_subcategory: false });
|
|
1299
|
-
}
|
|
1300
|
-
function onViewActions(properties) {
|
|
1301
|
-
trackNodeCreatorEvent("User viewed node actions", properties);
|
|
1302
|
-
}
|
|
1303
|
-
function onActionsCustomAPIClicked(properties) {
|
|
1304
|
-
trackNodeCreatorEvent("User clicked custom API from node actions", properties);
|
|
1305
|
-
}
|
|
1306
|
-
function onAddActions(properties) {
|
|
1307
|
-
trackNodeCreatorEvent("User added action", properties);
|
|
1308
|
-
}
|
|
1309
|
-
function onSubcategorySelected(properties) {
|
|
1310
|
-
trackNodeCreatorEvent("User viewed node category", {
|
|
1311
|
-
category_name: properties.subcategory,
|
|
1312
|
-
is_subcategory: true
|
|
1313
|
-
});
|
|
1314
|
-
}
|
|
1315
|
-
function onNodeAddedToCanvas(properties) {
|
|
1316
|
-
trackNodeCreatorEvent("User added node to workflow canvas", properties, true);
|
|
1317
|
-
}
|
|
1318
|
-
function getMode(mode) {
|
|
1319
|
-
if (mode === AI_NODE_CREATOR_VIEW || mode === AI_OTHERS_NODE_CREATOR_VIEW) {
|
|
1320
|
-
return "ai";
|
|
1321
|
-
}
|
|
1322
|
-
if (mode === TRIGGER_NODE_CREATOR_VIEW) {
|
|
1323
|
-
return "trigger";
|
|
1324
|
-
}
|
|
1325
|
-
return "regular";
|
|
1326
|
-
}
|
|
1327
|
-
return {
|
|
1328
|
-
isCreateNodeActive,
|
|
1329
|
-
openSource,
|
|
1330
|
-
selectedView,
|
|
1331
|
-
showScrim,
|
|
1332
|
-
mergedNodes,
|
|
1333
|
-
actions,
|
|
1334
|
-
allNodeCreatorNodes,
|
|
1335
|
-
setShowScrim,
|
|
1336
|
-
setSelectedView,
|
|
1337
|
-
setOpenSource,
|
|
1338
|
-
setActions,
|
|
1339
|
-
setMergeNodes,
|
|
1340
|
-
removeNodeFromMergedNodes,
|
|
1341
|
-
setNodeCreatorState,
|
|
1342
|
-
openSelectiveNodeCreator,
|
|
1343
|
-
openNodeCreatorForConnectingNode,
|
|
1344
|
-
openNodeCreatorForTriggerNodes,
|
|
1345
|
-
onCreatorOpened,
|
|
1346
|
-
onNodeFilterChanged,
|
|
1347
|
-
onCategoryExpanded,
|
|
1348
|
-
onActionsCustomAPIClicked,
|
|
1349
|
-
onViewActions,
|
|
1350
|
-
onAddActions,
|
|
1351
|
-
onSubcategorySelected,
|
|
1352
|
-
onNodeAddedToCanvas
|
|
1353
|
-
};
|
|
1354
|
-
});
|
|
1355
|
-
function useUniqueNodeName() {
|
|
1356
|
-
function numberSuffixedNames() {
|
|
1357
|
-
return useNodeTypesStore().allNodeTypes.reduce((acc, nodeType) => {
|
|
1358
|
-
if (typeof nodeType.defaults.name !== "string") {
|
|
1359
|
-
throw new Error("Expected node name default to be a string");
|
|
1360
|
-
}
|
|
1361
|
-
if (/\d$/.test(nodeType.defaults.name)) acc.push(nodeType.defaults.name);
|
|
1362
|
-
return acc;
|
|
1363
|
-
}, []);
|
|
1364
|
-
}
|
|
1365
|
-
function uniqueNodeName(originalName, extraNames = []) {
|
|
1366
|
-
const { canvasNames } = useWorkflowsStore();
|
|
1367
|
-
const isUnique = !canvasNames.has(originalName) && !extraNames.includes(originalName);
|
|
1368
|
-
if (isUnique) return originalName;
|
|
1369
|
-
const nsn = numberSuffixedNames().find((nsn2) => originalName.startsWith(nsn2));
|
|
1370
|
-
if (nsn) {
|
|
1371
|
-
let unique2 = "";
|
|
1372
|
-
let index2 = 1;
|
|
1373
|
-
const remainder = originalName.split(nsn).pop();
|
|
1374
|
-
const lastChar = remainder?.[remainder.length - 1];
|
|
1375
|
-
if (lastChar && Number.isInteger(Number(lastChar))) {
|
|
1376
|
-
index2 = parseInt(lastChar, 10);
|
|
1377
|
-
originalName = originalName.slice(0, -1);
|
|
1378
|
-
}
|
|
1379
|
-
unique2 = originalName;
|
|
1380
|
-
while (canvasNames.has(unique2) || extraNames.includes(unique2)) {
|
|
1381
|
-
unique2 = originalName + index2++;
|
|
1382
|
-
}
|
|
1383
|
-
return unique2;
|
|
1384
|
-
}
|
|
1385
|
-
if (/^\d+-?\d*$/.test(originalName)) {
|
|
1386
|
-
let unique2 = "";
|
|
1387
|
-
let index2 = 1;
|
|
1388
|
-
const match2 = originalName.match(/(?<base>\d+)-?(?<suffix>\d*)/);
|
|
1389
|
-
if (!match2?.groups) {
|
|
1390
|
-
throw new Error("Failed to find match for unique name");
|
|
1391
|
-
}
|
|
1392
|
-
if (match2?.groups?.suffix !== "") {
|
|
1393
|
-
index2 = parseInt(match2.groups.suffix, 10);
|
|
1394
|
-
}
|
|
1395
|
-
unique2 = match2.groups.base;
|
|
1396
|
-
while (canvasNames.has(unique2) || extraNames.includes(unique2)) {
|
|
1397
|
-
unique2 = match2.groups.base + "-" + index2++;
|
|
1398
|
-
}
|
|
1399
|
-
return unique2;
|
|
1400
|
-
}
|
|
1401
|
-
let unique = "";
|
|
1402
|
-
let index = 1;
|
|
1403
|
-
const match = originalName.match(/(?<base>.*\D+)(?<suffix>\d*)/);
|
|
1404
|
-
if (!match?.groups) {
|
|
1405
|
-
throw new Error("Failed to find match for unique name");
|
|
1406
|
-
}
|
|
1407
|
-
if (match?.groups?.suffix !== "") {
|
|
1408
|
-
index = parseInt(match.groups.suffix, 10);
|
|
1409
|
-
}
|
|
1410
|
-
unique = match.groups.base;
|
|
1411
|
-
while (canvasNames.has(unique) || extraNames.includes(unique)) {
|
|
1412
|
-
unique = match.groups.base + index++;
|
|
1413
|
-
}
|
|
1414
|
-
return unique;
|
|
1415
|
-
}
|
|
1416
|
-
return { uniqueNodeName };
|
|
1417
|
-
}
|
|
1418
|
-
function useCanvasOperations({ router }) {
|
|
1419
|
-
const rootStore = useRootStore();
|
|
1420
|
-
const workflowsStore = useWorkflowsStore();
|
|
1421
|
-
const credentialsStore = useCredentialsStore();
|
|
1422
|
-
const historyStore = useHistoryStore();
|
|
1423
|
-
const uiStore = useUIStore();
|
|
1424
|
-
const ndvStore = useNDVStore();
|
|
1425
|
-
const nodeTypesStore = useNodeTypesStore();
|
|
1426
|
-
const canvasStore = useCanvasStore();
|
|
1427
|
-
const settingsStore = useSettingsStore();
|
|
1428
|
-
const tagsStore = useTagsStore();
|
|
1429
|
-
const nodeCreatorStore = useNodeCreatorStore();
|
|
1430
|
-
const executionsStore = useExecutionsStore();
|
|
1431
|
-
const projectsStore = useProjectsStore();
|
|
1432
|
-
const i18n = useI18n();
|
|
1433
|
-
const toast = useToast();
|
|
1434
|
-
const workflowHelpers = useWorkflowHelpers({ router });
|
|
1435
|
-
const nodeHelpers = useNodeHelpers();
|
|
1436
|
-
const telemetry = useTelemetry();
|
|
1437
|
-
const externalHooks = useExternalHooks();
|
|
1438
|
-
const clipboard = useClipboard();
|
|
1439
|
-
const { uniqueNodeName } = useUniqueNodeName();
|
|
1440
|
-
const lastClickPosition = ref([0, 0]);
|
|
1441
|
-
const preventOpeningNDV = !!localStorage.getItem("NodeView.preventOpeningNDV");
|
|
1442
|
-
const editableWorkflow = computed(() => workflowsStore.workflow);
|
|
1443
|
-
const editableWorkflowObject = computed(() => workflowsStore.getCurrentWorkflow());
|
|
1444
|
-
const triggerNodes = computed(() => {
|
|
1445
|
-
return workflowsStore.workflowTriggerNodes;
|
|
1446
|
-
});
|
|
1447
|
-
function tidyUp({ result, source, target }) {
|
|
1448
|
-
updateNodesPosition(
|
|
1449
|
-
result.nodes.map(({ id, x, y }) => ({ id, position: { x, y } })),
|
|
1450
|
-
{ trackBulk: true, trackHistory: true }
|
|
1451
|
-
);
|
|
1452
|
-
trackTidyUp({ result, source, target });
|
|
1453
|
-
}
|
|
1454
|
-
function trackTidyUp({ result, source, target }) {
|
|
1455
|
-
telemetry.track(
|
|
1456
|
-
"User tidied up canvas",
|
|
1457
|
-
{
|
|
1458
|
-
source,
|
|
1459
|
-
target,
|
|
1460
|
-
nodes_count: result.nodes.length
|
|
1461
|
-
},
|
|
1462
|
-
{ withPostHog: true }
|
|
1463
|
-
);
|
|
1464
|
-
}
|
|
1465
|
-
function updateNodesPosition(events, { trackHistory = false, trackBulk = true } = {}) {
|
|
1466
|
-
if (trackHistory && trackBulk) {
|
|
1467
|
-
historyStore.startRecordingUndo();
|
|
1468
|
-
}
|
|
1469
|
-
events.forEach(({ id, position }) => {
|
|
1470
|
-
updateNodePosition(id, position, { trackHistory });
|
|
1471
|
-
});
|
|
1472
|
-
if (trackHistory && trackBulk) {
|
|
1473
|
-
historyStore.stopRecordingUndo();
|
|
1474
|
-
}
|
|
1475
|
-
}
|
|
1476
|
-
function updateNodePosition(id, position, { trackHistory = false } = {}) {
|
|
1477
|
-
const node = workflowsStore.getNodeById(id);
|
|
1478
|
-
if (!node) {
|
|
1479
|
-
return;
|
|
1480
|
-
}
|
|
1481
|
-
const oldPosition = [...node.position];
|
|
1482
|
-
const newPosition = [position.x, position.y];
|
|
1483
|
-
workflowsStore.setNodePositionById(id, newPosition);
|
|
1484
|
-
if (trackHistory) {
|
|
1485
|
-
historyStore.pushCommandToUndo(
|
|
1486
|
-
new MoveNodeCommand(node.name, oldPosition, newPosition, Date.now())
|
|
1487
|
-
);
|
|
1488
|
-
}
|
|
1489
|
-
}
|
|
1490
|
-
function revertUpdateNodePosition(nodeName, position) {
|
|
1491
|
-
const node = workflowsStore.getNodeByName(nodeName);
|
|
1492
|
-
if (!node) {
|
|
1493
|
-
return;
|
|
1494
|
-
}
|
|
1495
|
-
updateNodePosition(node.id, position);
|
|
1496
|
-
}
|
|
1497
|
-
async function renameNode(currentName, newName, { trackHistory = false, trackBulk = true } = {}) {
|
|
1498
|
-
if (currentName === newName) {
|
|
1499
|
-
return;
|
|
1500
|
-
}
|
|
1501
|
-
if (trackHistory && trackBulk) {
|
|
1502
|
-
historyStore.startRecordingUndo();
|
|
1503
|
-
}
|
|
1504
|
-
newName = uniqueNodeName(newName);
|
|
1505
|
-
const workflow = workflowsStore.getCurrentWorkflow(true);
|
|
1506
|
-
workflow.renameNode(currentName, newName);
|
|
1507
|
-
if (trackHistory) {
|
|
1508
|
-
historyStore.pushCommandToUndo(new RenameNodeCommand(currentName, newName, Date.now()));
|
|
1509
|
-
}
|
|
1510
|
-
workflowsStore.renameNodeSelectedAndExecution({ old: currentName, new: newName });
|
|
1511
|
-
workflowsStore.setNodes(Object.values(workflow.nodes));
|
|
1512
|
-
workflowsStore.setConnections(workflow.connectionsBySourceNode);
|
|
1513
|
-
const isRenamingActiveNode = ndvStore.activeNodeName === currentName;
|
|
1514
|
-
if (isRenamingActiveNode) {
|
|
1515
|
-
ndvStore.activeNodeName = newName;
|
|
1516
|
-
}
|
|
1517
|
-
if (trackHistory && trackBulk) {
|
|
1518
|
-
historyStore.stopRecordingUndo();
|
|
1519
|
-
}
|
|
1520
|
-
}
|
|
1521
|
-
async function revertRenameNode(currentName, previousName) {
|
|
1522
|
-
await renameNode(currentName, previousName);
|
|
1523
|
-
}
|
|
1524
|
-
function connectAdjacentNodes(id, { trackHistory = false } = {}) {
|
|
1525
|
-
const node = workflowsStore.getNodeById(id);
|
|
1526
|
-
if (!node) {
|
|
1527
|
-
return;
|
|
1528
|
-
}
|
|
1529
|
-
const outputConnectionsByType = workflowsStore.outgoingConnectionsByNodeName(node.name);
|
|
1530
|
-
const incomingConnectionsByType = workflowsStore.incomingConnectionsByNodeName(node.name);
|
|
1531
|
-
for (const [type, incomingConnectionsByInputIndex] of Object.entries(
|
|
1532
|
-
incomingConnectionsByType
|
|
1533
|
-
)) {
|
|
1534
|
-
for (const incomingConnection of incomingConnectionsByInputIndex.at(0) ?? []) {
|
|
1535
|
-
const incomingNodeId = workflowsStore.getNodeByName(incomingConnection.node)?.id;
|
|
1536
|
-
if (!incomingNodeId) continue;
|
|
1537
|
-
for (const outgoingConnection of outputConnectionsByType[type]?.at(0) ?? []) {
|
|
1538
|
-
const outgoingNodeId = workflowsStore.getNodeByName(outgoingConnection.node)?.id;
|
|
1539
|
-
if (!outgoingNodeId) continue;
|
|
1540
|
-
if (trackHistory) {
|
|
1541
|
-
historyStore.pushCommandToUndo(
|
|
1542
|
-
new AddConnectionCommand(
|
|
1543
|
-
[
|
|
1544
|
-
{
|
|
1545
|
-
node: incomingConnection.node,
|
|
1546
|
-
type,
|
|
1547
|
-
index: incomingConnection.index
|
|
1548
|
-
},
|
|
1549
|
-
{
|
|
1550
|
-
node: outgoingConnection.node,
|
|
1551
|
-
type,
|
|
1552
|
-
index: outgoingConnection.index
|
|
1553
|
-
}
|
|
1554
|
-
],
|
|
1555
|
-
Date.now()
|
|
1556
|
-
)
|
|
1557
|
-
);
|
|
1558
|
-
}
|
|
1559
|
-
createConnection({
|
|
1560
|
-
source: incomingNodeId,
|
|
1561
|
-
sourceHandle: createCanvasConnectionHandleString({
|
|
1562
|
-
mode: CanvasConnectionMode.Output,
|
|
1563
|
-
type,
|
|
1564
|
-
index: incomingConnection.index
|
|
1565
|
-
}),
|
|
1566
|
-
target: outgoingNodeId,
|
|
1567
|
-
targetHandle: createCanvasConnectionHandleString({
|
|
1568
|
-
mode: CanvasConnectionMode.Input,
|
|
1569
|
-
type,
|
|
1570
|
-
index: outgoingConnection.index
|
|
1571
|
-
})
|
|
1572
|
-
});
|
|
1573
|
-
}
|
|
1574
|
-
}
|
|
1575
|
-
}
|
|
1576
|
-
}
|
|
1577
|
-
function deleteNode(id, { trackHistory = false, trackBulk = true } = {}) {
|
|
1578
|
-
const node = workflowsStore.getNodeById(id);
|
|
1579
|
-
if (!node) {
|
|
1580
|
-
return;
|
|
1581
|
-
}
|
|
1582
|
-
if (trackHistory && trackBulk) {
|
|
1583
|
-
historyStore.startRecordingUndo();
|
|
1584
|
-
}
|
|
1585
|
-
if (uiStore.lastInteractedWithNodeId === id) {
|
|
1586
|
-
uiStore.lastInteractedWithNodeId = void 0;
|
|
1587
|
-
}
|
|
1588
|
-
connectAdjacentNodes(id, { trackHistory });
|
|
1589
|
-
deleteConnectionsByNodeId(id, { trackHistory, trackBulk: false });
|
|
1590
|
-
workflowsStore.removeNodeExecutionDataById(id);
|
|
1591
|
-
workflowsStore.removeNodeById(id);
|
|
1592
|
-
if (trackHistory) {
|
|
1593
|
-
historyStore.pushCommandToUndo(new RemoveNodeCommand(node, Date.now()));
|
|
1594
|
-
if (trackBulk) {
|
|
1595
|
-
historyStore.stopRecordingUndo();
|
|
1596
|
-
}
|
|
1597
|
-
}
|
|
1598
|
-
trackDeleteNode(id);
|
|
1599
|
-
}
|
|
1600
|
-
function deleteNodes(ids, { trackHistory = true, trackBulk = true } = {}) {
|
|
1601
|
-
if (trackHistory && trackBulk) {
|
|
1602
|
-
historyStore.startRecordingUndo();
|
|
1603
|
-
}
|
|
1604
|
-
ids.forEach((id) => deleteNode(id, { trackHistory, trackBulk: false }));
|
|
1605
|
-
if (trackHistory && trackBulk) {
|
|
1606
|
-
historyStore.stopRecordingUndo();
|
|
1607
|
-
}
|
|
1608
|
-
}
|
|
1609
|
-
function revertDeleteNode(node) {
|
|
1610
|
-
workflowsStore.addNode(node);
|
|
1611
|
-
}
|
|
1612
|
-
function trackDeleteNode(id) {
|
|
1613
|
-
const node = workflowsStore.getNodeById(id);
|
|
1614
|
-
if (!node) {
|
|
1615
|
-
return;
|
|
1616
|
-
}
|
|
1617
|
-
if (node.type === STICKY_NODE_TYPE) {
|
|
1618
|
-
telemetry.track("User deleted workflow note", {
|
|
1619
|
-
workflow_id: workflowsStore.workflowId
|
|
1620
|
-
});
|
|
1621
|
-
} else {
|
|
1622
|
-
void externalHooks.run("node.deleteNode", { node });
|
|
1623
|
-
telemetry.track("User deleted node", {
|
|
1624
|
-
node_type: node.type,
|
|
1625
|
-
workflow_id: workflowsStore.workflowId
|
|
1626
|
-
});
|
|
1627
|
-
}
|
|
1628
|
-
}
|
|
1629
|
-
function setNodeActive(id) {
|
|
1630
|
-
const node = workflowsStore.getNodeById(id);
|
|
1631
|
-
if (!node) {
|
|
1632
|
-
return;
|
|
1633
|
-
}
|
|
1634
|
-
workflowsStore.setNodePristine(node.name, false);
|
|
1635
|
-
setNodeActiveByName(node.name);
|
|
1636
|
-
}
|
|
1637
|
-
function setNodeActiveByName(name) {
|
|
1638
|
-
ndvStore.activeNodeName = name;
|
|
1639
|
-
}
|
|
1640
|
-
function clearNodeActive() {
|
|
1641
|
-
ndvStore.activeNodeName = null;
|
|
1642
|
-
}
|
|
1643
|
-
function setNodeParameters(id, parameters) {
|
|
1644
|
-
const node = workflowsStore.getNodeById(id);
|
|
1645
|
-
if (!node) {
|
|
1646
|
-
return;
|
|
1647
|
-
}
|
|
1648
|
-
workflowsStore.setNodeParameters(
|
|
1649
|
-
{
|
|
1650
|
-
name: node.name,
|
|
1651
|
-
value: parameters
|
|
1652
|
-
},
|
|
1653
|
-
true
|
|
1654
|
-
);
|
|
1655
|
-
}
|
|
1656
|
-
function setNodeSelected(id) {
|
|
1657
|
-
if (!id) {
|
|
1658
|
-
uiStore.lastInteractedWithNodeId = void 0;
|
|
1659
|
-
uiStore.lastSelectedNode = "";
|
|
1660
|
-
return;
|
|
1661
|
-
}
|
|
1662
|
-
const node = workflowsStore.getNodeById(id);
|
|
1663
|
-
if (!node) {
|
|
1664
|
-
return;
|
|
1665
|
-
}
|
|
1666
|
-
uiStore.lastInteractedWithNodeId = id;
|
|
1667
|
-
uiStore.lastSelectedNode = node.name;
|
|
1668
|
-
}
|
|
1669
|
-
function toggleNodesDisabled(ids, { trackHistory = true, trackBulk = true } = {}) {
|
|
1670
|
-
if (trackHistory && trackBulk) {
|
|
1671
|
-
historyStore.startRecordingUndo();
|
|
1672
|
-
}
|
|
1673
|
-
const nodes = workflowsStore.getNodesByIds(ids);
|
|
1674
|
-
nodeHelpers.disableNodes(nodes, { trackHistory, trackBulk: false });
|
|
1675
|
-
if (trackHistory && trackBulk) {
|
|
1676
|
-
historyStore.stopRecordingUndo();
|
|
1677
|
-
}
|
|
1678
|
-
}
|
|
1679
|
-
function revertToggleNodeDisabled(nodeName) {
|
|
1680
|
-
const node = workflowsStore.getNodeByName(nodeName);
|
|
1681
|
-
if (node) {
|
|
1682
|
-
nodeHelpers.disableNodes([node]);
|
|
1683
|
-
}
|
|
1684
|
-
}
|
|
1685
|
-
function toggleNodesPinned(ids, source, { trackHistory = true, trackBulk = true } = {}) {
|
|
1686
|
-
if (trackHistory && trackBulk) {
|
|
1687
|
-
historyStore.startRecordingUndo();
|
|
1688
|
-
}
|
|
1689
|
-
const nodes = workflowsStore.getNodesByIds(ids);
|
|
1690
|
-
const nextStatePinned = nodes.some((node) => !workflowsStore.pinDataByNodeName(node.name));
|
|
1691
|
-
for (const node of nodes) {
|
|
1692
|
-
const pinnedDataForNode = usePinnedData(node);
|
|
1693
|
-
if (nextStatePinned) {
|
|
1694
|
-
const dataToPin = useDataSchema().getInputDataWithPinned(node);
|
|
1695
|
-
if (dataToPin.length !== 0) {
|
|
1696
|
-
pinnedDataForNode.setData(dataToPin, source);
|
|
1697
|
-
}
|
|
1698
|
-
} else {
|
|
1699
|
-
pinnedDataForNode.unsetData(source);
|
|
1700
|
-
}
|
|
1701
|
-
}
|
|
1702
|
-
if (trackHistory && trackBulk) {
|
|
1703
|
-
historyStore.stopRecordingUndo();
|
|
1704
|
-
}
|
|
1705
|
-
}
|
|
1706
|
-
function requireNodeTypeDescription(type, version) {
|
|
1707
|
-
return nodeTypesStore.getNodeType(type, version) ?? {
|
|
1708
|
-
properties: [],
|
|
1709
|
-
displayName: type,
|
|
1710
|
-
name: type,
|
|
1711
|
-
group: [],
|
|
1712
|
-
description: "",
|
|
1713
|
-
version: version ?? 1,
|
|
1714
|
-
defaults: {},
|
|
1715
|
-
inputs: [],
|
|
1716
|
-
outputs: []
|
|
1717
|
-
};
|
|
1718
|
-
}
|
|
1719
|
-
async function addNodes(nodes, options = {}) {
|
|
1720
|
-
let insertPosition = options.position;
|
|
1721
|
-
let lastAddedNode;
|
|
1722
|
-
const addedNodes = [];
|
|
1723
|
-
const nodesWithTypeVersion = nodes.map((node) => {
|
|
1724
|
-
const typeVersion = node.typeVersion ?? resolveNodeVersion(requireNodeTypeDescription(node.type));
|
|
1725
|
-
return {
|
|
1726
|
-
...node,
|
|
1727
|
-
typeVersion
|
|
1728
|
-
};
|
|
1729
|
-
});
|
|
1730
|
-
await loadNodeTypesProperties(nodesWithTypeVersion);
|
|
1731
|
-
if (options.trackHistory && options.trackBulk) {
|
|
1732
|
-
historyStore.startRecordingUndo();
|
|
1733
|
-
}
|
|
1734
|
-
for (const nodeAddData of nodesWithTypeVersion) {
|
|
1735
|
-
const { isAutoAdd, openDetail: openNDV, ...node } = nodeAddData;
|
|
1736
|
-
const position = node.position ?? insertPosition;
|
|
1737
|
-
const nodeTypeDescription = requireNodeTypeDescription(node.type, node.typeVersion);
|
|
1738
|
-
try {
|
|
1739
|
-
const newNode = addNode(
|
|
1740
|
-
{
|
|
1741
|
-
...node,
|
|
1742
|
-
position
|
|
1743
|
-
},
|
|
1744
|
-
nodeTypeDescription,
|
|
1745
|
-
{
|
|
1746
|
-
...options,
|
|
1747
|
-
openNDV,
|
|
1748
|
-
isAutoAdd
|
|
1749
|
-
}
|
|
1750
|
-
);
|
|
1751
|
-
lastAddedNode = newNode;
|
|
1752
|
-
addedNodes.push(newNode);
|
|
1753
|
-
} catch (error) {
|
|
1754
|
-
toast.showError(error, i18n.baseText("error"));
|
|
1755
|
-
console.error(error);
|
|
1756
|
-
continue;
|
|
1757
|
-
}
|
|
1758
|
-
insertPosition = [
|
|
1759
|
-
lastAddedNode.position[0] + NODE_SIZE * 2 + GRID_SIZE,
|
|
1760
|
-
lastAddedNode.position[1]
|
|
1761
|
-
];
|
|
1762
|
-
}
|
|
1763
|
-
if (lastAddedNode) {
|
|
1764
|
-
updatePositionForNodeWithMultipleInputs(lastAddedNode);
|
|
1765
|
-
}
|
|
1766
|
-
if (options.trackHistory && options.trackBulk) {
|
|
1767
|
-
historyStore.stopRecordingUndo();
|
|
1768
|
-
}
|
|
1769
|
-
if (!options.keepPristine) {
|
|
1770
|
-
uiStore.stateIsDirty = true;
|
|
1771
|
-
}
|
|
1772
|
-
return addedNodes;
|
|
1773
|
-
}
|
|
1774
|
-
function updatePositionForNodeWithMultipleInputs(node) {
|
|
1775
|
-
const inputNodes = editableWorkflowObject.value.getParentNodesByDepth(node.name, 1);
|
|
1776
|
-
if (inputNodes.length > 1) {
|
|
1777
|
-
inputNodes.slice(1).forEach((inputNode, index) => {
|
|
1778
|
-
const nodeUi = workflowsStore.getNodeByName(inputNode.name);
|
|
1779
|
-
if (!nodeUi) return;
|
|
1780
|
-
updateNodePosition(nodeUi.id, {
|
|
1781
|
-
x: nodeUi.position[0],
|
|
1782
|
-
y: nodeUi.position[1] + 100 * (index + 1)
|
|
1783
|
-
});
|
|
1784
|
-
});
|
|
1785
|
-
}
|
|
1786
|
-
}
|
|
1787
|
-
function checkMaxNodesOfTypeReached(nodeTypeDescription) {
|
|
1788
|
-
if (nodeTypeDescription.maxNodes !== void 0 && workflowHelpers.getNodeTypeCount(nodeTypeDescription.name) >= nodeTypeDescription.maxNodes) {
|
|
1789
|
-
throw new Error(
|
|
1790
|
-
i18n.baseText("nodeView.showMessage.showMaxNodeTypeError.message", {
|
|
1791
|
-
adjustToNumber: nodeTypeDescription.maxNodes,
|
|
1792
|
-
interpolate: { nodeTypeDataDisplayName: nodeTypeDescription.displayName }
|
|
1793
|
-
})
|
|
1794
|
-
);
|
|
1795
|
-
}
|
|
1796
|
-
}
|
|
1797
|
-
function addNode(node, nodeTypeDescription, options = {}) {
|
|
1798
|
-
checkMaxNodesOfTypeReached(nodeTypeDescription);
|
|
1799
|
-
const nodeData = resolveNodeData(node, nodeTypeDescription);
|
|
1800
|
-
if (!nodeData) {
|
|
1801
|
-
throw new Error(i18n.baseText("nodeViewV2.showError.failedToCreateNode"));
|
|
1802
|
-
}
|
|
1803
|
-
workflowsStore.addNode(nodeData);
|
|
1804
|
-
if (options.trackHistory) {
|
|
1805
|
-
historyStore.pushCommandToUndo(new AddNodeCommand(nodeData, Date.now()));
|
|
1806
|
-
}
|
|
1807
|
-
if (!options.isAutoAdd) {
|
|
1808
|
-
createConnectionToLastInteractedWithNode(nodeData, options);
|
|
1809
|
-
}
|
|
1810
|
-
void nextTick(() => {
|
|
1811
|
-
if (!options.keepPristine) {
|
|
1812
|
-
uiStore.stateIsDirty = true;
|
|
1813
|
-
}
|
|
1814
|
-
workflowsStore.setNodePristine(nodeData.name, true);
|
|
1815
|
-
nodeHelpers.matchCredentials(nodeData);
|
|
1816
|
-
nodeHelpers.updateNodeParameterIssues(nodeData);
|
|
1817
|
-
nodeHelpers.updateNodeCredentialIssues(nodeData);
|
|
1818
|
-
nodeHelpers.updateNodeInputIssues(nodeData);
|
|
1819
|
-
if (options.telemetry) {
|
|
1820
|
-
trackAddNode(nodeData, options);
|
|
1821
|
-
}
|
|
1822
|
-
if (nodeData.type !== STICKY_NODE_TYPE) {
|
|
1823
|
-
void externalHooks.run("nodeView.addNodeButton", { nodeTypeName: nodeData.type });
|
|
1824
|
-
if (options.openNDV && !preventOpeningNDV) {
|
|
1825
|
-
ndvStore.setActiveNodeName(nodeData.name);
|
|
1826
|
-
}
|
|
1827
|
-
}
|
|
1828
|
-
});
|
|
1829
|
-
return nodeData;
|
|
1830
|
-
}
|
|
1831
|
-
async function revertAddNode(nodeName) {
|
|
1832
|
-
const node = workflowsStore.getNodeByName(nodeName);
|
|
1833
|
-
if (!node) {
|
|
1834
|
-
return;
|
|
1835
|
-
}
|
|
1836
|
-
deleteNode(node.id);
|
|
1837
|
-
}
|
|
1838
|
-
function createConnectionToLastInteractedWithNode(node, options = {}) {
|
|
1839
|
-
const lastInteractedWithNode = uiStore.lastInteractedWithNode;
|
|
1840
|
-
if (!lastInteractedWithNode) {
|
|
1841
|
-
return;
|
|
1842
|
-
}
|
|
1843
|
-
const lastInteractedWithNodeId = lastInteractedWithNode.id;
|
|
1844
|
-
const lastInteractedWithNodeConnection = uiStore.lastInteractedWithNodeConnection;
|
|
1845
|
-
const lastInteractedWithNodeHandle = uiStore.lastInteractedWithNodeHandle;
|
|
1846
|
-
if (lastInteractedWithNodeHandle) {
|
|
1847
|
-
const { type: connectionType, mode } = parseCanvasConnectionHandleString(
|
|
1848
|
-
lastInteractedWithNodeHandle
|
|
1849
|
-
);
|
|
1850
|
-
const nodeId = node.id;
|
|
1851
|
-
const nodeHandle = createCanvasConnectionHandleString({
|
|
1852
|
-
mode: CanvasConnectionMode.Input,
|
|
1853
|
-
type: connectionType,
|
|
1854
|
-
index: 0
|
|
1855
|
-
});
|
|
1856
|
-
if (mode === CanvasConnectionMode.Input) {
|
|
1857
|
-
createConnection({
|
|
1858
|
-
source: nodeId,
|
|
1859
|
-
sourceHandle: nodeHandle,
|
|
1860
|
-
target: lastInteractedWithNodeId,
|
|
1861
|
-
targetHandle: lastInteractedWithNodeHandle
|
|
1862
|
-
});
|
|
1863
|
-
} else {
|
|
1864
|
-
createConnection({
|
|
1865
|
-
source: lastInteractedWithNodeId,
|
|
1866
|
-
sourceHandle: lastInteractedWithNodeHandle,
|
|
1867
|
-
target: nodeId,
|
|
1868
|
-
targetHandle: nodeHandle
|
|
1869
|
-
});
|
|
1870
|
-
}
|
|
1871
|
-
} else {
|
|
1872
|
-
createConnection({
|
|
1873
|
-
source: lastInteractedWithNodeId,
|
|
1874
|
-
sourceHandle: createCanvasConnectionHandleString({
|
|
1875
|
-
mode: CanvasConnectionMode.Output,
|
|
1876
|
-
type: NodeConnectionTypes.Main,
|
|
1877
|
-
index: 0
|
|
1878
|
-
}),
|
|
1879
|
-
target: node.id,
|
|
1880
|
-
targetHandle: createCanvasConnectionHandleString({
|
|
1881
|
-
mode: CanvasConnectionMode.Input,
|
|
1882
|
-
type: NodeConnectionTypes.Main,
|
|
1883
|
-
index: 0
|
|
1884
|
-
})
|
|
1885
|
-
});
|
|
1886
|
-
}
|
|
1887
|
-
if (lastInteractedWithNodeConnection) {
|
|
1888
|
-
deleteConnection(lastInteractedWithNodeConnection, { trackHistory: options.trackHistory });
|
|
1889
|
-
const targetNode = workflowsStore.getNodeById(lastInteractedWithNodeConnection.target);
|
|
1890
|
-
if (targetNode) {
|
|
1891
|
-
createConnection({
|
|
1892
|
-
source: node.id,
|
|
1893
|
-
sourceHandle: createCanvasConnectionHandleString({
|
|
1894
|
-
mode: CanvasConnectionMode.Input,
|
|
1895
|
-
type: NodeConnectionTypes.Main,
|
|
1896
|
-
index: 0
|
|
1897
|
-
}),
|
|
1898
|
-
target: lastInteractedWithNodeConnection.target,
|
|
1899
|
-
targetHandle: lastInteractedWithNodeConnection.targetHandle
|
|
1900
|
-
});
|
|
1901
|
-
}
|
|
1902
|
-
}
|
|
1903
|
-
}
|
|
1904
|
-
function trackAddNode(nodeData, options) {
|
|
1905
|
-
switch (nodeData.type) {
|
|
1906
|
-
case STICKY_NODE_TYPE:
|
|
1907
|
-
trackAddStickyNoteNode();
|
|
1908
|
-
break;
|
|
1909
|
-
default:
|
|
1910
|
-
trackAddDefaultNode(nodeData, options);
|
|
1911
|
-
}
|
|
1912
|
-
}
|
|
1913
|
-
function trackAddStickyNoteNode() {
|
|
1914
|
-
telemetry.track("User inserted workflow note", {
|
|
1915
|
-
workflow_id: workflowsStore.workflowId
|
|
1916
|
-
});
|
|
1917
|
-
}
|
|
1918
|
-
function trackAddDefaultNode(nodeData, options) {
|
|
1919
|
-
nodeCreatorStore.onNodeAddedToCanvas({
|
|
1920
|
-
node_id: nodeData.id,
|
|
1921
|
-
node_type: nodeData.type,
|
|
1922
|
-
node_version: nodeData.typeVersion,
|
|
1923
|
-
is_auto_add: options.isAutoAdd,
|
|
1924
|
-
workflow_id: workflowsStore.workflowId,
|
|
1925
|
-
drag_and_drop: options.dragAndDrop,
|
|
1926
|
-
input_node_type: uiStore.lastInteractedWithNode ? uiStore.lastInteractedWithNode.type : void 0
|
|
1927
|
-
});
|
|
1928
|
-
}
|
|
1929
|
-
function resolveNodeData(node, nodeTypeDescription) {
|
|
1930
|
-
const id = node.id ?? nodeHelpers.assignNodeId(node);
|
|
1931
|
-
const name = node.name ?? nodeTypeDescription.defaults.name;
|
|
1932
|
-
const type = nodeTypeDescription.name;
|
|
1933
|
-
const typeVersion = node.typeVersion;
|
|
1934
|
-
const position = resolveNodePosition(node, nodeTypeDescription);
|
|
1935
|
-
const disabled = node.disabled ?? false;
|
|
1936
|
-
const parameters = node.parameters ?? {};
|
|
1937
|
-
const nodeData = {
|
|
1938
|
-
...node,
|
|
1939
|
-
id,
|
|
1940
|
-
name,
|
|
1941
|
-
type,
|
|
1942
|
-
typeVersion,
|
|
1943
|
-
position,
|
|
1944
|
-
disabled,
|
|
1945
|
-
parameters
|
|
1946
|
-
};
|
|
1947
|
-
resolveNodeName(nodeData);
|
|
1948
|
-
resolveNodeParameters(nodeData, nodeTypeDescription);
|
|
1949
|
-
resolveNodeWebhook(nodeData, nodeTypeDescription);
|
|
1950
|
-
return nodeData;
|
|
1951
|
-
}
|
|
1952
|
-
async function loadNodeTypesProperties(nodes) {
|
|
1953
|
-
const allNodeTypeDescriptions = nodeTypesStore.allNodeTypes;
|
|
1954
|
-
const nodesToBeFetched = [];
|
|
1955
|
-
allNodeTypeDescriptions.forEach((nodeTypeDescription) => {
|
|
1956
|
-
const nodeVersions = Array.isArray(nodeTypeDescription.version) ? nodeTypeDescription.version : [nodeTypeDescription.version];
|
|
1957
|
-
if (!!nodes.find(
|
|
1958
|
-
(n) => n.type === nodeTypeDescription.name && nodeVersions.includes(n.typeVersion)
|
|
1959
|
-
) && !nodeTypeDescription.hasOwnProperty("properties")) {
|
|
1960
|
-
nodesToBeFetched.push({
|
|
1961
|
-
name: nodeTypeDescription.name,
|
|
1962
|
-
version: Array.isArray(nodeTypeDescription.version) ? nodeTypeDescription.version.slice(-1)[0] : nodeTypeDescription.version
|
|
1963
|
-
});
|
|
1964
|
-
}
|
|
1965
|
-
});
|
|
1966
|
-
if (nodesToBeFetched.length > 0) {
|
|
1967
|
-
await nodeTypesStore.getNodesInformation(nodesToBeFetched);
|
|
1968
|
-
}
|
|
1969
|
-
}
|
|
1970
|
-
function resolveNodeVersion(nodeTypeDescription) {
|
|
1971
|
-
let nodeVersion = nodeTypeDescription.defaultVersion;
|
|
1972
|
-
if (typeof nodeVersion === "undefined") {
|
|
1973
|
-
nodeVersion = Array.isArray(nodeTypeDescription.version) ? nodeTypeDescription.version.slice(-1)[0] : nodeTypeDescription.version;
|
|
1974
|
-
}
|
|
1975
|
-
return nodeVersion;
|
|
1976
|
-
}
|
|
1977
|
-
function resolveNodeParameters(node, nodeTypeDescription) {
|
|
1978
|
-
const nodeParameters = getNodeParameters(
|
|
1979
|
-
nodeTypeDescription?.properties ?? [],
|
|
1980
|
-
node.parameters,
|
|
1981
|
-
true,
|
|
1982
|
-
false,
|
|
1983
|
-
node,
|
|
1984
|
-
nodeTypeDescription
|
|
1985
|
-
);
|
|
1986
|
-
node.parameters = nodeParameters ?? {};
|
|
1987
|
-
}
|
|
1988
|
-
function resolveNodePosition(node, nodeTypeDescription) {
|
|
1989
|
-
let position = node.position;
|
|
1990
|
-
let pushOffsets = [40, 40];
|
|
1991
|
-
if (position) {
|
|
1992
|
-
return getNewNodePosition(workflowsStore.allNodes, position, pushOffsets);
|
|
1993
|
-
}
|
|
1994
|
-
const lastInteractedWithNode = uiStore.lastInteractedWithNode;
|
|
1995
|
-
const lastInteractedWithNodeConnection = uiStore.lastInteractedWithNodeConnection;
|
|
1996
|
-
const lastInteractedWithNodeHandle = uiStore.lastInteractedWithNodeHandle;
|
|
1997
|
-
const { type: connectionType, index: connectionIndex } = parseCanvasConnectionHandleString(
|
|
1998
|
-
lastInteractedWithNodeHandle ?? lastInteractedWithNodeConnection?.sourceHandle ?? ""
|
|
1999
|
-
);
|
|
2000
|
-
const nodeSize = connectionType === NodeConnectionTypes.Main ? DEFAULT_NODE_SIZE : CONFIGURATION_NODE_SIZE;
|
|
2001
|
-
if (lastInteractedWithNode) {
|
|
2002
|
-
const lastInteractedWithNodeTypeDescription = nodeTypesStore.getNodeType(
|
|
2003
|
-
lastInteractedWithNode.type,
|
|
2004
|
-
lastInteractedWithNode.typeVersion
|
|
2005
|
-
);
|
|
2006
|
-
const lastInteractedWithNodeObject = editableWorkflowObject.value.getNode(
|
|
2007
|
-
lastInteractedWithNode.name
|
|
2008
|
-
);
|
|
2009
|
-
const newNodeInsertPosition = uiStore.lastCancelledConnectionPosition;
|
|
2010
|
-
if (newNodeInsertPosition) {
|
|
2011
|
-
const xOffset = connectionType === NodeConnectionTypes.Main ? 0 : -nodeSize[0] / 2;
|
|
2012
|
-
const yOffset = connectionType === NodeConnectionTypes.Main ? -nodeSize[1] / 2 : 0;
|
|
2013
|
-
position = [newNodeInsertPosition[0] + xOffset, newNodeInsertPosition[1] + yOffset];
|
|
2014
|
-
uiStore.lastCancelledConnectionPosition = void 0;
|
|
2015
|
-
} else if (lastInteractedWithNodeTypeDescription && lastInteractedWithNodeObject) {
|
|
2016
|
-
const lastInteractedWithNodeInputs = getNodeInputs(
|
|
2017
|
-
editableWorkflowObject.value,
|
|
2018
|
-
lastInteractedWithNodeObject,
|
|
2019
|
-
lastInteractedWithNodeTypeDescription
|
|
2020
|
-
);
|
|
2021
|
-
const lastInteractedWithNodeInputTypes = getConnectionTypes(
|
|
2022
|
-
lastInteractedWithNodeInputs
|
|
2023
|
-
);
|
|
2024
|
-
const lastInteractedWithNodeScopedInputTypes = (lastInteractedWithNodeInputTypes || []).filter((input) => input !== NodeConnectionTypes.Main);
|
|
2025
|
-
const lastInteractedWithNodeOutputs = getNodeOutputs(
|
|
2026
|
-
editableWorkflowObject.value,
|
|
2027
|
-
lastInteractedWithNodeObject,
|
|
2028
|
-
lastInteractedWithNodeTypeDescription
|
|
2029
|
-
);
|
|
2030
|
-
const lastInteractedWithNodeOutputTypes = getConnectionTypes(
|
|
2031
|
-
lastInteractedWithNodeOutputs
|
|
2032
|
-
);
|
|
2033
|
-
const lastInteractedWithNodeMainOutputs = lastInteractedWithNodeOutputTypes.filter(
|
|
2034
|
-
(output) => output === NodeConnectionTypes.Main
|
|
2035
|
-
);
|
|
2036
|
-
let yOffset = 0;
|
|
2037
|
-
if (lastInteractedWithNodeConnection) {
|
|
2038
|
-
shiftDownstreamNodesPosition(lastInteractedWithNode.name, PUSH_NODES_OFFSET, {
|
|
2039
|
-
trackHistory: true
|
|
2040
|
-
});
|
|
2041
|
-
}
|
|
2042
|
-
if (lastInteractedWithNodeMainOutputs.length > 1) {
|
|
2043
|
-
const yOffsetValues = generateOffsets(
|
|
2044
|
-
lastInteractedWithNodeMainOutputs.length,
|
|
2045
|
-
NODE_SIZE,
|
|
2046
|
-
GRID_SIZE
|
|
2047
|
-
);
|
|
2048
|
-
yOffset = yOffsetValues[connectionIndex];
|
|
2049
|
-
}
|
|
2050
|
-
let outputs = [];
|
|
2051
|
-
try {
|
|
2052
|
-
outputs = getNodeOutputs(
|
|
2053
|
-
editableWorkflowObject.value,
|
|
2054
|
-
node,
|
|
2055
|
-
nodeTypeDescription
|
|
2056
|
-
);
|
|
2057
|
-
} catch (e) {
|
|
2058
|
-
}
|
|
2059
|
-
const outputTypes = getConnectionTypes(outputs);
|
|
2060
|
-
pushOffsets = [100, 0];
|
|
2061
|
-
if (outputTypes.length > 0 && outputTypes.every((outputName) => outputName !== NodeConnectionTypes.Main)) {
|
|
2062
|
-
const scopedConnectionIndex = lastInteractedWithNodeScopedInputTypes.findIndex(
|
|
2063
|
-
(inputType) => outputs[0] === inputType
|
|
2064
|
-
);
|
|
2065
|
-
const lastInteractedWithNodeWidthDivisions = Math.max(
|
|
2066
|
-
lastInteractedWithNodeScopedInputTypes.length + 1,
|
|
2067
|
-
1
|
|
2068
|
-
);
|
|
2069
|
-
position = [
|
|
2070
|
-
lastInteractedWithNode.position[0] + CONFIGURABLE_NODE_SIZE[0] / lastInteractedWithNodeWidthDivisions * (scopedConnectionIndex + 1) - nodeSize[0] / 2,
|
|
2071
|
-
lastInteractedWithNode.position[1] + PUSH_NODES_OFFSET
|
|
2072
|
-
];
|
|
2073
|
-
} else {
|
|
2074
|
-
let pushOffset = PUSH_NODES_OFFSET;
|
|
2075
|
-
if (!!lastInteractedWithNodeInputTypes.find((input) => input !== NodeConnectionTypes.Main)) {
|
|
2076
|
-
pushOffset += 140;
|
|
2077
|
-
}
|
|
2078
|
-
position = [
|
|
2079
|
-
lastInteractedWithNode.position[0] + pushOffset,
|
|
2080
|
-
lastInteractedWithNode.position[1] + yOffset
|
|
2081
|
-
];
|
|
2082
|
-
}
|
|
2083
|
-
}
|
|
2084
|
-
}
|
|
2085
|
-
if (!position) {
|
|
2086
|
-
if (nodeTypesStore.isTriggerNode(node.type) && triggerNodes.value.length === 0) {
|
|
2087
|
-
position = [0, 0];
|
|
2088
|
-
} else {
|
|
2089
|
-
position = lastClickPosition.value;
|
|
2090
|
-
}
|
|
2091
|
-
}
|
|
2092
|
-
return getNewNodePosition(workflowsStore.allNodes, position, pushOffsets);
|
|
2093
|
-
}
|
|
2094
|
-
function resolveNodeName(node) {
|
|
2095
|
-
const localizedName = i18n.localizeNodeName(node.name, node.type);
|
|
2096
|
-
node.name = uniqueNodeName(localizedName);
|
|
2097
|
-
}
|
|
2098
|
-
function resolveNodeWebhook(node, nodeTypeDescription) {
|
|
2099
|
-
if (nodeTypeDescription.webhooks?.length && !node.webhookId) {
|
|
2100
|
-
nodeHelpers.assignWebhookId(node);
|
|
2101
|
-
}
|
|
2102
|
-
if ([WEBHOOK_NODE_TYPE, FORM_TRIGGER_NODE_TYPE, MCP_TRIGGER_NODE_TYPE].includes(node.type) && node.parameters.path === "") {
|
|
2103
|
-
node.parameters.path = node.webhookId;
|
|
2104
|
-
}
|
|
2105
|
-
}
|
|
2106
|
-
function shiftDownstreamNodesPosition(sourceNodeName, margin, { trackHistory = false }) {
|
|
2107
|
-
const sourceNode = workflowsStore.nodesByName[sourceNodeName];
|
|
2108
|
-
const checkNodes = workflowHelpers.getConnectedNodes(
|
|
2109
|
-
"downstream",
|
|
2110
|
-
editableWorkflowObject.value,
|
|
2111
|
-
sourceNodeName
|
|
2112
|
-
);
|
|
2113
|
-
for (const nodeName of checkNodes) {
|
|
2114
|
-
const node = workflowsStore.nodesByName[nodeName];
|
|
2115
|
-
if (node.position[0] < sourceNode.position[0]) {
|
|
2116
|
-
continue;
|
|
2117
|
-
}
|
|
2118
|
-
updateNodePosition(
|
|
2119
|
-
node.id,
|
|
2120
|
-
{
|
|
2121
|
-
x: node.position[0] + margin,
|
|
2122
|
-
y: node.position[1]
|
|
2123
|
-
},
|
|
2124
|
-
{ trackHistory }
|
|
2125
|
-
);
|
|
2126
|
-
}
|
|
2127
|
-
}
|
|
2128
|
-
function createConnection(connection, { trackHistory = false, keepPristine = false } = {}) {
|
|
2129
|
-
const sourceNode = workflowsStore.getNodeById(connection.source);
|
|
2130
|
-
const targetNode = workflowsStore.getNodeById(connection.target);
|
|
2131
|
-
if (!sourceNode || !targetNode) {
|
|
2132
|
-
return;
|
|
2133
|
-
}
|
|
2134
|
-
if (trackHistory) {
|
|
2135
|
-
historyStore.pushCommandToUndo(
|
|
2136
|
-
new AddConnectionCommand(
|
|
2137
|
-
mapCanvasConnectionToLegacyConnection(sourceNode, targetNode, connection),
|
|
2138
|
-
Date.now()
|
|
2139
|
-
)
|
|
2140
|
-
);
|
|
2141
|
-
}
|
|
2142
|
-
const mappedConnection = mapCanvasConnectionToLegacyConnection(
|
|
2143
|
-
sourceNode,
|
|
2144
|
-
targetNode,
|
|
2145
|
-
connection
|
|
2146
|
-
);
|
|
2147
|
-
if (!isConnectionAllowed(sourceNode, targetNode, mappedConnection[0], mappedConnection[1])) {
|
|
2148
|
-
return;
|
|
2149
|
-
}
|
|
2150
|
-
workflowsStore.addConnection({
|
|
2151
|
-
connection: mappedConnection
|
|
2152
|
-
});
|
|
2153
|
-
void nextTick(() => {
|
|
2154
|
-
nodeHelpers.updateNodeInputIssues(sourceNode);
|
|
2155
|
-
nodeHelpers.updateNodeInputIssues(targetNode);
|
|
2156
|
-
});
|
|
2157
|
-
if (!keepPristine) {
|
|
2158
|
-
uiStore.stateIsDirty = true;
|
|
2159
|
-
}
|
|
2160
|
-
}
|
|
2161
|
-
function revertCreateConnection(connection) {
|
|
2162
|
-
const sourceNodeName = connection[0].node;
|
|
2163
|
-
const sourceNode = workflowsStore.getNodeByName(sourceNodeName);
|
|
2164
|
-
const targetNodeName = connection[1].node;
|
|
2165
|
-
const targetNode = workflowsStore.getNodeByName(targetNodeName);
|
|
2166
|
-
if (!sourceNode || !targetNode) {
|
|
2167
|
-
return;
|
|
2168
|
-
}
|
|
2169
|
-
deleteConnection(mapLegacyConnectionToCanvasConnection(sourceNode, targetNode, connection));
|
|
2170
|
-
}
|
|
2171
|
-
function deleteConnectionsByNodeId(targetNodeId, { trackHistory = false, trackBulk = true } = {}) {
|
|
2172
|
-
const targetNode = workflowsStore.getNodeById(targetNodeId);
|
|
2173
|
-
if (!targetNode) {
|
|
2174
|
-
return;
|
|
2175
|
-
}
|
|
2176
|
-
if (trackHistory && trackBulk) {
|
|
2177
|
-
historyStore.startRecordingUndo();
|
|
2178
|
-
}
|
|
2179
|
-
const connections = workflowsStore.workflow.connections;
|
|
2180
|
-
for (const nodeName of Object.keys(connections)) {
|
|
2181
|
-
const node = workflowsStore.getNodeByName(nodeName);
|
|
2182
|
-
if (!node) {
|
|
2183
|
-
continue;
|
|
2184
|
-
}
|
|
2185
|
-
for (const type of Object.keys(connections[nodeName])) {
|
|
2186
|
-
for (const index of Object.keys(connections[nodeName][type])) {
|
|
2187
|
-
const connectionsToDelete = connections[nodeName][type][parseInt(index, 10)] ?? [];
|
|
2188
|
-
for (const connectionIndex of Object.keys(connectionsToDelete)) {
|
|
2189
|
-
const connectionData = connectionsToDelete[parseInt(connectionIndex, 10)];
|
|
2190
|
-
if (!connectionData) {
|
|
2191
|
-
continue;
|
|
2192
|
-
}
|
|
2193
|
-
const connectionDataNode = workflowsStore.getNodeByName(connectionData.node);
|
|
2194
|
-
if (connectionDataNode && (connectionDataNode.id === targetNode.id || node.name === targetNode.name)) {
|
|
2195
|
-
deleteConnection(
|
|
2196
|
-
{
|
|
2197
|
-
source: node.id,
|
|
2198
|
-
sourceHandle: createCanvasConnectionHandleString({
|
|
2199
|
-
mode: CanvasConnectionMode.Output,
|
|
2200
|
-
type,
|
|
2201
|
-
index: parseInt(index, 10)
|
|
2202
|
-
}),
|
|
2203
|
-
target: connectionDataNode.id,
|
|
2204
|
-
targetHandle: createCanvasConnectionHandleString({
|
|
2205
|
-
mode: CanvasConnectionMode.Input,
|
|
2206
|
-
type: connectionData.type,
|
|
2207
|
-
index: connectionData.index
|
|
2208
|
-
})
|
|
2209
|
-
},
|
|
2210
|
-
{ trackHistory, trackBulk: false }
|
|
2211
|
-
);
|
|
2212
|
-
}
|
|
2213
|
-
}
|
|
2214
|
-
}
|
|
2215
|
-
}
|
|
2216
|
-
}
|
|
2217
|
-
delete workflowsStore.workflow.connections[targetNode.name];
|
|
2218
|
-
if (trackHistory && trackBulk) {
|
|
2219
|
-
historyStore.stopRecordingUndo();
|
|
2220
|
-
}
|
|
2221
|
-
}
|
|
2222
|
-
function deleteConnection(connection, { trackHistory = false, trackBulk = true } = {}) {
|
|
2223
|
-
const sourceNode = workflowsStore.getNodeById(connection.source);
|
|
2224
|
-
const targetNode = workflowsStore.getNodeById(connection.target);
|
|
2225
|
-
if (!sourceNode || !targetNode) {
|
|
2226
|
-
return;
|
|
2227
|
-
}
|
|
2228
|
-
const mappedConnection = mapCanvasConnectionToLegacyConnection(
|
|
2229
|
-
sourceNode,
|
|
2230
|
-
targetNode,
|
|
2231
|
-
connection
|
|
2232
|
-
);
|
|
2233
|
-
if (trackHistory && trackBulk) {
|
|
2234
|
-
historyStore.startRecordingUndo();
|
|
2235
|
-
}
|
|
2236
|
-
workflowsStore.removeConnection({
|
|
2237
|
-
connection: mappedConnection
|
|
2238
|
-
});
|
|
2239
|
-
if (trackHistory) {
|
|
2240
|
-
historyStore.pushCommandToUndo(new RemoveConnectionCommand(mappedConnection, Date.now()));
|
|
2241
|
-
if (trackBulk) {
|
|
2242
|
-
historyStore.stopRecordingUndo();
|
|
2243
|
-
}
|
|
2244
|
-
}
|
|
2245
|
-
}
|
|
2246
|
-
function revertDeleteConnection(connection) {
|
|
2247
|
-
workflowsStore.addConnection({
|
|
2248
|
-
connection
|
|
2249
|
-
});
|
|
2250
|
-
}
|
|
2251
|
-
function revalidateNodeConnections(id, connectionMode) {
|
|
2252
|
-
const node = workflowsStore.getNodeById(id);
|
|
2253
|
-
const isInput = connectionMode === CanvasConnectionMode.Input;
|
|
2254
|
-
if (!node) {
|
|
2255
|
-
return;
|
|
2256
|
-
}
|
|
2257
|
-
const nodeType = nodeTypesStore.getNodeType(node.type, node.typeVersion);
|
|
2258
|
-
if (!nodeType) {
|
|
2259
|
-
return;
|
|
2260
|
-
}
|
|
2261
|
-
const connections = mapLegacyConnectionsToCanvasConnections(
|
|
2262
|
-
workflowsStore.workflow.connections,
|
|
2263
|
-
workflowsStore.workflow.nodes
|
|
2264
|
-
);
|
|
2265
|
-
connections.forEach((connection) => {
|
|
2266
|
-
const isRelevantConnection = isInput ? connection.target === id : connection.source === id;
|
|
2267
|
-
if (isRelevantConnection) {
|
|
2268
|
-
const otherNodeId = isInput ? connection.source : connection.target;
|
|
2269
|
-
const otherNode = workflowsStore.getNodeById(otherNodeId);
|
|
2270
|
-
if (!otherNode || !connection.data) {
|
|
2271
|
-
return;
|
|
2272
|
-
}
|
|
2273
|
-
const [firstNode, secondNode] = isInput ? [otherNode, node] : [node, otherNode];
|
|
2274
|
-
if (!isConnectionAllowed(
|
|
2275
|
-
firstNode,
|
|
2276
|
-
secondNode,
|
|
2277
|
-
connection.data.source,
|
|
2278
|
-
connection.data.target
|
|
2279
|
-
)) {
|
|
2280
|
-
void nextTick(() => deleteConnection(connection));
|
|
2281
|
-
}
|
|
2282
|
-
}
|
|
2283
|
-
});
|
|
2284
|
-
}
|
|
2285
|
-
function revalidateNodeInputConnections(id) {
|
|
2286
|
-
return revalidateNodeConnections(id, CanvasConnectionMode.Input);
|
|
2287
|
-
}
|
|
2288
|
-
function revalidateNodeOutputConnections(id) {
|
|
2289
|
-
return revalidateNodeConnections(id, CanvasConnectionMode.Output);
|
|
2290
|
-
}
|
|
2291
|
-
function isConnectionAllowed(sourceNode, targetNode, sourceConnection, targetConnection) {
|
|
2292
|
-
const blocklist = [STICKY_NODE_TYPE];
|
|
2293
|
-
if (sourceConnection.type !== targetConnection.type) {
|
|
2294
|
-
return false;
|
|
2295
|
-
}
|
|
2296
|
-
if (blocklist.includes(sourceNode.type) || blocklist.includes(targetNode.type)) {
|
|
2297
|
-
return false;
|
|
2298
|
-
}
|
|
2299
|
-
const sourceNodeType = nodeTypesStore.getNodeType(sourceNode.type, sourceNode.typeVersion);
|
|
2300
|
-
const sourceWorkflowNode = editableWorkflowObject.value.getNode(sourceNode.name);
|
|
2301
|
-
if (!sourceWorkflowNode) {
|
|
2302
|
-
return false;
|
|
2303
|
-
}
|
|
2304
|
-
let sourceNodeOutputs = [];
|
|
2305
|
-
if (sourceNodeType) {
|
|
2306
|
-
sourceNodeOutputs = getNodeOutputs(
|
|
2307
|
-
editableWorkflowObject.value,
|
|
2308
|
-
sourceWorkflowNode,
|
|
2309
|
-
sourceNodeType
|
|
2310
|
-
) || [];
|
|
2311
|
-
}
|
|
2312
|
-
const sourceNodeHasOutputConnectionOfType = !!sourceNodeOutputs.find((output) => {
|
|
2313
|
-
const outputType = typeof output === "string" ? output : output.type;
|
|
2314
|
-
return outputType === sourceConnection.type;
|
|
2315
|
-
});
|
|
2316
|
-
const sourceNodeHasOutputConnectionPortOfType = sourceConnection.index < sourceNodeOutputs.length;
|
|
2317
|
-
if (!sourceNodeHasOutputConnectionOfType || !sourceNodeHasOutputConnectionPortOfType) {
|
|
2318
|
-
return false;
|
|
2319
|
-
}
|
|
2320
|
-
const targetNodeType = nodeTypesStore.getNodeType(targetNode.type, targetNode.typeVersion);
|
|
2321
|
-
const targetWorkflowNode = editableWorkflowObject.value.getNode(targetNode.name);
|
|
2322
|
-
if (!targetWorkflowNode) {
|
|
2323
|
-
return false;
|
|
2324
|
-
}
|
|
2325
|
-
let targetNodeInputs = [];
|
|
2326
|
-
if (targetNodeType) {
|
|
2327
|
-
targetNodeInputs = getNodeInputs(
|
|
2328
|
-
editableWorkflowObject.value,
|
|
2329
|
-
targetWorkflowNode,
|
|
2330
|
-
targetNodeType
|
|
2331
|
-
) || [];
|
|
2332
|
-
}
|
|
2333
|
-
const targetNodeHasInputConnectionOfType = !!targetNodeInputs.find((input) => {
|
|
2334
|
-
const inputType = typeof input === "string" ? input : input.type;
|
|
2335
|
-
if (inputType !== targetConnection.type) return false;
|
|
2336
|
-
const filter = typeof input === "object" && "filter" in input ? input.filter : void 0;
|
|
2337
|
-
if (filter?.nodes.length && !filter.nodes.includes(sourceNode.type)) {
|
|
2338
|
-
toast.showToast({
|
|
2339
|
-
title: i18n.baseText("nodeView.showError.nodeNodeCompatible.title"),
|
|
2340
|
-
message: i18n.baseText("nodeView.showError.nodeNodeCompatible.message", {
|
|
2341
|
-
interpolate: { sourceNodeName: sourceNode.name, targetNodeName: targetNode.name }
|
|
2342
|
-
}),
|
|
2343
|
-
type: "error",
|
|
2344
|
-
duration: 5e3
|
|
2345
|
-
});
|
|
2346
|
-
return false;
|
|
2347
|
-
}
|
|
2348
|
-
return true;
|
|
2349
|
-
});
|
|
2350
|
-
const targetNodeHasInputConnectionPortOfType = targetConnection.index < targetNodeInputs.length;
|
|
2351
|
-
return targetNodeHasInputConnectionOfType && targetNodeHasInputConnectionPortOfType;
|
|
2352
|
-
}
|
|
2353
|
-
async function addConnections(connections, { trackBulk = true, trackHistory = false, keepPristine = false } = {}) {
|
|
2354
|
-
await nextTick();
|
|
2355
|
-
if (trackBulk && trackHistory) {
|
|
2356
|
-
historyStore.startRecordingUndo();
|
|
2357
|
-
}
|
|
2358
|
-
for (const connection of connections) {
|
|
2359
|
-
createConnection(connection, { trackHistory, keepPristine });
|
|
2360
|
-
}
|
|
2361
|
-
if (trackBulk && trackHistory) {
|
|
2362
|
-
historyStore.stopRecordingUndo();
|
|
2363
|
-
}
|
|
2364
|
-
if (!keepPristine) {
|
|
2365
|
-
uiStore.stateIsDirty = true;
|
|
2366
|
-
}
|
|
2367
|
-
}
|
|
2368
|
-
function resetWorkspace() {
|
|
2369
|
-
nodeCreatorStore.setNodeCreatorState({ createNodeActive: false });
|
|
2370
|
-
nodeCreatorStore.setShowScrim(false);
|
|
2371
|
-
if (workflowsStore.executionWaitingForWebhook) {
|
|
2372
|
-
try {
|
|
2373
|
-
void workflowsStore.removeTestWebhook(workflowsStore.workflowId);
|
|
2374
|
-
} catch (error) {
|
|
2375
|
-
}
|
|
2376
|
-
}
|
|
2377
|
-
workflowsStore.resetWorkflow();
|
|
2378
|
-
workflowsStore.resetState();
|
|
2379
|
-
workflowsStore.currentWorkflowExecutions = [];
|
|
2380
|
-
workflowsStore.setActiveExecutionId(void 0);
|
|
2381
|
-
uiStore.resetLastInteractedWith();
|
|
2382
|
-
uiStore.stateIsDirty = false;
|
|
2383
|
-
executionsStore.activeExecution = null;
|
|
2384
|
-
nodeHelpers.credentialsUpdated.value = false;
|
|
2385
|
-
}
|
|
2386
|
-
function initializeWorkspace(data) {
|
|
2387
|
-
workflowHelpers.initState(data);
|
|
2388
|
-
data.nodes.forEach((node) => {
|
|
2389
|
-
const nodeTypeDescription = requireNodeTypeDescription(node.type, node.typeVersion);
|
|
2390
|
-
nodeHelpers.matchCredentials(node);
|
|
2391
|
-
resolveNodeParameters(node, nodeTypeDescription);
|
|
2392
|
-
resolveNodeWebhook(node, nodeTypeDescription);
|
|
2393
|
-
});
|
|
2394
|
-
workflowsStore.setNodes(data.nodes);
|
|
2395
|
-
workflowsStore.setConnections(data.connections);
|
|
2396
|
-
}
|
|
2397
|
-
function removeUnknownCredentials(workflow) {
|
|
2398
|
-
if (!workflow?.nodes) return;
|
|
2399
|
-
for (const node of workflow.nodes) {
|
|
2400
|
-
if (!node.credentials) continue;
|
|
2401
|
-
for (const [name, credential] of Object.entries(node.credentials)) {
|
|
2402
|
-
if (typeof credential === "string" || credential.id === null) continue;
|
|
2403
|
-
if (!credentialsStore.getCredentialById(credential.id)) {
|
|
2404
|
-
delete node.credentials[name];
|
|
2405
|
-
}
|
|
2406
|
-
}
|
|
2407
|
-
}
|
|
2408
|
-
}
|
|
2409
|
-
async function addImportedNodesToWorkflow(data, { trackBulk = true, trackHistory = false } = {}) {
|
|
2410
|
-
const nodeNameTable = {};
|
|
2411
|
-
const newNodeNames = new Set((data.nodes ?? []).map((node) => node.name));
|
|
2412
|
-
if (!data.nodes) {
|
|
2413
|
-
throw new Error(i18n.baseText("nodeView.noNodesGivenToAdd"));
|
|
2414
|
-
}
|
|
2415
|
-
const nodeTypesCount = workflowHelpers.getNodeTypesMaxCount();
|
|
2416
|
-
let oldName;
|
|
2417
|
-
let newName;
|
|
2418
|
-
const createNodes = [];
|
|
2419
|
-
await nodeHelpers.loadNodesProperties(
|
|
2420
|
-
data.nodes.map((node) => ({ name: node.type, version: node.typeVersion }))
|
|
2421
|
-
);
|
|
2422
|
-
data.nodes.forEach((node) => {
|
|
2423
|
-
if (nodeTypesCount[node.type] !== void 0) {
|
|
2424
|
-
if (nodeTypesCount[node.type].exist >= nodeTypesCount[node.type].max) {
|
|
2425
|
-
nodeNameTable[node.name] = nodeTypesCount[node.type].nodeNames[0];
|
|
2426
|
-
return;
|
|
2427
|
-
} else {
|
|
2428
|
-
nodeTypesCount[node.type].exist += 1;
|
|
2429
|
-
}
|
|
2430
|
-
}
|
|
2431
|
-
oldName = node.name;
|
|
2432
|
-
const localized = i18n.localizeNodeName(node.name, node.type);
|
|
2433
|
-
newNodeNames.delete(oldName);
|
|
2434
|
-
newName = uniqueNodeName(localized, Array.from(newNodeNames));
|
|
2435
|
-
newNodeNames.add(newName);
|
|
2436
|
-
nodeNameTable[oldName] = newName;
|
|
2437
|
-
createNodes.push(node);
|
|
2438
|
-
});
|
|
2439
|
-
const newConnections = {};
|
|
2440
|
-
const currentConnections = data.connections ?? {};
|
|
2441
|
-
const createNodeNames = createNodes.map((node) => node.name);
|
|
2442
|
-
let sourceNode, type, sourceIndex, connectionIndex, connectionData;
|
|
2443
|
-
for (sourceNode of Object.keys(currentConnections)) {
|
|
2444
|
-
if (!createNodeNames.includes(sourceNode)) {
|
|
2445
|
-
continue;
|
|
2446
|
-
}
|
|
2447
|
-
const connection = {};
|
|
2448
|
-
for (type of Object.keys(currentConnections[sourceNode])) {
|
|
2449
|
-
connection[type] = [];
|
|
2450
|
-
for (sourceIndex = 0; sourceIndex < currentConnections[sourceNode][type].length; sourceIndex++) {
|
|
2451
|
-
const nodeSourceConnections = [];
|
|
2452
|
-
const connectionsToCheck = currentConnections[sourceNode][type][sourceIndex];
|
|
2453
|
-
if (connectionsToCheck) {
|
|
2454
|
-
for (connectionIndex = 0; connectionIndex < connectionsToCheck.length; connectionIndex++) {
|
|
2455
|
-
connectionData = connectionsToCheck[connectionIndex];
|
|
2456
|
-
if (!createNodeNames.includes(connectionData.node)) {
|
|
2457
|
-
continue;
|
|
2458
|
-
}
|
|
2459
|
-
nodeSourceConnections.push(connectionData);
|
|
2460
|
-
}
|
|
2461
|
-
}
|
|
2462
|
-
connection[type].push(nodeSourceConnections);
|
|
2463
|
-
}
|
|
2464
|
-
}
|
|
2465
|
-
newConnections[sourceNode] = connection;
|
|
2466
|
-
}
|
|
2467
|
-
const tempWorkflow = workflowsStore.getWorkflow(createNodes, newConnections);
|
|
2468
|
-
for (oldName in nodeNameTable) {
|
|
2469
|
-
if (oldName === nodeNameTable[oldName]) {
|
|
2470
|
-
continue;
|
|
2471
|
-
}
|
|
2472
|
-
tempWorkflow.renameNode(oldName, nodeNameTable[oldName]);
|
|
2473
|
-
}
|
|
2474
|
-
if (data.pinData) {
|
|
2475
|
-
let pinDataSuccess = true;
|
|
2476
|
-
for (const nodeName of Object.keys(data.pinData)) {
|
|
2477
|
-
if (!pinDataSuccess) {
|
|
2478
|
-
toast.showError(
|
|
2479
|
-
new Error(i18n.baseText("ndv.pinData.error.tooLarge.description")),
|
|
2480
|
-
i18n.baseText("ndv.pinData.error.tooLarge.title")
|
|
2481
|
-
);
|
|
2482
|
-
continue;
|
|
2483
|
-
}
|
|
2484
|
-
const node = tempWorkflow.nodes[nodeNameTable[nodeName]];
|
|
2485
|
-
try {
|
|
2486
|
-
const pinnedDataForNode = usePinnedData(node);
|
|
2487
|
-
pinnedDataForNode.setData(data.pinData[nodeName], "add-nodes");
|
|
2488
|
-
pinDataSuccess = true;
|
|
2489
|
-
} catch (error) {
|
|
2490
|
-
pinDataSuccess = false;
|
|
2491
|
-
console.error(error);
|
|
2492
|
-
}
|
|
2493
|
-
}
|
|
2494
|
-
}
|
|
2495
|
-
if (trackBulk && trackHistory) {
|
|
2496
|
-
historyStore.startRecordingUndo();
|
|
2497
|
-
}
|
|
2498
|
-
await addNodes(Object.values(tempWorkflow.nodes), { trackBulk: false, trackHistory });
|
|
2499
|
-
await addConnections(
|
|
2500
|
-
mapLegacyConnectionsToCanvasConnections(
|
|
2501
|
-
tempWorkflow.connectionsBySourceNode,
|
|
2502
|
-
Object.values(tempWorkflow.nodes)
|
|
2503
|
-
),
|
|
2504
|
-
{ trackBulk: false, trackHistory }
|
|
2505
|
-
);
|
|
2506
|
-
if (trackBulk && trackHistory) {
|
|
2507
|
-
historyStore.stopRecordingUndo();
|
|
2508
|
-
}
|
|
2509
|
-
uiStore.stateIsDirty = true;
|
|
2510
|
-
return {
|
|
2511
|
-
nodes: Object.values(tempWorkflow.nodes),
|
|
2512
|
-
connections: tempWorkflow.connectionsBySourceNode
|
|
2513
|
-
};
|
|
2514
|
-
}
|
|
2515
|
-
async function importWorkflowData(workflowData, source, importTags = true, { trackBulk = true, trackHistory = true } = {}) {
|
|
2516
|
-
uiStore.resetLastInteractedWith();
|
|
2517
|
-
if (!workflowData.hasOwnProperty("nodes") || !workflowData.hasOwnProperty("connections")) {
|
|
2518
|
-
return {};
|
|
2519
|
-
}
|
|
2520
|
-
try {
|
|
2521
|
-
const nodeIdMap = {};
|
|
2522
|
-
if (workflowData.nodes) {
|
|
2523
|
-
const nodeNames = new Set(workflowData.nodes.map((node) => node.name));
|
|
2524
|
-
workflowData.nodes.forEach((node) => {
|
|
2525
|
-
if (!node.name) {
|
|
2526
|
-
const nodeType = nodeTypesStore.getNodeType(node.type);
|
|
2527
|
-
const newName = uniqueNodeName(
|
|
2528
|
-
nodeType?.displayName ?? node.type,
|
|
2529
|
-
Array.from(nodeNames)
|
|
2530
|
-
);
|
|
2531
|
-
node.name = newName;
|
|
2532
|
-
nodeNames.add(newName);
|
|
2533
|
-
}
|
|
2534
|
-
if (node.webhookId && UPDATE_WEBHOOK_ID_NODE_TYPES.includes(node.type)) {
|
|
2535
|
-
const isDuplicate = Object.values(workflowHelpers.getCurrentWorkflow().nodes).some(
|
|
2536
|
-
(n) => n.webhookId === node.webhookId
|
|
2537
|
-
);
|
|
2538
|
-
if (isDuplicate) {
|
|
2539
|
-
nodeHelpers.assignWebhookId(node);
|
|
2540
|
-
if (node.parameters.path) {
|
|
2541
|
-
node.parameters.path = node.webhookId;
|
|
2542
|
-
} else if (node.parameters.options.path) {
|
|
2543
|
-
node.parameters.options.path = node.webhookId;
|
|
2544
|
-
}
|
|
2545
|
-
}
|
|
2546
|
-
}
|
|
2547
|
-
if (node.id) {
|
|
2548
|
-
const previousId = node.id;
|
|
2549
|
-
const newId = nodeHelpers.assignNodeId(node);
|
|
2550
|
-
nodeIdMap[newId] = previousId;
|
|
2551
|
-
} else {
|
|
2552
|
-
nodeHelpers.assignNodeId(node);
|
|
2553
|
-
}
|
|
2554
|
-
});
|
|
2555
|
-
}
|
|
2556
|
-
removeUnknownCredentials(workflowData);
|
|
2557
|
-
const nodeGraph = JSON.stringify(
|
|
2558
|
-
generateNodesGraph(
|
|
2559
|
-
workflowData,
|
|
2560
|
-
workflowHelpers.getNodeTypes(),
|
|
2561
|
-
{
|
|
2562
|
-
nodeIdMap,
|
|
2563
|
-
sourceInstanceId: workflowData.meta && workflowData.meta.instanceId !== rootStore.instanceId ? workflowData.meta.instanceId : "",
|
|
2564
|
-
isCloudDeployment: settingsStore.isCloudDeployment
|
|
2565
|
-
}
|
|
2566
|
-
).nodeGraph
|
|
2567
|
-
);
|
|
2568
|
-
if (source === "paste") {
|
|
2569
|
-
telemetry.track("User pasted nodes", {
|
|
2570
|
-
workflow_id: workflowsStore.workflowId,
|
|
2571
|
-
node_graph_string: nodeGraph
|
|
2572
|
-
});
|
|
2573
|
-
} else if (source === "duplicate") {
|
|
2574
|
-
telemetry.track("User duplicated nodes", {
|
|
2575
|
-
workflow_id: workflowsStore.workflowId,
|
|
2576
|
-
node_graph_string: nodeGraph
|
|
2577
|
-
});
|
|
2578
|
-
} else {
|
|
2579
|
-
telemetry.track("User imported workflow", {
|
|
2580
|
-
source,
|
|
2581
|
-
workflow_id: workflowsStore.workflowId,
|
|
2582
|
-
node_graph_string: nodeGraph
|
|
2583
|
-
});
|
|
2584
|
-
}
|
|
2585
|
-
workflowHelpers.updateNodePositions(
|
|
2586
|
-
workflowData,
|
|
2587
|
-
getNewNodePosition(editableWorkflow.value.nodes, lastClickPosition.value)
|
|
2588
|
-
);
|
|
2589
|
-
await addImportedNodesToWorkflow(workflowData, { trackBulk, trackHistory });
|
|
2590
|
-
if (importTags && settingsStore.areTagsEnabled && Array.isArray(workflowData.tags)) {
|
|
2591
|
-
await importWorkflowTags(workflowData);
|
|
2592
|
-
}
|
|
2593
|
-
return workflowData;
|
|
2594
|
-
} catch (error) {
|
|
2595
|
-
toast.showError(error, i18n.baseText("nodeView.showError.importWorkflowData.title"));
|
|
2596
|
-
return {};
|
|
2597
|
-
}
|
|
2598
|
-
}
|
|
2599
|
-
async function importWorkflowTags(workflowData) {
|
|
2600
|
-
const allTags = await tagsStore.fetchAll();
|
|
2601
|
-
const tagNames = new Set(allTags.map((tag) => tag.name));
|
|
2602
|
-
const workflowTags = workflowData.tags;
|
|
2603
|
-
const notFound = workflowTags.filter((tag) => !tagNames.has(tag.name));
|
|
2604
|
-
const creatingTagPromises = [];
|
|
2605
|
-
for (const tag of notFound) {
|
|
2606
|
-
const creationPromise = tagsStore.create(tag.name).then((newTag) => {
|
|
2607
|
-
allTags.push(newTag);
|
|
2608
|
-
return newTag;
|
|
2609
|
-
});
|
|
2610
|
-
creatingTagPromises.push(creationPromise);
|
|
2611
|
-
}
|
|
2612
|
-
await Promise.all(creatingTagPromises);
|
|
2613
|
-
const tagIds = workflowTags.reduce((accu, imported) => {
|
|
2614
|
-
const tag = allTags.find((t) => t.name === imported.name);
|
|
2615
|
-
if (tag) {
|
|
2616
|
-
accu.push(tag.id);
|
|
2617
|
-
}
|
|
2618
|
-
return accu;
|
|
2619
|
-
}, []);
|
|
2620
|
-
workflowsStore.addWorkflowTagIds(tagIds);
|
|
2621
|
-
}
|
|
2622
|
-
async function fetchWorkflowDataFromUrl(url) {
|
|
2623
|
-
let workflowData;
|
|
2624
|
-
canvasStore.startLoading();
|
|
2625
|
-
try {
|
|
2626
|
-
workflowData = await workflowsStore.getWorkflowFromUrl(url);
|
|
2627
|
-
} catch (error) {
|
|
2628
|
-
toast.showError(error, i18n.baseText("nodeView.showError.getWorkflowDataFromUrl.title"));
|
|
2629
|
-
return;
|
|
2630
|
-
} finally {
|
|
2631
|
-
canvasStore.stopLoading();
|
|
2632
|
-
}
|
|
2633
|
-
return workflowData;
|
|
2634
|
-
}
|
|
2635
|
-
function getNodesToSave(nodes) {
|
|
2636
|
-
const data = {
|
|
2637
|
-
nodes: [],
|
|
2638
|
-
connections: {},
|
|
2639
|
-
pinData: {}
|
|
2640
|
-
};
|
|
2641
|
-
const exportedNodeNames = /* @__PURE__ */ new Set();
|
|
2642
|
-
for (const node of nodes) {
|
|
2643
|
-
const nodeSaveData = workflowHelpers.getNodeDataToSave(node);
|
|
2644
|
-
const pinDataForNode = workflowsStore.pinDataByNodeName(node.name);
|
|
2645
|
-
if (pinDataForNode) {
|
|
2646
|
-
data.pinData[node.name] = pinDataForNode;
|
|
2647
|
-
}
|
|
2648
|
-
if (nodeSaveData.credentials && settingsStore.isEnterpriseFeatureEnabled[EnterpriseEditionFeature.Sharing]) {
|
|
2649
|
-
nodeSaveData.credentials = filterAllowedCredentials(
|
|
2650
|
-
nodeSaveData.credentials,
|
|
2651
|
-
workflowsStore.usedCredentials
|
|
2652
|
-
);
|
|
2653
|
-
}
|
|
2654
|
-
data.nodes.push(nodeSaveData);
|
|
2655
|
-
exportedNodeNames.add(node.name);
|
|
2656
|
-
}
|
|
2657
|
-
data.connections = getConnectionsForNodes(data.nodes, exportedNodeNames);
|
|
2658
|
-
workflowHelpers.removeForeignCredentialsFromWorkflow(data, credentialsStore.allCredentials);
|
|
2659
|
-
return data;
|
|
2660
|
-
}
|
|
2661
|
-
function filterAllowedCredentials(credentials, usedCredentials) {
|
|
2662
|
-
return Object.fromEntries(
|
|
2663
|
-
Object.entries(credentials).filter(([, credential]) => {
|
|
2664
|
-
return credential.id && (!usedCredentials[credential.id] || usedCredentials[credential.id]?.currentUserHasAccess);
|
|
2665
|
-
})
|
|
2666
|
-
);
|
|
2667
|
-
}
|
|
2668
|
-
function getConnectionsForNodes(nodes, includeNodeNames) {
|
|
2669
|
-
const connections = {};
|
|
2670
|
-
for (const node of nodes) {
|
|
2671
|
-
const outgoingConnections = workflowsStore.outgoingConnectionsByNodeName(node.name);
|
|
2672
|
-
if (!Object.keys(outgoingConnections).length) continue;
|
|
2673
|
-
const filteredConnections = filterConnectionsByNodes(outgoingConnections, includeNodeNames);
|
|
2674
|
-
if (Object.keys(filteredConnections).length) {
|
|
2675
|
-
connections[node.name] = filteredConnections;
|
|
2676
|
-
}
|
|
2677
|
-
}
|
|
2678
|
-
return connections;
|
|
2679
|
-
}
|
|
2680
|
-
function filterConnectionsByNodes(connections, includeNodeNames) {
|
|
2681
|
-
const filteredConnections = {};
|
|
2682
|
-
for (const [type, typeConnections] of Object.entries(connections)) {
|
|
2683
|
-
const validConnections = typeConnections.map(
|
|
2684
|
-
(sourceConnections) => (sourceConnections ?? []).filter((connection) => includeNodeNames.has(connection.node))
|
|
2685
|
-
);
|
|
2686
|
-
if (validConnections.length) {
|
|
2687
|
-
filteredConnections[type] = validConnections;
|
|
2688
|
-
}
|
|
2689
|
-
}
|
|
2690
|
-
return filteredConnections;
|
|
2691
|
-
}
|
|
2692
|
-
async function duplicateNodes(ids) {
|
|
2693
|
-
const workflowData = deepCopy(getNodesToSave(workflowsStore.getNodesByIds(ids)));
|
|
2694
|
-
const result = await importWorkflowData(workflowData, "duplicate", false);
|
|
2695
|
-
return result.nodes?.map((node) => node.id).filter(isPresent) ?? [];
|
|
2696
|
-
}
|
|
2697
|
-
async function copyNodes(ids) {
|
|
2698
|
-
const workflowData = deepCopy(getNodesToSave(workflowsStore.getNodesByIds(ids)));
|
|
2699
|
-
workflowData.meta = {
|
|
2700
|
-
...workflowData.meta,
|
|
2701
|
-
...workflowsStore.workflow.meta,
|
|
2702
|
-
instanceId: rootStore.instanceId
|
|
2703
|
-
};
|
|
2704
|
-
await clipboard.copy(JSON.stringify(workflowData, null, 2));
|
|
2705
|
-
telemetry.track("User copied nodes", {
|
|
2706
|
-
node_types: workflowData.nodes.map((node) => node.type),
|
|
2707
|
-
workflow_id: workflowsStore.workflowId
|
|
2708
|
-
});
|
|
2709
|
-
}
|
|
2710
|
-
async function cutNodes(ids) {
|
|
2711
|
-
await copyNodes(ids);
|
|
2712
|
-
deleteNodes(ids);
|
|
2713
|
-
}
|
|
2714
|
-
async function openExecution(executionId) {
|
|
2715
|
-
let data;
|
|
2716
|
-
try {
|
|
2717
|
-
data = await workflowsStore.getExecution(executionId);
|
|
2718
|
-
} catch (error) {
|
|
2719
|
-
toast.showError(error, i18n.baseText("nodeView.showError.openExecution.title"));
|
|
2720
|
-
return;
|
|
2721
|
-
}
|
|
2722
|
-
if (data === void 0) {
|
|
2723
|
-
throw new Error(`Execution with id "${executionId}" could not be found!`);
|
|
2724
|
-
}
|
|
2725
|
-
initializeWorkspace(data.workflowData);
|
|
2726
|
-
workflowsStore.setWorkflowExecutionData(data);
|
|
2727
|
-
if (!["manual", "evaluation"].includes(data.mode)) {
|
|
2728
|
-
workflowsStore.setWorkflowPinData({});
|
|
2729
|
-
}
|
|
2730
|
-
uiStore.stateIsDirty = false;
|
|
2731
|
-
return data;
|
|
2732
|
-
}
|
|
2733
|
-
async function toggleChatOpen(source, isOpen) {
|
|
2734
|
-
const workflow = workflowsStore.getCurrentWorkflow();
|
|
2735
|
-
workflowsStore.toggleLogsPanelOpen(isOpen);
|
|
2736
|
-
const payload = {
|
|
2737
|
-
workflow_id: workflow.id,
|
|
2738
|
-
button_type: source
|
|
2739
|
-
};
|
|
2740
|
-
void externalHooks.run("nodeView.onOpenChat", payload);
|
|
2741
|
-
telemetry.track("User clicked chat open button", payload);
|
|
2742
|
-
}
|
|
2743
|
-
async function importTemplate({
|
|
2744
|
-
id,
|
|
2745
|
-
name,
|
|
2746
|
-
workflow
|
|
2747
|
-
}) {
|
|
2748
|
-
const convertedNodes = workflow.nodes?.map(workflowsStore.convertTemplateNodeToNodeUi);
|
|
2749
|
-
if (workflow.connections) {
|
|
2750
|
-
workflowsStore.setConnections(workflow.connections);
|
|
2751
|
-
}
|
|
2752
|
-
await addNodes(convertedNodes ?? []);
|
|
2753
|
-
await workflowsStore.getNewWorkflowDataAndMakeShareable(name, projectsStore.currentProjectId);
|
|
2754
|
-
workflowsStore.addToWorkflowMetadata({ templateId: `${id}` });
|
|
2755
|
-
}
|
|
2756
|
-
function tryToOpenSubworkflowInNewTab(nodeId) {
|
|
2757
|
-
const node = workflowsStore.getNodeById(nodeId);
|
|
2758
|
-
if (!node) return false;
|
|
2759
|
-
const subWorkflowId = getSubworkflowId(node);
|
|
2760
|
-
if (!subWorkflowId) return false;
|
|
2761
|
-
window.open(`${rootStore.baseUrl}workflow/${subWorkflowId}`, "_blank");
|
|
2762
|
-
return true;
|
|
2763
|
-
}
|
|
2764
|
-
return {
|
|
2765
|
-
lastClickPosition,
|
|
2766
|
-
editableWorkflow,
|
|
2767
|
-
editableWorkflowObject,
|
|
2768
|
-
triggerNodes,
|
|
2769
|
-
requireNodeTypeDescription,
|
|
2770
|
-
addNodes,
|
|
2771
|
-
addNode,
|
|
2772
|
-
resolveNodePosition,
|
|
2773
|
-
revertAddNode,
|
|
2774
|
-
updateNodesPosition,
|
|
2775
|
-
updateNodePosition,
|
|
2776
|
-
tidyUp,
|
|
2777
|
-
revertUpdateNodePosition,
|
|
2778
|
-
setNodeActive,
|
|
2779
|
-
setNodeActiveByName,
|
|
2780
|
-
clearNodeActive,
|
|
2781
|
-
setNodeSelected,
|
|
2782
|
-
toggleNodesDisabled,
|
|
2783
|
-
revertToggleNodeDisabled,
|
|
2784
|
-
toggleNodesPinned,
|
|
2785
|
-
setNodeParameters,
|
|
2786
|
-
renameNode,
|
|
2787
|
-
revertRenameNode,
|
|
2788
|
-
deleteNode,
|
|
2789
|
-
deleteNodes,
|
|
2790
|
-
copyNodes,
|
|
2791
|
-
cutNodes,
|
|
2792
|
-
duplicateNodes,
|
|
2793
|
-
getNodesToSave,
|
|
2794
|
-
revertDeleteNode,
|
|
2795
|
-
addConnections,
|
|
2796
|
-
createConnection,
|
|
2797
|
-
revertCreateConnection,
|
|
2798
|
-
deleteConnection,
|
|
2799
|
-
revertDeleteConnection,
|
|
2800
|
-
deleteConnectionsByNodeId,
|
|
2801
|
-
revalidateNodeInputConnections,
|
|
2802
|
-
revalidateNodeOutputConnections,
|
|
2803
|
-
isConnectionAllowed,
|
|
2804
|
-
filterConnectionsByNodes,
|
|
2805
|
-
connectAdjacentNodes,
|
|
2806
|
-
importWorkflowData,
|
|
2807
|
-
fetchWorkflowDataFromUrl,
|
|
2808
|
-
resetWorkspace,
|
|
2809
|
-
initializeWorkspace,
|
|
2810
|
-
resolveNodeWebhook,
|
|
2811
|
-
openExecution,
|
|
2812
|
-
toggleChatOpen,
|
|
2813
|
-
importTemplate,
|
|
2814
|
-
tryToOpenSubworkflowInNewTab
|
|
2815
|
-
};
|
|
2816
|
-
}
|
|
2817
|
-
export {
|
|
2818
|
-
AINodesView as A,
|
|
2819
|
-
RegularView as R,
|
|
2820
|
-
TriggerView as T,
|
|
2821
|
-
useCanvasOperations as a,
|
|
2822
|
-
capitalize as b,
|
|
2823
|
-
createCanvasConnectionHandleString as c,
|
|
2824
|
-
checkOverlap as d,
|
|
2825
|
-
mapLegacyConnectionsToCanvasConnections as e,
|
|
2826
|
-
useViewStacks as f,
|
|
2827
|
-
camelCase as g,
|
|
2828
|
-
useKeyboardNavigation as h,
|
|
2829
|
-
insertSpacersBetweenEndpoints as i,
|
|
2830
|
-
AIView as j,
|
|
2831
|
-
mapLegacyEndpointsToCanvasConnectionPort as m,
|
|
2832
|
-
parseCanvasConnectionHandleString as p,
|
|
2833
|
-
useNodeCreatorStore as u
|
|
2834
|
-
};
|