Skip to content

Commit bd9d8fc

Browse files
Copilothotlong
andcommitted
fix: include viewName in navigation href for object items
When a NavigationItem of type 'object' has a viewName (e.g. 'calendar', 'pipeline'), append /view/{viewName} to the generated href so the correct list view is activated on navigation. Changes: - Add viewName property to NavigationItem interface - Add viewName to Zod validation schema - Update resolveHref in NavigationRenderer to append /view/{viewName} - Update MobileBottomNav href generation in AppSchemaRenderer - Add test for viewName href generation Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
1 parent ad17911 commit bd9d8fc

File tree

5 files changed

+26
-3
lines changed

5 files changed

+26
-3
lines changed

packages/layout/src/AppSchemaRenderer.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,10 @@ function MobileBottomNav({
195195
{leaves.map((item) => {
196196
const NavIcon = resolveIcon(item.icon);
197197
let href = '#';
198-
if (item.type === 'object') href = `${basePath}/${item.objectName}`;
198+
if (item.type === 'object') {
199+
href = `${basePath}/${item.objectName}`;
200+
if (item.viewName) href += `/view/${item.viewName}`;
201+
}
199202
else if (item.type === 'dashboard') href = item.dashboardName ? `${basePath}/dashboard/${item.dashboardName}` : '#';
200203
else if (item.type === 'page') href = item.pageName ? `${basePath}/page/${item.pageName}` : '#';
201204
else if (item.type === 'report') href = item.reportName ? `${basePath}/report/${item.reportName}` : '#';

packages/layout/src/NavigationRenderer.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -184,8 +184,10 @@ const defaultPermission: PermissionChecker = () => true;
184184

185185
function resolveHref(item: NavigationItem, basePath: string): { href: string; external: boolean } {
186186
switch (item.type) {
187-
case 'object':
188-
return { href: `${basePath}/${item.objectName ?? ''}`, external: false };
187+
case 'object': {
188+
const objectPath = `${basePath}/${item.objectName ?? ''}`;
189+
return { href: item.viewName ? `${objectPath}/view/${item.viewName}` : objectPath, external: false };
190+
}
189191
case 'dashboard':
190192
return { href: item.dashboardName ? `${basePath}/dashboard/${item.dashboardName}` : '#', external: false };
191193
case 'page':

packages/layout/src/__tests__/NavigationRenderer.test.tsx

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,20 @@ describe('NavigationRenderer', () => {
110110
expect(link?.getAttribute('href')).toBe('/apps/test/account');
111111
});
112112

113+
it('renders object navigation item with viewName in href', () => {
114+
const calendarItem: NavigationItem = {
115+
id: 'nav-calendar',
116+
type: 'object',
117+
label: 'Calendar',
118+
icon: 'Calendar',
119+
objectName: 'event',
120+
viewName: 'calendar',
121+
};
122+
renderNav([calendarItem]);
123+
const link = screen.getByText('Calendar').closest('a');
124+
expect(link?.getAttribute('href')).toBe('/apps/test/event/view/calendar');
125+
});
126+
113127
it('renders dashboard navigation item', () => {
114128
renderNav([dashboardItem]);
115129
expect(screen.getByText('Sales Dashboard')).toBeTruthy();

packages/types/src/app.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,9 @@ export interface NavigationItem {
6666
/** Target object name (for type: 'object') */
6767
objectName?: string;
6868

69+
/** Target view name (for type: 'object') — opens a specific named list view e.g. 'calendar', 'pipeline' */
70+
viewName?: string;
71+
6972
/** Target dashboard name (for type: 'dashboard') */
7073
dashboardName?: string;
7174

packages/types/src/zod/app.zod.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ export const NavigationItemSchema: z.ZodType<any> = z.lazy(() => z.object({
4141

4242
// Type-specific target fields
4343
objectName: z.string().optional().describe('Target object name (type: object)'),
44+
viewName: z.string().optional().describe('Target view name (type: object) — named list view e.g. calendar, pipeline'),
4445
dashboardName: z.string().optional().describe('Target dashboard name (type: dashboard)'),
4546
pageName: z.string().optional().describe('Target page name (type: page)'),
4647
reportName: z.string().optional().describe('Target report name (type: report)'),

0 commit comments

Comments
 (0)