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 3fca181e4c..57f5c2cd62 100644 --- a/packages/frontend/editor-ui/src/components/Projects/ProjectHeader.test.ts +++ b/packages/frontend/editor-ui/src/components/Projects/ProjectHeader.test.ts @@ -12,6 +12,7 @@ import { VIEWS } from '@/constants'; import userEvent from '@testing-library/user-event'; import { waitFor, within } from '@testing-library/vue'; import { useSettingsStore } from '@/stores/settings.store'; +import { useOverview } from '@/composables/useOverview'; const mockPush = vi.fn(); vi.mock('vue-router', async () => { @@ -30,6 +31,12 @@ vi.mock('vue-router', async () => { }; }); +vi.mock('@/composables/useOverview', () => ({ + useOverview: vi.fn().mockReturnValue({ + isOverviewSubPage: false, + }), +})); + const projectTabsSpy = vi.fn().mockReturnValue({ render: vi.fn(), }); @@ -45,6 +52,7 @@ const renderComponent = createComponentRenderer(ProjectHeader, { let route: ReturnType; let projectsStore: ReturnType>; let settingsStore: ReturnType>; +let overview: ReturnType; describe('ProjectHeader', () => { beforeEach(() => { @@ -52,6 +60,7 @@ describe('ProjectHeader', () => { route = router.useRoute(); projectsStore = mockedStore(useProjectsStore); settingsStore = mockedStore(useSettingsStore); + overview = useOverview(); projectsStore.teamProjectsLimit = -1; settingsStore.settings.folders = { enabled: false }; @@ -61,6 +70,27 @@ describe('ProjectHeader', () => { vi.clearAllMocks(); }); + it('should not render title icon on overview page', async () => { + vi.spyOn(overview, 'isOverviewSubPage', 'get').mockReturnValue(true); + const { container } = renderComponent(); + + expect(container.querySelector('.fa-home')).not.toBeInTheDocument(); + }); + + it('should render the correct icon', async () => { + vi.spyOn(overview, 'isOverviewSubPage', 'get').mockReturnValue(false); + const { container, rerender } = renderComponent(); + + projectsStore.currentProject = { type: ProjectTypes.Personal } as Project; + await rerender({}); + expect(container.querySelector('.fa-user')).toBeVisible(); + + const projectName = 'My Project'; + projectsStore.currentProject = { name: projectName } as Project; + await rerender({}); + expect(container.querySelector('.fa-layer-group')).toBeVisible(); + }); + it('should render the correct title and subtitle', async () => { const { getByText, queryByText, rerender } = renderComponent(); const subtitle = 'All the workflows, credentials and executions you have access to'; diff --git a/packages/frontend/editor-ui/src/components/Projects/ProjectHeader.vue b/packages/frontend/editor-ui/src/components/Projects/ProjectHeader.vue index 5cd8f35f87..d21fe6591b 100644 --- a/packages/frontend/editor-ui/src/components/Projects/ProjectHeader.vue +++ b/packages/frontend/editor-ui/src/components/Projects/ProjectHeader.vue @@ -4,14 +4,16 @@ import { useRoute, useRouter } from 'vue-router'; import type { UserAction } from '@n8n/design-system'; import { N8nButton, N8nTooltip } from '@n8n/design-system'; import { useI18n } from '@/composables/useI18n'; -import { ProjectTypes } from '@/types/projects.types'; +import { type ProjectIcon as ProjectIconType, ProjectTypes } from '@/types/projects.types'; import { useProjectsStore } from '@/stores/projects.store'; import ProjectTabs from '@/components/Projects/ProjectTabs.vue'; +import ProjectIcon from '@/components/Projects/ProjectIcon.vue'; import { getResourcePermissions } from '@/permissions'; import { VIEWS } from '@/constants'; import { useSourceControlStore } from '@/stores/sourceControl.store'; import ProjectCreateResource from '@/components/Projects/ProjectCreateResource.vue'; import { useSettingsStore } from '@/stores/settings.store'; +import { useOverview } from '@/composables/useOverview'; const route = useRoute(); const router = useRouter(); @@ -19,11 +21,22 @@ const i18n = useI18n(); const projectsStore = useProjectsStore(); const sourceControlStore = useSourceControlStore(); const settingsStore = useSettingsStore(); +const overview = useOverview(); const emit = defineEmits<{ createFolder: []; }>(); +const headerIcon = computed((): ProjectIconType => { + if (projectsStore.currentProject?.type === ProjectTypes.Personal) { + return { type: 'icon', value: 'user' }; + } else if (projectsStore.currentProject?.name) { + return projectsStore.currentProject.icon ?? { type: 'icon', value: 'layer-group' }; + } else { + return { type: 'icon', value: 'home' }; + } +}); + const projectName = computed(() => { if (!projectsStore.currentProject) { return i18n.baseText('projects.menu.overview'); @@ -126,6 +139,12 @@ const onSelect = (action: string) => {
+
{{ projectName }} @@ -168,7 +187,7 @@ const onSelect = (action: string) => { .projectHeader, .projectDescription { display: flex; - align-items: center; + align-items: flex-start; justify-content: space-between; padding-bottom: var(--spacing-m); min-height: var(--spacing-3xl);