Sidebar cleanup.
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import { NavLink, useParams } from 'react-router';
|
||||
import { Server, Play, Container, AppWindow, Settings, CloudLightning, Sun, Moon, Monitor, ChevronDown, Globe, Usb } from 'lucide-react';
|
||||
import { Server, Play, Container, AppWindow, Settings, CloudLightning, Sun, Moon, Monitor, ChevronDown, Globe, Usb, Download, CheckCircle } from 'lucide-react';
|
||||
import { cn } from '../lib/utils';
|
||||
import {
|
||||
Sidebar,
|
||||
@@ -71,7 +71,23 @@ export function AppSidebar() {
|
||||
</div>
|
||||
</div>
|
||||
<div className="px-2 group-data-[collapsible=icon]:px-2">
|
||||
<InstanceSwitcher />
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="flex-1 min-w-0">
|
||||
<InstanceSwitcher />
|
||||
</div>
|
||||
<NavLink to={`/instances/${instanceId}/cloud`}>
|
||||
{({ isActive }) => (
|
||||
<SidebarMenuButton
|
||||
isActive={isActive}
|
||||
tooltip="Configure instance settings"
|
||||
size="sm"
|
||||
className="h-8 w-8 p-0"
|
||||
>
|
||||
<Settings className="h-4 w-4" />
|
||||
</SidebarMenuButton>
|
||||
)}
|
||||
</NavLink>
|
||||
</div>
|
||||
</div>
|
||||
</SidebarHeader>
|
||||
|
||||
@@ -100,29 +116,6 @@ export function AppSidebar() {
|
||||
</NavLink>
|
||||
</SidebarMenuItem>
|
||||
|
||||
<SidebarMenuItem>
|
||||
<NavLink to={`/instances/${instanceId}/cloud`}>
|
||||
{({ isActive }) => (
|
||||
<SidebarMenuButton
|
||||
isActive={isActive}
|
||||
tooltip="Configure cloud settings and domains"
|
||||
>
|
||||
<div className={cn(
|
||||
"p-1 rounded-md",
|
||||
isActive && "bg-primary/10"
|
||||
)}>
|
||||
<CloudLightning className={cn(
|
||||
"h-4 w-4",
|
||||
isActive && "text-primary",
|
||||
!isActive && "text-muted-foreground"
|
||||
)} />
|
||||
</div>
|
||||
<span className="truncate">Cloud</span>
|
||||
</SidebarMenuButton>
|
||||
)}
|
||||
</NavLink>
|
||||
</SidebarMenuItem>
|
||||
|
||||
<Collapsible defaultOpen className="group/collapsible">
|
||||
<SidebarMenuItem>
|
||||
<CollapsibleTrigger asChild>
|
||||
@@ -177,17 +170,6 @@ export function AppSidebar() {
|
||||
</NavLink>
|
||||
</SidebarMenuSubButton>
|
||||
</SidebarMenuSubItem> */}
|
||||
|
||||
<SidebarMenuSubItem>
|
||||
<SidebarMenuSubButton asChild>
|
||||
<NavLink to={`/instances/${instanceId}/iso`}>
|
||||
<div className="p-1 rounded-md">
|
||||
<Usb className="h-4 w-4" />
|
||||
</div>
|
||||
<span className="truncate">ISO / USB</span>
|
||||
</NavLink>
|
||||
</SidebarMenuSubButton>
|
||||
</SidebarMenuSubItem>
|
||||
</SidebarMenuSub>
|
||||
</CollapsibleContent>
|
||||
</SidebarMenuItem>
|
||||
@@ -225,21 +207,58 @@ export function AppSidebar() {
|
||||
</NavLink>
|
||||
</SidebarMenuSubButton>
|
||||
</SidebarMenuSubItem>
|
||||
|
||||
<SidebarMenuSubItem>
|
||||
<SidebarMenuSubButton asChild>
|
||||
<NavLink to={`/instances/${instanceId}/iso`}>
|
||||
<div className="p-1 rounded-md">
|
||||
<Usb className="h-4 w-4" />
|
||||
</div>
|
||||
<span className="truncate">ISO / USB</span>
|
||||
</NavLink>
|
||||
</SidebarMenuSubButton>
|
||||
</SidebarMenuSubItem>
|
||||
</SidebarMenuSub>
|
||||
</CollapsibleContent>
|
||||
</SidebarMenuItem>
|
||||
</Collapsible>
|
||||
|
||||
<SidebarMenuItem>
|
||||
<SidebarMenuButton asChild tooltip="Install and manage applications">
|
||||
<NavLink to={`/instances/${instanceId}/apps`}>
|
||||
<div className="p-1 rounded-md">
|
||||
<Collapsible defaultOpen className="group/collapsible">
|
||||
<SidebarMenuItem>
|
||||
<CollapsibleTrigger asChild>
|
||||
<SidebarMenuButton>
|
||||
<AppWindow className="h-4 w-4" />
|
||||
</div>
|
||||
<span className="truncate">Apps</span>
|
||||
</NavLink>
|
||||
</SidebarMenuButton>
|
||||
</SidebarMenuItem>
|
||||
Apps
|
||||
<ChevronDown className="ml-auto transition-transform group-data-[state=open]/collapsible:rotate-180" />
|
||||
</SidebarMenuButton>
|
||||
</CollapsibleTrigger>
|
||||
<CollapsibleContent>
|
||||
<SidebarMenuSub>
|
||||
<SidebarMenuSubItem>
|
||||
<SidebarMenuSubButton asChild>
|
||||
<NavLink to={`/instances/${instanceId}/apps/available`}>
|
||||
<div className="p-1 rounded-md">
|
||||
<Download className="h-4 w-4" />
|
||||
</div>
|
||||
<span className="truncate">Available</span>
|
||||
</NavLink>
|
||||
</SidebarMenuSubButton>
|
||||
</SidebarMenuSubItem>
|
||||
|
||||
<SidebarMenuSubItem>
|
||||
<SidebarMenuSubButton asChild>
|
||||
<NavLink to={`/instances/${instanceId}/apps/installed`}>
|
||||
<div className="p-1 rounded-md">
|
||||
<CheckCircle className="h-4 w-4" />
|
||||
</div>
|
||||
<span className="truncate">Installed</span>
|
||||
</NavLink>
|
||||
</SidebarMenuSubButton>
|
||||
</SidebarMenuSubItem>
|
||||
</SidebarMenuSub>
|
||||
</CollapsibleContent>
|
||||
</SidebarMenuItem>
|
||||
</Collapsible>
|
||||
|
||||
<SidebarMenuItem>
|
||||
<SidebarMenuButton asChild tooltip="Advanced settings and system configuration">
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { useState } from 'react';
|
||||
import { useLocation } from 'react-router';
|
||||
import { Card } from './ui/card';
|
||||
import { Button } from './ui/button';
|
||||
import { Badge } from './ui/badge';
|
||||
@@ -37,6 +38,7 @@ interface MergedApp extends App {
|
||||
type TabView = 'available' | 'installed';
|
||||
|
||||
export function AppsComponent() {
|
||||
const location = useLocation();
|
||||
const { currentInstance } = useInstanceContext();
|
||||
const { data: availableAppsData, isLoading: loadingAvailable, error: availableError } = useAvailableApps();
|
||||
const {
|
||||
@@ -51,7 +53,8 @@ export function AppsComponent() {
|
||||
isDeleting
|
||||
} = useDeployedApps(currentInstance);
|
||||
|
||||
const [activeTab, setActiveTab] = useState<TabView>('available');
|
||||
// Determine active tab from URL path
|
||||
const activeTab: TabView = location.pathname.endsWith('/installed') ? 'installed' : 'available';
|
||||
const [searchTerm, setSearchTerm] = useState('');
|
||||
const [selectedCategory, setSelectedCategory] = useState<string>('all');
|
||||
const [configDialogOpen, setConfigDialogOpen] = useState(false);
|
||||
@@ -323,22 +326,6 @@ export function AppsComponent() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Tab Navigation */}
|
||||
<div className="flex gap-2 mb-6 border-b pb-4">
|
||||
<Button
|
||||
variant={activeTab === 'available' ? 'default' : 'outline'}
|
||||
onClick={() => setActiveTab('available')}
|
||||
>
|
||||
Available Apps ({availableApps.length})
|
||||
</Button>
|
||||
<Button
|
||||
variant={activeTab === 'installed' ? 'default' : 'outline'}
|
||||
onClick={() => setActiveTab('installed')}
|
||||
>
|
||||
Installed Apps ({installedApps.length})
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col sm:flex-row gap-4 mb-6">
|
||||
<div className="relative flex-1">
|
||||
<Search className="absolute left-3 top-1/2 transform -translate-y-1/2 h-4 w-4 text-muted-foreground" />
|
||||
|
||||
Reference in New Issue
Block a user