fix(frontend): wrong usage, tooltips, ...

This commit is contained in:
Alois 2026-08-30 11:58:15 +02:00
commit 3db5ec25c2
Signed by: alois
SSH key fingerprint: SHA256:GBzT2DXvAuGV9XIV5W3WrzVpjU54FThmxHXdbz95J24
2 changed files with 59 additions and 43 deletions

View file

@ -317,8 +317,13 @@ func (h *Handler) RequestCodexToken(c *gin.Context) {
FileName: fileName,
Storage: tokenStorage,
Metadata: map[string]any{
"email": tokenStorage.Email,
"account_id": tokenStorage.AccountID,
"email": tokenStorage.Email,
"account_id": tokenStorage.AccountID,
"access_token": tokenStorage.AccessToken,
"refresh_token": tokenStorage.RefreshToken,
"id_token": tokenStorage.IDToken,
"expired": tokenStorage.Expire,
"last_refresh": tokenStorage.LastRefresh,
},
}
if errGuard := guardOAuthSessionPendingForSave(state, "codex"); errGuard != nil {

View file

@ -32,26 +32,23 @@ import {
Spinner,
Tooltip,
TooltipContent,
TooltipProvider,
TooltipTrigger,
useTheme,
} from '@methanium/ui';
import {
AlertTriangle,
Check,
CheckCircle2,
Clock3,
ExternalLink,
Eye,
EyeClosed,
EyeOff,
EyeOffIcon,
KeyRound,
LogOut,
Moon,
Plus,
RefreshCw,
ShieldAlert,
Star,
Sun,
Trash2,
UserRound,
@ -101,6 +98,21 @@ function titleFromKey(key: string) {
return key.replace(/[_-]+/g, ' ').replace(/\b\w/g, (letter) => letter.toUpperCase());
}
function quotaWindowLabel(record: Record<string, unknown>, key: string) {
const rawSeconds =
record.limit_window_seconds ?? record.limitWindowSeconds ?? record.window_seconds;
if (typeof rawSeconds === 'number') {
if (rawSeconds === 5 * 60 * 60) return '5-hour limit';
if (rawSeconds === 7 * 24 * 60 * 60) return 'Weekly limit';
const days = rawSeconds / 86400;
if (Number.isInteger(days)) return `${days}-day limit`;
const hours = rawSeconds / 3600;
if (Number.isInteger(hours)) return `${hours}-hour limit`;
}
return titleFromKey(key);
}
function quotaWindows(data: unknown) {
const windows: Array<{
key: string;
@ -119,7 +131,7 @@ function quotaWindows(data: unknown) {
const rawResetAfter = record.reset_after_seconds ?? record.resetAfterSeconds;
windows.push({
key,
label: titleFromKey(path[path.length - 1] || 'Usage'),
label: quotaWindowLabel(record, path[path.length - 1] || 'Usage'),
usedPercent: Math.max(0, Math.min(100, used)),
resetAt: typeof rawResetAt === 'number' ? rawResetAt : undefined,
resetAfterSeconds: typeof rawResetAfter === 'number' ? rawResetAfter : undefined,
@ -302,22 +314,17 @@ function AccountCard({
<CardTitle className="flex min-w-0 items-center gap-2">
<UserRound className="size-4 shrink-0" />
{emailHidden ? (
<Tooltip>
<TooltipTrigger className="truncate">
<code>
{Array.from({ length: (identity || account.name).length }).map((_, index) => (
<span key={index}>*</span>
))}
</code>
</TooltipTrigger>
<TooltipContent className="truncate">{account.name}</TooltipContent>
</Tooltip>
<code className="truncate">
{Array.from({ length: (identity || account.name).length }).map((_, index) => (
<span key={index}>*</span>
))}
</code>
) : (
<Tooltip>
<TooltipTrigger className="truncate">
<code>{identity || account.name}</code>
</TooltipTrigger>
<TooltipContent className="truncate">{account.name}</TooltipContent>
<TooltipTrigger
render={<code className="truncate">{identity || account.name}</code>}
/>
<TooltipContent>{account.name}</TooltipContent>
</Tooltip>
)}
<button
@ -392,9 +399,11 @@ function AccountCard({
<div className="space-y-4">
{windows.map((window) => (
<div key={window.key}>
<Progress value={window.usedPercent}>
<Progress value={100 - window.usedPercent} max={100}>
<ProgressLabel>{window.label}</ProgressLabel>
<ProgressValue>{() => `${Math.round(window.usedPercent)}% used`}</ProgressValue>
<ProgressValue>
{() => `${Math.round(100 - window.usedPercent)}% used`}
</ProgressValue>
</Progress>
{resetLabel(window) && (
<div className="mt-1 text-xs text-muted-foreground">{resetLabel(window)}</div>
@ -709,25 +718,27 @@ export function App() {
};
return (
<div className="min-h-screen bg-background text-foreground">
<Header loggedIn={Boolean(managementKey && accounts)} onLogout={logout} />
{!managementKey ? (
<Login
onLogin={async (key) => {
const trimmed = key.trim();
const files = await listAuthFiles(trimmed);
sessionStorage.setItem(managementKeyStorage, trimmed);
setManagementKey(trimmed);
setAccounts(files);
}}
/>
) : accounts === null ? (
<main className="flex min-h-[calc(100vh-3rem)] items-center justify-center">
<Spinner className="size-5" />
</main>
) : (
<Dashboard managementKey={managementKey} initialAccounts={accounts} />
)}
</div>
<TooltipProvider>
<div className="min-h-screen bg-background text-foreground">
<Header loggedIn={Boolean(managementKey && accounts)} onLogout={logout} />
{!managementKey ? (
<Login
onLogin={async (key) => {
const trimmed = key.trim();
const files = await listAuthFiles(trimmed);
sessionStorage.setItem(managementKeyStorage, trimmed);
setManagementKey(trimmed);
setAccounts(files);
}}
/>
) : accounts === null ? (
<main className="flex min-h-[calc(100vh-3rem)] items-center justify-center">
<Spinner className="size-5" />
</main>
) : (
<Dashboard managementKey={managementKey} initialAccounts={accounts} />
)}
</div>
</TooltipProvider>
);
}