Use routes closer to the route for objects

This commit is contained in:
Francisco Gaona
2025-12-22 10:24:02 +01:00
parent cdc202454f
commit db9848cce7
3 changed files with 435 additions and 64 deletions

View File

@@ -1,4 +1,5 @@
<script setup lang="ts">
import { ref, onMounted } from 'vue'
import {
Sidebar,
SidebarContent,
@@ -19,12 +20,52 @@ import { Collapsible, CollapsibleContent, CollapsibleTrigger } from '@/component
import { LayoutGrid, Boxes, Settings, Home, ChevronRight, Database, Layers, LogOut } from 'lucide-vue-next'
const { logout } = useAuth()
const { api } = useApi()
const handleLogout = async () => {
await logout()
}
const menuItems = [
// Fetch objects and group by app
const apps = ref<any[]>([])
const topLevelObjects = ref<any[]>([])
const loading = ref(true)
onMounted(async () => {
try {
const response = await api.get('/setup/objects')
const allObjects = response.data || response || []
// Group objects by app
const appMap = new Map<string, any>()
const noAppObjects: any[] = []
allObjects.forEach((obj: any) => {
if (obj.appId) {
if (!appMap.has(obj.appId)) {
appMap.set(obj.appId, {
id: obj.appId,
name: obj.app?.name || obj.app?.label || 'Unknown App',
label: obj.app?.label || obj.app?.name || 'Unknown App',
objects: []
})
}
appMap.get(obj.appId)!.objects.push(obj)
} else {
noAppObjects.push(obj)
}
})
apps.value = Array.from(appMap.values())
topLevelObjects.value = noAppObjects
} catch (e) {
console.error('Failed to load objects:', e)
} finally {
loading.value = false
}
})
const staticMenuItems = [
{
title: 'Home',
url: '/',
@@ -46,17 +87,6 @@ const menuItems = [
},
],
},
{
title: 'Runtime',
icon: Database,
items: [
{
title: 'My Apps',
url: '/app',
icon: Layers,
},
],
},
]
</script>
@@ -82,11 +112,12 @@ const menuItems = [
</SidebarMenu>
</SidebarHeader>
<SidebarContent>
<!-- Static Menu Items -->
<SidebarGroup>
<SidebarGroupLabel>Application</SidebarGroupLabel>
<SidebarGroupLabel>Navigation</SidebarGroupLabel>
<SidebarGroupContent>
<SidebarMenu>
<template v-for="item in menuItems" :key="item.title">
<template v-for="item in staticMenuItems" :key="item.title">
<!-- Simple menu item -->
<SidebarMenuItem v-if="!item.items">
<SidebarMenuButton as-child>
@@ -127,6 +158,63 @@ const menuItems = [
</SidebarMenu>
</SidebarGroupContent>
</SidebarGroup>
<!-- Top-level Objects (no app) -->
<SidebarGroup v-if="!loading && topLevelObjects.length > 0">
<SidebarGroupLabel>Objects</SidebarGroupLabel>
<SidebarGroupContent>
<SidebarMenu>
<SidebarMenuItem v-for="obj in topLevelObjects" :key="obj.id">
<SidebarMenuButton as-child>
<NuxtLink :to="`/${obj.apiName.toLowerCase()}`">
<Database class="h-4 w-4" />
<span>{{ obj.label || obj.apiName }}</span>
</NuxtLink>
</SidebarMenuButton>
</SidebarMenuItem>
</SidebarMenu>
</SidebarGroupContent>
</SidebarGroup>
<!-- App-grouped Objects -->
<SidebarGroup v-if="!loading && apps.length > 0">
<SidebarGroupLabel>Apps</SidebarGroupLabel>
<SidebarGroupContent>
<SidebarMenu>
<Collapsible
v-for="app in apps"
:key="app.id"
as-child
:default-open="true"
class="group/collapsible"
>
<SidebarMenuItem>
<CollapsibleTrigger as-child>
<SidebarMenuButton :tooltip="app.label">
<LayoutGrid class="h-4 w-4" />
<span>{{ app.label }}</span>
<ChevronRight
class="ml-auto transition-transform duration-200 group-data-[state=open]/collapsible:rotate-90"
/>
</SidebarMenuButton>
</CollapsibleTrigger>
<CollapsibleContent>
<SidebarMenuSub>
<SidebarMenuSubItem v-for="obj in app.objects" :key="obj.id">
<SidebarMenuSubButton as-child>
<NuxtLink :to="`/${obj.apiName.toLowerCase()}`">
<Database class="h-4 w-4" />
<span>{{ obj.label || obj.apiName }}</span>
</NuxtLink>
</SidebarMenuSubButton>
</SidebarMenuSubItem>
</SidebarMenuSub>
</CollapsibleContent>
</SidebarMenuItem>
</Collapsible>
</SidebarMenu>
</SidebarGroupContent>
</SidebarGroup>
</SidebarContent>
<SidebarFooter>
<SidebarMenu>