fix(editor): Add project header subtitle (#11797)

This commit is contained in:
Csaba Tuncsik 2024-11-20 13:03:09 +01:00 committed by GitHub
parent 7d3ad669e2
commit ff4261c168
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 57 additions and 10 deletions

View file

@ -1,4 +1,5 @@
import { createTestingPinia } from '@pinia/testing'; import { createTestingPinia } from '@pinia/testing';
import { within } from '@testing-library/dom';
import { createComponentRenderer } from '@/__tests__/render'; import { createComponentRenderer } from '@/__tests__/render';
import { mockedStore } from '@/__tests__/utils'; import { mockedStore } from '@/__tests__/utils';
import { createTestProject } from '@/__tests__/data/projects'; import { createTestProject } from '@/__tests__/data/projects';
@ -65,19 +66,37 @@ describe('ProjectHeader', () => {
expect(container.querySelector('.fa-layer-group')).toBeVisible(); expect(container.querySelector('.fa-layer-group')).toBeVisible();
}); });
it('should render the correct title', async () => { it('should render the correct title and subtitle', async () => {
const { getByText, rerender } = renderComponent(); const { getByText, queryByText, rerender } = renderComponent();
const subtitle = 'All the workflows, credentials and executions you have access to';
expect(getByText('Overview')).toBeVisible(); expect(getByText('Overview')).toBeVisible();
expect(getByText(subtitle)).toBeVisible();
projectsStore.currentProject = { type: ProjectTypes.Personal } as Project; projectsStore.currentProject = { type: ProjectTypes.Personal } as Project;
await rerender({}); await rerender({});
expect(getByText('Personal')).toBeVisible(); expect(getByText('Personal')).toBeVisible();
expect(queryByText(subtitle)).not.toBeInTheDocument();
const projectName = 'My Project'; const projectName = 'My Project';
projectsStore.currentProject = { name: projectName } as Project; projectsStore.currentProject = { name: projectName } as Project;
await rerender({}); await rerender({});
expect(getByText(projectName)).toBeVisible(); expect(getByText(projectName)).toBeVisible();
expect(queryByText(subtitle)).not.toBeInTheDocument();
});
it('should overwrite default subtitle with slot', () => {
const defaultSubtitle = 'All the workflows, credentials and executions you have access to';
const subtitle = 'Custom subtitle';
const { getByText, queryByText } = renderComponent({
slots: {
subtitle,
},
});
expect(getByText(subtitle)).toBeVisible();
expect(queryByText(defaultSubtitle)).not.toBeInTheDocument();
}); });
it('should render ProjectTabs Settings if project is team project and user has update scope', () => { it('should render ProjectTabs Settings if project is team project and user has update scope', () => {
@ -108,9 +127,10 @@ describe('ProjectHeader', () => {
it('should render ProjectTabs without Settings if project is not team project', () => { it('should render ProjectTabs without Settings if project is not team project', () => {
route.params.projectId = '123'; route.params.projectId = '123';
projectsStore.currentProject = createTestProject( projectsStore.currentProject = createTestProject({
createTestProject({ type: ProjectTypes.Personal, scopes: ['project:update'] }), type: ProjectTypes.Personal,
); scopes: ['project:update'],
});
renderComponent(); renderComponent();
expect(projectTabsSpy).toHaveBeenCalledWith( expect(projectTabsSpy).toHaveBeenCalledWith(
@ -120,4 +140,23 @@ describe('ProjectHeader', () => {
null, null,
); );
}); });
test.each([
[null, 'Create'],
[createTestProject({ type: ProjectTypes.Personal }), 'Create in personal'],
[createTestProject({ type: ProjectTypes.Team }), 'Create in project'],
])('in project %s should render correct create button label %s', (project, label) => {
projectsStore.currentProject = project;
const { getByTestId } = renderComponent({
global: {
stubs: {
N8nNavigationDropdown: {
template: '<div><slot></slot></div>',
},
},
},
});
expect(within(getByTestId('resource-add')).getByRole('button', { name: label })).toBeVisible();
});
}); });

View file

@ -53,11 +53,11 @@ const { menu, handleSelect } = useGlobalEntityCreation(
const createLabel = computed(() => { const createLabel = computed(() => {
if (!projectsStore.currentProject) { if (!projectsStore.currentProject) {
return 'Create'; return i18n.baseText('projects.create');
} else if (projectsStore.currentProject.type === ProjectTypes.Personal) { } else if (projectsStore.currentProject.type === ProjectTypes.Personal) {
return 'Create personal'; return i18n.baseText('projects.create.personal');
} else { } else {
return 'Create in project'; return i18n.baseText('projects.create.team');
} }
}); });
@ -74,8 +74,12 @@ onClickOutside(createBtn as Ref<VueInstance>, () => {
</div> </div>
<div> <div>
<N8nHeading bold tag="h2" size="xlarge">{{ projectName }}</N8nHeading> <N8nHeading bold tag="h2" size="xlarge">{{ projectName }}</N8nHeading>
<N8nText v-if="$slots.subtitle" size="small" color="text-light"> <N8nText color="text-light">
<slot name="subtitle" /> <slot name="subtitle">
<span v-if="!projectsStore.currentProject">{{
i18n.baseText('projects.header.subtitle')
}}</span>
</slot>
</N8nText> </N8nText>
</div> </div>
</div> </div>

View file

@ -2504,6 +2504,10 @@
"settings.mfa.title": "Multi-factor Authentication", "settings.mfa.title": "Multi-factor Authentication",
"settings.mfa.updateConfiguration": "MFA configuration updated", "settings.mfa.updateConfiguration": "MFA configuration updated",
"settings.mfa.invalidAuthenticatorCode": "Invalid authenticator code", "settings.mfa.invalidAuthenticatorCode": "Invalid authenticator code",
"projects.header.subtitle": "All the workflows, credentials and executions you have access to",
"projects.create": "Create",
"projects.create.personal": "Create in personal",
"projects.create.team": "Create in project",
"projects.menu.overview": "Overview", "projects.menu.overview": "Overview",
"projects.menu.title": "Projects", "projects.menu.title": "Projects",
"projects.menu.personal": "Personal", "projects.menu.personal": "Personal",