mirror of
https://github.com/Abdulazizzn/n8n-enterprise-unlocked.git
synced 2025-12-18 10:31:15 +00:00
feat(editor): Address data tables UI feedback (no-changelog) (#18566)
Co-authored-by: Milorad FIlipović <milorad@n8n.io>
This commit is contained in:
@@ -44,10 +44,27 @@ const projectTabsSpy = vi.fn().mockReturnValue({
|
||||
render: vi.fn(),
|
||||
});
|
||||
|
||||
const ProjectCreateResourceStub = {
|
||||
props: {
|
||||
actions: Array,
|
||||
},
|
||||
template: `
|
||||
<div>
|
||||
<div data-test-id="add-resource"><button role="button"></button></div>
|
||||
<button data-test-id="add-resource-workflow" @click="$emit('action', 'workflow')">Workflow</button>
|
||||
<button data-test-id="action-credential" @click="$emit('action', 'credential')">Credentials</button>
|
||||
<div data-test-id="add-resource-actions" >
|
||||
<button v-for="action in $props.actions" :key="action.value"></button>
|
||||
</div>
|
||||
</div>
|
||||
`,
|
||||
};
|
||||
|
||||
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);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -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<Props>(), {
|
||||
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<ActionTypes, (projectId: string) => 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);
|
||||
};
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user