diff --git a/packages/editor-ui/src/plugins/i18n/locales/en.json b/packages/editor-ui/src/plugins/i18n/locales/en.json index 37a3401d03..443e754537 100644 --- a/packages/editor-ui/src/plugins/i18n/locales/en.json +++ b/packages/editor-ui/src/plugins/i18n/locales/en.json @@ -1304,6 +1304,7 @@ "nodeView.confirmMessage.debug.headline": "Unpin workflow data", "nodeView.confirmMessage.debug.message": "Loading this execution will unpin the data currently pinned in these nodes", "nodeView.couldntImportWorkflow": "Could not import workflow", + "nodeView.couldntLoadWorkflow.invalidWorkflowObject": "Invalid workflow object", "nodeView.deletesTheCurrentExecutionData": "Deletes the current execution data", "nodeView.itLooksLikeYouHaveBeenEditingSomething": "It looks like you made some edits. If you leave before saving, your changes will be lost.", "nodeView.loadingTemplate": "Loading template", diff --git a/packages/editor-ui/src/views/NodeView.v2.vue b/packages/editor-ui/src/views/NodeView.v2.vue index 91c5375cb0..886b4dbc70 100644 --- a/packages/editor-ui/src/views/NodeView.v2.vue +++ b/packages/editor-ui/src/views/NodeView.v2.vue @@ -32,6 +32,7 @@ import type { IWorkflowTemplate, NodeCreatorOpenSource, ToggleNodeCreatorOptions, + WorkflowDataWithTemplateId, XYPosition, } from '@/Interface'; import type { @@ -107,6 +108,7 @@ import { getResourcePermissions } from '@/permissions'; import NodeViewUnfinishedWorkflowMessage from '@/components/NodeViewUnfinishedWorkflowMessage.vue'; import { createCanvasConnectionHandleString } from '@/utils/canvasUtilsV2'; import { isValidNodeConnectionType } from '@/utils/typeGuards'; +import { EASY_AI_WORKFLOW_JSON } from '@/constants.workflows'; const LazyNodeCreation = defineAsyncComponent( async () => await import('@/components/Node/NodeCreation.vue'), @@ -315,7 +317,13 @@ async function initializeRoute(force = false) { isBlankRedirect.value = false; } else if (route.name === VIEWS.TEMPLATE_IMPORT) { const templateId = route.params.id; - await openWorkflowTemplate(templateId.toString()); + const loadWorkflowFromJSON = route.query.fromJson === 'true'; + + if (loadWorkflowFromJSON) { + await openTemplateFromWorkflowJSON(EASY_AI_WORKFLOW_JSON); + } else { + await openWorkflowTemplate(templateId.toString()); + } } else if (isWorkflowRoute.value) { if (!isAlreadyInitialized) { historyStore.reset(); @@ -423,6 +431,42 @@ function trackOpenWorkflowFromOnboardingTemplate() { * Templates */ +async function openTemplateFromWorkflowJSON(workflow: WorkflowDataWithTemplateId) { + if (!workflow.nodes || !workflow.connections) { + toast.showError( + new Error(i18n.baseText('nodeView.couldntLoadWorkflow.invalidWorkflowObject')), + i18n.baseText('nodeView.couldntImportWorkflow'), + ); + await router.replace({ name: VIEWS.NEW_WORKFLOW }); + return; + } + resetWorkspace(); + + canvasStore.startLoading(); + canvasStore.setLoadingText(i18n.baseText('nodeView.loadingTemplate')); + + workflowsStore.currentWorkflowExecutions = []; + executionsStore.activeExecution = null; + + isBlankRedirect.value = true; + await router.replace({ + name: VIEWS.NEW_WORKFLOW, + query: { templateId: workflow.meta.templateId }, + }); + + const convertedNodes = workflow.nodes.map(workflowsStore.convertTemplateNodeToNodeUi); + + workflowsStore.setConnections(workflow.connections); + await addNodes(convertedNodes); + await workflowsStore.getNewWorkflowData(workflow.name, projectsStore.currentProjectId); + + uiStore.stateIsDirty = true; + + canvasStore.stopLoading(); + + fitView(); +} + async function openWorkflowTemplate(templateId: string) { resetWorkspace(); diff --git a/packages/editor-ui/src/views/NodeView.vue b/packages/editor-ui/src/views/NodeView.vue index 25daff29f4..8dac152e5e 100644 --- a/packages/editor-ui/src/views/NodeView.vue +++ b/packages/editor-ui/src/views/NodeView.vue @@ -101,6 +101,7 @@ import type { AddedNodesAndConnections, ToggleNodeCreatorOptions, NodeFilterType, + WorkflowDataWithTemplateId, } from '@/Interface'; import { type RouteLocation, useRoute, useRouter } from 'vue-router'; @@ -180,6 +181,7 @@ import { useNpsSurveyStore } from '@/stores/npsSurvey.store'; import { getResourcePermissions } from '@/permissions'; import { useBeforeUnload } from '@/composables/useBeforeUnload'; import NodeViewUnfinishedWorkflowMessage from '@/components/NodeViewUnfinishedWorkflowMessage.vue'; +import { EASY_AI_WORKFLOW_JSON } from '@/constants.workflows'; interface AddNodeOptions { position?: XYPosition; @@ -1090,6 +1092,42 @@ export default defineComponent({ await this.$nextTick(); this.canvasStore.zoomToFit(); }, + async openWorkflowTemplateFromJson(data: { workflow: WorkflowDataWithTemplateId }) { + if (!data.workflow.nodes || !data.workflow.connections) { + this.showError( + new Error(this.i18n.baseText('nodeView.couldntLoadWorkflow.invalidWorkflowObject')), + this.i18n.baseText('nodeView.couldntImportWorkflow'), + ); + await this.$router.replace({ name: VIEWS.NEW_WORKFLOW }); + return; + } + this.canvasStore.startLoading(); + this.canvasStore.setLoadingText(this.i18n.baseText('nodeView.loadingTemplate')); + this.resetWorkspace(); + + this.workflowsStore.currentWorkflowExecutions = []; + this.executionsStore.activeExecution = null; + + this.blankRedirect = true; + await this.$router.replace({ + name: VIEWS.NEW_WORKFLOW, + query: { templateId: data.workflow.meta.templateId }, + }); + + const convertedNodes = data.workflow.nodes.map( + this.workflowsStore.convertTemplateNodeToNodeUi, + ); + await this.nodeHelpers.addNodes(convertedNodes, data.workflow.connections); + this.workflowData = + (await this.workflowsStore.getNewWorkflowData( + data.workflow.name, + this.projectsStore.currentProjectId, + )) || {}; + await this.$nextTick(); + this.canvasStore.zoomToFit(); + this.uiStore.stateIsDirty = true; + this.canvasStore.stopLoading(); + }, async openWorkflowTemplate(templateId: string) { this.canvasStore.startLoading(); this.canvasStore.setLoadingText(this.i18n.baseText('nodeView.loadingTemplate')); @@ -3361,7 +3399,12 @@ export default defineComponent({ this.blankRedirect = false; } else if (this.$route.name === VIEWS.TEMPLATE_IMPORT) { const templateId = this.$route.params.id; - await this.openWorkflowTemplate(templateId.toString()); + const loadWorkflowFromJSON = this.$route.query.fromJson === 'true'; + if (loadWorkflowFromJSON) { + await this.openWorkflowTemplateFromJson({ workflow: EASY_AI_WORKFLOW_JSON }); + } else { + await this.openWorkflowTemplate(templateId.toString()); + } } else { if ( this.uiStore.stateIsDirty && diff --git a/packages/editor-ui/src/views/WorkflowOnboardingView.vue b/packages/editor-ui/src/views/WorkflowOnboardingView.vue index 04cbe3a1df..f467406726 100644 --- a/packages/editor-ui/src/views/WorkflowOnboardingView.vue +++ b/packages/editor-ui/src/views/WorkflowOnboardingView.vue @@ -7,7 +7,7 @@ import { useWorkflowsStore } from '@/stores/workflows.store'; import { onMounted } from 'vue'; import { useRoute, useRouter } from 'vue-router'; import type { IWorkflowDataCreate } from '@/Interface'; -import { EASY_AI_WORKFLOW_JSON, SAMPLE_SUBWORKFLOW_WORKFLOW } from '@/constants.workflows'; +import { SAMPLE_SUBWORKFLOW_WORKFLOW } from '@/constants.workflows'; const loadingService = useLoadingService(); const templateStore = useTemplatesStore(); @@ -21,11 +21,6 @@ const openWorkflowTemplate = async (templateId: string) => { await openSampleSubworkflow(); return; } - if (templateId === EASY_AI_WORKFLOW_JSON.meta.templateId) { - await openEasyAIWorkflow(); - return; - } - try { loadingService.startLoading(); const template = await templateStore.getFixedWorkflowTemplate(templateId); @@ -63,21 +58,6 @@ const openWorkflowTemplate = async (templateId: string) => { } }; -const openEasyAIWorkflow = async () => { - try { - loadingService.startLoading(); - const newWorkflow = await workflowsStore.createNewWorkflow(EASY_AI_WORKFLOW_JSON); - await router.replace({ - name: VIEWS.WORKFLOW, - params: { name: newWorkflow.id }, - }); - loadingService.stopLoading(); - } catch (e) { - await router.replace({ name: VIEWS.NEW_WORKFLOW }); - loadingService.stopLoading(); - } -}; - const openSampleSubworkflow = async () => { try { loadingService.startLoading(); diff --git a/packages/editor-ui/src/views/WorkflowsView.vue b/packages/editor-ui/src/views/WorkflowsView.vue index 84da8cf9d6..253946751f 100644 --- a/packages/editor-ui/src/views/WorkflowsView.vue +++ b/packages/editor-ui/src/views/WorkflowsView.vue @@ -270,8 +270,9 @@ const openAIWorkflow = async (source: string) => { { withPostHog: true }, ); await router.push({ - name: VIEWS.WORKFLOW_ONBOARDING, + name: VIEWS.TEMPLATE_IMPORT, params: { id: EASY_AI_WORKFLOW_JSON.meta.templateId }, + query: { fromJson: 'true' }, }); };