diff --git a/cypress/support/commands.ts b/cypress/support/commands.ts
index 35f100fded..e27468cd55 100644
--- a/cypress/support/commands.ts
+++ b/cypress/support/commands.ts
@@ -70,6 +70,10 @@ Cypress.Commands.add('signin', ({ email, password }) => {
})
.then((response) => {
Cypress.env('currentUserId', response.body.data.id);
+
+ cy.window().then((win) => {
+ win.localStorage.setItem('NodeView.switcher.discovered', 'true'); // @TODO Remove this once the switcher is removed
+ });
});
});
});
diff --git a/packages/design-system/src/components/N8nActionDropdown/ActionDropdown.vue b/packages/design-system/src/components/N8nActionDropdown/ActionDropdown.vue
index 7284dea7dd..4b3f4d7df4 100644
--- a/packages/design-system/src/components/N8nActionDropdown/ActionDropdown.vue
+++ b/packages/design-system/src/components/N8nActionDropdown/ActionDropdown.vue
@@ -117,6 +117,9 @@ defineExpose({ open, close });
{{ item.label }}
+
+ {{ item.badge }}
+
();
const tagsEventBus = createEventBus();
const sourceControlModalEventBus = createEventBus();
-const nodeViewSwitcher = useLocalStorage('NodeView.switcher', '');
-const nodeViewVersion = useLocalStorage('NodeView.version', '1');
-
-const isNodeViewSwitcherEnabled = computed(() => {
- return (
- import.meta.env.DEV ||
- nodeViewSwitcher.value === 'true' ||
- settingsStore.deploymentType === 'n8n-internal'
- );
-});
+const {
+ nodeViewVersion,
+ nodeViewSwitcherDiscovered,
+ isNodeViewDiscoveryTooltipVisible,
+ switchNodeViewVersion,
+ setNodeViewSwitcherDropdownOpened,
+ setNodeViewSwitcherDiscovered,
+} = useNodeViewVersionSwitcher();
const hasChanged = (prev: string[], curr: string[]) => {
if (prev.length !== curr.length) {
@@ -189,16 +187,17 @@ const workflowMenuItems = computed(() => {
disabled: !onWorkflowPage.value || isNewWorkflow.value,
});
- if (isNodeViewSwitcherEnabled.value) {
- actions.push({
- id: WORKFLOW_MENU_ACTIONS.SWITCH_NODE_VIEW_VERSION,
- label:
- nodeViewVersion.value === '2'
- ? locale.baseText('menuActions.switchToOldNodeViewVersion')
- : locale.baseText('menuActions.switchToNewNodeViewVersion'),
- disabled: !onWorkflowPage.value,
- });
- }
+ actions.push({
+ id: WORKFLOW_MENU_ACTIONS.SWITCH_NODE_VIEW_VERSION,
+ ...(nodeViewSwitcherDiscovered.value
+ ? {}
+ : { badge: locale.baseText('menuActions.badge.new') }),
+ label:
+ nodeViewVersion.value === '2'
+ ? locale.baseText('menuActions.switchToOldNodeViewVersion')
+ : locale.baseText('menuActions.switchToNewNodeViewVersion'),
+ disabled: !onWorkflowPage.value,
+ });
if ((workflowPermissions.value.delete && !props.readOnly) || isNewWorkflow.value) {
actions.push({
@@ -399,6 +398,10 @@ async function handleFileImport(): Promise {
}
}
+function onWorkflowMenuOpen() {
+ setNodeViewSwitcherDropdownOpened();
+}
+
async function onWorkflowMenuSelect(action: WORKFLOW_MENU_ACTIONS): Promise {
switch (action) {
case WORKFLOW_MENU_ACTIONS.DUPLICATE: {
@@ -499,6 +502,8 @@ async function onWorkflowMenuSelect(action: WORKFLOW_MENU_ACTIONS): Promise
-
+
+
+
+ {{ $locale.baseText('menuActions.nodeViewDiscovery.tooltip') }}
+
+
diff --git a/packages/editor-ui/src/composables/useNodeViewVersionSwitcher.ts b/packages/editor-ui/src/composables/useNodeViewVersionSwitcher.ts
new file mode 100644
index 0000000000..8e0690d692
--- /dev/null
+++ b/packages/editor-ui/src/composables/useNodeViewVersionSwitcher.ts
@@ -0,0 +1,63 @@
+import { computed, ref } from 'vue';
+import { useLocalStorage } from '@vueuse/core';
+import { useSettingsStore } from '@/stores/settings.store';
+import { useTelemetry } from '@/composables/useTelemetry';
+import { useWorkflowsStore } from '@/stores/workflows.store';
+import { debouncedRef } from '@vueuse/core';
+
+export function useNodeViewVersionSwitcher() {
+ const workflowsStore = useWorkflowsStore();
+ const settingsStore = useSettingsStore();
+ const telemetry = useTelemetry();
+
+ const isNewUser = computed(() => workflowsStore.activeWorkflows.length === 0);
+
+ const nodeViewVersion = useLocalStorage(
+ 'NodeView.version',
+ settingsStore.deploymentType === 'n8n-internal' ? '2' : '1',
+ );
+
+ const nodeViewSwitcherDropdownOpened = ref(false);
+ function setNodeViewSwitcherDropdownOpened() {
+ nodeViewSwitcherDropdownOpened.value = true;
+ }
+
+ const nodeViewSwitcherDiscovered = useLocalStorage('NodeView.switcher.discovered', false);
+ function setNodeViewSwitcherDiscovered() {
+ nodeViewSwitcherDiscovered.value = true;
+ }
+
+ const isNodeViewDiscoveryTooltipVisibleRaw = computed(
+ () =>
+ nodeViewVersion.value !== '2' &&
+ !(
+ isNewUser.value ||
+ nodeViewSwitcherDropdownOpened.value ||
+ nodeViewSwitcherDiscovered.value
+ ),
+ );
+
+ const isNodeViewDiscoveryTooltipVisible = debouncedRef(
+ isNodeViewDiscoveryTooltipVisibleRaw,
+ 3000,
+ );
+
+ function switchNodeViewVersion() {
+ const toVersion = nodeViewVersion.value === '1' ? '2' : '1';
+
+ telemetry.track('User switched canvas version', {
+ to_version: toVersion,
+ });
+
+ nodeViewVersion.value = toVersion;
+ }
+
+ return {
+ nodeViewVersion,
+ nodeViewSwitcherDiscovered,
+ isNodeViewDiscoveryTooltipVisible,
+ setNodeViewSwitcherDropdownOpened,
+ setNodeViewSwitcherDiscovered,
+ switchNodeViewVersion,
+ };
+}
diff --git a/packages/editor-ui/src/plugins/i18n/locales/en.json b/packages/editor-ui/src/plugins/i18n/locales/en.json
index e975ebb12c..2a40bfbeb6 100644
--- a/packages/editor-ui/src/plugins/i18n/locales/en.json
+++ b/packages/editor-ui/src/plugins/i18n/locales/en.json
@@ -906,6 +906,8 @@
"menuActions.delete": "Delete",
"menuActions.switchToNewNodeViewVersion": "Switch to new canvas",
"menuActions.switchToOldNodeViewVersion": "Switch to old canvas",
+ "menuActions.badge.new": "NEW",
+ "menuActions.nodeViewDiscovery.tooltip": "Try our new, more performant canvas",
"multipleParameter.addItem": "Add item",
"multipleParameter.currentlyNoItemsExist": "Currently no items exist",
"multipleParameter.deleteItem": "Delete item",
diff --git a/packages/editor-ui/src/views/NodeViewSwitcher.vue b/packages/editor-ui/src/views/NodeViewSwitcher.vue
index adcc58fc98..d40f92e626 100644
--- a/packages/editor-ui/src/views/NodeViewSwitcher.vue
+++ b/packages/editor-ui/src/views/NodeViewSwitcher.vue
@@ -1,5 +1,4 @@