From 0229dc20573f728ec1140543cdee291197d67e8c Mon Sep 17 00:00:00 2001 From: CaIon Date: Fri, 19 Jun 2026 20:17:45 +0800 Subject: [PATCH] refactor: refine toolbar controls and model drawer --- .../components/data-table/toolbar/toolbar.tsx | 7 -- .../channels/components/channels-table.tsx | 2 +- .../drawers/model-mutate-drawer.tsx | 103 +++++++++--------- .../components/common-logs-filter-bar.tsx | 41 +++---- .../components/logs-filter-toolbar.tsx | 5 +- 5 files changed, 80 insertions(+), 78 deletions(-) diff --git a/web/default/src/components/data-table/toolbar/toolbar.tsx b/web/default/src/components/data-table/toolbar/toolbar.tsx index 636ee94c..bfb9514b 100644 --- a/web/default/src/components/data-table/toolbar/toolbar.tsx +++ b/web/default/src/components/data-table/toolbar/toolbar.tsx @@ -76,11 +76,6 @@ export type DataTableToolbarProps = { * search input and filter chips. */ additionalSearch?: ReactNode - /** - * Extra controls displayed immediately after the filter chips, before the - * right-aligned action cluster. - */ - afterFilters?: ReactNode /** * Whether non-table filters (e.g. `additionalSearch` or `expandable` * inputs) are currently active. Controls Reset button visibility @@ -351,7 +346,6 @@ export function DataTableToolbar(props: DataTableToolbarProps) { {props.customSearch !== undefined ? props.customSearch : searchInput} {props.additionalSearch} {filterChips} - {props.afterFilters}
{expandToggle}
@@ -387,7 +381,6 @@ export function DataTableToolbar(props: DataTableToolbarProps) { {props.customSearch !== undefined ? props.customSearch : searchInput} {props.additionalSearch} {filterChips} - {props.afterFilters} {expanded && hasExpandable && props.expandable}
diff --git a/web/default/src/features/channels/components/channels-table.tsx b/web/default/src/features/channels/components/channels-table.tsx index 1c091422..9d22e494 100644 --- a/web/default/src/features/channels/components/channels-table.tsx +++ b/web/default/src/features/channels/components/channels-table.tsx @@ -409,7 +409,7 @@ export function ChannelsTable() { singleSelect: true, }, ], - afterFilters: ( + preActions: ( ('per-token') const [pricingSubMode, setPricingSubMode] = useState('ratio') @@ -143,8 +144,13 @@ export function ModelMutateDrawer({ // Fetch model detail if editing const { data: modelData } = useQuery({ - queryKey: modelsQueryKeys.detail(currentRow?.id || 0), - queryFn: () => getModel(currentRow!.id), + queryKey: modelsQueryKeys.detail(currentModelId || 0), + queryFn: () => { + if (!currentModelId) { + throw new Error('Model ID is required') + } + return getModel(currentModelId) + }, enabled: open && isEditing, }) @@ -230,13 +236,13 @@ export function ModelMutateDrawer({ const validateNumber = (value: string) => { if (value === '') return true - return !isNaN(parseFloat(value)) + return !Number.isNaN(Number.parseFloat(value)) } const handlePromptPriceChange = (value: string) => { setPromptPrice(value) - if (value && !isNaN(parseFloat(value))) { - const ratio = parseFloat(value) / 2 + if (value && !Number.isNaN(Number.parseFloat(value))) { + const ratio = Number.parseFloat(value) / 2 form.setValue('ratio', ratio.toString()) } else { form.setValue('ratio', '') @@ -247,12 +253,12 @@ export function ModelMutateDrawer({ setCompletionPrice(value) if ( value && - !isNaN(parseFloat(value)) && + !Number.isNaN(Number.parseFloat(value)) && promptPrice && - !isNaN(parseFloat(promptPrice)) && - parseFloat(promptPrice) > 0 + !Number.isNaN(Number.parseFloat(promptPrice)) && + Number.parseFloat(promptPrice) > 0 ) { - const completionRatio = parseFloat(value) / parseFloat(promptPrice) + const completionRatio = Number.parseFloat(value) / Number.parseFloat(promptPrice) form.setValue('completionRatio', completionRatio.toString()) } else { form.setValue('completionRatio', '') @@ -398,7 +404,7 @@ export function ModelMutateDrawer({ try { const submitData = { ...values, - id: isEditing ? currentRow!.id : undefined, + id: isEditing ? currentModelId : undefined, tags: Array.isArray(values.tags) ? values.tags.join(',') : '', status: values.status ? 1 : 0, sync_official: values.sync_official ? 1 : 0, @@ -416,9 +422,10 @@ export function ModelMutateDrawer({ ...modelData } = submitData - const response = isEditing - ? await updateModel({ ...modelData, id: currentRow!.id }) - : await createModel(modelData) + const response = + isEditing && currentModelId + ? await updateModel({ ...modelData, id: currentModelId }) + : await createModel(modelData) if (response.success) { // Handle ratio configuration updates in system settings @@ -496,30 +503,30 @@ export function ModelMutateDrawer({ values.price && values.price !== '' ) { - priceMap[finalModelName] = parseFloat(values.price) + priceMap[finalModelName] = Number.parseFloat(values.price) } else if (pricingMode === 'per-token') { if (values.ratio && values.ratio !== '') { - ratioMap[finalModelName] = parseFloat(values.ratio) + ratioMap[finalModelName] = Number.parseFloat(values.ratio) } if (values.cacheRatio && values.cacheRatio !== '') { - cacheMap[finalModelName] = parseFloat(values.cacheRatio) + cacheMap[finalModelName] = Number.parseFloat(values.cacheRatio) } if (values.completionRatio && values.completionRatio !== '') { - completionMap[finalModelName] = parseFloat( + completionMap[finalModelName] = Number.parseFloat( values.completionRatio ) } if (values.imageRatio && values.imageRatio !== '') { - imageMap[finalModelName] = parseFloat(values.imageRatio) + imageMap[finalModelName] = Number.parseFloat(values.imageRatio) } if (values.audioRatio && values.audioRatio !== '') { - audioMap[finalModelName] = parseFloat(values.audioRatio) + audioMap[finalModelName] = Number.parseFloat(values.audioRatio) } if ( values.audioCompletionRatio && values.audioCompletionRatio !== '' ) { - audioCompletionMap[finalModelName] = parseFloat( + audioCompletionMap[finalModelName] = Number.parseFloat( values.audioCompletionRatio ) } @@ -615,7 +622,7 @@ export function ModelMutateDrawer({ }, [ isEditing, - currentRow, + currentModelId, queryClient, onOpenChange, pricingMode, @@ -728,14 +735,14 @@ export function ModelMutateDrawer({ {t('Vendor')}

- {promptPrice && !isNaN(parseFloat(promptPrice)) - ? `Calculated ratio: ${(parseFloat(promptPrice) / 2).toFixed(4)}` + {promptPrice && !Number.isNaN(Number.parseFloat(promptPrice)) + ? `Calculated ratio: ${(Number.parseFloat(promptPrice) / 2).toFixed(4)}` : t('Enter Input price to calculate ratio')}

@@ -1084,16 +1088,15 @@ export function ModelMutateDrawer({ />

{completionPrice && - !isNaN(parseFloat(completionPrice)) && + !Number.isNaN(Number.parseFloat(completionPrice)) && promptPrice && - !isNaN(parseFloat(promptPrice)) && - parseFloat(promptPrice) > 0 - ? `Calculated ratio: ${(parseFloat(completionPrice) / parseFloat(promptPrice)).toFixed(4)}` + !Number.isNaN(Number.parseFloat(promptPrice)) && + Number.parseFloat(promptPrice) > 0 + ? `Calculated ratio: ${(Number.parseFloat(completionPrice) / Number.parseFloat(promptPrice)).toFixed(4)}` : t('Enter Completion price to calculate ratio')}

- - + )} ( const statsBar = (
- - setSensitiveVisible(!sensitiveVisible)} - aria-label={sensitiveVisible ? t('Hide') : t('Show')} - className='text-muted-foreground hover:text-foreground size-7' - /> - } - > - {sensitiveVisible ? : } - - - {sensitiveVisible ? t('Hide') : t('Show')} - -
) + const sensitiveToggle = ( + + setSensitiveVisible(!sensitiveVisible)} + aria-label={sensitiveVisible ? t('Hide') : t('Show')} + className='text-muted-foreground hover:text-foreground size-7' + /> + } + > + {sensitiveVisible ? : } + + + {sensitiveVisible ? t('Hide') : t('Show')} + + + ) const dateRangeFilter = ( @@ -410,6 +412,7 @@ export function CommonLogsFilterBar( {dateRangeFilter} diff --git a/web/default/src/features/usage-logs/components/logs-filter-toolbar.tsx b/web/default/src/features/usage-logs/components/logs-filter-toolbar.tsx index e02824c5..792838d3 100644 --- a/web/default/src/features/usage-logs/components/logs-filter-toolbar.tsx +++ b/web/default/src/features/usage-logs/components/logs-filter-toolbar.tsx @@ -17,7 +17,7 @@ along with this program. If not, see . For commercial licensing, please contact support@quantumnous.com */ import { useState, type ComponentProps, type ReactNode } from 'react' -import { type Table } from '@tanstack/react-table' +import type { Table } from '@tanstack/react-table' import { useMediaQuery } from '@/hooks' import { ChevronDown, Loader2 } from 'lucide-react' import { useTranslation } from 'react-i18next' @@ -44,6 +44,7 @@ interface LogsFilterToolbarProps { mobileFilters?: ReactNode mobileFilterCount?: number stats?: ReactNode + actionStart?: ReactNode hasActiveFilters: boolean hasAdvancedActiveFilters?: boolean advancedFilterCount?: number @@ -142,6 +143,7 @@ export function LogsFilterToolbar(props: LogsFilterToolbarProps) {
{props.stats}
+ {props.actionStart}