mirror of
https://github.com/Abdulazizzn/n8n-enterprise-unlocked.git
synced 2025-12-16 17:46:45 +00:00
fix(editor): Show custom project icons on create sidebar dropdown (#18204)
This commit is contained in:
@@ -5,13 +5,14 @@ import type { RouteLocationRaw } from 'vue-router';
|
||||
|
||||
import ConditionalRouterLink from '../ConditionalRouterLink';
|
||||
import N8nIcon from '../N8nIcon';
|
||||
import { type IconName } from '../N8nIcon/icons';
|
||||
import type { IconName } from '../N8nIcon/icons';
|
||||
import N8nText from '../N8nText';
|
||||
|
||||
type BaseItem = {
|
||||
id: string;
|
||||
title: string;
|
||||
disabled?: boolean;
|
||||
icon?: IconName;
|
||||
icon?: IconName | { type: 'icon'; value: IconName } | { type: 'emoji'; value: string };
|
||||
route?: RouteLocationRaw;
|
||||
};
|
||||
|
||||
@@ -99,7 +100,21 @@ defineExpose({
|
||||
:disabled="subitem.disabled"
|
||||
@click="emit('itemClick', $event)"
|
||||
>
|
||||
<N8nIcon v-if="subitem.icon" :icon="subitem.icon" :class="$style.submenu__icon" />
|
||||
<!-- <N8nIcon v-if="subitem.icon" :icon="subitem.icon" :class="$style.submenu__icon" /> -->
|
||||
<template v-if="subitem.icon">
|
||||
<N8nIcon
|
||||
v-if="typeof subitem.icon === 'string' || subitem.icon.type === 'icon'"
|
||||
:class="$style.submenu__icon"
|
||||
:icon="typeof subitem.icon === 'object' ? subitem.icon.value : subitem.icon"
|
||||
/>
|
||||
<N8nText
|
||||
v-else-if="subitem.icon.type === 'emoji'"
|
||||
:class="$style.submenu__icon"
|
||||
>
|
||||
{{ subitem.icon.value }}
|
||||
</N8nText>
|
||||
</template>
|
||||
|
||||
{{ subitem.title }}
|
||||
<slot :name="`item.append.${item.id}`" v-bind="{ item }" />
|
||||
</ElMenuItem>
|
||||
|
||||
@@ -4,8 +4,8 @@ import { createComponentRenderer } from '@/__tests__/render';
|
||||
import ResourcesListLayout from '@/components/layouts/ResourcesListLayout.vue';
|
||||
import type { Resource } from '@/Interface';
|
||||
import type router from 'vue-router';
|
||||
import type { ProjectSharingData } from 'n8n-workflow';
|
||||
import { waitAllPromises } from '@/__tests__/utils';
|
||||
import type { ProjectSharingData } from '@/types/projects.types';
|
||||
|
||||
const TEST_HOME_PROJECT: ProjectSharingData = vi.hoisted(() => ({
|
||||
id: '1',
|
||||
|
||||
@@ -12,13 +12,27 @@ import { getResourcePermissions } from '@n8n/permissions';
|
||||
import { usePageRedirectionHelper } from '@/composables/usePageRedirectionHelper';
|
||||
import type { Scope } from '@n8n/permissions';
|
||||
import type { RouteLocationRaw } from 'vue-router';
|
||||
import { type IconName } from '@n8n/design-system/components/N8nIcon/icons';
|
||||
import { updatedIconSet, type IconName } from '@n8n/design-system/components/N8nIcon/icons';
|
||||
|
||||
type ProjectIcon = IconName | { type: 'icon'; value: IconName } | { type: 'emoji'; value: string };
|
||||
|
||||
const isIconName = (icon: unknown): icon is IconName =>
|
||||
typeof icon === 'string' && Object.keys(updatedIconSet).includes(icon);
|
||||
|
||||
const isProjectIcon = (icon: unknown): icon is ProjectIcon =>
|
||||
isIconName(icon) ||
|
||||
(typeof icon === 'object' &&
|
||||
icon !== null &&
|
||||
'value' in icon &&
|
||||
typeof icon.value === 'string' &&
|
||||
'type' in icon &&
|
||||
(icon.type === 'emoji' || (icon.type === 'icon' && isIconName(icon.value))));
|
||||
|
||||
type BaseItem = {
|
||||
id: string;
|
||||
title: string;
|
||||
disabled?: boolean;
|
||||
icon?: IconName;
|
||||
icon?: ProjectIcon;
|
||||
route?: RouteLocationRaw;
|
||||
};
|
||||
|
||||
@@ -30,6 +44,7 @@ export const useGlobalEntityCreation = () => {
|
||||
const CREATE_PROJECT_ID = 'create-project';
|
||||
const WORKFLOWS_MENU_ID = 'workflow';
|
||||
const CREDENTIALS_MENU_ID = 'credential';
|
||||
const DEFAULT_ICON: IconName = 'layers';
|
||||
|
||||
const settingsStore = useSettingsStore();
|
||||
const cloudPlanStore = useCloudPlanStore();
|
||||
@@ -117,7 +132,7 @@ export const useGlobalEntityCreation = () => {
|
||||
...displayProjects.value.map((project) => ({
|
||||
id: `workflow-${project.id}`,
|
||||
title: project.name as string,
|
||||
icon: 'layers' as IconName,
|
||||
icon: isProjectIcon(project.icon) ? project.icon : DEFAULT_ICON,
|
||||
disabled: disabledWorkflow(project.scopes),
|
||||
route: {
|
||||
name: VIEWS.NEW_WORKFLOW,
|
||||
@@ -141,7 +156,7 @@ export const useGlobalEntityCreation = () => {
|
||||
{
|
||||
id: 'credential-personal',
|
||||
title: i18n.baseText('projects.menu.personal'),
|
||||
icon: 'user' as IconName,
|
||||
icon: 'user',
|
||||
disabled: disabledCredential(projectsStore.personalProject?.scopes),
|
||||
route: {
|
||||
name: VIEWS.PROJECTS_CREDENTIALS,
|
||||
@@ -151,7 +166,7 @@ export const useGlobalEntityCreation = () => {
|
||||
...displayProjects.value.map((project) => ({
|
||||
id: `credential-${project.id}`,
|
||||
title: project.name as string,
|
||||
icon: 'layers' as IconName,
|
||||
icon: isProjectIcon(project.icon) ? project.icon : DEFAULT_ICON,
|
||||
disabled: disabledCredential(project.scopes),
|
||||
route: {
|
||||
name: VIEWS.PROJECTS_CREDENTIALS,
|
||||
@@ -166,7 +181,7 @@ export const useGlobalEntityCreation = () => {
|
||||
title: 'Project',
|
||||
disabled: !projectsStore.canCreateProjects || !projectsStore.hasPermissionToCreateProjects,
|
||||
},
|
||||
];
|
||||
] satisfies Item[];
|
||||
});
|
||||
|
||||
const createProject = async () => {
|
||||
@@ -175,7 +190,7 @@ export const useGlobalEntityCreation = () => {
|
||||
try {
|
||||
const newProject = await projectsStore.createProject({
|
||||
name: i18n.baseText('projects.settings.newProjectName'),
|
||||
icon: { type: 'icon', value: 'layers' },
|
||||
icon: { type: 'icon', value: DEFAULT_ICON },
|
||||
});
|
||||
await router.push({ name: VIEWS.PROJECT_SETTINGS, params: { projectId: newProject.id } });
|
||||
toast.showMessage({
|
||||
|
||||
Reference in New Issue
Block a user