From 354edf6886fa3cc5a59d317dcab59cc75e62dc2d Mon Sep 17 00:00:00 2001 From: OlegIvaniv Date: Wed, 8 Mar 2023 15:11:13 +0100 Subject: [PATCH] feat(editor): Redirect users to canvas if they don't have any workflows (#5629) * feat(editor): Bring new users to empty canvas * Fix failing e2e tests and revert CLI implementation * Revert editor-ui Interface changes * Try to mock /settings and /active * Revert canvas test changes, reload after executions in 20-workflow-executions * Make sure we include manual executiosn before running them in 20-workflow-executions * Make sure to re-init node view when replacing empty workflows route, show phantom loader --- cypress/e2e/1-workflows.cy.ts | 19 ++++++++--------- cypress/e2e/10-undo-redo.cy.ts | 1 - cypress/e2e/12-canvas.cy.ts | 1 - cypress/e2e/13-pinning.cy.ts | 1 - cypress/e2e/14-mapping.cy.ts | 1 - cypress/e2e/15-scheduler-node.cy.ts | 5 ----- cypress/e2e/16-webhook-node.cy.ts | 1 - cypress/e2e/17-sharing.cy.ts | 4 +--- cypress/e2e/17-workflow-tags.cy.ts | 2 -- cypress/e2e/19-execution.cy.ts | 3 --- cypress/e2e/2-credentials.cy.ts | 7 ------- cypress/e2e/20-workflow-executions.cy.ts | 1 - cypress/e2e/3-default-owner.cy.ts | 5 ----- cypress/e2e/4-node-creator.cy.ts | 3 +-- cypress/e2e/5-ndv.cy.ts | 9 ++++---- cypress/e2e/6-code-node.cy.ts | 1 - cypress/e2e/7-workflow-actions.cy.ts | 1 - cypress/e2e/8-http-request-node.cy.ts | 6 +----- cypress/pages/settings-users.ts | 8 +++---- cypress/pages/workflow.ts | 8 +++++++ cypress/support/commands.ts | 21 ++++++++++++------- cypress/support/e2e.ts | 12 +++++------ .../editor-ui/src/views/WorkflowsView.vue | 20 +++++++++++++----- 23 files changed, 62 insertions(+), 78 deletions(-) diff --git a/cypress/e2e/1-workflows.cy.ts b/cypress/e2e/1-workflows.cy.ts index 303ec68b5a..d341a762f2 100644 --- a/cypress/e2e/1-workflows.cy.ts +++ b/cypress/e2e/1-workflows.cy.ts @@ -27,13 +27,12 @@ describe('Workflows', () => { }); cy.signin({ email, password }); - cy.visit(WorkflowsPage.url); + cy.visit('/'); + cy.waitForLoad(); }); - it('should create a new workflow using empty state card', () => { - WorkflowsPage.getters.newWorkflowButtonCard().should('be.visible'); - WorkflowsPage.getters.newWorkflowButtonCard().click(); - + it('should land on empty canvas after registration', () => { + cy.url().should('include', WorkflowPage.url); cy.createFixtureWorkflow('Test_workflow_1.json', `Empty State Card Workflow ${uuid()}`); WorkflowPage.getters.workflowTags().should('contain.text', 'some-tag-1'); @@ -41,8 +40,6 @@ describe('Workflows', () => { }); it('should create multiple new workflows using add workflow button', () => { - WorkflowsPage.getters.newWorkflowButtonCard().should('not.exist'); - [...Array(multipleWorkflowsCount).keys()].forEach(() => { cy.visit(WorkflowsPage.url); WorkflowsPage.getters.createWorkflowButton().click(); @@ -95,8 +92,10 @@ describe('Workflows', () => { WorkflowsPage.getters.newWorkflowTemplateCard().should('be.visible'); }); - it('should contain empty state cards', () => { - WorkflowsPage.getters.newWorkflowButtonCard().should('be.visible'); - WorkflowsPage.getters.newWorkflowTemplateCard().should('be.visible'); + it('should redirect to new canvas if no workflows', () => { + cy.wait(1000); + cy.visit(WorkflowsPage.url); + cy.wait(1000); + cy.url().should('include', WorkflowPage.url); }); }); diff --git a/cypress/e2e/10-undo-redo.cy.ts b/cypress/e2e/10-undo-redo.cy.ts index b8f238b8f2..8f9b90d68c 100644 --- a/cypress/e2e/10-undo-redo.cy.ts +++ b/cypress/e2e/10-undo-redo.cy.ts @@ -17,7 +17,6 @@ describe('Undo/Redo', () => { beforeEach(() => { WorkflowPage.actions.visit(); - cy.waitForLoad(); }); it('should undo/redo adding nodes', () => { diff --git a/cypress/e2e/12-canvas.cy.ts b/cypress/e2e/12-canvas.cy.ts index e0f984d13a..3f78e49590 100644 --- a/cypress/e2e/12-canvas.cy.ts +++ b/cypress/e2e/12-canvas.cy.ts @@ -28,7 +28,6 @@ describe('Canvas Actions', () => { beforeEach(() => { WorkflowPage.actions.visit(); - cy.waitForLoad(); }); it('should render canvas', () => { diff --git a/cypress/e2e/13-pinning.cy.ts b/cypress/e2e/13-pinning.cy.ts index cea2c4fef7..8a3ea4a7c8 100644 --- a/cypress/e2e/13-pinning.cy.ts +++ b/cypress/e2e/13-pinning.cy.ts @@ -11,7 +11,6 @@ describe('Data pinning', () => { beforeEach(() => { workflowPage.actions.visit(); - cy.waitForLoad(); }); it('Should be able to pin node output', () => { diff --git a/cypress/e2e/14-mapping.cy.ts b/cypress/e2e/14-mapping.cy.ts index 6b8cd6282a..73e628216e 100644 --- a/cypress/e2e/14-mapping.cy.ts +++ b/cypress/e2e/14-mapping.cy.ts @@ -16,7 +16,6 @@ describe('Data mapping', () => { beforeEach(() => { workflowPage.actions.visit(); - cy.waitForLoad(); cy.window() // @ts-ignore diff --git a/cypress/e2e/15-scheduler-node.cy.ts b/cypress/e2e/15-scheduler-node.cy.ts index 7ba5acec3e..ae3de65c26 100644 --- a/cypress/e2e/15-scheduler-node.cy.ts +++ b/cypress/e2e/15-scheduler-node.cy.ts @@ -8,12 +8,9 @@ describe('Schedule Trigger node', async () => { beforeEach(() => { cy.resetAll(); cy.skipSetup(); - cy.visit(workflowsPage.url); }); it('should execute and return the execution timestamp', () => { - workflowsPage.actions.createWorkflowFromCard(); - cy.waitForLoad(); workflowPage.actions.addInitialNodeToCanvas('Schedule Trigger'); workflowPage.actions.openNode('Schedule Trigger'); ndv.actions.execute(); @@ -22,8 +19,6 @@ describe('Schedule Trigger node', async () => { }); it('should execute once per second when activated', () => { - workflowsPage.actions.createWorkflowFromCard(); - cy.waitForLoad(); workflowPage.actions.renameWorkflow('Schedule Trigger Workflow'); workflowPage.actions.addInitialNodeToCanvas('Schedule Trigger'); workflowPage.actions.openNode('Schedule Trigger'); diff --git a/cypress/e2e/16-webhook-node.cy.ts b/cypress/e2e/16-webhook-node.cy.ts index 83c99cb982..7da46167ec 100644 --- a/cypress/e2e/16-webhook-node.cy.ts +++ b/cypress/e2e/16-webhook-node.cy.ts @@ -98,7 +98,6 @@ describe('Webhook Trigger node', async () => { beforeEach(() => { workflowPage.actions.visit(); - cy.waitForLoad(); cy.window() // @ts-ignore diff --git a/cypress/e2e/17-sharing.cy.ts b/cypress/e2e/17-sharing.cy.ts index ff3456f7dc..1a8b0a3d00 100644 --- a/cypress/e2e/17-sharing.cy.ts +++ b/cypress/e2e/17-sharing.cy.ts @@ -80,9 +80,7 @@ describe('Sharing', () => { credentialsModal.actions.save(); credentialsModal.actions.close(); - cy.visit(workflowsPage.url); - workflowsPage.getters.newWorkflowButtonCard().click(); - cy.waitForLoad(); + workflowPage.actions.visit(); workflowPage.actions.setWorkflowName('Workflow W1'); workflowPage.actions.addInitialNodeToCanvas('Manual Trigger'); workflowPage.actions.addNodeToCanvas('Notion', true, true); diff --git a/cypress/e2e/17-workflow-tags.cy.ts b/cypress/e2e/17-workflow-tags.cy.ts index 87926bf0f2..8e14897508 100644 --- a/cypress/e2e/17-workflow-tags.cy.ts +++ b/cypress/e2e/17-workflow-tags.cy.ts @@ -8,8 +8,6 @@ describe('Workflow tags', () => { beforeEach(() => { cy.resetAll(); cy.skipSetup(); - wf.actions.visit(); - cy.waitForLoad(); }); it('should create and attach tags inline', () => { diff --git a/cypress/e2e/19-execution.cy.ts b/cypress/e2e/19-execution.cy.ts index 9fcf27d91a..6ad2ce6592 100644 --- a/cypress/e2e/19-execution.cy.ts +++ b/cypress/e2e/19-execution.cy.ts @@ -9,9 +9,6 @@ describe('Execution', () => { beforeEach(() => { cy.resetAll(); cy.skipSetup(); - // Import workflow - workflowsPage.getters.newWorkflowButtonCard().click(); - cy.waitForLoad(); }); it('should test manual workflow', () => { diff --git a/cypress/e2e/2-credentials.cy.ts b/cypress/e2e/2-credentials.cy.ts index 3fe9dd1968..e281512e09 100644 --- a/cypress/e2e/2-credentials.cy.ts +++ b/cypress/e2e/2-credentials.cy.ts @@ -112,7 +112,6 @@ describe('Credentials', () => { it('should create credentials from NDV for node with multiple auth options', () => { workflowPage.actions.visit(); - cy.waitForLoad(); workflowPage.actions.addNodeToCanvas(SCHEDULE_TRIGGER_NODE_NAME); workflowPage.actions.addNodeToCanvas(GMAIL_NODE_NAME); workflowPage.getters.canvasNodes().last().click(); @@ -129,7 +128,6 @@ describe('Credentials', () => { it('should show multiple credential types in the same dropdown', () => { workflowPage.actions.visit(); - cy.waitForLoad(); workflowPage.actions.addNodeToCanvas(SCHEDULE_TRIGGER_NODE_NAME); workflowPage.actions.addNodeToCanvas(GMAIL_NODE_NAME); workflowPage.getters.canvasNodes().last().click(); @@ -155,7 +153,6 @@ describe('Credentials', () => { it('should correctly render required and optional credentials', () => { workflowPage.actions.visit(); - cy.waitForLoad(); workflowPage.actions.addNodeToCanvas(PIPEDRIVE_NODE_NAME, true, true); cy.get('body').type('{downArrow}'); cy.get('body').type('{enter}'); @@ -180,7 +177,6 @@ describe('Credentials', () => { it('should create credentials from NDV for node with no auth options', () => { workflowPage.actions.visit(); - cy.waitForLoad(); workflowPage.actions.addNodeToCanvas(SCHEDULE_TRIGGER_NODE_NAME); workflowPage.actions.addNodeToCanvas(TRELLO_NODE_NAME); workflowPage.getters.canvasNodes().last().click(); @@ -194,7 +190,6 @@ describe('Credentials', () => { it('should delete credentials from NDV', () => { workflowPage.actions.visit(); - cy.waitForLoad(); workflowPage.actions.addNodeToCanvas(SCHEDULE_TRIGGER_NODE_NAME); workflowPage.actions.addNodeToCanvas(NOTION_NODE_NAME); workflowPage.getters.canvasNodes().last().click(); @@ -214,7 +209,6 @@ describe('Credentials', () => { it('should rename credentials from NDV', () => { workflowPage.actions.visit(); - cy.waitForLoad(); workflowPage.actions.addNodeToCanvas(SCHEDULE_TRIGGER_NODE_NAME); workflowPage.actions.addNodeToCanvas(TRELLO_NODE_NAME); workflowPage.getters.canvasNodes().last().click(); @@ -235,7 +229,6 @@ describe('Credentials', () => { it('should setup generic authentication for HTTP node', () => { workflowPage.actions.visit(); - cy.waitForLoad(); workflowPage.actions.addNodeToCanvas(SCHEDULE_TRIGGER_NODE_NAME); workflowPage.actions.addNodeToCanvas(HTTP_REQUEST_NODE_NAME); workflowPage.getters.canvasNodes().last().click(); diff --git a/cypress/e2e/20-workflow-executions.cy.ts b/cypress/e2e/20-workflow-executions.cy.ts index d619659ac3..1e40b7dcc4 100644 --- a/cypress/e2e/20-workflow-executions.cy.ts +++ b/cypress/e2e/20-workflow-executions.cy.ts @@ -13,7 +13,6 @@ describe('Current Workflow Executions', () => { beforeEach(() => { workflowPage.actions.visit(); - cy.waitForLoad(); cy.createFixtureWorkflow('Test_workflow_4_executions_view.json', `My test workflow`); createMockExecutions(); }); diff --git a/cypress/e2e/3-default-owner.cy.ts b/cypress/e2e/3-default-owner.cy.ts index 95b83b043f..1871dd9c6c 100644 --- a/cypress/e2e/3-default-owner.cy.ts +++ b/cypress/e2e/3-default-owner.cy.ts @@ -37,11 +37,6 @@ describe('Default owner', () => { it('should be able to create workflows', () => { cy.resetAll(); cy.skipSetup(); - cy.visit('/'); - workflowsPage.getters.newWorkflowButtonCard().should('be.visible'); - workflowsPage.getters.newWorkflowButtonCard().click(); - - cy.waitForLoad(); cy.createFixtureWorkflow('Test_workflow_1.json', `Test workflow`); // reload page, ensure owner still has access diff --git a/cypress/e2e/4-node-creator.cy.ts b/cypress/e2e/4-node-creator.cy.ts index a6e986c645..2054209f4f 100644 --- a/cypress/e2e/4-node-creator.cy.ts +++ b/cypress/e2e/4-node-creator.cy.ts @@ -13,8 +13,7 @@ describe('Node Creator', () => { }); beforeEach(() => { - cy.visit(nodeCreatorFeature.url); - cy.waitForLoad(); + WorkflowPage.actions.visit(); }); it('should open node creator on trigger tab if no trigger is on canvas', () => { diff --git a/cypress/e2e/5-ndv.cy.ts b/cypress/e2e/5-ndv.cy.ts index 3a57d51bcf..a8f0d4cc9c 100644 --- a/cypress/e2e/5-ndv.cy.ts +++ b/cypress/e2e/5-ndv.cy.ts @@ -5,12 +5,13 @@ const workflowPage = new WorkflowPage(); const ndv = new NDV(); describe('NDV', () => { - - beforeEach(() => { + before(() => { cy.resetAll(); cy.skipSetup(); - cy.visit(workflowPage.url) - cy.waitForLoad(); + + }); + beforeEach(() => { + workflowPage.actions.visit(); workflowPage.actions.renameWorkflow(uuid()); workflowPage.actions.saveWorkflowOnButtonClick(); }); diff --git a/cypress/e2e/6-code-node.cy.ts b/cypress/e2e/6-code-node.cy.ts index 0e4a16d933..7fa465d2ee 100644 --- a/cypress/e2e/6-code-node.cy.ts +++ b/cypress/e2e/6-code-node.cy.ts @@ -11,7 +11,6 @@ describe('Code node', () => { }); it('should execute the placeholder in all-items mode successfully', () => { - WorkflowPage.actions.visit(); WorkflowPage.actions.addInitialNodeToCanvas('Manual'); WorkflowPage.actions.addNodeToCanvas('Code'); WorkflowPage.actions.openNode('Code'); diff --git a/cypress/e2e/7-workflow-actions.cy.ts b/cypress/e2e/7-workflow-actions.cy.ts index 8896953c3b..a56ff58622 100644 --- a/cypress/e2e/7-workflow-actions.cy.ts +++ b/cypress/e2e/7-workflow-actions.cy.ts @@ -21,7 +21,6 @@ describe('Workflow Actions', () => { beforeEach(() => { WorkflowPage.actions.visit(); - cy.waitForLoad(); }); it('should be able to save on button click', () => { diff --git a/cypress/e2e/8-http-request-node.cy.ts b/cypress/e2e/8-http-request-node.cy.ts index 11c9619472..9c3cce11e8 100644 --- a/cypress/e2e/8-http-request-node.cy.ts +++ b/cypress/e2e/8-http-request-node.cy.ts @@ -1,6 +1,5 @@ -import { WorkflowPage, WorkflowsPage, NDV } from '../pages'; +import { WorkflowPage, NDV } from '../pages'; -const workflowsPage = new WorkflowsPage(); const workflowPage = new WorkflowPage(); const ndv = new NDV(); @@ -11,9 +10,6 @@ describe('HTTP Request node', () => { }); it('should make a request with a URL and receive a response', () => { - cy.visit(workflowsPage.url); - - workflowsPage.actions.createWorkflowFromCard(); workflowPage.actions.addInitialNodeToCanvas('Manual'); workflowPage.actions.addNodeToCanvas('HTTP Request'); workflowPage.actions.openNode('HTTP Request'); diff --git a/cypress/pages/settings-users.ts b/cypress/pages/settings-users.ts index e52d43a809..4d6903c858 100644 --- a/cypress/pages/settings-users.ts +++ b/cypress/pages/settings-users.ts @@ -1,9 +1,9 @@ import { SettingsSidebar } from './sidebar/settings-sidebar'; import { MainSidebar } from './sidebar/main-sidebar'; -import { WorkflowsPage } from './workflows'; +import { WorkflowPage } from './workflow'; import { BasePage } from './base'; -const workflowsPage = new WorkflowsPage(); +const workflowPage = new WorkflowPage(); const mainSidebar = new MainSidebar(); const settingsSidebar = new SettingsSidebar(); @@ -30,7 +30,7 @@ export class SettingsUsersPage extends BasePage { goToOwnerSetup: () => this.getters.setUpOwnerButton().click(), loginAndVisit: (email: string, password: string, isOwner: boolean) => { cy.signin({ email, password }); - cy.visit(workflowsPage.url); + workflowPage.actions.visit(); mainSidebar.actions.goToSettings(); if (isOwner) { settingsSidebar.getters.menuItem('Users').click(); @@ -39,7 +39,7 @@ export class SettingsUsersPage extends BasePage { settingsSidebar.getters.menuItem('Users').should('not.exist'); // Should be redirected to workflows page if trying to access UM url cy.visit('/settings/users'); - cy.url().should('match', new RegExp(workflowsPage.url)); + cy.url().should('match', new RegExp(workflowPage.url)); } }, opedDeleteDialog: (email: string) => { diff --git a/cypress/pages/workflow.ts b/cypress/pages/workflow.ts index f5167e01cb..2dc647e4bf 100644 --- a/cypress/pages/workflow.ts +++ b/cypress/pages/workflow.ts @@ -256,12 +256,20 @@ export class WorkflowPage extends BasePage { turnOnManualExecutionSaving: () => { this.getters.workflowMenu().click(); this.getters.workflowMenuItemSettings().click(); + cy.get('.el-loading-mask').should('not.be.visible'); this.getters .workflowSettingsSaveManualExecutionsSelect() .find('li:contains("Yes")') .click({ force: true }); + + this.getters.workflowSettingsSaveManualExecutionsSelect().should('contain', 'Yes'); this.getters.workflowSettingsSaveButton().click(); this.getters.successToast().should('exist'); + + this.getters.workflowMenu().click(); + this.getters.workflowMenuItemSettings().click(); + this.getters.workflowSettingsSaveManualExecutionsSelect().should('contain', 'Yes'); + this.getters.workflowSettingsSaveButton().click(); }, }; } diff --git a/cypress/support/commands.ts b/cypress/support/commands.ts index 2497b3abec..233c74ee55 100644 --- a/cypress/support/commands.ts +++ b/cypress/support/commands.ts @@ -24,7 +24,7 @@ // -- This will overwrite an existing command -- // Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... }) import 'cypress-real-events'; -import { WorkflowsPage, SigninPage, SignupPage, SettingsUsersPage } from '../pages'; +import { WorkflowsPage, SigninPage, SignupPage, SettingsUsersPage, WorkflowPage } from '../pages'; import { N8N_AUTH_COOKIE } from '../constants'; import { WorkflowPage as WorkflowPageClass } from '../pages/workflow'; import { MessageBox } from '../pages/modals/message-box'; @@ -54,13 +54,13 @@ Cypress.Commands.add( ); Cypress.Commands.add('waitForLoad', () => { - cy.getByTestId('node-view-loader', { timeout: 10000 }).should('not.exist'); - cy.get('.el-loading-mask', { timeout: 10000 }).should('not.exist'); + cy.getByTestId('node-view-loader', { timeout: 20000 }).should('not.exist'); + cy.get('.el-loading-mask', { timeout: 20000 }).should('not.exist'); }); Cypress.Commands.add('signin', ({ email, password }) => { const signinPage = new SigninPage(); - const workflowsPage = new WorkflowsPage(); + const workflowPage = new WorkflowPage(); cy.session( [email, password], @@ -74,7 +74,10 @@ Cypress.Commands.add('signin', ({ email, password }) => { }); // we should be redirected to /workflows - cy.url().should('include', workflowsPage.url); + cy.visit(workflowPage.url); + cy.url().should('include', workflowPage.url); + cy.intercept('GET', '/rest/workflows/new').as('loading'); + cy.wait('@loading'); }, { validate() { @@ -158,7 +161,7 @@ Cypress.Commands.add('inviteUsers', ({ instanceOwner, users }) => { Cypress.Commands.add('skipSetup', () => { const signupPage = new SignupPage(); - const workflowsPage = new WorkflowsPage(); + const workflowPage = new WorkflowPage(); const Confirmation = new MessageBox(); cy.visit(signupPage.url); @@ -171,8 +174,10 @@ Cypress.Commands.add('skipSetup', () => { Confirmation.getters.header().should('contain.text', 'Skip owner account setup?'); Confirmation.actions.confirm(); - // we should be redirected to /workflows - cy.url().should('include', workflowsPage.url); + // we should be redirected to empty canvas + cy.intercept('GET', '/rest/workflows/new').as('loading'); + cy.url().should('include', workflowPage.url); + cy.wait('@loading'); } else { cy.log('User already signed up'); } diff --git a/cypress/support/e2e.ts b/cypress/support/e2e.ts index 3977b48210..21236be4f1 100644 --- a/cypress/support/e2e.ts +++ b/cypress/support/e2e.ts @@ -22,22 +22,20 @@ import CustomCredential from '../fixtures/Custom_credential.json'; // Load custom nodes and credentials fixtures beforeEach(() => { cy.intercept('GET', '/types/nodes.json', (req) => { - req.continue((res) => { - const nodes = res.body; + req.on('response', (res) => { + const nodes = res.body || []; res.headers['cache-control'] = 'no-cache, no-store'; nodes.push(CustomNodeFixture, CustomNodeWithN8nCredentialFixture, CustomNodeWithCustomCredentialFixture); - res.send(nodes); }); }).as('nodesIntercept'); cy.intercept('GET', '/types/credentials.json', (req) => { - req.continue((res) => { - const credentials = res.body; + req.on('response', (res) => { + const credentials = res.body || []; res.headers['cache-control'] = 'no-cache, no-store'; credentials.push(CustomCredential); - res.send(credentials); - }); + }) }).as('credentialsIntercept'); }) diff --git a/packages/editor-ui/src/views/WorkflowsView.vue b/packages/editor-ui/src/views/WorkflowsView.vue index cd7ac10133..624fb52f52 100644 --- a/packages/editor-ui/src/views/WorkflowsView.vue +++ b/packages/editor-ui/src/views/WorkflowsView.vue @@ -3,11 +3,11 @@ ref="layout" resource-key="workflows" :resources="allWorkflows" - :initialize="initialize" :filters="filters" :additional-filters-handler="onFilter" :show-aside="allWorkflows.length > 0" :shareable="isShareable" + :initialize="initialize" @click:add="addWorkflow" @update:filters="filters = $event" > @@ -148,7 +148,7 @@ const StatusFilter = { ALL: '', }; -export default mixins(showMessage, debounceHelper, newVersions).extend({ +const WorkflowsView = mixins(showMessage, debounceHelper, newVersions).extend({ name: 'WorkflowsView', components: { ResourcesListLayout, @@ -224,12 +224,20 @@ export default mixins(showMessage, debounceHelper, newVersions).extend({ } }, async initialize() { - this.usersStore.fetchUsers(); // Can be loaded in the background, used for filtering - - return await Promise.all([ + await Promise.all([ + this.usersStore.fetchUsers(), this.workflowsStore.fetchAllWorkflows(), this.workflowsStore.fetchActiveWorkflows(), ]); + + // If the user has no workflows and is not participating in the demo experiment, + // redirect to the new workflow view + if (!this.isDemoTest && this.allWorkflows.length === 0) { + this.uiStore.nodeViewInitialized = false; + this.$router.replace({ name: VIEWS.NEW_WORKFLOW }); + } + + return Promise.resolve(); }, onClickTag(tagId: string, event: PointerEvent) { if (!this.filters.tags.includes(tagId)) { @@ -273,6 +281,8 @@ export default mixins(showMessage, debounceHelper, newVersions).extend({ this.usersStore.showPersonalizationSurvey(); }, }); + +export default WorkflowsView;