refactor(ui): Improve usage log filter responsiveness and mobile UX

Refactor the usage log filter toolbar into a shared reusable component for common, drawing, and task logs. Optimize desktop filters with a responsive grid, move secondary filters into a mobile drawer, standardize filter typography, remove redundant filter icons, and add the missing i18n translations for the new drawer description.
This commit is contained in:
t0ng7u
2026-05-25 05:35:44 +08:00
parent b302be30e3
commit 583da45296
79 changed files with 1879 additions and 1262 deletions
@@ -21,7 +21,6 @@ import { useState } from 'react'
import type { ColumnDef } from '@tanstack/react-table'
import { Zap } from 'lucide-react'
import { formatTimestampToDate, formatTokens } from '@/lib/format'
import { cn } from '@/lib/utils'
import {
Tooltip,
TooltipContent,
@@ -97,36 +96,6 @@ export function createTimestampColumn<T>(config: {
}
}
/**
* Duration pill colors matching common logs timing column
*/
const durationPillBg: Record<string, string> = {
green:
'border border-emerald-200/60 bg-emerald-50/70 dark:border-emerald-800/50 dark:bg-emerald-950/25',
red: 'border border-rose-200/70 bg-rose-50/70 dark:border-rose-800/50 dark:bg-rose-950/25',
success:
'border border-emerald-200/60 bg-emerald-50/50 dark:border-emerald-800/50 dark:bg-emerald-950/20',
info: 'border border-sky-200/60 bg-sky-50/50 dark:border-sky-800/50 dark:bg-sky-950/20',
warning:
'border border-amber-200/60 bg-amber-50/50 dark:border-amber-800/50 dark:bg-amber-950/20',
}
const durationTextColor: Record<string, string> = {
green: 'text-emerald-700 dark:text-emerald-400',
red: 'text-rose-700 dark:text-rose-400',
success: 'text-emerald-700 dark:text-emerald-400',
info: 'text-sky-700 dark:text-sky-400',
warning: 'text-amber-700 dark:text-amber-400',
}
const durationDotColor: Record<string, string> = {
green: 'bg-emerald-500',
red: 'bg-rose-500',
success: 'bg-emerald-500',
info: 'bg-sky-500',
warning: 'bg-amber-500',
}
/**
* Create a duration column - pill style matching common logs timing
*/
@@ -163,25 +132,16 @@ export function createDurationColumn<T>(config: {
}
const variant =
duration.durationSec > warningThresholdSec ? 'red' : 'green'
duration.durationSec > warningThresholdSec ? 'danger' : 'success'
return (
<span
className={cn(
'inline-flex w-fit items-center gap-1 rounded-md px-1.5 py-0.5 font-mono text-xs font-medium',
durationPillBg[variant],
durationTextColor[variant]
)}
>
<span
className={cn(
'size-1.5 shrink-0 rounded-full',
durationDotColor[variant]
)}
aria-hidden='true'
/>
{duration.durationSec.toFixed(1)}s
</span>
<StatusBadge
label={`${duration.durationSec.toFixed(1)}s`}
variant={variant}
size='sm'
copyable={false}
className='font-mono'
/>
)
},
meta: { label: headerLabel },
@@ -37,6 +37,7 @@ import {
} from '@/components/ui/tooltip'
import { DataTableColumnHeader } from '@/components/data-table'
import { StatusBadge, type StatusBadgeProps } from '@/components/status-badge'
import { LOG_TYPE_ALL_VALUE } from '../../constants'
import type { UsageLog } from '../../data/schema'
import {
formatModelName,
@@ -281,7 +282,8 @@ export function useCommonLogsColumns(isAdmin: boolean): ColumnDef<UsageLog>[] {
)
},
filterFn: (row, _id, value) => {
if (!value || value.length === 0) return true
if (!Array.isArray(value) || value.length === 0) return true
if (value.includes(LOG_TYPE_ALL_VALUE)) return true
return value.includes(String(row.original.type))
},
enableHiding: false,
@@ -488,7 +490,6 @@ export function useCommonLogsColumns(isAdmin: boolean): ColumnDef<UsageLog>[] {
icon={KeyRound}
copyText={sensitiveVisible ? tokenName : undefined}
size='sm'
showDot={false}
className='border-border/60 bg-muted/30 text-foreground max-w-full overflow-hidden rounded-md border px-1.5 py-0.5 font-mono'
/>
</TooltipTrigger>
@@ -554,59 +555,32 @@ export function useCommonLogsColumns(isAdmin: boolean): ColumnDef<UsageLog>[] {
const timeVariant = getResponseTimeColor(useTime, log.completion_tokens)
const frtVariant = frt ? getFirstResponseTimeColor(frt / 1000) : null
const pillBg: Record<string, string> = {
success:
'border border-emerald-200/40 bg-emerald-50/35 dark:border-emerald-900/40 dark:bg-emerald-950/15',
warning:
'border border-amber-200/45 bg-amber-50/35 dark:border-amber-900/40 dark:bg-amber-950/15',
danger:
'border border-rose-200/50 bg-rose-50/35 dark:border-rose-900/40 dark:bg-rose-950/15',
}
const pillText: Record<string, string> = {
success: 'text-emerald-700/85 dark:text-emerald-400/85',
warning: 'text-amber-700/85 dark:text-amber-400/85',
danger: 'text-rose-700/85 dark:text-rose-400/85',
}
const pillDot: Record<string, string> = {
success: 'bg-emerald-500/80',
warning: 'bg-amber-500/80',
danger: 'bg-rose-500/80',
}
return (
<div className='flex flex-col gap-1'>
<div className='flex items-center gap-1.5'>
<span
className={cn(
'inline-flex items-center gap-1 rounded-md px-1.5 py-0.5 font-mono text-xs font-medium',
pillBg[timeVariant],
pillText[timeVariant]
)}
>
<span
className={cn(
'size-1.5 shrink-0 rounded-full',
pillDot[timeVariant]
)}
aria-hidden='true'
/>
{formatUseTime(useTime)}
</span>
<StatusBadge
label={formatUseTime(useTime)}
variant={timeVariant as StatusBadgeProps['variant']}
size='sm'
copyable={false}
className='font-mono'
/>
{log.is_stream &&
(frt != null && frt > 0 ? (
<span
className={cn(
'inline-flex items-center rounded-md px-1.5 py-0.5 font-mono text-xs font-medium',
pillBg[frtVariant!],
pillText[frtVariant!]
)}
>
{formatUseTime(frt / 1000)}
</span>
<StatusBadge
label={formatUseTime(frt / 1000)}
variant={frtVariant as StatusBadgeProps['variant']}
size='sm'
copyable={false}
className='font-mono'
/>
) : (
<span className='border-border/60 text-muted-foreground/50 inline-flex items-center rounded-md border px-1.5 py-0.5 text-[11px]'>
N/A
</span>
<StatusBadge
label='N/A'
variant='neutral'
size='sm'
copyable={false}
/>
))}
</div>
<div className='flex items-center gap-1 text-[11px]'>
@@ -724,15 +698,15 @@ export function useCommonLogsColumns(isAdmin: boolean): ColumnDef<UsageLog>[] {
<Tooltip>
<TooltipTrigger
render={
<span className='inline-flex items-center gap-1 rounded-md border border-emerald-200 bg-emerald-50 px-1.5 py-0.5 text-xs font-medium text-emerald-700 dark:border-emerald-800 dark:bg-emerald-950/40 dark:text-emerald-300' />
<StatusBadge
label={t('Subscription')}
variant='success'
size='sm'
copyable={false}
className='cursor-help'
/>
}
>
<span
className='size-1.5 rounded-full bg-emerald-500'
aria-hidden='true'
/>
{t('Subscription')}
</TooltipTrigger>
/>
<TooltipContent>
<span>
{t('Deducted by subscription')}: {formatLogQuota(quota)}
@@ -132,7 +132,6 @@ export function useDrawingLogsColumns(
icon={getDrawingTypeIcon(action)}
size='sm'
copyable={false}
showDot={false}
/>
)
},
@@ -157,7 +156,6 @@ export function useDrawingLogsColumns(
label={mjId}
autoColor={mjId}
size='sm'
showDot={false}
className='border-border/60 bg-muted/30 max-w-full truncate rounded-md border px-1.5 py-0.5 font-mono'
/>
</div>
@@ -189,7 +187,6 @@ export function useDrawingLogsColumns(
variant={mjSubmitResultMapper.getVariant(String(code))}
size='sm'
copyable={false}
showDot
/>
)
},
@@ -183,7 +183,6 @@ export function useTaskLogsColumns(isAdmin: boolean): ColumnDef<TaskLog>[] {
label={taskId}
autoColor={taskId}
size='sm'
showDot={false}
className='border-border/60 bg-muted/30 max-w-full truncate rounded-md border px-1.5 py-0.5 font-mono'
/>
<span className='text-muted-foreground/60 truncate text-[11px]'>
@@ -214,7 +213,6 @@ export function useTaskLogsColumns(isAdmin: boolean): ColumnDef<TaskLog>[] {
variant={taskStatusMapper.getVariant(status)}
size='sm'
copyable={false}
showDot
/>
)
},