Navbar customization v2 (#18026)

Adds color support for navigation menu items.

---------

Co-authored-by: Copilot Autofix powered by AI <223894421+github-code-quality[bot]@users.noreply.github.com>
Co-authored-by: Devessier <baptiste@devessier.fr>
Co-authored-by: Charles Bochet <charles@twenty.com>
This commit is contained in:
Abdul Rahman
2026-02-28 16:18:28 +05:30
committed by GitHub
parent 63f17eec2c
commit 9fe2a07c55
94 changed files with 1204 additions and 474 deletions
@@ -17,6 +17,7 @@ export const fromNavigationMenuItemManifestToUniversalFlatNavigationMenuItem =
applicationUniversalIdentifier,
name: navigationMenuItemManifest.name ?? null,
icon: navigationMenuItemManifest.icon ?? null,
color: navigationMenuItemManifest.color ?? null,
position: navigationMenuItemManifest.position,
viewUniversalIdentifier:
navigationMenuItemManifest.viewUniversalIdentifier ?? null,
@@ -106,6 +106,7 @@ exports[`ALL_UNIVERSAL_FLAT_ENTITY_PROPERTIES_TO_COMPARE_AND_STRINGIFY should ma
"name",
"link",
"icon",
"color",
],
"propertiesToStringify": [],
},
@@ -1020,6 +1020,11 @@ export const ALL_ENTITY_PROPERTIES_CONFIGURATION_BY_METADATA_NAME = {
name: { toCompare: true, toStringify: false, universalProperty: undefined },
link: { toCompare: true, toStringify: false, universalProperty: undefined },
icon: { toCompare: true, toStringify: false, universalProperty: undefined },
color: {
toCompare: true,
toStringify: false,
universalProperty: undefined,
},
createdAt: {
toCompare: false,
toStringify: false,
@@ -6,4 +6,5 @@ export const FLAT_NAVIGATION_MENU_ITEM_EDITABLE_PROPERTIES = [
'name',
'link',
'icon',
'color',
] as const satisfies MetadataEntityPropertyName<'navigationMenuItem'>[];
@@ -82,6 +82,7 @@ export const fromCreateNavigationMenuItemInputToFlatNavigationMenuItemToCreate =
name: createNavigationMenuItemInput.name ?? null,
link: createNavigationMenuItemInput.link ?? null,
icon: createNavigationMenuItemInput.icon ?? null,
color: createNavigationMenuItemInput.color ?? null,
position,
workspaceId,
applicationId: flatApplication.id,
@@ -14,6 +14,7 @@ export const fromFlatNavigationMenuItemToNavigationMenuItemDto = (
name: flatNavigationMenuItem.name ?? undefined,
link: flatNavigationMenuItem.link ?? undefined,
icon: flatNavigationMenuItem.icon ?? undefined,
color: flatNavigationMenuItem.color ?? undefined,
position: flatNavigationMenuItem.position,
workspaceId: flatNavigationMenuItem.workspaceId,
applicationId: flatNavigationMenuItem.applicationId ?? undefined,
@@ -83,6 +83,7 @@ export const fromNavigationMenuItemEntityToFlatNavigationMenuItem = ({
name: navigationMenuItemEntity.name,
link: navigationMenuItemEntity.link,
icon: navigationMenuItemEntity.icon,
color: navigationMenuItemEntity.color,
position: navigationMenuItemEntity.position,
workspaceId: navigationMenuItemEntity.workspaceId,
universalIdentifier: navigationMenuItemEntity.universalIdentifier,
@@ -41,6 +41,11 @@ export class CreateNavigationMenuItemInput {
@Field(() => String, { nullable: true })
icon?: string | null;
@IsOptional()
@IsString()
@Field(() => String, { nullable: true })
color?: string | null;
@IsUUID()
@IsOptional()
@Field(() => UUIDScalarType, { nullable: true })
@@ -51,6 +51,10 @@ export class NavigationMenuItemDTO {
@Field(() => String, { nullable: true })
icon?: string | null;
@IsOptional()
@Field(() => String, { nullable: true })
color?: string | null;
@IsUUID()
@IsOptional()
@Field(() => UUIDScalarType, { nullable: true })
@@ -38,6 +38,11 @@ export class UpdateNavigationMenuItemInput {
@IsString()
@Field(() => String, { nullable: true })
icon?: string | null;
@IsOptional()
@IsString()
@Field(() => String, { nullable: true })
color?: string | null;
}
@InputType()
@@ -87,6 +87,9 @@ export class NavigationMenuItemEntity
@Column({ nullable: true, type: 'text' })
icon: string | null;
@Column({ nullable: true, type: 'text' })
color: string | null;
@ManyToOne(() => NavigationMenuItemEntity, {
onDelete: 'CASCADE',
nullable: true,
@@ -896,6 +896,7 @@ export class ObjectMetadataService extends TypeOrmQueryService<ObjectMetadataEnt
name: null,
link: null,
icon: null,
color: null,
position: nextPosition,
workspaceId,
applicationId: workspaceCustomApplicationId,
@@ -7,34 +7,34 @@ export const STANDARD_NAVIGATION_MENU_ITEMS = {
STANDARD_OBJECTS.company.views.allCompanies.universalIdentifier,
position: 0,
},
allDashboards: {
universalIdentifier: '20202020-b002-4b02-8b02-c0aba11c0002',
allPeople: {
universalIdentifier: '20202020-b005-4b05-8b05-c0aba11c0005',
viewUniversalIdentifier:
STANDARD_OBJECTS.dashboard.views.allDashboards.universalIdentifier,
STANDARD_OBJECTS.person.views.allPeople.universalIdentifier,
position: 1,
},
allNotes: {
universalIdentifier: '20202020-b003-4b03-8b03-c0aba11c0003',
viewUniversalIdentifier:
STANDARD_OBJECTS.note.views.allNotes.universalIdentifier,
position: 2,
},
allOpportunities: {
universalIdentifier: '20202020-b004-4b04-8b04-c0aba11c0004',
viewUniversalIdentifier:
STANDARD_OBJECTS.opportunity.views.allOpportunities.universalIdentifier,
position: 3,
},
allPeople: {
universalIdentifier: '20202020-b005-4b05-8b05-c0aba11c0005',
viewUniversalIdentifier:
STANDARD_OBJECTS.person.views.allPeople.universalIdentifier,
position: 4,
position: 2,
},
allTasks: {
universalIdentifier: '20202020-b006-4b06-8b06-c0aba11c0006',
viewUniversalIdentifier:
STANDARD_OBJECTS.task.views.allTasks.universalIdentifier,
position: 3,
},
allNotes: {
universalIdentifier: '20202020-b003-4b03-8b03-c0aba11c0003',
viewUniversalIdentifier:
STANDARD_OBJECTS.note.views.allNotes.universalIdentifier,
position: 4,
},
allDashboards: {
universalIdentifier: '20202020-b002-4b02-8b02-c0aba11c0002',
viewUniversalIdentifier:
STANDARD_OBJECTS.dashboard.views.allDashboards.universalIdentifier,
position: 5,
},
workflowsFolder: {
@@ -66,3 +66,18 @@ export const STANDARD_NAVIGATION_MENU_ITEMS = {
position: 2,
},
} as const;
export const STANDARD_NAVIGATION_MENU_ITEM_DEFAULT_COLORS: Partial<
Record<keyof typeof STANDARD_NAVIGATION_MENU_ITEMS, string>
> = {
allCompanies: 'blue',
allPeople: 'blue',
allTasks: 'turquoise',
allNotes: 'turquoise',
allOpportunities: 'red',
workflowsFolder: 'orange',
allDashboards: 'gray',
workflowsFolderAllWorkflows: 'gray',
workflowsFolderAllWorkflowRuns: 'gray',
workflowsFolderAllWorkflowVersions: 'gray',
};
@@ -1,11 +1,14 @@
import { isDefined } from 'twenty-shared/utils';
import { type FlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-maps.type';
import { TWENTY_STANDARD_APPLICATION } from 'src/engine/workspace-manager/twenty-standard-application/constants/twenty-standard-applications';
import { findFlatEntityByUniversalIdentifier } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-universal-identifier.util';
import { type FlatNavigationMenuItem } from 'src/engine/metadata-modules/flat-navigation-menu-item/types/flat-navigation-menu-item.type';
import { type FlatView } from 'src/engine/metadata-modules/flat-view/types/flat-view.type';
import { STANDARD_NAVIGATION_MENU_ITEMS } from 'src/engine/workspace-manager/twenty-standard-application/constants/standard-navigation-menu-item.constant';
import {
STANDARD_NAVIGATION_MENU_ITEM_DEFAULT_COLORS,
STANDARD_NAVIGATION_MENU_ITEMS,
} from 'src/engine/workspace-manager/twenty-standard-application/constants/standard-navigation-menu-item.constant';
import { TWENTY_STANDARD_APPLICATION } from 'src/engine/workspace-manager/twenty-standard-application/constants/twenty-standard-applications';
export const createStandardNavigationMenuItemFlatMetadata = ({
workspaceId,
@@ -66,6 +69,9 @@ export const createStandardNavigationMenuItemFlatMetadata = ({
name: null,
link: null,
icon: null,
color:
STANDARD_NAVIGATION_MENU_ITEM_DEFAULT_COLORS[navigationMenuItemName] ??
null,
position,
createdAt: now,
updatedAt: now,
@@ -40,6 +40,7 @@ export const createStandardNavigationMenuItemFolderFlatMetadata = ({
name,
link: null,
icon: icon ?? null,
color: 'orange',
position,
createdAt: now,
updatedAt: now,
@@ -99,6 +100,7 @@ export const createStandardNavigationMenuItemFolderItemFlatMetadata = ({
name: null,
link: null,
icon: null,
color: 'gray',
position,
createdAt: now,
updatedAt: now,