UNPKG

n8n-editor-ui

Version:

Workflow Editor UI for n8n

330 lines (328 loc) 14.5 kB
; (function () { System.register(["./_MapCache-legacy-DlYNX_X1.js", "./useMessage-legacy-M2m6s8Ce.js", "./useTelemetry-legacy-B3pzzkAE.js", "./useToast-legacy-C4Vu5mt9.js", "./constants-legacy-TKxWCqvM.js", "./useExternalHooks-legacy-8pg6K3ln.js", "./npsSurvey.store-legacy-mkSIzcGP.js", "./templates.store-legacy-BBcmaAs_.js", "./focusPanel.store-legacy-DdqLHRV1.js"], function (_export, _context) { "use strict"; var useI18n, useMessage, useSourceControlStore, useUIStore, useCanvasStore, injectWorkflowState, tryToParseNumber, useNodeTypesStore, useWorkflowHelpers, useWorkflowsStore, useTelemetry, useNodeHelpers, useToast, MODAL_CANCEL, getResourcePermissions, NON_ACTIVATABLE_TRIGGER_NODE_TYPES, VIEWS, MODAL_CLOSE, PLACEHOLDER_EMPTY_WORKFLOW_ID, MODAL_CONFIRM, useExternalHooks, useNpsSurveyStore, useTemplatesStore, useFocusPanelStore; //#region src/app/composables/useWorkflowSaving.ts function useWorkflowSaving({ router, workflowState: providedWorkflowState }) { const uiStore = useUIStore(); const npsSurveyStore = useNpsSurveyStore(); const message = useMessage(); const i18n = useI18n(); const workflowsStore = useWorkflowsStore(); const workflowState = providedWorkflowState ?? injectWorkflowState(); const focusPanelStore = useFocusPanelStore(); const nodeTypesStore = useNodeTypesStore(); const toast = useToast(); const telemetry = useTelemetry(); const nodeHelpers = useNodeHelpers(); const templatesStore = useTemplatesStore(); const { getWorkflowDataToSave, checkConflictingWebhooks, getWorkflowProjectRole } = useWorkflowHelpers(); async function promptSaveUnsavedWorkflowChanges(next, { confirm = async () => true, cancel = async () => {} } = {}) { if (!uiStore.stateIsDirty || workflowsStore.workflow.isArchived || !getResourcePermissions(workflowsStore.workflow.scopes).workflow.update) { next(); return; } switch (await message.confirm(i18n.baseText("generic.unsavedWork.confirmMessage.message"), { title: i18n.baseText("generic.unsavedWork.confirmMessage.headline"), type: "warning", confirmButtonText: i18n.baseText("generic.unsavedWork.confirmMessage.confirmButtonText"), cancelButtonText: i18n.baseText("generic.unsavedWork.confirmMessage.cancelButtonText"), showClose: true })) { case MODAL_CONFIRM: if (await saveCurrentWorkflow({}, false)) { await npsSurveyStore.fetchPromptsData(); uiStore.stateIsDirty = false; next(await confirm()); } else stayOnCurrentWorkflow(next); return; case MODAL_CANCEL: await cancel(); uiStore.stateIsDirty = false; next(); return; case MODAL_CLOSE: if (workflowsStore.workflow.id !== "__EMPTY__") stayOnCurrentWorkflow(next); return; } } function stayOnCurrentWorkflow(next) { next(router.resolve({ name: VIEWS.WORKFLOW, params: { name: workflowsStore.workflow.id } })); } function isNodeActivatable(node) { if (node.disabled) return false; const nodeType = nodeTypesStore.getNodeType(node.type, node.typeVersion); return nodeType !== null && nodeType.group.includes("trigger") && !NON_ACTIVATABLE_TRIGGER_NODE_TYPES.includes(node.type); } async function getWorkflowDeactivationInfo(workflowId, request) { if (request.nodes !== void 0 && !request.nodes.some(isNodeActivatable)) return { title: i18n.baseText("workflows.autodeactivated"), message: i18n.baseText("workflowActivator.thisWorkflowHasNoTriggerNodes"), type: "info" }; const conflictData = await checkConflictingWebhooks(workflowId); if (conflictData) return { title: "Conflicting Webhook Path", message: `Workflow set to inactive: Workflow set to inactive: Live webhook in another workflow uses same path as node '${conflictData.trigger.name}'.`, type: "error" }; } function getQueryParam(query, key) { const value = query[key]; if (Array.isArray(value)) return value[0] ?? void 0; if (value === null) return void 0; return value; } async function saveCurrentWorkflow({ id, name, tags } = {}, redirect = true, forceSave = false) { if (useSourceControlStore().preferences.branchReadOnly) return false; const isLoading = useCanvasStore().isLoading; const currentWorkflow = id ?? getQueryParam(router.currentRoute.value.params, "name"); const parentFolderId = getQueryParam(router.currentRoute.value.query, "parentFolderId"); const uiContext = getQueryParam(router.currentRoute.value.query, "uiContext"); if (!currentWorkflow || ["new", "__EMPTY__"].includes(currentWorkflow)) return !!(await saveAsNewWorkflow({ name, tags, parentFolderId, uiContext }, redirect)); try { if (!forceSave && isLoading) return true; uiStore.addActiveAction("workflowSaving"); const workflowDataRequest = await getWorkflowDataToSave(); if (workflowDataRequest.id !== currentWorkflow) throw new Error("Attempted to save a workflow different from the current workflow"); if (name) workflowDataRequest.name = name.trim(); if (tags) workflowDataRequest.tags = tags; workflowDataRequest.versionId = workflowsStore.workflowVersionId; const deactivateReason = await getWorkflowDeactivationInfo(currentWorkflow, workflowDataRequest); if (deactivateReason !== void 0) { workflowDataRequest.active = false; if (workflowsStore.isWorkflowActive) { toast.showMessage(deactivateReason); workflowsStore.setWorkflowInactive(currentWorkflow); } } const workflowData = await workflowsStore.updateWorkflow(currentWorkflow, workflowDataRequest, forceSave); workflowsStore.setWorkflowVersionId(workflowData.versionId); if (name) workflowState.setWorkflowName({ newName: workflowData.name, setStateDirty: false }); if (tags) { const tagIds = (workflowData.tags || []).map(tag => tag.id); workflowState.setWorkflowTagIds(tagIds); } uiStore.stateIsDirty = false; uiStore.removeActiveAction("workflowSaving"); useExternalHooks().run("workflow.afterUpdate", { workflowData }); return true; } catch (error) { console.error(error); uiStore.removeActiveAction("workflowSaving"); if (error.errorCode === 100) { telemetry.track("User attempted to save locked workflow", { workflowId: currentWorkflow, sharing_role: getWorkflowProjectRole(currentWorkflow) }); const url = router.resolve({ name: VIEWS.WORKFLOW, params: { name: currentWorkflow } }).href; if ((await message.confirm(i18n.baseText("workflows.concurrentChanges.confirmMessage.message", { interpolate: { url } }), i18n.baseText("workflows.concurrentChanges.confirmMessage.title"), { confirmButtonText: i18n.baseText("workflows.concurrentChanges.confirmMessage.confirmButtonText"), cancelButtonText: i18n.baseText("workflows.concurrentChanges.confirmMessage.cancelButtonText") })) === "confirm") return await saveCurrentWorkflow({ id, name, tags }, redirect, true); return false; } toast.showMessage({ title: i18n.baseText("workflowHelpers.showMessage.title"), message: error.message, type: "error" }); return false; } } async function saveAsNewWorkflow({ name, tags, resetWebhookUrls, resetNodeIds, openInNewWindow, parentFolderId, uiContext, data } = {}, redirect = true) { try { uiStore.addActiveAction("workflowSaving"); const workflowDataRequest = data || (await getWorkflowDataToSave()); const changedNodes = {}; if (resetNodeIds) workflowDataRequest.nodes = workflowDataRequest.nodes.map(node => { nodeHelpers.assignNodeId(node); return node; }); if (resetWebhookUrls) workflowDataRequest.nodes = workflowDataRequest.nodes.map(node => { if (node.webhookId) { const newId = nodeHelpers.assignWebhookId(node); node.parameters.path = newId; changedNodes[node.name] = node.webhookId; } return node; }); if (name) workflowDataRequest.name = name.trim(); if (tags) workflowDataRequest.tags = tags; if (parentFolderId) workflowDataRequest.parentFolderId = parentFolderId; if (uiContext) workflowDataRequest.uiContext = uiContext; const workflowData = await workflowsStore.createNewWorkflow(workflowDataRequest); workflowsStore.addWorkflow(workflowData); focusPanelStore.onNewWorkflowSave(workflowData.id); if (openInNewWindow) { const routeData = router.resolve({ name: VIEWS.WORKFLOW, params: { name: workflowData.id } }); window.open(routeData.href, "_blank"); uiStore.removeActiveAction("workflowSaving"); return workflowData.id; } if (workflowData.activeVersionId !== null) { const conflict = await checkConflictingWebhooks(workflowData.id); if (conflict) { workflowData.active = false; workflowData.activeVersionId = null; toast.showMessage({ title: "Conflicting Webhook Path", message: `Workflow set to inactive: Live webhook in another workflow uses same path as node '${conflict.trigger.name}'.`, type: "error" }); } } workflowState.setActive(workflowData.activeVersionId); workflowState.setWorkflowId(workflowData.id); workflowsStore.setWorkflowVersionId(workflowData.versionId); workflowState.setWorkflowName({ newName: workflowData.name, setStateDirty: false }); workflowState.setWorkflowSettings(workflowData.settings || {}); uiStore.stateIsDirty = false; Object.keys(changedNodes).forEach(nodeName => { const changes = { key: "webhookId", value: changedNodes[nodeName], name: nodeName }; workflowState.setNodeValue(changes); }); const tagIds = (workflowData.tags || []).map(tag => tag.id); workflowState.setWorkflowTagIds(tagIds); const templateId = router.currentRoute.value.query.templateId; if (templateId) telemetry.track("User saved new workflow from template", { template_id: tryToParseNumber(String(templateId)), workflow_id: workflowData.id, wf_template_repo_session_id: templatesStore.previousSessionId }); if (redirect) await router.replace({ name: VIEWS.WORKFLOW, params: { name: workflowData.id }, query: { action: "workflowSave" } }); uiStore.removeActiveAction("workflowSaving"); uiStore.stateIsDirty = false; useExternalHooks().run("workflow.afterUpdate", { workflowData }); return workflowData.id; } catch (e) { uiStore.removeActiveAction("workflowSaving"); toast.showMessage({ title: i18n.baseText("workflowHelpers.showMessage.title"), message: e.message, type: "error" }); return null; } } return { promptSaveUnsavedWorkflowChanges, saveCurrentWorkflow, saveAsNewWorkflow }; } //#endregion _export("t", useWorkflowSaving); return { setters: [function (_MapCacheLegacy005Js) { useI18n = _MapCacheLegacy005Js.gt; }, function (_useMessageLegacy00xJs) { useMessage = _useMessageLegacy00xJs.t; }, function (_useTelemetryLegacy00HJs) { useSourceControlStore = _useTelemetryLegacy00HJs.Dn; useUIStore = _useTelemetryLegacy00HJs.Fi; useCanvasStore = _useTelemetryLegacy00HJs.Gn; injectWorkflowState = _useTelemetryLegacy00HJs.Sn; tryToParseNumber = _useTelemetryLegacy00HJs.Ti; useNodeTypesStore = _useTelemetryLegacy00HJs.at; useWorkflowHelpers = _useTelemetryLegacy00HJs.mn; useWorkflowsStore = _useTelemetryLegacy00HJs.o; useTelemetry = _useTelemetryLegacy00HJs.t; useNodeHelpers = _useTelemetryLegacy00HJs.xn; }, function (_useToastLegacy00JJs) { useToast = _useToastLegacy00JJs.t; }, function (_constantsLegacy00TJs) { MODAL_CANCEL = _constantsLegacy00TJs.$o; getResourcePermissions = _constantsLegacy00TJs.Do; NON_ACTIVATABLE_TRIGGER_NODE_TYPES = _constantsLegacy00TJs.In; VIEWS = _constantsLegacy00TJs.Io; MODAL_CLOSE = _constantsLegacy00TJs.es; PLACEHOLDER_EMPTY_WORKFLOW_ID = _constantsLegacy00TJs.s; MODAL_CONFIRM = _constantsLegacy00TJs.ts; }, function (_useExternalHooksLegacy013Js) { useExternalHooks = _useExternalHooksLegacy013Js.t; }, function (_npsSurveyStoreLegacy01bJs) { useNpsSurveyStore = _npsSurveyStoreLegacy01bJs.t; }, function (_templatesStoreLegacy01fJs) { useTemplatesStore = _templatesStoreLegacy01fJs.t; }, function (_focusPanelStoreLegacy01hJs) { useFocusPanelStore = _focusPanelStoreLegacy01hJs.t; }], execute: function () {} }; }); })();