Skip to content

Commit 1a553c4

Browse files
wrt95TomasEngErlingHauanKonrad-Simsostanderen
authored
feat: add header utils for dashboardheader (#14940)
Co-authored-by: Tomas Engebretsen <[email protected]> Co-authored-by: Erling Hauan <[email protected]> Co-authored-by: Konrad-Simso <[email protected]> Co-authored-by: andreastanderen <[email protected]> Co-authored-by: Tomas <[email protected]> Co-authored-by: andreastanderen <[email protected]> Co-authored-by: Erling Hauan <[email protected]>
1 parent 21575c6 commit 1a553c4

File tree

4 files changed

+164
-1
lines changed

4 files changed

+164
-1
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import type { HeaderMenuItem } from './HeaderMenuItem';
2+
3+
export type HeaderMenuGroup = {
4+
groupName: string;
5+
menuItems: HeaderMenuItem[];
6+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
import {
2+
groupMenuItemsByGroup,
3+
mapHeaderMenuGroupToNavigationMenu,
4+
dashboardHeaderMenuItems,
5+
mapNavigationMenuToProfileMenu,
6+
} from './headerUtils';
7+
import { HeaderMenuGroupKey } from '../../enums/HeaderMenuGroupKey';
8+
import { HeaderMenuItemKey } from '../../enums/HeaderMenuItemKey';
9+
import type { NavigationMenuGroup } from '../../types/NavigationMenuGroup';
10+
import type { StudioProfileMenuGroup } from '@studio/components';
11+
import type { NavigationMenuItem } from '../../types/NavigationMenuItem';
12+
13+
describe('headerMenuUtils', () => {
14+
describe('groupMenuItemsByGroup', () => {
15+
it('should group items by their group key', () => {
16+
const groupedItems = groupMenuItemsByGroup(dashboardHeaderMenuItems);
17+
expect(groupedItems.length).toBeGreaterThan(0);
18+
19+
groupedItems.forEach((group) => {
20+
group.menuItems.forEach((item) => {
21+
expect(item.group).toBe(group.groupName);
22+
});
23+
});
24+
});
25+
});
26+
27+
describe('mapHeaderMenuGroupToNavigationMenu', () => {
28+
it('should correctly map header menu group to navigation menu group', () => {
29+
const group = {
30+
groupName: HeaderMenuGroupKey.Tools,
31+
menuItems: [
32+
dashboardHeaderMenuItems.find((item) => item.key === HeaderMenuItemKey.AppDashboard)!,
33+
],
34+
};
35+
const mappedGroup = mapHeaderMenuGroupToNavigationMenu(group);
36+
expect(mappedGroup.name).toBe(HeaderMenuGroupKey.Tools);
37+
expect(mappedGroup.items.length).toBe(1);
38+
expect(mappedGroup.items[0].itemName).toBe('dashboard.header_item_dashboard');
39+
});
40+
});
41+
42+
describe('mapNavigationMenuToProfileMenu', () => {
43+
const buttonItem: NavigationMenuItem = {
44+
itemName: 'Button Item',
45+
action: { type: 'button', onClick: jest.fn() },
46+
};
47+
const linkItem: NavigationMenuItem = {
48+
itemName: 'Link Item',
49+
action: { type: 'link', href: 'https://example.com', openInNewTab: true },
50+
};
51+
const linkItem2: NavigationMenuItem = {
52+
itemName: 'Link Item 2',
53+
action: { type: 'link', href: 'https://example.com', openInNewTab: false },
54+
};
55+
const profileMenuButtonItem: NavigationMenuItem = {
56+
itemName: buttonItem.itemName,
57+
action: buttonItem.action,
58+
};
59+
const profileMenuLinkItem: NavigationMenuItem = {
60+
itemName: linkItem.itemName,
61+
action: linkItem.action,
62+
};
63+
const profileMenuLinkItem2: NavigationMenuItem = {
64+
itemName: linkItem2.itemName,
65+
action: linkItem2.action,
66+
};
67+
68+
it('should map an empty array to an empty array', () => {
69+
expect(mapNavigationMenuToProfileMenu([])).toEqual([]);
70+
});
71+
72+
it('should correctly map a single group with a single button item', () => {
73+
const navigationGroups: NavigationMenuGroup[] = [{ name: 'Group 1', items: [buttonItem] }];
74+
75+
const result: StudioProfileMenuGroup[] = [{ items: [profileMenuButtonItem] }];
76+
expect(mapNavigationMenuToProfileMenu(navigationGroups)).toEqual(result);
77+
});
78+
79+
it('should correctly map a single group with a single link item', () => {
80+
const navigationGroups: NavigationMenuGroup[] = [{ name: 'Group 1', items: [linkItem] }];
81+
const result: StudioProfileMenuGroup[] = [{ items: [profileMenuLinkItem] }];
82+
83+
expect(mapNavigationMenuToProfileMenu(navigationGroups)).toEqual(result);
84+
});
85+
86+
it('should handle multiple groups and items correctly', () => {
87+
const navigationGroups: NavigationMenuGroup[] = [
88+
{ name: 'Group 1', items: [buttonItem, linkItem] },
89+
{ name: 'Group 2', items: [linkItem2] },
90+
];
91+
const result: StudioProfileMenuGroup[] = [
92+
{ items: [profileMenuButtonItem, profileMenuLinkItem] },
93+
{ items: [profileMenuLinkItem2] },
94+
];
95+
96+
expect(mapNavigationMenuToProfileMenu(navigationGroups)).toEqual(result);
97+
});
98+
99+
it('should handle missing optional properties (openInNewTab)', () => {
100+
const navigationGroups: NavigationMenuGroup[] = [
101+
{
102+
name: 'Group 1',
103+
items: [{ itemName: 'Link Item', action: { type: 'link', href: 'https://example.com' } }],
104+
},
105+
];
106+
const result: StudioProfileMenuGroup[] = mapNavigationMenuToProfileMenu(navigationGroups);
107+
expect(result[0].items[0].action).not.toBeUndefined();
108+
});
109+
});
110+
});

frontend/dashboard/utils/headerUtils/headerUtils.ts

+42
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@ import type { HeaderMenuItem } from '../../types/HeaderMenuItem';
22
import { Subroute } from '../../enums/Subroute';
33
import { HeaderMenuItemKey } from '../../enums/HeaderMenuItemKey';
44
import { HeaderMenuGroupKey } from '../../enums/HeaderMenuGroupKey';
5+
import type { HeaderMenuGroup } from '../../types/HeaderMenuGroup';
6+
import type { NavigationMenuGroup } from '../../types/NavigationMenuGroup';
7+
import { type StudioProfileMenuGroup } from '@studio/components';
58

69
export const dashboardHeaderMenuItems: HeaderMenuItem[] = [
710
{
@@ -17,3 +20,42 @@ export const dashboardHeaderMenuItems: HeaderMenuItem[] = [
1720
group: HeaderMenuGroupKey.Tools,
1821
},
1922
];
23+
24+
export const groupMenuItemsByGroup = (menuItems: HeaderMenuItem[]): HeaderMenuGroup[] => {
25+
const groups: { [key: string]: HeaderMenuGroup } = {};
26+
27+
menuItems.forEach((item: HeaderMenuItem) => {
28+
if (!groups[item.group]) {
29+
groups[item.group] = { groupName: item.group, menuItems: [] };
30+
}
31+
groups[item.group].menuItems.push(item);
32+
});
33+
34+
return Object.values(groups);
35+
};
36+
37+
export const mapHeaderMenuGroupToNavigationMenu = (
38+
menuGroup: HeaderMenuGroup,
39+
): NavigationMenuGroup => ({
40+
name: menuGroup.groupName,
41+
showName: menuGroup.groupName === HeaderMenuGroupKey.Tools,
42+
items: menuGroup.menuItems.map((menuItem: HeaderMenuItem) => ({
43+
action: {
44+
type: 'link',
45+
href: menuItem.link,
46+
},
47+
itemName: menuItem.name,
48+
})),
49+
});
50+
51+
export function mapNavigationMenuToProfileMenu(
52+
navigationGroups: NavigationMenuGroup[],
53+
): StudioProfileMenuGroup[] {
54+
return navigationGroups.map(mapNavigationGroup);
55+
}
56+
57+
function mapNavigationGroup(group: NavigationMenuGroup): StudioProfileMenuGroup {
58+
return {
59+
items: group.items,
60+
};
61+
}
Original file line numberDiff line numberDiff line change
@@ -1 +1,6 @@
1-
export { dashboardHeaderMenuItems } from './headerUtils';
1+
export {
2+
groupMenuItemsByGroup,
3+
mapHeaderMenuGroupToNavigationMenu,
4+
dashboardHeaderMenuItems,
5+
mapNavigationMenuToProfileMenu,
6+
} from './headerUtils';

0 commit comments

Comments
 (0)