diff --git a/packages/frontend/@n8n/i18n/src/locales/en.json b/packages/frontend/@n8n/i18n/src/locales/en.json index bec3227f1a..d27f49d3d2 100644 --- a/packages/frontend/@n8n/i18n/src/locales/en.json +++ b/packages/frontend/@n8n/i18n/src/locales/en.json @@ -2837,7 +2837,7 @@ "dataStore.dataStores": "Data Tables", "dataStore.empty.label": "You don't have any data tables yet", "dataStore.empty.description": "Once you create data tables for your projects, they will appear here", - "dataStore.empty.button.label": "Create data table in \"{projectName}\"", + "dataStore.empty.button.label": "Create Data Table in \"{projectName}\"", "dataStore.card.size": "{size}MB", "dataStore.card.column.count": "{count} column | {count} columns", "dataStore.card.row.count": "{count} record | {count} records", @@ -2847,9 +2847,9 @@ "dataStore.sort.nameDesc": "Sort by name (Z-A)", "dataStore.search.placeholder": "Search", "dataStore.error.fetching": "Error loading data tables", - "dataStore.add.title": "Create data table", + "dataStore.add.title": "Create new data table", "dataStore.add.description": "Set up a new data table to organize and manage your data.", - "dataStore.add.button.label": "Create data table", + "dataStore.add.button.label": "Create Data Table", "dataStore.add.input.name.label": "Data Table Name", "dataStore.add.input.name.placeholder": "Enter data table name", "dataStore.add.error": "Error creating data table", diff --git a/packages/frontend/editor-ui/src/components/Projects/ProjectHeader.test.ts b/packages/frontend/editor-ui/src/components/Projects/ProjectHeader.test.ts index 8955d8f1b0..ed64094b95 100644 --- a/packages/frontend/editor-ui/src/components/Projects/ProjectHeader.test.ts +++ b/packages/frontend/editor-ui/src/components/Projects/ProjectHeader.test.ts @@ -44,10 +44,27 @@ const projectTabsSpy = vi.fn().mockReturnValue({ render: vi.fn(), }); +const ProjectCreateResourceStub = { + props: { + actions: Array, + }, + template: ` +
+
+ + +
+ +
+
+ `, +}; + const renderComponent = createComponentRenderer(ProjectHeader, { global: { stubs: { ProjectTabs: projectTabsSpy, + ProjectCreateResource: ProjectCreateResourceStub, }, }, }); @@ -69,6 +86,7 @@ describe('ProjectHeader', () => { projectsStore.teamProjectsLimit = -1; settingsStore.settings.folders = { enabled: false }; + settingsStore.isDataStoreFeatureEnabled = true; // Setup default moduleTabs structure uiStore.moduleTabs = { @@ -436,4 +454,21 @@ describe('ProjectHeader', () => { ); }); }); + + describe('ProjectCreateResource', () => { + it('should render menu items', () => { + const { getByTestId } = renderComponent(); + const actionsContainer = getByTestId('add-resource-actions'); + expect(actionsContainer).toBeInTheDocument(); + expect(actionsContainer.children).toHaveLength(2); + }); + + it('should not render datastore menu item if data store feature is disabled', () => { + settingsStore.isDataStoreFeatureEnabled = false; + const { getByTestId } = renderComponent(); + const actionsContainer = getByTestId('add-resource-actions'); + expect(actionsContainer).toBeInTheDocument(); + expect(actionsContainer.children).toHaveLength(1); + }); + }); }); diff --git a/packages/frontend/editor-ui/src/components/Projects/ProjectHeader.vue b/packages/frontend/editor-ui/src/components/Projects/ProjectHeader.vue index b3e518a131..d2c71a3fa8 100644 --- a/packages/frontend/editor-ui/src/components/Projects/ProjectHeader.vue +++ b/packages/frontend/editor-ui/src/components/Projects/ProjectHeader.vue @@ -20,12 +20,7 @@ import { type IconName } from '@n8n/design-system/components/N8nIcon/icons'; import type { IUser } from 'n8n-workflow'; import { type IconOrEmoji, isIconOrEmoji } from '@n8n/design-system/components/N8nIconPicker/types'; import { useUIStore } from '@/stores/ui.store'; - -export type CustomAction = { - id: string; - label: string; - disabled?: boolean; -}; +import { PROJECT_DATA_STORES } from '@/features/dataStore/constants'; const route = useRoute(); const router = useRouter(); @@ -37,17 +32,8 @@ const uiStore = useUIStore(); const projectPages = useProjectPages(); -type Props = { - customActions?: CustomAction[]; -}; - -const props = withDefaults(defineProps(), { - customActions: () => [], -}); - const emit = defineEmits<{ createFolder: []; - customActionSelected: [actionId: string, projectId: string]; }>(); const headerIcon = computed((): IconOrEmoji => { @@ -122,6 +108,7 @@ const ACTION_TYPES = { WORKFLOW: 'workflow', CREDENTIAL: 'credential', FOLDER: 'folder', + DATA_STORE: 'dataStore', } as const; type ActionTypes = (typeof ACTION_TYPES)[keyof typeof ACTION_TYPES]; @@ -155,16 +142,17 @@ const menu = computed(() => { }); } - // Append custom actions - if (props.customActions?.length) { - props.customActions.forEach((customAction) => { - items.push({ - value: customAction.id, - label: customAction.label, - disabled: customAction.disabled ?? false, - }); + if (settingsStore.isDataStoreFeatureEnabled) { + // TODO: this should probably be moved to the module descriptor as a setting + items.push({ + value: ACTION_TYPES.DATA_STORE, + label: i18n.baseText('dataStore.add.button.label'), + disabled: + sourceControlStore.preferences.branchReadOnly || + !getResourcePermissions(homeProject.value?.scopes)?.dataStore?.create, }); } + return items; }); @@ -196,6 +184,12 @@ const actions: Record void> = { [ACTION_TYPES.FOLDER]: () => { emit('createFolder'); }, + [ACTION_TYPES.DATA_STORE]: (projectId: string) => { + void router.push({ + name: PROJECT_DATA_STORES, + params: { projectId, new: 'new' }, + }); + }, } as const; const pageType = computed(() => { @@ -267,12 +261,6 @@ const onSelect = (action: string) => { return; } - // Check if this is a custom action - if (!executableAction) { - emit('customActionSelected', action, homeProject.value.id); - return; - } - executableAction(homeProject.value.id); }; diff --git a/packages/frontend/editor-ui/src/features/dataStore/DataStoreView.vue b/packages/frontend/editor-ui/src/features/dataStore/DataStoreView.vue index 6ddf34be85..6b07d518a6 100644 --- a/packages/frontend/editor-ui/src/features/dataStore/DataStoreView.vue +++ b/packages/frontend/editor-ui/src/features/dataStore/DataStoreView.vue @@ -1,13 +1,12 @@