perf(web): align table badge spacing
- remove built-in horizontal padding from status badges so table columns align with headers. - drop legacy negative-margin compensation from badge cells and affected table renderers. - clean touched table components to satisfy lint rules around type imports, keys, and JSX flow.
This commit is contained in:
@@ -27,7 +27,7 @@ export function BadgeCell({ className, ...props }: BadgeCellProps) {
|
|||||||
<div
|
<div
|
||||||
data-slot='badge-cell'
|
data-slot='badge-cell'
|
||||||
className={cn(
|
className={cn(
|
||||||
'-ml-1.5 flex max-w-full min-w-0 items-center gap-1 overflow-hidden [&_[data-slot=status-badge]]:max-w-full [&_[data-slot=status-badge]]:min-w-0',
|
'flex max-w-full min-w-0 items-center gap-1 overflow-hidden [&_[data-slot=status-badge]]:max-w-full [&_[data-slot=status-badge]]:min-w-0',
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
|
|||||||
@@ -35,7 +35,6 @@ interface BadgeListCellProps {
|
|||||||
/**
|
/**
|
||||||
* Table cell renderer for a list of badges with overflow tooltip.
|
* Table cell renderer for a list of badges with overflow tooltip.
|
||||||
* Displays up to `max` badges inline; remaining items appear in a tooltip.
|
* Displays up to `max` badges inline; remaining items appear in a tooltip.
|
||||||
* Applies -ml-1.5 to compensate for badge px-1.5 and align with column header.
|
|
||||||
*/
|
*/
|
||||||
export function BadgeListCell({
|
export function BadgeListCell({
|
||||||
items,
|
items,
|
||||||
@@ -51,7 +50,7 @@ export function BadgeListCell({
|
|||||||
return (
|
return (
|
||||||
<TooltipProvider>
|
<TooltipProvider>
|
||||||
<Tooltip>
|
<Tooltip>
|
||||||
<TooltipTrigger render={<div className='-ml-1.5 max-w-full' />}>
|
<TooltipTrigger render={<div className='max-w-full' />}>
|
||||||
<StatusBadgeList
|
<StatusBadgeList
|
||||||
items={items}
|
items={items}
|
||||||
max={max}
|
max={max}
|
||||||
|
|||||||
@@ -114,7 +114,7 @@ function CompactContent<TData>({ row }: { row: Row<TData> }) {
|
|||||||
{label}
|
{label}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<div className='min-w-0 overflow-hidden text-xs [&_:is([data-slot=badge-cell],[data-slot=provider-badge],[data-slot=status-badge])]:ml-0'>
|
<div className='min-w-0 overflow-hidden text-xs'>
|
||||||
<StatusBadgeTypeContext.Provider value='text'>
|
<StatusBadgeTypeContext.Provider value='text'>
|
||||||
{renderCellContent(cell) ?? '-'}
|
{renderCellContent(cell) ?? '-'}
|
||||||
</StatusBadgeTypeContext.Provider>
|
</StatusBadgeTypeContext.Provider>
|
||||||
@@ -164,10 +164,7 @@ function FallbackContent<TData>({ row }: { row: Row<TData> }) {
|
|||||||
|
|
||||||
if (!label) {
|
if (!label) {
|
||||||
return (
|
return (
|
||||||
<div
|
<div key={cell.id} className='flex justify-end overflow-hidden'>
|
||||||
key={cell.id}
|
|
||||||
className='flex justify-end overflow-hidden [&_:is([data-slot=badge-cell],[data-slot=provider-badge],[data-slot=status-badge])]:ml-0'
|
|
||||||
>
|
|
||||||
<StatusBadgeTypeContext.Provider value='text'>
|
<StatusBadgeTypeContext.Provider value='text'>
|
||||||
{renderCellContent(cell)}
|
{renderCellContent(cell)}
|
||||||
</StatusBadgeTypeContext.Provider>
|
</StatusBadgeTypeContext.Provider>
|
||||||
@@ -183,7 +180,7 @@ function FallbackContent<TData>({ row }: { row: Row<TData> }) {
|
|||||||
<span className='text-muted-foreground shrink-0 text-[10px] font-medium select-none'>
|
<span className='text-muted-foreground shrink-0 text-[10px] font-medium select-none'>
|
||||||
{label}
|
{label}
|
||||||
</span>
|
</span>
|
||||||
<div className='flex min-w-0 flex-1 items-center justify-end overflow-hidden text-xs [&_:is([data-slot=badge-cell],[data-slot=provider-badge],[data-slot=status-badge])]:ml-0'>
|
<div className='flex min-w-0 flex-1 items-center justify-end overflow-hidden text-xs'>
|
||||||
<StatusBadgeTypeContext.Provider value='text'>
|
<StatusBadgeTypeContext.Provider value='text'>
|
||||||
{renderCellContent(cell) ?? '-'}
|
{renderCellContent(cell) ?? '-'}
|
||||||
</StatusBadgeTypeContext.Provider>
|
</StatusBadgeTypeContext.Provider>
|
||||||
|
|||||||
+1
-1
@@ -50,7 +50,7 @@ export function ProviderBadge({
|
|||||||
autoColor={colorText ? label : undefined}
|
autoColor={colorText ? label : undefined}
|
||||||
variant={colorText ? undefined : 'neutral'}
|
variant={colorText ? undefined : 'neutral'}
|
||||||
size='sm'
|
size='sm'
|
||||||
className={cn('min-w-0 shrink overflow-hidden', !icon && 'pl-0')}
|
className='min-w-0 shrink overflow-hidden'
|
||||||
{...badgeProps}
|
{...badgeProps}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
+3
-3
@@ -87,9 +87,9 @@ export const StatusBadgeTypeContext =
|
|||||||
React.createContext<StatusBadgeType>('badge')
|
React.createContext<StatusBadgeType>('badge')
|
||||||
|
|
||||||
const sizeMap = {
|
const sizeMap = {
|
||||||
sm: 'h-5 gap-1 px-1.5 text-sm leading-none',
|
sm: 'h-5 gap-1 text-sm leading-none',
|
||||||
md: 'h-5 gap-1 px-1.5 text-sm leading-none',
|
md: 'h-5 gap-1 text-sm leading-none',
|
||||||
lg: 'h-6 gap-1.5 px-2 text-sm leading-none',
|
lg: 'h-6 gap-1.5 text-sm leading-none',
|
||||||
} as const
|
} as const
|
||||||
|
|
||||||
const textSizeMap = {
|
const textSizeMap = {
|
||||||
|
|||||||
@@ -159,7 +159,7 @@ function ChannelCardComponent({
|
|||||||
{/* Last row: groups span the full width, showing every group (no label) */}
|
{/* Last row: groups span the full width, showing every group (no label) */}
|
||||||
<div className='min-w-0'>
|
<div className='min-w-0'>
|
||||||
{groups.length > 0 ? (
|
{groups.length > 0 ? (
|
||||||
<div className='-ml-1.5 flex flex-wrap gap-1'>
|
<div className='flex flex-wrap gap-1'>
|
||||||
{groups.map((g) => (
|
{groups.map((g) => (
|
||||||
<GroupBadge
|
<GroupBadge
|
||||||
key={g}
|
key={g}
|
||||||
|
|||||||
@@ -46,12 +46,12 @@ import {
|
|||||||
TooltipProvider,
|
TooltipProvider,
|
||||||
TooltipTrigger,
|
TooltipTrigger,
|
||||||
} from '@/components/ui/tooltip'
|
} from '@/components/ui/tooltip'
|
||||||
|
import { toIntlLocale } from '@/i18n/languages'
|
||||||
import {
|
import {
|
||||||
formatCurrencyFromUSD,
|
formatCurrencyFromUSD,
|
||||||
formatQuotaWithCurrency,
|
formatQuotaWithCurrency,
|
||||||
getCurrencyLabel,
|
getCurrencyLabel,
|
||||||
} from '@/lib/currency'
|
} from '@/lib/currency'
|
||||||
import { toIntlLocale } from '@/i18n/languages'
|
|
||||||
import { formatTimestampToDate } from '@/lib/format'
|
import { formatTimestampToDate } from '@/lib/format'
|
||||||
import { truncateText } from '@/lib/utils'
|
import { truncateText } from '@/lib/utils'
|
||||||
|
|
||||||
@@ -372,7 +372,7 @@ function BalanceCell({ channel }: { channel: Channel }) {
|
|||||||
size='sm'
|
size='sm'
|
||||||
copyable={false}
|
copyable={false}
|
||||||
showDot={false}
|
showDot={false}
|
||||||
className='-ml-1.5 cursor-help'
|
className='cursor-help'
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
@@ -435,7 +435,7 @@ function BalanceCell({ channel }: { channel: Channel }) {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<TooltipProvider>
|
<TooltipProvider>
|
||||||
<div className='-ml-1.5 flex items-center gap-1'>
|
<div className='flex items-center gap-1'>
|
||||||
<Tooltip>
|
<Tooltip>
|
||||||
<TooltipTrigger
|
<TooltipTrigger
|
||||||
render={
|
render={
|
||||||
@@ -703,7 +703,6 @@ export function useChannelsColumns(
|
|||||||
variant='blue'
|
variant='blue'
|
||||||
size='sm'
|
size='sm'
|
||||||
copyable={false}
|
copyable={false}
|
||||||
className='-ml-1.5'
|
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -846,7 +845,6 @@ export function useChannelsColumns(
|
|||||||
variant='success'
|
variant='success'
|
||||||
size='sm'
|
size='sm'
|
||||||
copyable={false}
|
copyable={false}
|
||||||
className='-ml-1.5'
|
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
@@ -856,7 +854,6 @@ export function useChannelsColumns(
|
|||||||
variant='neutral'
|
variant='neutral'
|
||||||
size='sm'
|
size='sm'
|
||||||
copyable={false}
|
copyable={false}
|
||||||
className='-ml-1.5'
|
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -1025,14 +1022,7 @@ export function useChannelsColumns(
|
|||||||
return <span className='text-muted-foreground text-xs'>-</span>
|
return <span className='text-muted-foreground text-xs'>-</span>
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return <StatusBadge label={tag} autoColor={tag} size='sm' />
|
||||||
<StatusBadge
|
|
||||||
label={tag}
|
|
||||||
autoColor={tag}
|
|
||||||
size='sm'
|
|
||||||
className='-ml-1.5'
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
},
|
},
|
||||||
size: 120,
|
size: 120,
|
||||||
enableSorting: false,
|
enableSorting: false,
|
||||||
@@ -1080,7 +1070,6 @@ export function useChannelsColumns(
|
|||||||
variant={config.variant}
|
variant={config.variant}
|
||||||
size='sm'
|
size='sm'
|
||||||
copyable={false}
|
copyable={false}
|
||||||
className='-ml-1.5'
|
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
@@ -1114,7 +1103,7 @@ export function useChannelsColumns(
|
|||||||
variant='neutral'
|
variant='neutral'
|
||||||
size='sm'
|
size='sm'
|
||||||
copyable={false}
|
copyable={false}
|
||||||
className='-ml-1.5 cursor-pointer'
|
className='cursor-pointer'
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
|||||||
+17
-22
@@ -36,7 +36,7 @@ import {
|
|||||||
} from '@/components/ui/tooltip'
|
} from '@/components/ui/tooltip'
|
||||||
import { copyToClipboard } from '@/lib/copy-to-clipboard'
|
import { copyToClipboard } from '@/lib/copy-to-clipboard'
|
||||||
|
|
||||||
import { type ApiKey } from '../types'
|
import type { ApiKey } from '../types'
|
||||||
import { useApiKeys } from './api-keys-provider'
|
import { useApiKeys } from './api-keys-provider'
|
||||||
|
|
||||||
export function ApiKeyCell({ apiKey }: { apiKey: ApiKey }) {
|
export function ApiKeyCell({ apiKey }: { apiKey: ApiKey }) {
|
||||||
@@ -54,6 +54,19 @@ export function ApiKeyCell({ apiKey }: { apiKey: ApiKey }) {
|
|||||||
const resolvedFullKey = resolvedKeys[apiKey.id]
|
const resolvedFullKey = resolvedKeys[apiKey.id]
|
||||||
const isCopied = copiedKeyId === apiKey.id
|
const isCopied = copiedKeyId === apiKey.id
|
||||||
const maskedKey = `sk-${apiKey.key}`
|
const maskedKey = `sk-${apiKey.key}`
|
||||||
|
let copyIcon = <Copy className='size-3.5' />
|
||||||
|
if (isLoading) {
|
||||||
|
copyIcon = <Loader2 className='size-3.5 animate-spin' />
|
||||||
|
} else if (isCopied) {
|
||||||
|
copyIcon = <Check className='size-3.5 text-green-600' />
|
||||||
|
}
|
||||||
|
|
||||||
|
let copyTooltip = t('Copy API key')
|
||||||
|
if (isLoading) {
|
||||||
|
copyTooltip = t('Loading...')
|
||||||
|
} else if (isCopied) {
|
||||||
|
copyTooltip = t('Copied!')
|
||||||
|
}
|
||||||
|
|
||||||
const handlePopoverOpen = useCallback(
|
const handlePopoverOpen = useCallback(
|
||||||
(open: boolean) => {
|
(open: boolean) => {
|
||||||
@@ -135,21 +148,9 @@ export function ApiKeyCell({ apiKey }: { apiKey: ApiKey }) {
|
|||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
{isLoading ? (
|
{copyIcon}
|
||||||
<Loader2 className='size-3.5 animate-spin' />
|
|
||||||
) : isCopied ? (
|
|
||||||
<Check className='size-3.5 text-green-600' />
|
|
||||||
) : (
|
|
||||||
<Copy className='size-3.5' />
|
|
||||||
)}
|
|
||||||
</TooltipTrigger>
|
</TooltipTrigger>
|
||||||
<TooltipContent>
|
<TooltipContent>{copyTooltip}</TooltipContent>
|
||||||
{isLoading
|
|
||||||
? t('Loading...')
|
|
||||||
: isCopied
|
|
||||||
? t('Copied!')
|
|
||||||
: t('Copy API key')}
|
|
||||||
</TooltipContent>
|
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
@@ -160,12 +161,7 @@ export function ModelLimitsCell({ apiKey }: { apiKey: ApiKey }) {
|
|||||||
|
|
||||||
if (!apiKey.model_limits_enabled || !apiKey.model_limits) {
|
if (!apiKey.model_limits_enabled || !apiKey.model_limits) {
|
||||||
return (
|
return (
|
||||||
<StatusBadge
|
<StatusBadge label={t('Unlimited')} variant='neutral' copyable={false} />
|
||||||
label={t('Unlimited')}
|
|
||||||
variant='neutral'
|
|
||||||
copyable={false}
|
|
||||||
className='-ml-1.5'
|
|
||||||
/>
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -203,7 +199,6 @@ export function IpRestrictionsCell({ apiKey }: { apiKey: ApiKey }) {
|
|||||||
label={t('No restriction')}
|
label={t('No restriction')}
|
||||||
variant='neutral'
|
variant='neutral'
|
||||||
copyable={false}
|
copyable={false}
|
||||||
className='-ml-1.5'
|
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|||||||
For commercial licensing, please contact support@quantumnous.com
|
For commercial licensing, please contact support@quantumnous.com
|
||||||
*/
|
*/
|
||||||
import { useQuery } from '@tanstack/react-query'
|
import { useQuery } from '@tanstack/react-query'
|
||||||
import { type ColumnDef } from '@tanstack/react-table'
|
import type { ColumnDef } from '@tanstack/react-table'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
|
|
||||||
import { BadgeCell, TruncatedCell } from '@/components/data-table'
|
import { BadgeCell, TruncatedCell } from '@/components/data-table'
|
||||||
@@ -35,7 +35,7 @@ import { formatQuota, formatTimestampToDate } from '@/lib/format'
|
|||||||
import { cn } from '@/lib/utils'
|
import { cn } from '@/lib/utils'
|
||||||
|
|
||||||
import { API_KEY_STATUSES } from '../constants'
|
import { API_KEY_STATUSES } from '../constants'
|
||||||
import { type ApiKey } from '../types'
|
import type { ApiKey } from '../types'
|
||||||
import {
|
import {
|
||||||
ApiKeyCell,
|
ApiKeyCell,
|
||||||
ModelLimitsCell,
|
ModelLimitsCell,
|
||||||
@@ -116,7 +116,6 @@ export function useApiKeysColumns(): ColumnDef<ApiKey>[] {
|
|||||||
label={t(statusConfig.label)}
|
label={t(statusConfig.label)}
|
||||||
variant={statusConfig.variant}
|
variant={statusConfig.variant}
|
||||||
copyable={false}
|
copyable={false}
|
||||||
className='-ml-1.5'
|
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
@@ -144,7 +143,6 @@ export function useApiKeysColumns(): ColumnDef<ApiKey>[] {
|
|||||||
label={t('Unlimited')}
|
label={t('Unlimited')}
|
||||||
variant='neutral'
|
variant='neutral'
|
||||||
copyable={false}
|
copyable={false}
|
||||||
className='-ml-1.5'
|
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -224,7 +222,6 @@ export function useApiKeysColumns(): ColumnDef<ApiKey>[] {
|
|||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<TruncatedCell
|
<TruncatedCell
|
||||||
className='-ml-1.5'
|
|
||||||
tooltipContent={group || '-'}
|
tooltipContent={group || '-'}
|
||||||
tooltipClassName='break-all'
|
tooltipClassName='break-all'
|
||||||
>
|
>
|
||||||
@@ -292,7 +289,6 @@ export function useApiKeysColumns(): ColumnDef<ApiKey>[] {
|
|||||||
label={t('Never')}
|
label={t('Never')}
|
||||||
variant='neutral'
|
variant='neutral'
|
||||||
copyable={false}
|
copyable={false}
|
||||||
className='-ml-1.5'
|
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ export function useDeploymentsColumns(opts: {
|
|||||||
variant='neutral'
|
variant='neutral'
|
||||||
copyText={name}
|
copyText={name}
|
||||||
size='sm'
|
size='sm'
|
||||||
className='-ml-1.5 font-mono'
|
className='font-mono'
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
@@ -98,7 +98,6 @@ export function useDeploymentsColumns(opts: {
|
|||||||
variant={config.variant}
|
variant={config.variant}
|
||||||
size='sm'
|
size='sm'
|
||||||
copyable={false}
|
copyable={false}
|
||||||
className='-ml-1.5'
|
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
@@ -130,7 +129,6 @@ export function useDeploymentsColumns(opts: {
|
|||||||
autoColor={String(provider)}
|
autoColor={String(provider)}
|
||||||
size='sm'
|
size='sm'
|
||||||
copyable={false}
|
copyable={false}
|
||||||
className='-ml-1.5'
|
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
|||||||
+13
-18
@@ -16,7 +16,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|||||||
|
|
||||||
For commercial licensing, please contact support@quantumnous.com
|
For commercial licensing, please contact support@quantumnous.com
|
||||||
*/
|
*/
|
||||||
import { type ColumnDef } from '@tanstack/react-table'
|
import type { ColumnDef } from '@tanstack/react-table'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
|
|
||||||
import { BadgeCell, BadgeListCell } from '@/components/data-table'
|
import { BadgeCell, BadgeListCell } from '@/components/data-table'
|
||||||
@@ -139,7 +139,7 @@ export function useModelsColumns(vendors: Vendor[] = []): ColumnDef<Model>[] {
|
|||||||
variant='neutral'
|
variant='neutral'
|
||||||
copyText={name}
|
copyText={name}
|
||||||
size='sm'
|
size='sm'
|
||||||
className='-ml-1.5 font-mono'
|
className='font-mono'
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
@@ -172,7 +172,6 @@ export function useModelsColumns(vendors: Vendor[] = []): ColumnDef<Model>[] {
|
|||||||
| 'info'
|
| 'info'
|
||||||
}
|
}
|
||||||
size='sm'
|
size='sm'
|
||||||
className='-ml-1.5'
|
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -182,16 +181,14 @@ export function useModelsColumns(vendors: Vendor[] = []): ColumnDef<Model>[] {
|
|||||||
model.matched_models &&
|
model.matched_models &&
|
||||||
model.matched_models.length > 0
|
model.matched_models.length > 0
|
||||||
) {
|
) {
|
||||||
const matchedBadges = model.matched_models.map((m, idx) => (
|
const matchedBadges = model.matched_models.map((m) => (
|
||||||
<StatusBadge key={idx} label={m} autoColor={m} size='sm' />
|
<StatusBadge key={m} label={m} autoColor={m} size='sm' />
|
||||||
))
|
))
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<TooltipProvider>
|
<TooltipProvider>
|
||||||
<Tooltip>
|
<Tooltip>
|
||||||
<TooltipTrigger render={<div className='-ml-1.5' />}>
|
<TooltipTrigger render={<div />}>{badge}</TooltipTrigger>
|
||||||
{badge}
|
|
||||||
</TooltipTrigger>
|
|
||||||
<TooltipContent
|
<TooltipContent
|
||||||
side='top'
|
side='top'
|
||||||
className='border-border bg-popover max-h-48 max-w-[320px] overflow-y-auto p-2'
|
className='border-border bg-popover max-h-48 max-w-[320px] overflow-y-auto p-2'
|
||||||
@@ -225,7 +222,6 @@ export function useModelsColumns(vendors: Vendor[] = []): ColumnDef<Model>[] {
|
|||||||
variant={config.variant}
|
variant={config.variant}
|
||||||
size='sm'
|
size='sm'
|
||||||
copyable={false}
|
copyable={false}
|
||||||
className='-ml-1.5'
|
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
@@ -293,8 +289,8 @@ export function useModelsColumns(vendors: Vendor[] = []): ColumnDef<Model>[] {
|
|||||||
const tagArray = parseModelTags(tags)
|
const tagArray = parseModelTags(tags)
|
||||||
return (
|
return (
|
||||||
<BadgeListCell
|
<BadgeListCell
|
||||||
items={tagArray.map((tag, idx) => (
|
items={tagArray.map((tag) => (
|
||||||
<StatusBadge key={idx} label={tag} autoColor={tag} size='sm' />
|
<StatusBadge key={tag} label={tag} autoColor={tag} size='sm' />
|
||||||
))}
|
))}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
@@ -313,8 +309,8 @@ export function useModelsColumns(vendors: Vendor[] = []): ColumnDef<Model>[] {
|
|||||||
const endpointArray = formatEndpointsDisplay(endpoints)
|
const endpointArray = formatEndpointsDisplay(endpoints)
|
||||||
return (
|
return (
|
||||||
<BadgeListCell
|
<BadgeListCell
|
||||||
items={endpointArray.map((ep, idx) => (
|
items={endpointArray.map((ep) => (
|
||||||
<StatusBadge key={idx} label={ep} autoColor={ep} size='sm' />
|
<StatusBadge key={ep} label={ep} autoColor={ep} size='sm' />
|
||||||
))}
|
))}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
@@ -337,9 +333,9 @@ export function useModelsColumns(vendors: Vendor[] = []): ColumnDef<Model>[] {
|
|||||||
}>
|
}>
|
||||||
return (
|
return (
|
||||||
<BadgeListCell
|
<BadgeListCell
|
||||||
items={(channels ?? []).map((c, idx) => (
|
items={(channels ?? []).map((c) => (
|
||||||
<StatusBadge
|
<StatusBadge
|
||||||
key={idx}
|
key={`${c.id}-${c.name}-${c.type ?? ''}`}
|
||||||
label={`${c.name} (${c.type})`}
|
label={`${c.name} (${c.type})`}
|
||||||
autoColor={c.name}
|
autoColor={c.name}
|
||||||
size='sm'
|
size='sm'
|
||||||
@@ -380,11 +376,11 @@ export function useModelsColumns(vendors: Vendor[] = []): ColumnDef<Model>[] {
|
|||||||
const quotaTypes = row.getValue('quota_types') as number[]
|
const quotaTypes = row.getValue('quota_types') as number[]
|
||||||
return (
|
return (
|
||||||
<BadgeListCell
|
<BadgeListCell
|
||||||
items={(quotaTypes ?? []).map((qt, idx) => {
|
items={(quotaTypes ?? []).map((qt) => {
|
||||||
const config = QUOTA_TYPE_CONFIG[qt]
|
const config = QUOTA_TYPE_CONFIG[qt]
|
||||||
return (
|
return (
|
||||||
<StatusBadge
|
<StatusBadge
|
||||||
key={idx}
|
key={qt}
|
||||||
label={config?.label || String(qt)}
|
label={config?.label || String(qt)}
|
||||||
variant={
|
variant={
|
||||||
(config?.color === 'error' ? 'danger' : config?.color) as
|
(config?.color === 'error' ? 'danger' : config?.color) as
|
||||||
@@ -418,7 +414,6 @@ export function useModelsColumns(vendors: Vendor[] = []): ColumnDef<Model>[] {
|
|||||||
variant={syncOfficial === 1 ? 'success' : 'warning'}
|
variant={syncOfficial === 1 ? 'success' : 'warning'}
|
||||||
size='sm'
|
size='sm'
|
||||||
copyable={false}
|
copyable={false}
|
||||||
className='-ml-1.5'
|
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -104,7 +104,6 @@ export function usePricingColumns(
|
|||||||
label={isTokenBased ? t('Token') : t('Request')}
|
label={isTokenBased ? t('Token') : t('Request')}
|
||||||
variant={isTokenBased ? 'info' : 'neutral'}
|
variant={isTokenBased ? 'info' : 'neutral'}
|
||||||
copyable={false}
|
copyable={false}
|
||||||
className='-ml-1.5'
|
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
|||||||
+3
-7
@@ -16,7 +16,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|||||||
|
|
||||||
For commercial licensing, please contact support@quantumnous.com
|
For commercial licensing, please contact support@quantumnous.com
|
||||||
*/
|
*/
|
||||||
import { type ColumnDef } from '@tanstack/react-table'
|
import type { ColumnDef } from '@tanstack/react-table'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
|
|
||||||
import { MaskedValueDisplay } from '@/components/masked-value-display'
|
import { MaskedValueDisplay } from '@/components/masked-value-display'
|
||||||
@@ -32,7 +32,7 @@ import { formatQuota, formatTimestampToDate } from '@/lib/format'
|
|||||||
|
|
||||||
import { REDEMPTION_FILTER_EXPIRED, REDEMPTION_STATUSES } from '../constants'
|
import { REDEMPTION_FILTER_EXPIRED, REDEMPTION_STATUSES } from '../constants'
|
||||||
import { isRedemptionExpired, isTimestampExpired } from '../lib'
|
import { isRedemptionExpired, isTimestampExpired } from '../lib'
|
||||||
import { type Redemption } from '../types'
|
import type { Redemption } from '../types'
|
||||||
import { DataTableRowActions } from './data-table-row-actions'
|
import { DataTableRowActions } from './data-table-row-actions'
|
||||||
|
|
||||||
export function useRedemptionsColumns(): ColumnDef<Redemption>[] {
|
export function useRedemptionsColumns(): ColumnDef<Redemption>[] {
|
||||||
@@ -96,7 +96,6 @@ export function useRedemptionsColumns(): ColumnDef<Redemption>[] {
|
|||||||
label={t('Expired')}
|
label={t('Expired')}
|
||||||
variant='warning'
|
variant='warning'
|
||||||
copyable={false}
|
copyable={false}
|
||||||
className='-ml-1.5'
|
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -112,7 +111,6 @@ export function useRedemptionsColumns(): ColumnDef<Redemption>[] {
|
|||||||
label={t(statusConfig.labelKey)}
|
label={t(statusConfig.labelKey)}
|
||||||
variant={statusConfig.variant}
|
variant={statusConfig.variant}
|
||||||
copyable={false}
|
copyable={false}
|
||||||
className='-ml-1.5'
|
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
@@ -164,7 +162,6 @@ export function useRedemptionsColumns(): ColumnDef<Redemption>[] {
|
|||||||
label={formatQuota(quota)}
|
label={formatQuota(quota)}
|
||||||
variant='neutral'
|
variant='neutral'
|
||||||
copyable={false}
|
copyable={false}
|
||||||
className='-ml-1.5'
|
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
@@ -195,7 +192,6 @@ export function useRedemptionsColumns(): ColumnDef<Redemption>[] {
|
|||||||
label={t('Never')}
|
label={t('Never')}
|
||||||
variant='neutral'
|
variant='neutral'
|
||||||
copyable={false}
|
copyable={false}
|
||||||
className='-ml-1.5'
|
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -233,7 +229,7 @@ export function useRedemptionsColumns(): ColumnDef<Redemption>[] {
|
|||||||
className='cursor-help'
|
className='cursor-help'
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
></TooltipTrigger>
|
/>
|
||||||
<TooltipContent>
|
<TooltipContent>
|
||||||
<div className='space-y-1 text-xs'>
|
<div className='space-y-1 text-xs'>
|
||||||
<div>
|
<div>
|
||||||
|
|||||||
+1
-3
@@ -16,7 +16,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|||||||
|
|
||||||
For commercial licensing, please contact support@quantumnous.com
|
For commercial licensing, please contact support@quantumnous.com
|
||||||
*/
|
*/
|
||||||
import { type ColumnDef } from '@tanstack/react-table'
|
import type { ColumnDef } from '@tanstack/react-table'
|
||||||
import { useMemo } from 'react'
|
import { useMemo } from 'react'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
|
|
||||||
@@ -118,14 +118,12 @@ export function useSubscriptionsColumns(): ColumnDef<PlanRecord>[] {
|
|||||||
label={t('Enable')}
|
label={t('Enable')}
|
||||||
variant='success'
|
variant='success'
|
||||||
copyable={false}
|
copyable={false}
|
||||||
className='-ml-1.5'
|
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<StatusBadge
|
<StatusBadge
|
||||||
label={t('Disable')}
|
label={t('Disable')}
|
||||||
variant='neutral'
|
variant='neutral'
|
||||||
copyable={false}
|
copyable={false}
|
||||||
className='-ml-1.5'
|
|
||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
size: 80,
|
size: 80,
|
||||||
|
|||||||
@@ -113,7 +113,6 @@ export function buildModelRatioColumns({
|
|||||||
variant={getModeVariant(row.original.billingMode)}
|
variant={getModeVariant(row.original.billingMode)}
|
||||||
copyable={false}
|
copyable={false}
|
||||||
showDot={false}
|
showDot={false}
|
||||||
className='-ml-1.5 px-0'
|
|
||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
filterFn: (row, id, value) =>
|
filterFn: (row, id, value) =>
|
||||||
|
|||||||
-2
@@ -129,7 +129,6 @@ export function useDrawingLogsColumns(
|
|||||||
icon={getDrawingTypeIcon(action)}
|
icon={getDrawingTypeIcon(action)}
|
||||||
size='sm'
|
size='sm'
|
||||||
copyable={false}
|
copyable={false}
|
||||||
className='-ml-1.5'
|
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
@@ -181,7 +180,6 @@ export function useDrawingLogsColumns(
|
|||||||
variant={mjSubmitResultMapper.getVariant(String(code))}
|
variant={mjSubmitResultMapper.getVariant(String(code))}
|
||||||
size='sm'
|
size='sm'
|
||||||
copyable={false}
|
copyable={false}
|
||||||
className='-ml-1.5'
|
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -207,7 +207,6 @@ export function useTaskLogsColumns(isAdmin: boolean): ColumnDef<TaskLog>[] {
|
|||||||
variant={taskStatusMapper.getVariant(status)}
|
variant={taskStatusMapper.getVariant(status)}
|
||||||
size='sm'
|
size='sm'
|
||||||
copyable={false}
|
copyable={false}
|
||||||
className='-ml-1.5'
|
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -145,7 +145,7 @@ export function useUsersColumns(): ColumnDef<User>[] {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Tooltip>
|
<Tooltip>
|
||||||
<TooltipTrigger render={<div className='-ml-1.5 cursor-help' />}>
|
<TooltipTrigger render={<div className='cursor-help' />}>
|
||||||
<StatusBadge
|
<StatusBadge
|
||||||
label={t(statusConfig.labelKey)}
|
label={t(statusConfig.labelKey)}
|
||||||
variant={statusConfig.variant}
|
variant={statusConfig.variant}
|
||||||
@@ -184,7 +184,6 @@ export function useUsersColumns(): ColumnDef<User>[] {
|
|||||||
label={t('No Quota')}
|
label={t('No Quota')}
|
||||||
variant='neutral'
|
variant='neutral'
|
||||||
copyable={false}
|
copyable={false}
|
||||||
className='-ml-1.5'
|
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user