From 10d05502f305f5f351562da8b0aa2b64dca41a4c Mon Sep 17 00:00:00 2001 From: kaitranntt Date: Mon, 8 Dec 2025 00:28:06 -0500 Subject: [PATCH] fix(ui): improve cliproxy dashboard layout and dropdown styling --- ui/src/components/cliproxy-table.tsx | 56 +++--- ui/src/components/ui/dropdown-menu.tsx | 2 +- ui/src/pages/cliproxy.tsx | 227 ++++++++++++++----------- 3 files changed, 161 insertions(+), 124 deletions(-) diff --git a/ui/src/components/cliproxy-table.tsx b/ui/src/components/cliproxy-table.tsx index af467c4b..b9f7e2bb 100644 --- a/ui/src/components/cliproxy-table.tsx +++ b/ui/src/components/cliproxy-table.tsx @@ -44,6 +44,7 @@ export function CliproxyTable({ data }: CliproxyTableProps) { { accessorKey: 'name', header: 'Name', + cell: ({ row }) => {row.original.name}, }, { accessorKey: 'provider', @@ -56,11 +57,11 @@ export function CliproxyTable({ data }: CliproxyTableProps) { cell: ({ row }) => { const account = row.original.account; if (!account) { - return default; + return default; } return ( - + {account} ); @@ -69,27 +70,35 @@ export function CliproxyTable({ data }: CliproxyTableProps) { { accessorKey: 'settings', header: 'Settings Path', + cell: ({ row }) => ( + + {row.original.settings || `config.cliproxy.${row.original.name}`} + + ), }, { id: 'actions', header: 'Actions', cell: ({ row }) => ( - - - - - - deleteMutation.mutate(row.original.name)} - > - - Delete - - - +
+ + + + + + deleteMutation.mutate(row.original.name)} + > + + Delete + + + +
), }, ]; @@ -103,16 +112,19 @@ export function CliproxyTable({ data }: CliproxyTableProps) { if (data.length === 0) { return ( -
- No CLIProxy variants found. Create one to use OAuth-based providers. +
+
No CLIProxy variants found.
+
+ Create one to use OAuth-based providers with specific account configurations. +
); } return ( -
+
- + {table.getHeaderGroups().map((headerGroup) => ( {headerGroup.headers.map((header) => ( diff --git a/ui/src/components/ui/dropdown-menu.tsx b/ui/src/components/ui/dropdown-menu.tsx index dbb5b694..8e2f660d 100644 --- a/ui/src/components/ui/dropdown-menu.tsx +++ b/ui/src/components/ui/dropdown-menu.tsx @@ -31,7 +31,7 @@ function DropdownMenuContent({ data-slot="dropdown-menu-content" sideOffset={sideOffset} className={cn( - 'bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 max-h-(--radix-dropdown-menu-content-available-height) min-w-[8rem] origin-(--radix-dropdown-menu-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-md border p-1 shadow-md', + 'bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 max-h-(--radix-dropdown-menu-content-available-height) min-w-[8rem] origin-(--radix-dropdown-menu-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-md border p-1 shadow-md bg-white dark:bg-zinc-950', className )} {...props} diff --git a/ui/src/pages/cliproxy.tsx b/ui/src/pages/cliproxy.tsx index 56b6cbbc..6ef4c94b 100644 --- a/ui/src/pages/cliproxy.tsx +++ b/ui/src/pages/cliproxy.tsx @@ -7,12 +7,12 @@ import { useState } from 'react'; import { Button } from '@/components/ui/button'; import { Badge } from '@/components/ui/badge'; +import { Card, CardContent } from '@/components/ui/card'; import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger, - DropdownMenuSeparator, } from '@/components/ui/dropdown-menu'; import { Plus, Check, X, User, ChevronDown, Star, Trash2 } from 'lucide-react'; import { CliproxyTable } from '@/components/cliproxy-table'; @@ -40,10 +40,10 @@ function AccountBadge({ - -
- {account.email || account.id} + +
+
+ {account.email || account.id} +
{account.lastUsedAt && ( -
- Last used: {new Date(account.lastUsedAt).toLocaleDateString()} -
+
Last used: {new Date(account.lastUsedAt).toLocaleDateString()}
)}
- {!account.isDefault && ( @@ -69,7 +68,7 @@ function AccountBadge({ )} @@ -81,7 +80,7 @@ function AccountBadge({ ); } -function ProviderCard({ +function ProviderRow({ status, setDefaultMutation, removeMutation, @@ -91,79 +90,85 @@ function ProviderCard({ removeMutation: ReturnType; }) { const accounts = status.accounts || []; - const hasMultipleAccounts = accounts.length > 1; return ( -
-
-
- {status.authenticated ? ( - - ) : ( - - )} - {status.displayName} +
+
+
+ {status.authenticated ? : }
- {accounts.length > 0 && ( - - {accounts.length} account{accounts.length !== 1 ? 's' : ''} - +
+
+ {status.displayName} + {accounts.length > 0 && ( + + {accounts.length} + + )} +
+
{status.provider}
+
+
+ +
+ {status.authenticated && accounts.length > 0 ? ( + accounts.map((account) => ( + + setDefaultMutation.mutate({ + provider: status.provider, + accountId: account.id, + }) + } + onRemove={() => + removeMutation.mutate({ + provider: status.provider, + accountId: account.id, + }) + } + isRemoving={removeMutation.isPending} + /> + )) + ) : ( +
+ {status.authenticated + ? 'Authenticated (No specific accounts tracked)' + : 'Not authenticated'} +
)}
- {status.authenticated ? ( -
- {accounts.length > 0 ? ( -
- {accounts.map((account) => ( - - setDefaultMutation.mutate({ - provider: status.provider, - accountId: account.id, - }) - } - onRemove={() => - removeMutation.mutate({ - provider: status.provider, - accountId: account.id, - }) - } - isRemoving={removeMutation.isPending} - /> - ))} -
- ) : ( -
- Authenticated - {status.lastAuth && ( - ({new Date(status.lastAuth).toLocaleDateString()}) - )} -
- )} - {hasMultipleAccounts && ( -
- Click account to manage. Star = default. -
- )} -
- Add account: ccs {status.provider} --auth +
+ {!status.authenticated && ( +
+ ccs {status.provider} --auth
-
- ) : ( -
- Not authenticated - - Run: ccs {status.provider} --auth - -
- )} + )} + {status.authenticated && ( + + )} +
); } @@ -176,12 +181,12 @@ export function CliproxyPage() { const removeMutation = useRemoveAccount(); return ( -
-
+
+
-

CLIProxy

+

CLIProxy

- Manage OAuth-based provider variants with multi-account support + Manage OAuth-based provider variants and multi-account configurations

{/* Built-in Profiles with Account Management */} -
-

Built-in Profiles & Accounts

- {authLoading ? ( -
Loading auth status...
- ) : ( -
- {authData?.authStatus.map((status) => ( - - ))} -
- )} +
+
+

Built-in Providers

+

+ Manage authentication status and accounts for built-in providers. +

+
+ + + + {authLoading ? ( +
+ Loading authentication status... +
+ ) : ( +
+ {authData?.authStatus.map((status) => ( + + ))} +
+ )} +
+
{/* Custom Variants */} -
-

Custom Variants

+
+
+
+

Custom Variants

+

+ Create custom aliases for providers with specific accounts. +

+
+
+ {isLoading ? (
Loading variants...
) : (