From 705a78156afd714e976c95cf4ef7c507a8e04145 Mon Sep 17 00:00:00 2001 From: Romeo Balta <7095569+romeobalta@users.noreply.github.com> Date: Mon, 17 Nov 2025 12:43:05 +0000 Subject: [PATCH] feat(editor): New simplified empty layout (#21214) --- .../frontend/@n8n/i18n/src/locales/en.json | 2 +- .../frontend/@n8n/stores/src/constants.ts | 1 + .../components/layouts/EmptyStateLayout.vue} | 43 +- .../handlers/executionFinished.test.ts | 216 ++++++- .../handlers/executionFinished.ts | 13 +- .../src/app/views/WorkflowsView.test.ts | 101 +++ .../editor-ui/src/app/views/WorkflowsView.vue | 10 +- .../projects/components/ProjectHeader.vue | 4 +- .../components/ReadyToRunButton.test.ts | 223 +++++++ .../components/ReadyToRunButton.vue} | 18 +- .../useEmptyStateDetection.test.ts | 92 +++ .../composables/useEmptyStateDetection.ts | 48 ++ .../stores/readyToRun.store.test.ts | 573 ++++++++++++++++++ .../readyToRun/stores/readyToRun.store.ts | 168 +++++ .../readyToRun/workflows/aiWorkflow.ts | 253 ++++++++ .../composables/TestEntryComposer.ts | 2 +- .../composables/WorkflowComposer.ts | 23 +- .../playwright/tests/ui/1-workflows.spec.ts | 8 +- .../playwright/tests/ui/10-undo-redo.spec.ts | 2 +- .../tests/ui/12-canvas-actions.spec.ts | 2 +- .../playwright/tests/ui/13-pinning.spec.ts | 14 +- ...14-data-transformation-expressions.spec.ts | 12 +- .../tests/ui/15-scheduler-node.spec.ts | 2 +- .../playwright/tests/ui/17-sharing.spec.ts | 10 +- .../tests/ui/18-user-management.spec.ts | 4 +- ...hook-ndv-marks-workflow-as-unsaved.spec.ts | 2 +- .../playwright/tests/ui/27-cloud.spec.ts | 12 +- .../playwright/tests/ui/28-debug.spec.ts | 2 +- .../tests/ui/28-resource-mapper.spec.ts | 2 +- .../53-workflow-production-checklist.spec.ts | 2 +- .../playwright/tests/ui/6-code-node.spec.ts | 6 +- .../tests/ui/7-workflow-actions.spec.ts | 2 +- ...tly-set-up-agent-model-shows-error.spec.ts | 2 +- .../building-blocks/02-canvas-actions.spec.ts | 2 +- .../playwright/tests/ui/evaluations.spec.ts | 2 +- .../testing/playwright/tests/ui/pdf.spec.ts | 2 +- .../tests/ui/security-notifications.spec.ts | 2 + .../tests/ui/task-runner-demo.spec.ts | 4 +- .../testing/playwright/utils/requirements.ts | 2 +- 39 files changed, 1786 insertions(+), 102 deletions(-) rename packages/frontend/editor-ui/src/{experiments/readyToRunWorkflowsV2/components/SimplifiedEmptyLayout.vue => app/components/layouts/EmptyStateLayout.vue} (86%) create mode 100644 packages/frontend/editor-ui/src/features/workflows/readyToRun/components/ReadyToRunButton.test.ts rename packages/frontend/editor-ui/src/{experiments/readyToRunWorkflowsV2/components/ReadyToRunV2Button.vue => features/workflows/readyToRun/components/ReadyToRunButton.vue} (77%) create mode 100644 packages/frontend/editor-ui/src/features/workflows/readyToRun/composables/useEmptyStateDetection.test.ts create mode 100644 packages/frontend/editor-ui/src/features/workflows/readyToRun/composables/useEmptyStateDetection.ts create mode 100644 packages/frontend/editor-ui/src/features/workflows/readyToRun/stores/readyToRun.store.test.ts create mode 100644 packages/frontend/editor-ui/src/features/workflows/readyToRun/stores/readyToRun.store.ts create mode 100644 packages/frontend/editor-ui/src/features/workflows/readyToRun/workflows/aiWorkflow.ts diff --git a/packages/frontend/@n8n/i18n/src/locales/en.json b/packages/frontend/@n8n/i18n/src/locales/en.json index c2df6d004bf..2ddb23a5ba1 100644 --- a/packages/frontend/@n8n/i18n/src/locales/en.json +++ b/packages/frontend/@n8n/i18n/src/locales/en.json @@ -3098,7 +3098,7 @@ "workflows.empty.preBuiltAgents": "Try a pre-built agent", "workflows.empty.shared-with-me": "No {resource} has been shared with you", "workflows.empty.shared-with-me.link": "Back to Personal", - "workflows.empty.readyToRunV2": "Try an AI workflow", + "workflows.empty.readyToRun": "Try an AI workflow", "workflows.list.easyAI": "Test the power of AI in n8n with this simple AI Agent Workflow", "workflows.list.error.fetching.one": "Error fetching workflow", "workflows.list.error.fetching": "Error fetching workflows", diff --git a/packages/frontend/@n8n/stores/src/constants.ts b/packages/frontend/@n8n/stores/src/constants.ts index 3f3e32ad60f..3d63dc969cb 100644 --- a/packages/frontend/@n8n/stores/src/constants.ts +++ b/packages/frontend/@n8n/stores/src/constants.ts @@ -40,6 +40,7 @@ export const STORES = { EXPERIMENT_READY_TO_RUN_WORKFLOWS_V2: 'readyToRunWorkflowsV2', EXPERIMENT_TEMPLATE_RECO_V2: 'templateRecoV2', PERSONALIZED_TEMPLATES_V3: 'personalizedTemplatesV3', + READY_TO_RUN: 'readyToRun', TEMPLATES_DATA_QUALITY: 'templatesDataQuality', BANNERS: 'banners', CONSENT: 'consent', diff --git a/packages/frontend/editor-ui/src/experiments/readyToRunWorkflowsV2/components/SimplifiedEmptyLayout.vue b/packages/frontend/editor-ui/src/app/components/layouts/EmptyStateLayout.vue similarity index 86% rename from packages/frontend/editor-ui/src/experiments/readyToRunWorkflowsV2/components/SimplifiedEmptyLayout.vue rename to packages/frontend/editor-ui/src/app/components/layouts/EmptyStateLayout.vue index a7ca9475cdf..69c92cefb3c 100644 --- a/packages/frontend/editor-ui/src/experiments/readyToRunWorkflowsV2/components/SimplifiedEmptyLayout.vue +++ b/packages/frontend/editor-ui/src/app/components/layouts/EmptyStateLayout.vue @@ -9,9 +9,13 @@ import { useSourceControlStore } from '@/features/integrations/sourceControl.ee/ import { getResourcePermissions } from '@n8n/permissions'; import { useProjectPages } from '@/features/collaboration/projects/composables/useProjectPages'; import { useToast } from '@/app/composables/useToast'; -import { useReadyToRunWorkflowsV2Store } from '../stores/readyToRunWorkflowsV2.store'; +import { useReadyToRunStore } from '@/features/workflows/readyToRun/stores/readyToRun.store'; import type { IUser } from 'n8n-workflow'; +const emit = defineEmits<{ + 'click:add': []; +}>(); + const route = useRoute(); const i18n = useI18n(); const toast = useToast(); @@ -19,7 +23,7 @@ const usersStore = useUsersStore(); const projectsStore = useProjectsStore(); const sourceControlStore = useSourceControlStore(); const projectPages = useProjectPages(); -const readyToRunWorkflowsV2Store = useReadyToRunWorkflowsV2Store(); +const readyToRunStore = useReadyToRunStore(); const isLoadingReadyToRun = ref(false); @@ -43,18 +47,14 @@ const emptyListDescription = computed(() => { } }); -const showReadyToRunV2Card = computed(() => { +const showReadyToRunCard = computed(() => { return ( isLoadingReadyToRun.value || - readyToRunWorkflowsV2Store.getCardVisibility( - projectPermissions.value.workflow.create, - readOnlyEnv.value, - false, // loading is false in simplified layout - ) + readyToRunStore.getCardVisibility(projectPermissions.value.workflow.create, readOnlyEnv.value) ); }); -const handleReadyToRunV2Click = async () => { +const handleReadyToRunClick = async () => { if (isLoadingReadyToRun.value) return; isLoadingReadyToRun.value = true; @@ -63,7 +63,7 @@ const handleReadyToRunV2Click = async () => { : (route.params.projectId as string); try { - await readyToRunWorkflowsV2Store.claimCreditsAndOpenWorkflow( + await readyToRunStore.claimCreditsAndOpenWorkflow( 'card', route.params.folderId as string, projectId, @@ -77,14 +77,10 @@ const handleReadyToRunV2Click = async () => { const addWorkflow = () => { emit('click:add'); }; - -const emit = defineEmits<{ - 'click:add': []; -}>();