From 7ca69063bd29fded483ae5e0dce53802eac1b99f Mon Sep 17 00:00:00 2001 From: 9qeklajc Date: Wed, 10 Dec 2025 22:49:48 +0100 Subject: [PATCH] make format required & fix ui formating --- .github/workflows/test.yml | 8 +- ui/app/balances/page.tsx | 4 +- ui/app/login/page.tsx | 4 +- ui/app/logs/log-details-dialog.tsx | 13 ++- ui/app/model/page.tsx | 33 ++++-- ui/app/page.tsx | 72 ++++++++---- ui/app/providers/page.tsx | 107 ++++++++++++------ ui/components/AddProviderModelDialog.tsx | 117 +++++++++++++------- ui/components/ModelSelector.tsx | 23 ++-- ui/components/currency-toggle.tsx | 19 ++-- ui/components/dashboard-balance-summary.tsx | 1 - ui/components/error-details-table.tsx | 2 +- ui/components/landing/cheat-sheet.tsx | 86 +++++++------- ui/components/revenue-by-model-table.tsx | 63 +++++++---- ui/components/usage-metrics-chart.tsx | 6 +- ui/components/usage-summary-cards.tsx | 14 ++- ui/lib/api/services/admin.ts | 21 ++-- ui/lib/stores/currency.ts | 1 - 18 files changed, 378 insertions(+), 216 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index aca29594..ae676584 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -62,14 +62,18 @@ jobs: - name: Setup Node.js uses: actions/setup-node@v4 with: - node-version: '18' - cache: 'npm' + node-version: "18" + cache: "npm" cache-dependency-path: ui/package-lock.json - name: Install UI dependencies working-directory: ./ui run: npm ci + - name: Run UI format check + working-directory: ./ui + run: npm run format-check + - name: Run UI linting working-directory: ./ui run: npm run lint diff --git a/ui/app/balances/page.tsx b/ui/app/balances/page.tsx index b5213287..89e44f3a 100644 --- a/ui/app/balances/page.tsx +++ b/ui/app/balances/page.tsx @@ -29,9 +29,7 @@ export default function BalancesPage() {
-

- Balances -

+

Balances

Monitor and manage wallet balances

diff --git a/ui/app/login/page.tsx b/ui/app/login/page.tsx index 7df50995..ba47a120 100644 --- a/ui/app/login/page.tsx +++ b/ui/app/login/page.tsx @@ -78,8 +78,8 @@ export default function AdminLoginPage(): ReactElement { }; return ( -
- +
+ Admin Login diff --git a/ui/app/logs/log-details-dialog.tsx b/ui/app/logs/log-details-dialog.tsx index 852aa4a8..5c0193ce 100644 --- a/ui/app/logs/log-details-dialog.tsx +++ b/ui/app/logs/log-details-dialog.tsx @@ -97,7 +97,7 @@ export function LogDetailsDialog({

Message

-
+                
                   {log.message}
                 
@@ -116,7 +116,12 @@ export function LogDetailsDialog({
{totalModels === 0 && ( - +

No models found for this provider

-
-

Common issues:

-
    +
    +

    + Common issues: +

    +
    • - API credentials: Check if the API key is correct and has the right permissions + API credentials:{' '} + Check if the API key is correct + and has the right permissions
    • - Base URL: Verify the base URL is correct for your provider + Base URL: Verify + the base URL is correct for your + provider
    • - Network access: Ensure the server can reach the provider's API endpoint + Network access:{' '} + Ensure the server can reach the + provider's API endpoint
    • - Provider status: The upstream provider might be temporarily unavailable + Provider status:{' '} + The upstream provider might be + temporarily unavailable
    {groupData?.group_url && ( -

    - Current endpoint: {groupData.group_url} +

    + Current endpoint:{' '} + + {groupData.group_url} +

    )}
    diff --git a/ui/app/page.tsx b/ui/app/page.tsx index 041512eb..ba5dff37 100644 --- a/ui/app/page.tsx +++ b/ui/app/page.tsx @@ -53,7 +53,7 @@ export default function DashboardPage() { window.removeEventListener('storage', syncAuthState); }; }, []); - + const { data: btcUsdPrice } = useQuery({ queryKey: ['btc-usd-price'], queryFn: fetchBtcUsdPrice, @@ -131,8 +131,13 @@ export default function DashboardPage() {
    -

    Dashboard

    - +

    + Dashboard +

    +
    @@ -140,8 +145,9 @@ export default function DashboardPage() {

    Usage Analytics

    -

    - Monitor requests, errors, and revenue over the last {timeRange} hours +

    + Monitor requests, errors, and revenue over the last {timeRange}{' '} + hours

    @@ -176,27 +182,31 @@ export default function DashboardPage() {
    {summaryLoading ? ( -
    Loading summary...
    +
    Loading summary...
    ) : summaryData ? ( ) : null}
    {metricsLoading ? ( -
    +
    Loading metrics...
    ) : metricsData && metricsData.metrics.length > 0 ? ( <> -
    +
    ({ - ...m, - revenue_sats: m.revenue_msats / 1000, - refunds_sats: m.refunds_msats / 1000, - net_revenue_sats: - (m.revenue_msats - m.refunds_msats) / 1000, - })) as Array & { timestamp: string }>} + data={ + metricsData.metrics.map((m) => ({ + ...m, + revenue_sats: m.revenue_msats / 1000, + refunds_sats: m.refunds_msats / 1000, + net_revenue_sats: + (m.revenue_msats - m.refunds_msats) / 1000, + })) as Array< + Record & { timestamp: string } + > + } title='Revenue Over Time (sats)' dataKeys={[ { @@ -218,7 +228,11 @@ export default function DashboardPage() { />
    & { timestamp: string }>} + data={ + metricsData.metrics as Array< + Record & { timestamp: string } + > + } title='Request Volume' dataKeys={[ { @@ -239,7 +253,11 @@ export default function DashboardPage() { ]} /> & { timestamp: string }>} + data={ + metricsData.metrics as Array< + Record & { timestamp: string } + > + } title='Error Tracking' dataKeys={[ { @@ -260,7 +278,11 @@ export default function DashboardPage() { ]} /> & { timestamp: string }>} + data={ + metricsData.metrics as Array< + Record & { timestamp: string } + > + } title='Payment Activity' dataKeys={[ { @@ -270,7 +292,7 @@ export default function DashboardPage() { }, ]} /> -
    +
    {summaryData && summaryData.unique_models.length > 0 && ( @@ -306,7 +328,9 @@ export default function DashboardPage() { key={type} className='flex items-center justify-between' > - {type} + + {type} + {count} @@ -335,16 +359,18 @@ export default function DashboardPage() {
    {revenueByModelLoading ? ( -
    Loading revenue by model...
    +
    + Loading revenue by model... +
    ) : revenueByModelData && revenueByModelData.models.length > 0 ? ( - ) : null} {errorLoading ? ( -
    Loading errors...
    +
    Loading errors...
    ) : errorData ? ( ) : null} diff --git a/ui/app/providers/page.tsx b/ui/app/providers/page.tsx index f431f101..4624f26a 100644 --- a/ui/app/providers/page.tsx +++ b/ui/app/providers/page.tsx @@ -76,7 +76,11 @@ function ProviderBalance({ ); const queryClient = useQueryClient(); - const { data: balanceData, isLoading, error } = useQuery({ + const { + data: balanceData, + isLoading, + error, + } = useQuery({ queryKey: ['provider-balance', providerId], queryFn: () => AdminService.getProviderBalance(providerId), refetchInterval: 30000, @@ -108,7 +112,10 @@ function ProviderBalance({ mutationFn: async (amount: number) => { console.log('Calling top-up API with:', { providerId, amount }); try { - const result = await AdminService.initiateProviderTopup(providerId, amount); + const result = await AdminService.initiateProviderTopup( + providerId, + amount + ); console.log('API returned:', result); return result; } catch (err) { @@ -120,11 +127,8 @@ function ProviderBalance({ console.log('Top-up response:', data); console.log('Type of data:', typeof data); console.log('Keys in data:', Object.keys(data || {})); - - if ( - data?.topup_data?.payment_request && - data?.topup_data?.invoice_id - ) { + + if (data?.topup_data?.payment_request && data?.topup_data?.invoice_id) { setInvoiceData({ payment_request: data.topup_data.payment_request as string, invoice_id: data.topup_data.invoice_id as string, @@ -172,19 +176,23 @@ function ProviderBalance({ // The backend throws 500/400 if not implemented. // A better approach is to check if we have a platform URL and maybe redirect there // if we know it's not supported. - + // BUT, we don't know for sure if it's supported without checking metadata or trying. // Let's rely on the "can_topup" metadata if available, but currently we only have "can_show_balance". - + // Simple heuristic: If platformUrl exists and we suspect no direct topup, redirect? // Actually, let's try to open the dialog, but if it's OpenRouter/OpenAI, maybe we just redirect? // The user specifically mentioned "like in openrouter". - - if (platformUrl && (platformUrl.includes('openrouter.ai') || platformUrl.includes('openai.com'))) { - window.open(platformUrl, '_blank'); - return; + + if ( + platformUrl && + (platformUrl.includes('openrouter.ai') || + platformUrl.includes('openai.com')) + ) { + window.open(platformUrl, '_blank'); + return; } - + setIsTopupDialogOpen(true); }; @@ -266,9 +274,7 @@ function ProviderBalance({
    -

    - Top-up successful! -

    +

    Top-up successful!

    ) : invoiceData ? (
    @@ -482,7 +488,9 @@ export default function ProvidersPage() { ...formData, api_key: String(response.account_data.api_key), }); - toast.success('Account created successfully! API key has been filled in.'); + toast.success( + 'Account created successfully! API key has been filled in.' + ); } else { toast.success('Account created, but no API key returned.'); } @@ -778,8 +786,7 @@ export default function ProvidersPage() { )} />

    - 1.01 means +1% e.g. currency exchange, card - fees, etc. + 1.01 means +1% e.g. currency exchange, card fees, etc.

    @@ -856,9 +863,11 @@ export default function ProvidersPage() {
    {canShowBalance(provider.provider_type) && provider.api_key && ( - )} @@ -970,7 +986,12 @@ export default function ProvidersPage() { variant='ghost' size='icon' className='h-8 w-8' - onClick={() => handleEditModel(provider.id, model)} + onClick={() => + handleEditModel( + provider.id, + model + ) + } > @@ -1027,10 +1048,17 @@ export default function ProvidersPage() {
    {providerModels.db_models.length > 0 && (
    - Custom models override or extend the provider's catalog. + Custom models override or extend the + provider's catalog.
    )} - @@ -1079,7 +1107,12 @@ export default function ProvidersPage() { variant='ghost' size='icon' className='h-8 w-8' - onClick={() => handleEditModel(provider.id, model)} + onClick={() => + handleEditModel( + provider.id, + model + ) + } > @@ -1126,7 +1159,12 @@ export default function ProvidersPage() { variant='outline' size='sm' className='h-7 text-xs' - onClick={() => handleOverrideModel(provider.id, model)} + onClick={() => + handleOverrideModel( + provider.id, + model + ) + } > Override @@ -1245,7 +1283,7 @@ export default function ProvidersPage() {
    )}
    - @@ -1277,8 +1315,7 @@ export default function ProvidersPage() { )} />

    - 1.01 means +1% e.g. currency exchange, card - fees, etc. + 1.01 means +1% e.g. currency exchange, card fees, etc.

    @@ -1303,7 +1340,9 @@ export default function ProvidersPage() { setModelDialogState((prev) => ({ ...prev, isOpen: false }))} + onClose={() => + setModelDialogState((prev) => ({ ...prev, isOpen: false })) + } onSuccess={() => { queryClient.invalidateQueries({ queryKey: ['provider-models', modelDialogState.providerId], diff --git a/ui/components/AddProviderModelDialog.tsx b/ui/components/AddProviderModelDialog.tsx index 1bc17154..301682f4 100644 --- a/ui/components/AddProviderModelDialog.tsx +++ b/ui/components/AddProviderModelDialog.tsx @@ -102,7 +102,8 @@ export function AddProviderModelDialog({ }: AddProviderModelDialogProps) { const [isSubmitting, setIsSubmitting] = useState(false); const [isPresetOpen, setIsPresetOpen] = useState(false); - const [selectedPresetLabel, setSelectedPresetLabel] = useState('Select a preset'); + const [selectedPresetLabel, setSelectedPresetLabel] = + useState('Select a preset'); const form = useForm({ resolver: zodResolver(FormSchema) as never, @@ -149,7 +150,10 @@ export function AddProviderModelDialog({ if (initialData) { const architecture = initialData.architecture as Record; const pricing = initialData.pricing as Record; - const topProvider = initialData.top_provider as Record | null; + const topProvider = initialData.top_provider as Record< + string, + unknown + > | null; form.reset({ id: initialData.id, @@ -250,7 +254,9 @@ export function AddProviderModelDialog({ form.setValue('context_length', model.context_length); form.setValue( 'modality', - typeof architecture?.modality === 'string' ? architecture.modality : 'text' + typeof architecture?.modality === 'string' + ? architecture.modality + : 'text' ); form.setValue( 'input_modalities_raw', @@ -318,7 +324,10 @@ export function AddProviderModelDialog({ setIsSubmitting(true); try { let perRequestLimits: Record | null = null; - if (data.per_request_limits_raw && data.per_request_limits_raw.trim().length) { + if ( + data.per_request_limits_raw && + data.per_request_limits_raw.trim().length + ) { try { perRequestLimits = JSON.parse(data.per_request_limits_raw); } catch { @@ -336,7 +345,9 @@ export function AddProviderModelDialog({ context_length: data.context_length, architecture: { modality: data.modality, - input_modalities: listFromString(data.input_modalities_raw || data.modality), + input_modalities: listFromString( + data.input_modalities_raw || data.modality + ), output_modalities: listFromString( data.output_modalities_raw || data.modality ), @@ -366,10 +377,9 @@ export function AddProviderModelDialog({ is_moderated: data.top_provider_is_moderated, } : null, - upstream_provider_id: - data.upstream_provider_id?.trim().length - ? data.upstream_provider_id.trim() - : providerId, + upstream_provider_id: data.upstream_provider_id?.trim().length + ? data.upstream_provider_id.trim() + : providerId, canonical_slug: data.canonical_slug?.trim() || null, alias_ids: listFromString(data.alias_ids_raw || ''), enabled: data.enabled, @@ -416,7 +426,7 @@ export function AddProviderModelDialog({ {description} {!isEdit && !isOverride && ( -
    +
    Presets
    @@ -425,23 +435,25 @@ export function AddProviderModelDialog({ variant='outline' role='combobox' aria-expanded={isPresetOpen} - className='w-full justify-between text-left text-sm overflow-hidden' + className='w-full justify-between overflow-hidden text-left text-sm' > - {isLoadingPresets ? 'Loading presets...' : selectedPresetLabel} + {isLoadingPresets + ? 'Loading presets...' + : selectedPresetLabel} - e.preventDefault()} > - e.stopPropagation()} > @@ -475,8 +487,9 @@ export function AddProviderModelDialog({
    -
    - Prefill fields from a preset model definition, then adjust as needed. +
    + Prefill fields from a preset model definition, then adjust as + needed.
    )} @@ -496,7 +509,9 @@ export function AddProviderModelDialog({ disabled={isOverride || isEdit} /> - Unique identifier for the model + + Unique identifier for the model + )} @@ -524,7 +539,11 @@ export function AddProviderModelDialog({ Description -