fix(editor): Follow-up fixes to projects side menu (#11327)

This commit is contained in:
Csaba Tuncsik 2024-10-22 10:19:01 +02:00 committed by GitHub
parent 0fa2e8ca85
commit 4dde772814
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 50 additions and 13 deletions

View file

@ -147,7 +147,8 @@ describe('ProjectsNavigation', () => {
expect(uiStore.goToUpgrade).toHaveBeenCalledWith('rbac', 'upgrade-rbac');
});
it('should show "Projects" title and projects if the user has access to any team project', async () => {
it('should show "Projects" title and Personal project when the feature is enabled', async () => {
projectsStore.isTeamProjectFeatureEnabled = true;
projectsStore.myProjects = [...personalProjects, ...teamProjects];
const { getByRole, getAllByTestId, getByTestId } = renderComponent({
@ -158,11 +159,12 @@ describe('ProjectsNavigation', () => {
expect(getByRole('heading', { level: 3, name: 'Projects' })).toBeVisible();
expect(getByTestId('project-personal-menu-item')).toBeVisible();
expect(getByTestId('project-personal-menu-item').querySelector('svg')).toBeVisible();
expect(getAllByTestId('project-menu-item')).toHaveLength(teamProjects.length);
});
it('should not show "Projects" title when the menu is collapsed', async () => {
projectsStore.myProjects = [...personalProjects, ...teamProjects];
projectsStore.isTeamProjectFeatureEnabled = true;
const { queryByRole } = renderComponent({
props: {
@ -173,8 +175,8 @@ describe('ProjectsNavigation', () => {
expect(queryByRole('heading', { level: 3, name: 'Projects' })).not.toBeInTheDocument();
});
it('should not show "Projects" title when there are no available projects', async () => {
projectsStore.myProjects = [];
it('should not show "Projects" title when the feature is not enabled', async () => {
projectsStore.isTeamProjectFeatureEnabled = false;
const { queryByRole } = renderComponent({
props: {
@ -184,4 +186,17 @@ describe('ProjectsNavigation', () => {
expect(queryByRole('heading', { level: 3, name: 'Projects' })).not.toBeInTheDocument();
});
it('should not show project icons when the menu is collapsed', async () => {
projectsStore.isTeamProjectFeatureEnabled = true;
const { getByTestId } = renderComponent({
props: {
collapsed: true,
},
});
expect(getByTestId('project-personal-menu-item')).toBeVisible();
expect(getByTestId('project-personal-menu-item').querySelector('svg')).not.toBeInTheDocument();
});
});

View file

@ -45,7 +45,7 @@ const addProject = computed<IMenuItem>(() => ({
const getProjectMenuItem = (project: ProjectListItem) => ({
id: project.id,
label: project.name,
icon: 'layer-group',
icon: props.collapsed ? undefined : 'layer-group',
route: {
to: {
name: VIEWS.PROJECTS_WORKFLOWS,
@ -57,7 +57,7 @@ const getProjectMenuItem = (project: ProjectListItem) => ({
const personalProject = computed<IMenuItem>(() => ({
id: projectsStore.personalProject?.id ?? '',
label: locale.baseText('projects.menu.personal'),
icon: 'user',
icon: props.collapsed ? undefined : 'user',
route: {
to: {
name: VIEWS.PROJECTS_WORKFLOWS,
@ -119,16 +119,20 @@ onMounted(async () => {
data-test-id="project-home-menu-item"
/>
</ElMenu>
<hr v-if="displayProjects.length || canCreateProjects" class="mt-m mb-m" />
<hr v-if="projectsStore.isTeamProjectFeatureEnabled" class="mt-m mb-m" />
<N8nText
v-if="!props.collapsed && displayProjects.length"
v-if="!props.collapsed && projectsStore.isTeamProjectFeatureEnabled"
:class="$style.projectsLabel"
tag="h3"
bold
>
<span>{{ locale.baseText('projects.menu.title') }}</span>
</N8nText>
<ElMenu v-if="displayProjects.length" :collapse="props.collapsed" :class="$style.projectItems">
<ElMenu
v-if="projectsStore.isTeamProjectFeatureEnabled"
:collapse="props.collapsed"
:class="$style.projectItems"
>
<N8nMenuItem
:item="personalProject"
:compact="props.collapsed"
@ -154,7 +158,7 @@ onMounted(async () => {
placement="right"
:disabled="projectsStore.canCreateProjects"
>
<ElMenu :collapse="props.collapsed" class="pl-xs pr-xs">
<ElMenu :collapse="props.collapsed" class="pl-xs pr-xs mb-m">
<N8nMenuItem
:item="addProject"
:compact="props.collapsed"
@ -182,7 +186,7 @@ onMounted(async () => {
</i18n-t>
</template>
</N8nTooltip>
<hr v-if="displayProjects.length || canCreateProjects" class="mt-m mb-m" />
<hr v-if="projectsStore.isTeamProjectFeatureEnabled" class="mb-m" />
</div>
</template>

View file

@ -4,6 +4,7 @@ import { createComponentRenderer } from '@/__tests__/render';
import { createTestProject } from '@/__tests__/data/projects';
import ProjectTabs from '@/components/Projects/ProjectTabs.vue';
import { useProjectsStore } from '@/stores/projects.store';
import { ProjectTypes } from '@/types/projects.types';
vi.mock('vue-router', () => {
const params = {};
@ -47,7 +48,7 @@ describe('ProjectTabs', () => {
expect(queryByText('Project settings')).not.toBeInTheDocument();
});
it('should render project tab Settings if user has permissions', () => {
it('should render project tab Settings if user has permissions and current project is of type Team', () => {
route.params.projectId = '123';
projectsStore.setCurrentProject(createTestProject({ scopes: ['project:update'] }));
const { getByText } = renderComponent();
@ -66,4 +67,16 @@ describe('ProjectTabs', () => {
expect(getByText('Credentials')).toBeInTheDocument();
expect(queryByText('Project settings')).not.toBeInTheDocument();
});
it('should render project tabs without Settings if project is the Personal project', () => {
route.params.projectId = '123';
projectsStore.setCurrentProject(
createTestProject({ type: ProjectTypes.Personal, scopes: ['project:update'] }),
);
const { queryByText, getByText } = renderComponent();
expect(getByText('Workflows')).toBeInTheDocument();
expect(getByText('Credentials')).toBeInTheDocument();
expect(queryByText('Project settings')).not.toBeInTheDocument();
});
});

View file

@ -6,6 +6,7 @@ import { VIEWS } from '@/constants';
import { useI18n } from '@/composables/useI18n';
import { useProjectsStore } from '@/stores/projects.store';
import { getResourcePermissions } from '@/permissions';
import { ProjectTypes } from '@/types/projects.types';
const locale = useI18n();
const route = useRoute();
@ -50,7 +51,11 @@ const options = computed(() => {
},
];
if (projectId && projectPermissions.value.update) {
if (
projectId &&
projectPermissions.value.update &&
projectsStore.currentProject?.type === ProjectTypes.Team
) {
tabs.push({
label: locale.baseText('projects.settings'),
value: VIEWS.PROJECT_SETTINGS,