fix: migrate select to Base UI items API (#4655)
This commit is contained in:
parent
38a3314b9b
commit
d98f0e8ac3
@ -11,6 +11,7 @@ import { Button } from '@/components/ui/button'
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectGroup,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
@ -45,6 +46,12 @@ export function DataTablePagination<TData>({
|
||||
</div>
|
||||
<div className='flex items-center gap-2 @max-2xl/content:flex-row-reverse'>
|
||||
<Select
|
||||
items={[
|
||||
...[10, 20, 30, 40, 50, 100].map((pageSize) => ({
|
||||
value: `${pageSize}`,
|
||||
label: pageSize,
|
||||
})),
|
||||
]}
|
||||
value={`${table.getState().pagination.pageSize}`}
|
||||
onValueChange={(value) => {
|
||||
table.setPageSize(Number(value))
|
||||
@ -53,12 +60,14 @@ export function DataTablePagination<TData>({
|
||||
<SelectTrigger className='h-8 w-[64px] sm:w-[70px]'>
|
||||
<SelectValue placeholder={table.getState().pagination.pageSize} />
|
||||
</SelectTrigger>
|
||||
<SelectContent side='top'>
|
||||
{[10, 20, 30, 40, 50, 100].map((pageSize) => (
|
||||
<SelectItem key={pageSize} value={`${pageSize}`}>
|
||||
{pageSize}
|
||||
</SelectItem>
|
||||
))}
|
||||
<SelectContent side='top' alignItemWithTrigger={false}>
|
||||
<SelectGroup>
|
||||
{[10, 20, 30, 40, 50, 100].map((pageSize) => (
|
||||
<SelectItem key={pageSize} value={`${pageSize}`}>
|
||||
{pageSize}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectGroup>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<p className='hidden text-sm font-medium sm:block'>
|
||||
|
||||
2
web/default/src/components/ui/select.tsx
vendored
2
web/default/src/components/ui/select.tsx
vendored
@ -93,7 +93,7 @@ function SelectContent({
|
||||
data-slot='select-content'
|
||||
data-align-trigger={alignItemWithTrigger}
|
||||
className={cn(
|
||||
'dark bg-popover text-popover-foreground ring-foreground/10 data-[side=bottom]:slide-in-from-top-2 data-[side=inline-end]:slide-in-from-left-2 data-[side=inline-start]:slide-in-from-right-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95 relative isolate z-50 max-h-(--available-height) w-(--anchor-width) min-w-36 origin-(--transform-origin) overflow-x-hidden overflow-y-auto rounded-lg shadow-md ring-1 duration-100 data-[align-trigger=true]:animate-none',
|
||||
'bg-popover text-popover-foreground ring-foreground/10 data-[side=bottom]:slide-in-from-top-2 data-[side=inline-end]:slide-in-from-left-2 data-[side=inline-start]:slide-in-from-right-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95 relative isolate z-50 max-h-(--available-height) w-(--anchor-width) min-w-36 origin-(--transform-origin) overflow-x-hidden overflow-y-auto rounded-lg shadow-md ring-1 duration-100 data-[align-trigger=true]:animate-none',
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
|
||||
@ -25,6 +25,7 @@ import { Label } from '@/components/ui/label'
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectGroup,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
@ -431,21 +432,29 @@ export function ChannelTestDialog({
|
||||
<div className='grid gap-2'>
|
||||
<Label htmlFor='endpoint-type'>{t('Endpoint Type')}</Label>
|
||||
<Select
|
||||
items={[
|
||||
...endpointTypeOptions.map((option) => {
|
||||
const itemValue = option.value
|
||||
return { value: itemValue, label: t(option.label) }
|
||||
}),
|
||||
]}
|
||||
value={endpointType}
|
||||
onValueChange={(v) => v !== null && setEndpointType(v)}
|
||||
>
|
||||
<SelectTrigger id='endpoint-type'>
|
||||
<SelectValue placeholder={t('Auto detect (default)')} />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{endpointTypeOptions.map((option) => {
|
||||
const itemValue = option.value
|
||||
return (
|
||||
<SelectItem key={itemValue} value={itemValue}>
|
||||
{t(option.label)}
|
||||
</SelectItem>
|
||||
)
|
||||
})}
|
||||
<SelectContent alignItemWithTrigger={false}>
|
||||
<SelectGroup>
|
||||
{endpointTypeOptions.map((option) => {
|
||||
const itemValue = option.value
|
||||
return (
|
||||
<SelectItem key={itemValue} value={itemValue}>
|
||||
{t(option.label)}
|
||||
</SelectItem>
|
||||
)
|
||||
})}
|
||||
</SelectGroup>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<p className='text-muted-foreground text-xs'>
|
||||
|
||||
@ -18,6 +18,7 @@ import { ScrollArea } from '@/components/ui/scroll-area'
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectGroup,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
@ -276,6 +277,12 @@ export function EditTagDialog({ open, onOpenChange }: EditTagDialogProps) {
|
||||
|
||||
<div className='flex gap-2'>
|
||||
<Select<string>
|
||||
items={[
|
||||
...availableModels.map((model) => ({
|
||||
value: model,
|
||||
label: model,
|
||||
})),
|
||||
]}
|
||||
onValueChange={(value) => {
|
||||
if (value === null) return
|
||||
if (!selectedModels.includes(value)) {
|
||||
@ -288,14 +295,16 @@ export function EditTagDialog({ open, onOpenChange }: EditTagDialogProps) {
|
||||
placeholder={t('Add from available models...')}
|
||||
/>
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<ScrollArea className='h-60'>
|
||||
{availableModels.map((model) => (
|
||||
<SelectItem key={model} value={model}>
|
||||
{model}
|
||||
</SelectItem>
|
||||
))}
|
||||
</ScrollArea>
|
||||
<SelectContent alignItemWithTrigger={false}>
|
||||
<SelectGroup>
|
||||
<ScrollArea className='h-60'>
|
||||
{availableModels.map((model) => (
|
||||
<SelectItem key={model} value={model}>
|
||||
{model}
|
||||
</SelectItem>
|
||||
))}
|
||||
</ScrollArea>
|
||||
</SelectGroup>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
|
||||
@ -14,6 +14,7 @@ import {
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectGroup,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
@ -257,18 +258,26 @@ export function MultiKeyManageDialog({
|
||||
{/* Toolbar */}
|
||||
<div className='flex shrink-0 items-center justify-between'>
|
||||
<Select
|
||||
items={[
|
||||
...MULTI_KEY_FILTER_OPTIONS.map((option) => ({
|
||||
value: option.value,
|
||||
label: t(option.label),
|
||||
})),
|
||||
]}
|
||||
value={statusFilter === null ? 'all' : statusFilter.toString()}
|
||||
onValueChange={(v) => v !== null && handleStatusFilterChange(v)}
|
||||
>
|
||||
<SelectTrigger className='w-40'>
|
||||
<SelectValue placeholder={t('All Status')} />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{MULTI_KEY_FILTER_OPTIONS.map((option) => (
|
||||
<SelectItem key={option.value} value={option.value}>
|
||||
{t(option.label)}
|
||||
</SelectItem>
|
||||
))}
|
||||
<SelectContent alignItemWithTrigger={false}>
|
||||
<SelectGroup>
|
||||
{MULTI_KEY_FILTER_OPTIONS.map((option) => (
|
||||
<SelectItem key={option.value} value={option.value}>
|
||||
{t(option.label)}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectGroup>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
|
||||
|
||||
@ -38,6 +38,7 @@ import { ScrollArea } from '@/components/ui/scroll-area'
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectGroup,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
@ -1722,6 +1723,12 @@ export function ParamOverrideEditorDialog(
|
||||
{t('Template')}
|
||||
</span>
|
||||
<Select
|
||||
items={[
|
||||
...templatePresetOptions.map((o) => ({
|
||||
value: o.value,
|
||||
label: t(o.label),
|
||||
})),
|
||||
]}
|
||||
value={templatePresetKey}
|
||||
onValueChange={(v) =>
|
||||
setTemplatePresetKey(v || 'operations_default')
|
||||
@ -1730,12 +1737,14 @@ export function ParamOverrideEditorDialog(
|
||||
<SelectTrigger className='h-8 w-[220px]'>
|
||||
<SelectValue />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{templatePresetOptions.map((o) => (
|
||||
<SelectItem key={o.value} value={o.value}>
|
||||
{t(o.label)}
|
||||
</SelectItem>
|
||||
))}
|
||||
<SelectContent alignItemWithTrigger={false}>
|
||||
<SelectGroup>
|
||||
{templatePresetOptions.map((o) => (
|
||||
<SelectItem key={o.value} value={o.value}>
|
||||
{t(o.label)}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectGroup>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<Button
|
||||
@ -2140,6 +2149,12 @@ function RuleEditor(ruleEditorProps: RuleEditorProps) {
|
||||
<div className='space-y-1.5'>
|
||||
<label className='text-xs font-medium'>{t('Operation Type')}</label>
|
||||
<Select
|
||||
items={[
|
||||
...OPERATION_MODE_OPTIONS.map((o) => ({
|
||||
value: o.value,
|
||||
label: t(o.label),
|
||||
})),
|
||||
]}
|
||||
value={mode}
|
||||
onValueChange={(nextMode) =>
|
||||
nextMode !== null &&
|
||||
@ -2151,12 +2166,14 @@ function RuleEditor(ruleEditorProps: RuleEditorProps) {
|
||||
<SelectTrigger className='h-9'>
|
||||
<SelectValue />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{OPERATION_MODE_OPTIONS.map((o) => (
|
||||
<SelectItem key={o.value} value={o.value}>
|
||||
{t(o.label)}
|
||||
</SelectItem>
|
||||
))}
|
||||
<SelectContent alignItemWithTrigger={false}>
|
||||
<SelectGroup>
|
||||
{OPERATION_MODE_OPTIONS.map((o) => (
|
||||
<SelectItem key={o.value} value={o.value}>
|
||||
{t(o.label)}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectGroup>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
@ -2339,6 +2356,10 @@ function RuleEditor(ruleEditorProps: RuleEditorProps) {
|
||||
<div className='flex items-center gap-2'>
|
||||
<span className='text-sm font-medium'>{t('Conditions')}</span>
|
||||
<Select
|
||||
items={[
|
||||
{ value: 'OR', label: t('Match Any (OR)') },
|
||||
{ value: 'AND', label: t('Match All (AND)') },
|
||||
]}
|
||||
value={operation.logic || 'OR'}
|
||||
onValueChange={(v) =>
|
||||
v !== null &&
|
||||
@ -2350,9 +2371,11 @@ function RuleEditor(ruleEditorProps: RuleEditorProps) {
|
||||
<SelectTrigger className='h-7 w-[120px] text-xs'>
|
||||
<SelectValue />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value='OR'>{t('Match Any (OR)')}</SelectItem>
|
||||
<SelectItem value='AND'>{t('Match All (AND)')}</SelectItem>
|
||||
<SelectContent alignItemWithTrigger={false}>
|
||||
<SelectGroup>
|
||||
<SelectItem value='OR'>{t('Match Any (OR)')}</SelectItem>
|
||||
<SelectItem value='AND'>{t('Match All (AND)')}</SelectItem>
|
||||
</SelectGroup>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
@ -2515,6 +2538,12 @@ function ConditionEditor(conditionEditorProps: ConditionEditorProps) {
|
||||
{t('Match Mode')}
|
||||
</label>
|
||||
<Select
|
||||
items={[
|
||||
...CONDITION_MODE_OPTIONS.map((o) => ({
|
||||
value: o.value,
|
||||
label: t(o.label),
|
||||
})),
|
||||
]}
|
||||
value={condition.mode}
|
||||
onValueChange={(v) =>
|
||||
v !== null &&
|
||||
@ -2528,12 +2557,14 @@ function ConditionEditor(conditionEditorProps: ConditionEditorProps) {
|
||||
<SelectTrigger className='h-8 text-xs'>
|
||||
<SelectValue />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{CONDITION_MODE_OPTIONS.map((o) => (
|
||||
<SelectItem key={o.value} value={o.value}>
|
||||
{t(o.label)}
|
||||
</SelectItem>
|
||||
))}
|
||||
<SelectContent alignItemWithTrigger={false}>
|
||||
<SelectGroup>
|
||||
{CONDITION_MODE_OPTIONS.map((o) => (
|
||||
<SelectItem key={o.value} value={o.value}>
|
||||
{t(o.label)}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectGroup>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
@ -2889,6 +2920,10 @@ function PruneObjectsEditor(pruneObjectsEditorProps: PruneObjectsEditorProps) {
|
||||
<div className='space-y-1'>
|
||||
<label className='text-xs font-medium'>{t('Logic')}</label>
|
||||
<Select
|
||||
items={[
|
||||
{ value: 'AND', label: t('All Must Match (AND)') },
|
||||
{ value: 'OR', label: t('Any Match (OR)') },
|
||||
]}
|
||||
value={draft.logic}
|
||||
onValueChange={(v) =>
|
||||
pruneObjectsEditorProps.updateDraft(
|
||||
@ -2900,11 +2935,13 @@ function PruneObjectsEditor(pruneObjectsEditorProps: PruneObjectsEditorProps) {
|
||||
<SelectTrigger className='h-8 text-xs'>
|
||||
<SelectValue />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value='AND'>
|
||||
{t('All Must Match (AND)')}
|
||||
</SelectItem>
|
||||
<SelectItem value='OR'>{t('Any Match (OR)')}</SelectItem>
|
||||
<SelectContent alignItemWithTrigger={false}>
|
||||
<SelectGroup>
|
||||
<SelectItem value='AND'>
|
||||
{t('All Must Match (AND)')}
|
||||
</SelectItem>
|
||||
<SelectItem value='OR'>{t('Any Match (OR)')}</SelectItem>
|
||||
</SelectGroup>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
@ -3021,6 +3058,12 @@ function PruneObjectsEditor(pruneObjectsEditorProps: PruneObjectsEditorProps) {
|
||||
{t('Match Mode')}
|
||||
</label>
|
||||
<Select
|
||||
items={[
|
||||
...CONDITION_MODE_OPTIONS.map((o) => ({
|
||||
value: o.value,
|
||||
label: t(o.label),
|
||||
})),
|
||||
]}
|
||||
value={rule.mode}
|
||||
onValueChange={(v) =>
|
||||
v !== null &&
|
||||
@ -3034,12 +3077,14 @@ function PruneObjectsEditor(pruneObjectsEditorProps: PruneObjectsEditorProps) {
|
||||
<SelectTrigger className='h-7 text-xs'>
|
||||
<SelectValue />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{CONDITION_MODE_OPTIONS.map((o) => (
|
||||
<SelectItem key={o.value} value={o.value}>
|
||||
{t(o.label)}
|
||||
</SelectItem>
|
||||
))}
|
||||
<SelectContent alignItemWithTrigger={false}>
|
||||
<SelectGroup>
|
||||
{CONDITION_MODE_OPTIONS.map((o) => (
|
||||
<SelectItem key={o.value} value={o.value}>
|
||||
{t(o.label)}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectGroup>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
@ -3126,6 +3171,12 @@ function SyncFieldsEditor(syncFieldsEditorProps: SyncFieldsEditorProps) {
|
||||
</label>
|
||||
<div className='flex gap-2'>
|
||||
<Select
|
||||
items={[
|
||||
...SYNC_TARGET_TYPE_OPTIONS.map((o) => ({
|
||||
value: o.value,
|
||||
label: t(o.label),
|
||||
})),
|
||||
]}
|
||||
value={syncFieldsEditorProps.syncFromTarget.type || 'json'}
|
||||
onValueChange={(v) =>
|
||||
v !== null &&
|
||||
@ -3143,12 +3194,14 @@ function SyncFieldsEditor(syncFieldsEditorProps: SyncFieldsEditorProps) {
|
||||
<SelectTrigger className='h-8 w-[110px] text-xs'>
|
||||
<SelectValue />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{SYNC_TARGET_TYPE_OPTIONS.map((o) => (
|
||||
<SelectItem key={o.value} value={o.value}>
|
||||
{t(o.label)}
|
||||
</SelectItem>
|
||||
))}
|
||||
<SelectContent alignItemWithTrigger={false}>
|
||||
<SelectGroup>
|
||||
{SYNC_TARGET_TYPE_OPTIONS.map((o) => (
|
||||
<SelectItem key={o.value} value={o.value}>
|
||||
{t(o.label)}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectGroup>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<Input
|
||||
@ -3175,6 +3228,12 @@ function SyncFieldsEditor(syncFieldsEditorProps: SyncFieldsEditorProps) {
|
||||
</label>
|
||||
<div className='flex gap-2'>
|
||||
<Select
|
||||
items={[
|
||||
...SYNC_TARGET_TYPE_OPTIONS.map((o) => ({
|
||||
value: o.value,
|
||||
label: t(o.label),
|
||||
})),
|
||||
]}
|
||||
value={syncFieldsEditorProps.syncToTarget.type || 'json'}
|
||||
onValueChange={(v) =>
|
||||
v !== null &&
|
||||
@ -3192,12 +3251,14 @@ function SyncFieldsEditor(syncFieldsEditorProps: SyncFieldsEditorProps) {
|
||||
<SelectTrigger className='h-8 w-[110px] text-xs'>
|
||||
<SelectValue />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{SYNC_TARGET_TYPE_OPTIONS.map((o) => (
|
||||
<SelectItem key={o.value} value={o.value}>
|
||||
{t(o.label)}
|
||||
</SelectItem>
|
||||
))}
|
||||
<SelectContent alignItemWithTrigger={false}>
|
||||
<SelectGroup>
|
||||
{SYNC_TARGET_TYPE_OPTIONS.map((o) => (
|
||||
<SelectItem key={o.value} value={o.value}>
|
||||
{t(o.label)}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectGroup>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<Input
|
||||
|
||||
@ -59,6 +59,7 @@ import { Input } from '@/components/ui/input'
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectGroup,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
@ -1376,6 +1377,13 @@ export function ChannelMutateDrawer({
|
||||
<FormItem>
|
||||
<FormLabel>{t('AWS Key Format')}</FormLabel>
|
||||
<Select
|
||||
items={[
|
||||
{
|
||||
value: 'ak_sk',
|
||||
label: t('AccessKey / SecretAccessKey'),
|
||||
},
|
||||
{ value: 'api_key', label: t('API Key') },
|
||||
]}
|
||||
onValueChange={field.onChange}
|
||||
value={field.value}
|
||||
>
|
||||
@ -1386,13 +1394,15 @@ export function ChannelMutateDrawer({
|
||||
/>
|
||||
</SelectTrigger>
|
||||
</FormControl>
|
||||
<SelectContent>
|
||||
<SelectItem value='ak_sk'>
|
||||
{t('AccessKey / SecretAccessKey')}
|
||||
</SelectItem>
|
||||
<SelectItem value='api_key'>
|
||||
{t('API Key')}
|
||||
</SelectItem>
|
||||
<SelectContent alignItemWithTrigger={false}>
|
||||
<SelectGroup>
|
||||
<SelectItem value='ak_sk'>
|
||||
{t('AccessKey / SecretAccessKey')}
|
||||
</SelectItem>
|
||||
<SelectItem value='api_key'>
|
||||
{t('API Key')}
|
||||
</SelectItem>
|
||||
</SelectGroup>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<FormDescription>
|
||||
@ -1534,6 +1544,10 @@ export function ChannelMutateDrawer({
|
||||
<FormItem>
|
||||
<FormLabel>{t('Vertex AI Key Format')}</FormLabel>
|
||||
<Select
|
||||
items={[
|
||||
{ value: 'json', label: t('JSON') },
|
||||
{ value: 'api_key', label: t('API Key') },
|
||||
]}
|
||||
onValueChange={field.onChange}
|
||||
value={field.value}
|
||||
>
|
||||
@ -1542,11 +1556,15 @@ export function ChannelMutateDrawer({
|
||||
<SelectValue />
|
||||
</SelectTrigger>
|
||||
</FormControl>
|
||||
<SelectContent>
|
||||
<SelectItem value='json'>{t('JSON')}</SelectItem>
|
||||
<SelectItem value='api_key'>
|
||||
{t('API Key')}
|
||||
</SelectItem>
|
||||
<SelectContent alignItemWithTrigger={false}>
|
||||
<SelectGroup>
|
||||
<SelectItem value='json'>
|
||||
{t('JSON')}
|
||||
</SelectItem>
|
||||
<SelectItem value='api_key'>
|
||||
{t('API Key')}
|
||||
</SelectItem>
|
||||
</SelectGroup>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<FormDescription>
|
||||
@ -1672,6 +1690,22 @@ export function ChannelMutateDrawer({
|
||||
{t('API Base URL *')}
|
||||
</FormLabel>
|
||||
<Select
|
||||
items={[
|
||||
{
|
||||
value: 'https://ark.cn-beijing.volces.com',
|
||||
label: t('https://ark.cn-beijing.volces.com'),
|
||||
},
|
||||
{
|
||||
value: 'https://ark.ap-southeast.bytepluses.com',
|
||||
label: t(
|
||||
'https://ark.ap-southeast.bytepluses.com'
|
||||
),
|
||||
},
|
||||
{
|
||||
value: 'doubao-coding-plan',
|
||||
label: t('Doubao Coding Plan'),
|
||||
},
|
||||
]}
|
||||
onValueChange={field.onChange}
|
||||
value={
|
||||
field.value || 'https://ark.cn-beijing.volces.com'
|
||||
@ -1682,16 +1716,18 @@ export function ChannelMutateDrawer({
|
||||
<SelectValue />
|
||||
</SelectTrigger>
|
||||
</FormControl>
|
||||
<SelectContent>
|
||||
<SelectItem value='https://ark.cn-beijing.volces.com'>
|
||||
{t('https://ark.cn-beijing.volces.com')}
|
||||
</SelectItem>
|
||||
<SelectItem value='https://ark.ap-southeast.bytepluses.com'>
|
||||
{t('https://ark.ap-southeast.bytepluses.com')}
|
||||
</SelectItem>
|
||||
<SelectItem value='doubao-coding-plan'>
|
||||
{t('Doubao Coding Plan')}
|
||||
</SelectItem>
|
||||
<SelectContent alignItemWithTrigger={false}>
|
||||
<SelectGroup>
|
||||
<SelectItem value='https://ark.cn-beijing.volces.com'>
|
||||
{t('https://ark.cn-beijing.volces.com')}
|
||||
</SelectItem>
|
||||
<SelectItem value='https://ark.ap-southeast.bytepluses.com'>
|
||||
{t('https://ark.ap-southeast.bytepluses.com')}
|
||||
</SelectItem>
|
||||
<SelectItem value='doubao-coding-plan'>
|
||||
{t('Doubao Coding Plan')}
|
||||
</SelectItem>
|
||||
</SelectGroup>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<FormDescription>
|
||||
@ -1790,6 +1826,12 @@ export function ChannelMutateDrawer({
|
||||
<FormItem>
|
||||
<FormLabel>{t('Add Mode')}</FormLabel>
|
||||
<Select
|
||||
items={[
|
||||
...ADD_MODE_OPTIONS.map((option) => ({
|
||||
value: option.value,
|
||||
label: t(option.label),
|
||||
})),
|
||||
]}
|
||||
onValueChange={field.onChange}
|
||||
value={field.value}
|
||||
>
|
||||
@ -1798,15 +1840,17 @@ export function ChannelMutateDrawer({
|
||||
<SelectValue />
|
||||
</SelectTrigger>
|
||||
</FormControl>
|
||||
<SelectContent>
|
||||
{ADD_MODE_OPTIONS.map((option) => (
|
||||
<SelectItem
|
||||
key={option.value}
|
||||
value={option.value}
|
||||
>
|
||||
{t(option.label)}
|
||||
</SelectItem>
|
||||
))}
|
||||
<SelectContent alignItemWithTrigger={false}>
|
||||
<SelectGroup>
|
||||
{ADD_MODE_OPTIONS.map((option) => (
|
||||
<SelectItem
|
||||
key={option.value}
|
||||
value={option.value}
|
||||
>
|
||||
{t(option.label)}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectGroup>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<FormDescription>
|
||||
@ -2027,6 +2071,16 @@ export function ChannelMutateDrawer({
|
||||
<FormItem>
|
||||
<FormLabel>{t('Key Update Mode')}</FormLabel>
|
||||
<Select
|
||||
items={[
|
||||
{
|
||||
value: 'append',
|
||||
label: t('Append to existing keys'),
|
||||
},
|
||||
{
|
||||
value: 'replace',
|
||||
label: t('Replace all existing keys'),
|
||||
},
|
||||
]}
|
||||
onValueChange={field.onChange}
|
||||
value={field.value}
|
||||
>
|
||||
@ -2035,13 +2089,15 @@ export function ChannelMutateDrawer({
|
||||
<SelectValue />
|
||||
</SelectTrigger>
|
||||
</FormControl>
|
||||
<SelectContent>
|
||||
<SelectItem value='append'>
|
||||
{t('Append to existing keys')}
|
||||
</SelectItem>
|
||||
<SelectItem value='replace'>
|
||||
{t('Replace all existing keys')}
|
||||
</SelectItem>
|
||||
<SelectContent alignItemWithTrigger={false}>
|
||||
<SelectGroup>
|
||||
<SelectItem value='append'>
|
||||
{t('Append to existing keys')}
|
||||
</SelectItem>
|
||||
<SelectItem value='replace'>
|
||||
{t('Replace all existing keys')}
|
||||
</SelectItem>
|
||||
</SelectGroup>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<FormDescription>
|
||||
@ -2067,6 +2123,10 @@ export function ChannelMutateDrawer({
|
||||
<FormItem>
|
||||
<FormLabel>{t('Multi-Key Strategy')}</FormLabel>
|
||||
<Select
|
||||
items={[
|
||||
{ value: 'random', label: t('Random') },
|
||||
{ value: 'polling', label: t('Polling') },
|
||||
]}
|
||||
onValueChange={field.onChange}
|
||||
value={field.value}
|
||||
>
|
||||
@ -2075,13 +2135,15 @@ export function ChannelMutateDrawer({
|
||||
<SelectValue />
|
||||
</SelectTrigger>
|
||||
</FormControl>
|
||||
<SelectContent>
|
||||
<SelectItem value='random'>
|
||||
{t('Random')}
|
||||
</SelectItem>
|
||||
<SelectItem value='polling'>
|
||||
{t('Polling')}
|
||||
</SelectItem>
|
||||
<SelectContent alignItemWithTrigger={false}>
|
||||
<SelectGroup>
|
||||
<SelectItem value='random'>
|
||||
{t('Random')}
|
||||
</SelectItem>
|
||||
<SelectItem value='polling'>
|
||||
{t('Polling')}
|
||||
</SelectItem>
|
||||
</SelectGroup>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<FormDescription>
|
||||
|
||||
@ -16,6 +16,7 @@ import { Label } from '@/components/ui/label'
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectGroup,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
@ -73,6 +74,12 @@ export function ModelsChartPreferences(props: ModelsChartPreferencesProps) {
|
||||
<div className='grid gap-2'>
|
||||
<Label htmlFor='default-time-range'>{t('Default range')}</Label>
|
||||
<Select
|
||||
items={[
|
||||
...TIME_RANGE_PRESETS.map((option) => ({
|
||||
value: String(option.days),
|
||||
label: t(option.label),
|
||||
})),
|
||||
]}
|
||||
value={String(draft.defaultTimeRangeDays)}
|
||||
onValueChange={(value) =>
|
||||
setDraft((prev) => ({
|
||||
@ -84,12 +91,14 @@ export function ModelsChartPreferences(props: ModelsChartPreferencesProps) {
|
||||
<SelectTrigger id='default-time-range'>
|
||||
<SelectValue placeholder={t('Select default range')} />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{TIME_RANGE_PRESETS.map((option) => (
|
||||
<SelectItem key={option.days} value={String(option.days)}>
|
||||
{t(option.label)}
|
||||
</SelectItem>
|
||||
))}
|
||||
<SelectContent alignItemWithTrigger={false}>
|
||||
<SelectGroup>
|
||||
{TIME_RANGE_PRESETS.map((option) => (
|
||||
<SelectItem key={option.days} value={String(option.days)}>
|
||||
{t(option.label)}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectGroup>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
@ -99,6 +108,12 @@ export function ModelsChartPreferences(props: ModelsChartPreferencesProps) {
|
||||
{t('Default time granularity')}
|
||||
</Label>
|
||||
<Select
|
||||
items={[
|
||||
...TIME_GRANULARITY_OPTIONS.map((option) => ({
|
||||
value: option.value,
|
||||
label: t(option.label),
|
||||
})),
|
||||
]}
|
||||
value={draft.defaultTimeGranularity}
|
||||
onValueChange={(value) =>
|
||||
setDraft((prev) => ({
|
||||
@ -110,12 +125,14 @@ export function ModelsChartPreferences(props: ModelsChartPreferencesProps) {
|
||||
<SelectTrigger id='default-time-granularity'>
|
||||
<SelectValue placeholder={t('Select time granularity')} />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{TIME_GRANULARITY_OPTIONS.map((option) => (
|
||||
<SelectItem key={option.value} value={option.value}>
|
||||
{t(option.label)}
|
||||
</SelectItem>
|
||||
))}
|
||||
<SelectContent alignItemWithTrigger={false}>
|
||||
<SelectGroup>
|
||||
{TIME_GRANULARITY_OPTIONS.map((option) => (
|
||||
<SelectItem key={option.value} value={option.value}>
|
||||
{t(option.label)}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectGroup>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
@ -125,6 +142,12 @@ export function ModelsChartPreferences(props: ModelsChartPreferencesProps) {
|
||||
{t('Default consumption chart')}
|
||||
</Label>
|
||||
<Select
|
||||
items={[
|
||||
...CONSUMPTION_DISTRIBUTION_CHART_OPTIONS.map((option) => ({
|
||||
value: option.value,
|
||||
label: t(option.labelKey),
|
||||
})),
|
||||
]}
|
||||
value={draft.consumptionDistributionChart}
|
||||
onValueChange={(value) =>
|
||||
setDraft((prev) => ({
|
||||
@ -137,12 +160,14 @@ export function ModelsChartPreferences(props: ModelsChartPreferencesProps) {
|
||||
<SelectTrigger id='consumption-distribution-chart'>
|
||||
<SelectValue placeholder={t('Select default chart')} />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{CONSUMPTION_DISTRIBUTION_CHART_OPTIONS.map((option) => (
|
||||
<SelectItem key={option.value} value={option.value}>
|
||||
{t(option.labelKey)}
|
||||
</SelectItem>
|
||||
))}
|
||||
<SelectContent alignItemWithTrigger={false}>
|
||||
<SelectGroup>
|
||||
{CONSUMPTION_DISTRIBUTION_CHART_OPTIONS.map((option) => (
|
||||
<SelectItem key={option.value} value={option.value}>
|
||||
{t(option.labelKey)}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectGroup>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
@ -152,6 +177,12 @@ export function ModelsChartPreferences(props: ModelsChartPreferencesProps) {
|
||||
{t('Default model call chart')}
|
||||
</Label>
|
||||
<Select
|
||||
items={[
|
||||
...MODEL_ANALYTICS_CHART_OPTIONS.map((option) => ({
|
||||
value: option.value,
|
||||
label: t(option.labelKey),
|
||||
})),
|
||||
]}
|
||||
value={draft.modelAnalyticsChart}
|
||||
onValueChange={(value) =>
|
||||
setDraft((prev) => ({
|
||||
@ -163,12 +194,14 @@ export function ModelsChartPreferences(props: ModelsChartPreferencesProps) {
|
||||
<SelectTrigger id='model-analytics-chart'>
|
||||
<SelectValue placeholder={t('Select default chart')} />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{MODEL_ANALYTICS_CHART_OPTIONS.map((option) => (
|
||||
<SelectItem key={option.value} value={option.value}>
|
||||
{t(option.labelKey)}
|
||||
</SelectItem>
|
||||
))}
|
||||
<SelectContent alignItemWithTrigger={false}>
|
||||
<SelectGroup>
|
||||
{MODEL_ANALYTICS_CHART_OPTIONS.map((option) => (
|
||||
<SelectItem key={option.value} value={option.value}>
|
||||
{t(option.labelKey)}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectGroup>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
|
||||
@ -20,6 +20,7 @@ import { ScrollArea } from '@/components/ui/scroll-area'
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectGroup,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
@ -197,6 +198,12 @@ export function ModelsFilter(props: ModelsFilterProps) {
|
||||
<div className='grid gap-2'>
|
||||
<Label htmlFor='time_granularity'>{t('Time Granularity')}</Label>
|
||||
<Select
|
||||
items={[
|
||||
...TIME_GRANULARITY_OPTIONS.map((option) => ({
|
||||
value: option.value,
|
||||
label: t(option.label),
|
||||
})),
|
||||
]}
|
||||
value={filters.time_granularity}
|
||||
onValueChange={(value) =>
|
||||
handleChange('time_granularity', value as TimeGranularity)
|
||||
@ -205,12 +212,14 @@ export function ModelsFilter(props: ModelsFilterProps) {
|
||||
<SelectTrigger>
|
||||
<SelectValue placeholder={t('Select time granularity')} />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{TIME_GRANULARITY_OPTIONS.map((option) => (
|
||||
<SelectItem key={option.value} value={option.value}>
|
||||
{t(option.label)}
|
||||
</SelectItem>
|
||||
))}
|
||||
<SelectContent alignItemWithTrigger={false}>
|
||||
<SelectGroup>
|
||||
{TIME_GRANULARITY_OPTIONS.map((option) => (
|
||||
<SelectItem key={option.value} value={option.value}>
|
||||
{t(option.label)}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectGroup>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
|
||||
@ -18,6 +18,7 @@ import { Input } from '@/components/ui/input'
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectGroup,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
@ -432,6 +433,12 @@ export function CreateDeploymentDrawer({
|
||||
<FormItem>
|
||||
<FormLabel>{t('Hardware type')}</FormLabel>
|
||||
<Select
|
||||
items={[
|
||||
...hardwareOptions.map((opt) => ({
|
||||
value: opt.value,
|
||||
label: opt.label,
|
||||
})),
|
||||
]}
|
||||
value={field.value}
|
||||
onValueChange={(v) => field.onChange(v)}
|
||||
disabled={isLoadingHardware}
|
||||
@ -441,12 +448,14 @@ export function CreateDeploymentDrawer({
|
||||
<SelectValue placeholder={t('Select')} />
|
||||
</SelectTrigger>
|
||||
</FormControl>
|
||||
<SelectContent>
|
||||
{hardwareOptions.map((opt) => (
|
||||
<SelectItem key={opt.value} value={opt.value}>
|
||||
{opt.label}
|
||||
</SelectItem>
|
||||
))}
|
||||
<SelectContent alignItemWithTrigger={false}>
|
||||
<SelectGroup>
|
||||
{hardwareOptions.map((opt) => (
|
||||
<SelectItem key={opt.value} value={opt.value}>
|
||||
{opt.label}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectGroup>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<FormMessage />
|
||||
@ -593,6 +602,10 @@ export function CreateDeploymentDrawer({
|
||||
<FormItem>
|
||||
<FormLabel>{t('Billing currency')}</FormLabel>
|
||||
<Select
|
||||
items={[
|
||||
{ value: 'usdc', label: 'USDC' },
|
||||
{ value: 'iocoin', label: 'IOCOIN' },
|
||||
]}
|
||||
value={field.value || 'usdc'}
|
||||
onValueChange={(v) => field.onChange(v)}
|
||||
>
|
||||
@ -601,9 +614,11 @@ export function CreateDeploymentDrawer({
|
||||
<SelectValue placeholder={t('Select')} />
|
||||
</SelectTrigger>
|
||||
</FormControl>
|
||||
<SelectContent>
|
||||
<SelectItem value='usdc'>USDC</SelectItem>
|
||||
<SelectItem value='iocoin'>IOCOIN</SelectItem>
|
||||
<SelectContent alignItemWithTrigger={false}>
|
||||
<SelectGroup>
|
||||
<SelectItem value='usdc'>USDC</SelectItem>
|
||||
<SelectItem value='iocoin'>IOCOIN</SelectItem>
|
||||
</SelectGroup>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</FormItem>
|
||||
|
||||
@ -36,6 +36,7 @@ import {
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectGroup,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
@ -550,6 +551,12 @@ export function UpstreamConflictDialog({
|
||||
{t('Rows per page')}
|
||||
</span>
|
||||
<Select
|
||||
items={[
|
||||
...[5, 10, 20, 50].map((size) => ({
|
||||
value: String(size),
|
||||
label: size,
|
||||
})),
|
||||
]}
|
||||
value={String(pageSize)}
|
||||
onValueChange={(value) => {
|
||||
setPageSize(Number(value))
|
||||
@ -559,12 +566,14 @@ export function UpstreamConflictDialog({
|
||||
<SelectTrigger className='h-8 w-[70px] text-xs sm:h-8 sm:w-[72px]'>
|
||||
<SelectValue />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{[5, 10, 20, 50].map((size) => (
|
||||
<SelectItem key={size} value={String(size)}>
|
||||
{size}
|
||||
</SelectItem>
|
||||
))}
|
||||
<SelectContent alignItemWithTrigger={false}>
|
||||
<SelectGroup>
|
||||
{[5, 10, 20, 50].map((size) => (
|
||||
<SelectItem key={size} value={String(size)}>
|
||||
{size}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectGroup>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
|
||||
@ -12,6 +12,7 @@ import {
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectGroup,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
@ -175,6 +176,27 @@ export function ViewLogsDialog({
|
||||
{t('Container')}
|
||||
</div>
|
||||
<Select
|
||||
items={[
|
||||
...containers.flatMap((c) => {
|
||||
const id = c?.container_id
|
||||
if (typeof id !== 'string' || !id) return []
|
||||
const status =
|
||||
typeof c?.status === 'string' && c.status
|
||||
? ` (${c.status})`
|
||||
: ''
|
||||
return [
|
||||
{
|
||||
value: id,
|
||||
label: (
|
||||
<>
|
||||
{id}
|
||||
{status}
|
||||
</>
|
||||
),
|
||||
},
|
||||
]
|
||||
}),
|
||||
]}
|
||||
value={containerId}
|
||||
onValueChange={(v) => v !== null && setContainerId(v)}
|
||||
disabled={isLoadingContainers || containers.length === 0}
|
||||
@ -190,27 +212,34 @@ export function ViewLogsDialog({
|
||||
}
|
||||
/>
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{containers.map((c) => {
|
||||
const id = c?.container_id
|
||||
if (typeof id !== 'string' || !id) return null
|
||||
const status =
|
||||
typeof c?.status === 'string' && c.status
|
||||
? ` (${c.status})`
|
||||
: ''
|
||||
return (
|
||||
<SelectItem key={id} value={id}>
|
||||
{id}
|
||||
{status}
|
||||
</SelectItem>
|
||||
)
|
||||
})}
|
||||
<SelectContent alignItemWithTrigger={false}>
|
||||
<SelectGroup>
|
||||
{containers.map((c) => {
|
||||
const id = c?.container_id
|
||||
if (typeof id !== 'string' || !id) return null
|
||||
const status =
|
||||
typeof c?.status === 'string' && c.status
|
||||
? ` (${c.status})`
|
||||
: ''
|
||||
return (
|
||||
<SelectItem key={id} value={id}>
|
||||
{id}
|
||||
{status}
|
||||
</SelectItem>
|
||||
)
|
||||
})}
|
||||
</SelectGroup>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
<div className='space-y-1'>
|
||||
<div className='text-muted-foreground text-xs'>{t('Stream')}</div>
|
||||
<Select
|
||||
items={[
|
||||
{ value: 'stdout', label: 'stdout' },
|
||||
{ value: 'stderr', label: 'stderr' },
|
||||
{ value: 'all', label: 'all' },
|
||||
]}
|
||||
value={stream}
|
||||
onValueChange={(v) => {
|
||||
if (v === 'stderr' || v === 'all' || v === 'stdout') {
|
||||
@ -223,10 +252,12 @@ export function ViewLogsDialog({
|
||||
<SelectTrigger>
|
||||
<SelectValue placeholder={t('Select')} />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value='stdout'>stdout</SelectItem>
|
||||
<SelectItem value='stderr'>stderr</SelectItem>
|
||||
<SelectItem value='all'>all</SelectItem>
|
||||
<SelectContent alignItemWithTrigger={false}>
|
||||
<SelectGroup>
|
||||
<SelectItem value='stdout'>stdout</SelectItem>
|
||||
<SelectItem value='stderr'>stderr</SelectItem>
|
||||
<SelectItem value='all'>all</SelectItem>
|
||||
</SelectGroup>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
|
||||
@ -27,6 +27,7 @@ import { RadioGroup, RadioGroupItem } from '@/components/ui/radio-group'
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectGroup,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
@ -701,6 +702,12 @@ export function ModelMutateDrawer({
|
||||
<FormItem>
|
||||
<FormLabel>{t('Vendor')}</FormLabel>
|
||||
<Select
|
||||
items={[
|
||||
...vendors.map((vendor) => ({
|
||||
value: String(vendor.id),
|
||||
label: vendor.name,
|
||||
})),
|
||||
]}
|
||||
onValueChange={(value) =>
|
||||
field.onChange(value ? parseInt(value) : undefined)
|
||||
}
|
||||
@ -711,12 +718,17 @@ export function ModelMutateDrawer({
|
||||
<SelectValue placeholder={t('Select vendor')} />
|
||||
</SelectTrigger>
|
||||
</FormControl>
|
||||
<SelectContent>
|
||||
{vendors.map((vendor) => (
|
||||
<SelectItem key={vendor.id} value={String(vendor.id)}>
|
||||
{vendor.name}
|
||||
</SelectItem>
|
||||
))}
|
||||
<SelectContent alignItemWithTrigger={false}>
|
||||
<SelectGroup>
|
||||
{vendors.map((vendor) => (
|
||||
<SelectItem
|
||||
key={vendor.id}
|
||||
value={String(vendor.id)}
|
||||
>
|
||||
{vendor.name}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectGroup>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<FormMessage />
|
||||
@ -801,6 +813,12 @@ export function ModelMutateDrawer({
|
||||
<div className='flex items-center justify-between'>
|
||||
<h3 className='text-sm font-semibold'>{t('Endpoints')}</h3>
|
||||
<Select<string>
|
||||
items={[
|
||||
...Object.keys(ENDPOINT_TEMPLATES).map((key) => ({
|
||||
value: key,
|
||||
label: key,
|
||||
})),
|
||||
]}
|
||||
onValueChange={(v) =>
|
||||
v !== null && handleFillEndpointTemplate(v)
|
||||
}
|
||||
@ -808,12 +826,14 @@ export function ModelMutateDrawer({
|
||||
<SelectTrigger size='sm' className='w-[200px]'>
|
||||
<SelectValue placeholder={t('Load template...')} />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{Object.keys(ENDPOINT_TEMPLATES).map((key) => (
|
||||
<SelectItem key={key} value={key}>
|
||||
{key}
|
||||
</SelectItem>
|
||||
))}
|
||||
<SelectContent alignItemWithTrigger={false}>
|
||||
<SelectGroup>
|
||||
{Object.keys(ENDPOINT_TEMPLATES).map((key) => (
|
||||
<SelectItem key={key} value={key}>
|
||||
{key}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectGroup>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
|
||||
@ -19,6 +19,7 @@ import { Input } from '@/components/ui/input'
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectGroup,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
@ -252,6 +253,22 @@ export function PrefillGroupFormDrawer({
|
||||
<FormItem>
|
||||
<FormLabel>Group Type</FormLabel>
|
||||
<Select
|
||||
items={[
|
||||
...PREFILL_GROUP_TYPES.map((type) => ({
|
||||
value: type.value,
|
||||
label: (
|
||||
<div className='flex flex-col text-left'>
|
||||
<span className='font-medium'>{type.label}</span>
|
||||
<span
|
||||
data-prefill-description
|
||||
className='text-muted-foreground text-xs'
|
||||
>
|
||||
{type.description}
|
||||
</span>
|
||||
</div>
|
||||
),
|
||||
})),
|
||||
]}
|
||||
value={field.value}
|
||||
onValueChange={(value) =>
|
||||
value !== null &&
|
||||
@ -263,20 +280,24 @@ export function PrefillGroupFormDrawer({
|
||||
<SelectValue placeholder={t('Select a group type')} />
|
||||
</SelectTrigger>
|
||||
</FormControl>
|
||||
<SelectContent>
|
||||
{PREFILL_GROUP_TYPES.map((type) => (
|
||||
<SelectItem key={type.value} value={type.value}>
|
||||
<div className='flex flex-col text-left'>
|
||||
<span className='font-medium'>{type.label}</span>
|
||||
<span
|
||||
data-prefill-description
|
||||
className='text-muted-foreground text-xs'
|
||||
>
|
||||
{type.description}
|
||||
</span>
|
||||
</div>
|
||||
</SelectItem>
|
||||
))}
|
||||
<SelectContent alignItemWithTrigger={false}>
|
||||
<SelectGroup>
|
||||
{PREFILL_GROUP_TYPES.map((type) => (
|
||||
<SelectItem key={type.value} value={type.value}>
|
||||
<div className='flex flex-col text-left'>
|
||||
<span className='font-medium'>
|
||||
{type.label}
|
||||
</span>
|
||||
<span
|
||||
data-prefill-description
|
||||
className='text-muted-foreground text-xs'
|
||||
>
|
||||
{type.description}
|
||||
</span>
|
||||
</div>
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectGroup>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<FormDescription>
|
||||
|
||||
@ -6,6 +6,7 @@ import { useAuthStore } from '@/stores/auth-store'
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectGroup,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
@ -112,6 +113,12 @@ export function LanguagePreferencesCard(props: LanguagePreferencesCardProps) {
|
||||
</div>
|
||||
<div className='flex items-center gap-2 sm:min-w-48'>
|
||||
<Select
|
||||
items={[
|
||||
...LANGUAGE_OPTIONS.map((language) => ({
|
||||
value: language.value,
|
||||
label: language.label,
|
||||
})),
|
||||
]}
|
||||
value={currentLanguage}
|
||||
onValueChange={handleLanguageChange}
|
||||
disabled={saving}
|
||||
@ -119,12 +126,14 @@ export function LanguagePreferencesCard(props: LanguagePreferencesCardProps) {
|
||||
<SelectTrigger className='w-full sm:w-48'>
|
||||
<SelectValue placeholder={t('Select language')} />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{LANGUAGE_OPTIONS.map((language) => (
|
||||
<SelectItem key={language.value} value={language.value}>
|
||||
{language.label}
|
||||
</SelectItem>
|
||||
))}
|
||||
<SelectContent alignItemWithTrigger={false}>
|
||||
<SelectGroup>
|
||||
{LANGUAGE_OPTIONS.map((language) => (
|
||||
<SelectItem key={language.value} value={language.value}>
|
||||
{language.label}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectGroup>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
{saving && (
|
||||
|
||||
@ -13,6 +13,7 @@ import {
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectGroup,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
@ -270,6 +271,12 @@ export function SubscriptionPurchaseDialog(props: Props) {
|
||||
{hasEpay && (
|
||||
<div className='grid grid-cols-[minmax(0,1fr)_auto] gap-2'>
|
||||
<Select
|
||||
items={[
|
||||
...(props.epayMethods || []).map((m) => ({
|
||||
value: m.type,
|
||||
label: m.name || m.type,
|
||||
})),
|
||||
]}
|
||||
value={selectedEpayMethod}
|
||||
onValueChange={(v) =>
|
||||
v !== null && setSelectedEpayMethod(v)
|
||||
@ -279,12 +286,14 @@ export function SubscriptionPurchaseDialog(props: Props) {
|
||||
<SelectTrigger className='flex-1'>
|
||||
<SelectValue>{selectedEpayMethodLabel}</SelectValue>
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{(props.epayMethods || []).map((m) => (
|
||||
<SelectItem key={m.type} value={m.type}>
|
||||
{m.name || m.type}
|
||||
</SelectItem>
|
||||
))}
|
||||
<SelectContent alignItemWithTrigger={false}>
|
||||
<SelectGroup>
|
||||
{(props.epayMethods || []).map((m) => (
|
||||
<SelectItem key={m.type} value={m.type}>
|
||||
{m.name || m.type}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectGroup>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<Button
|
||||
|
||||
@ -6,6 +6,7 @@ import { Button } from '@/components/ui/button'
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectGroup,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
@ -183,19 +184,32 @@ export function UserSubscriptionsDialog(props: Props) {
|
||||
<div className='mt-4 space-y-4'>
|
||||
<div className='flex gap-2'>
|
||||
<Select
|
||||
items={[
|
||||
...plans.map((p) => ({
|
||||
value: String(p.plan.id),
|
||||
label: (
|
||||
<>
|
||||
{p.plan.title}($
|
||||
{Number(p.plan.price_amount || 0).toFixed(2)})
|
||||
</>
|
||||
),
|
||||
})),
|
||||
]}
|
||||
value={selectedPlanId}
|
||||
onValueChange={(v) => v !== null && setSelectedPlanId(v)}
|
||||
>
|
||||
<SelectTrigger className='flex-1'>
|
||||
<SelectValue placeholder={t('Select subscription plan')} />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{plans.map((p) => (
|
||||
<SelectItem key={p.plan.id} value={String(p.plan.id)}>
|
||||
{p.plan.title} ($
|
||||
{Number(p.plan.price_amount || 0).toFixed(2)})
|
||||
</SelectItem>
|
||||
))}
|
||||
<SelectContent alignItemWithTrigger={false}>
|
||||
<SelectGroup>
|
||||
{plans.map((p) => (
|
||||
<SelectItem key={p.plan.id} value={String(p.plan.id)}>
|
||||
{p.plan.title} ($
|
||||
{Number(p.plan.price_amount || 0).toFixed(2)})
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectGroup>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<Button
|
||||
|
||||
@ -18,6 +18,7 @@ import { Input } from '@/components/ui/input'
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectGroup,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
@ -237,6 +238,10 @@ export function SubscriptionsMutateDrawer({
|
||||
<FormItem>
|
||||
<FormLabel>{t('Upgrade Group')}</FormLabel>
|
||||
<Select
|
||||
items={[
|
||||
{ value: '__none__', label: t('No Upgrade') },
|
||||
...groupOptions.map((g) => ({ value: g, label: g })),
|
||||
]}
|
||||
onValueChange={(v) =>
|
||||
field.onChange(v === '__none__' ? '' : v)
|
||||
}
|
||||
@ -247,15 +252,17 @@ export function SubscriptionsMutateDrawer({
|
||||
<SelectValue placeholder={t('No Upgrade')} />
|
||||
</SelectTrigger>
|
||||
</FormControl>
|
||||
<SelectContent>
|
||||
<SelectItem value='__none__'>
|
||||
{t('No Upgrade')}
|
||||
</SelectItem>
|
||||
{groupOptions.map((g) => (
|
||||
<SelectItem key={g} value={g}>
|
||||
{g}
|
||||
<SelectContent alignItemWithTrigger={false}>
|
||||
<SelectGroup>
|
||||
<SelectItem value='__none__'>
|
||||
{t('No Upgrade')}
|
||||
</SelectItem>
|
||||
))}
|
||||
{groupOptions.map((g) => (
|
||||
<SelectItem key={g} value={g}>
|
||||
{g}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectGroup>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<FormMessage />
|
||||
@ -344,6 +351,12 @@ export function SubscriptionsMutateDrawer({
|
||||
<FormItem>
|
||||
<FormLabel>{t('Duration Unit')}</FormLabel>
|
||||
<Select
|
||||
items={[
|
||||
...durationUnitOpts.map((o) => ({
|
||||
value: o.value,
|
||||
label: o.label,
|
||||
})),
|
||||
]}
|
||||
onValueChange={field.onChange}
|
||||
value={field.value}
|
||||
>
|
||||
@ -352,12 +365,14 @@ export function SubscriptionsMutateDrawer({
|
||||
<SelectValue />
|
||||
</SelectTrigger>
|
||||
</FormControl>
|
||||
<SelectContent>
|
||||
{durationUnitOpts.map((o) => (
|
||||
<SelectItem key={o.value} value={o.value}>
|
||||
{o.label}
|
||||
</SelectItem>
|
||||
))}
|
||||
<SelectContent alignItemWithTrigger={false}>
|
||||
<SelectGroup>
|
||||
{durationUnitOpts.map((o) => (
|
||||
<SelectItem key={o.value} value={o.value}>
|
||||
{o.label}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectGroup>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<FormMessage />
|
||||
@ -426,6 +441,12 @@ export function SubscriptionsMutateDrawer({
|
||||
<FormItem>
|
||||
<FormLabel>{t('Reset Cycle')}</FormLabel>
|
||||
<Select
|
||||
items={[
|
||||
...resetPeriodOpts.map((o) => ({
|
||||
value: o.value,
|
||||
label: o.label,
|
||||
})),
|
||||
]}
|
||||
onValueChange={field.onChange}
|
||||
value={field.value}
|
||||
>
|
||||
@ -434,12 +455,14 @@ export function SubscriptionsMutateDrawer({
|
||||
<SelectValue />
|
||||
</SelectTrigger>
|
||||
</FormControl>
|
||||
<SelectContent>
|
||||
{resetPeriodOpts.map((o) => (
|
||||
<SelectItem key={o.value} value={o.value}>
|
||||
{o.label}
|
||||
</SelectItem>
|
||||
))}
|
||||
<SelectContent alignItemWithTrigger={false}>
|
||||
<SelectGroup>
|
||||
{resetPeriodOpts.map((o) => (
|
||||
<SelectItem key={o.value} value={o.value}>
|
||||
{o.label}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectGroup>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<FormMessage />
|
||||
|
||||
@ -6,6 +6,7 @@ import { Label } from '@/components/ui/label'
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectGroup,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
@ -89,18 +90,26 @@ export function PresetSelector(props: PresetSelectorProps) {
|
||||
<div className='space-y-1.5'>
|
||||
<Label>{t('Preset Template')}</Label>
|
||||
<Select
|
||||
items={[
|
||||
...OAUTH_PRESETS.map((preset) => ({
|
||||
value: preset.key,
|
||||
label: preset.name,
|
||||
})),
|
||||
]}
|
||||
value={selectedPreset}
|
||||
onValueChange={(v) => v !== null && handlePresetChange(v)}
|
||||
>
|
||||
<SelectTrigger className='w-full'>
|
||||
<SelectValue placeholder={t('Select a preset...')} />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{OAUTH_PRESETS.map((preset) => (
|
||||
<SelectItem key={preset.key} value={preset.key}>
|
||||
{preset.name}
|
||||
</SelectItem>
|
||||
))}
|
||||
<SelectContent alignItemWithTrigger={false}>
|
||||
<SelectGroup>
|
||||
{OAUTH_PRESETS.map((preset) => (
|
||||
<SelectItem key={preset.key} value={preset.key}>
|
||||
{preset.name}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectGroup>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
|
||||
@ -24,6 +24,7 @@ import { Input } from '@/components/ui/input'
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectGroup,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
@ -302,6 +303,12 @@ export function ProviderFormDialog(props: ProviderFormDialogProps) {
|
||||
<FormItem>
|
||||
<FormLabel>{t('Auth Style')}</FormLabel>
|
||||
<Select
|
||||
items={[
|
||||
...AUTH_STYLE_OPTIONS.map((option) => ({
|
||||
value: String(option.value),
|
||||
label: t(option.labelKey),
|
||||
})),
|
||||
]}
|
||||
value={String(field.value)}
|
||||
onValueChange={(val) => field.onChange(Number(val))}
|
||||
>
|
||||
@ -310,15 +317,17 @@ export function ProviderFormDialog(props: ProviderFormDialogProps) {
|
||||
<SelectValue />
|
||||
</SelectTrigger>
|
||||
</FormControl>
|
||||
<SelectContent>
|
||||
{AUTH_STYLE_OPTIONS.map((option) => (
|
||||
<SelectItem
|
||||
key={option.value}
|
||||
value={String(option.value)}
|
||||
>
|
||||
{t(option.labelKey)}
|
||||
</SelectItem>
|
||||
))}
|
||||
<SelectContent alignItemWithTrigger={false}>
|
||||
<SelectGroup>
|
||||
{AUTH_STYLE_OPTIONS.map((option) => (
|
||||
<SelectItem
|
||||
key={option.value}
|
||||
value={String(option.value)}
|
||||
>
|
||||
{t(option.labelKey)}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectGroup>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<FormDescription>
|
||||
|
||||
@ -17,6 +17,7 @@ import { Input } from '@/components/ui/input'
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectGroup,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
@ -221,18 +222,30 @@ export function PasskeySection({ defaultValues }: PasskeySectionProps) {
|
||||
<FormItem>
|
||||
<FormLabel>{t('User Verification')}</FormLabel>
|
||||
<FormControl>
|
||||
<Select value={field.value} onValueChange={field.onChange}>
|
||||
<Select
|
||||
items={[
|
||||
{ value: 'required', label: t('Required') },
|
||||
{ value: 'preferred', label: t('Recommended') },
|
||||
{ value: 'discouraged', label: t('Discouraged') },
|
||||
]}
|
||||
value={field.value}
|
||||
onValueChange={field.onChange}
|
||||
>
|
||||
<SelectTrigger>
|
||||
<SelectValue placeholder={t('Select requirement')} />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value='required'>{t('Required')}</SelectItem>
|
||||
<SelectItem value='preferred'>
|
||||
{t('Recommended')}
|
||||
</SelectItem>
|
||||
<SelectItem value='discouraged'>
|
||||
{t('Discouraged')}
|
||||
</SelectItem>
|
||||
<SelectContent alignItemWithTrigger={false}>
|
||||
<SelectGroup>
|
||||
<SelectItem value='required'>
|
||||
{t('Required')}
|
||||
</SelectItem>
|
||||
<SelectItem value='preferred'>
|
||||
{t('Recommended')}
|
||||
</SelectItem>
|
||||
<SelectItem value='discouraged'>
|
||||
{t('Discouraged')}
|
||||
</SelectItem>
|
||||
</SelectGroup>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</FormControl>
|
||||
@ -253,18 +266,28 @@ export function PasskeySection({ defaultValues }: PasskeySectionProps) {
|
||||
<FormItem>
|
||||
<FormLabel>{t('Device Type Preference')}</FormLabel>
|
||||
<FormControl>
|
||||
<Select value={field.value} onValueChange={field.onChange}>
|
||||
<Select
|
||||
items={[
|
||||
{ value: 'none', label: t('Unlimited') },
|
||||
{ value: 'platform', label: t('Built-in Device') },
|
||||
{ value: 'cross-platform', label: t('External Device') },
|
||||
]}
|
||||
value={field.value}
|
||||
onValueChange={field.onChange}
|
||||
>
|
||||
<SelectTrigger>
|
||||
<SelectValue placeholder={t('No preference')} />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value='none'>{t('Unlimited')}</SelectItem>
|
||||
<SelectItem value='platform'>
|
||||
{t('Built-in Device')}
|
||||
</SelectItem>
|
||||
<SelectItem value='cross-platform'>
|
||||
{t('External Device')}
|
||||
</SelectItem>
|
||||
<SelectContent alignItemWithTrigger={false}>
|
||||
<SelectGroup>
|
||||
<SelectItem value='none'>{t('Unlimited')}</SelectItem>
|
||||
<SelectItem value='platform'>
|
||||
{t('Built-in Device')}
|
||||
</SelectItem>
|
||||
<SelectItem value='cross-platform'>
|
||||
{t('External Device')}
|
||||
</SelectItem>
|
||||
</SelectGroup>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</FormControl>
|
||||
|
||||
@ -39,6 +39,7 @@ import { Input } from '@/components/ui/input'
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectGroup,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
@ -513,7 +514,23 @@ export function AnnouncementsSection({
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>{t('Type')}</FormLabel>
|
||||
<Select onValueChange={field.onChange} value={field.value}>
|
||||
<Select
|
||||
items={[
|
||||
...typeOptions.map((option) => ({
|
||||
value: option.value,
|
||||
label: (
|
||||
<div className='flex items-center gap-2'>
|
||||
<div
|
||||
className={`h-3 w-3 rounded-full ${option.color}`}
|
||||
/>
|
||||
{option.label}
|
||||
</div>
|
||||
),
|
||||
})),
|
||||
]}
|
||||
onValueChange={field.onChange}
|
||||
value={field.value}
|
||||
>
|
||||
<FormControl>
|
||||
<SelectTrigger>
|
||||
<SelectValue
|
||||
@ -521,17 +538,19 @@ export function AnnouncementsSection({
|
||||
/>
|
||||
</SelectTrigger>
|
||||
</FormControl>
|
||||
<SelectContent>
|
||||
{typeOptions.map((option) => (
|
||||
<SelectItem key={option.value} value={option.value}>
|
||||
<div className='flex items-center gap-2'>
|
||||
<div
|
||||
className={`h-3 w-3 rounded-full ${option.color}`}
|
||||
/>
|
||||
{option.label}
|
||||
</div>
|
||||
</SelectItem>
|
||||
))}
|
||||
<SelectContent alignItemWithTrigger={false}>
|
||||
<SelectGroup>
|
||||
{typeOptions.map((option) => (
|
||||
<SelectItem key={option.value} value={option.value}>
|
||||
<div className='flex items-center gap-2'>
|
||||
<div
|
||||
className={`h-3 w-3 rounded-full ${option.color}`}
|
||||
/>
|
||||
{option.label}
|
||||
</div>
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectGroup>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<FormMessage />
|
||||
|
||||
@ -38,6 +38,7 @@ import { Input } from '@/components/ui/input'
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectGroup,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
@ -462,23 +463,41 @@ export function ApiInfoSection({ enabled, data }: ApiInfoSectionProps) {
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>{t('Badge Color')}</FormLabel>
|
||||
<Select onValueChange={field.onChange} value={field.value}>
|
||||
<FormControl>
|
||||
<SelectTrigger>
|
||||
<SelectValue placeholder={t('Select a color')} />
|
||||
</SelectTrigger>
|
||||
</FormControl>
|
||||
<SelectContent>
|
||||
{colorOptions.map((option) => (
|
||||
<SelectItem key={option.value} value={option.value}>
|
||||
<Select
|
||||
items={[
|
||||
...colorOptions.map((option) => ({
|
||||
value: option.value,
|
||||
label: (
|
||||
<div className='flex items-center gap-2'>
|
||||
<div
|
||||
className={`h-4 w-4 rounded-full ${option.bgClass}`}
|
||||
/>
|
||||
{option.label}
|
||||
</div>
|
||||
</SelectItem>
|
||||
))}
|
||||
),
|
||||
})),
|
||||
]}
|
||||
onValueChange={field.onChange}
|
||||
value={field.value}
|
||||
>
|
||||
<FormControl>
|
||||
<SelectTrigger>
|
||||
<SelectValue placeholder={t('Select a color')} />
|
||||
</SelectTrigger>
|
||||
</FormControl>
|
||||
<SelectContent alignItemWithTrigger={false}>
|
||||
<SelectGroup>
|
||||
{colorOptions.map((option) => (
|
||||
<SelectItem key={option.value} value={option.value}>
|
||||
<div className='flex items-center gap-2'>
|
||||
<div
|
||||
className={`h-4 w-4 rounded-full ${option.bgClass}`}
|
||||
/>
|
||||
{option.label}
|
||||
</div>
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectGroup>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<FormDescription>
|
||||
|
||||
@ -17,6 +17,7 @@ import { Input } from '@/components/ui/input'
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectGroup,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
@ -129,6 +130,12 @@ export function DashboardSection({ defaultValues }: DashboardSectionProps) {
|
||||
<FormItem>
|
||||
<FormLabel>{t('Default time granularity')}</FormLabel>
|
||||
<Select
|
||||
items={[
|
||||
...granularityOptions.map((option) => ({
|
||||
value: option.value,
|
||||
label: option.label,
|
||||
})),
|
||||
]}
|
||||
onValueChange={field.onChange}
|
||||
value={field.value}
|
||||
disabled={!isEnabled}
|
||||
@ -138,12 +145,14 @@ export function DashboardSection({ defaultValues }: DashboardSectionProps) {
|
||||
<SelectValue placeholder={t('Select granularity')} />
|
||||
</SelectTrigger>
|
||||
</FormControl>
|
||||
<SelectContent>
|
||||
{granularityOptions.map((option) => (
|
||||
<SelectItem key={option.value} value={option.value}>
|
||||
{option.label}
|
||||
</SelectItem>
|
||||
))}
|
||||
<SelectContent alignItemWithTrigger={false}>
|
||||
<SelectGroup>
|
||||
{granularityOptions.map((option) => (
|
||||
<SelectItem key={option.value} value={option.value}>
|
||||
{option.label}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectGroup>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<FormDescription>
|
||||
|
||||
@ -21,6 +21,7 @@ import { Label } from '@/components/ui/label'
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectGroup,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
@ -276,6 +277,9 @@ export function RuleEditorDialog(props: Props) {
|
||||
{keySources.map((src, idx) => (
|
||||
<div key={idx} className='flex items-center gap-2'>
|
||||
<Select
|
||||
items={[
|
||||
...KEY_SOURCE_TYPES.map((t) => ({ value: t, label: t })),
|
||||
]}
|
||||
value={src.type}
|
||||
onValueChange={(v) => {
|
||||
if (v === null) return
|
||||
@ -290,12 +294,14 @@ export function RuleEditorDialog(props: Props) {
|
||||
<SelectTrigger className='w-[160px]'>
|
||||
<SelectValue />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{KEY_SOURCE_TYPES.map((t) => (
|
||||
<SelectItem key={t} value={t}>
|
||||
{t}
|
||||
</SelectItem>
|
||||
))}
|
||||
<SelectContent alignItemWithTrigger={false}>
|
||||
<SelectGroup>
|
||||
{KEY_SOURCE_TYPES.map((t) => (
|
||||
<SelectItem key={t} value={t}>
|
||||
{t}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectGroup>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<Input
|
||||
|
||||
@ -18,6 +18,7 @@ import { Input } from '@/components/ui/input'
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectGroup,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
@ -162,23 +163,34 @@ export function PricingSection({ defaultValues }: PricingSectionProps) {
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>{t('Display Mode')}</FormLabel>
|
||||
<Select value={field.value} onValueChange={field.onChange}>
|
||||
<Select
|
||||
items={[
|
||||
{ value: 'USD', label: t('USD') },
|
||||
{ value: 'CNY', label: t('CNY') },
|
||||
{ value: 'CUSTOM', label: t('Custom Currency') },
|
||||
{ value: 'TOKENS', label: t('Tokens Only') },
|
||||
]}
|
||||
value={field.value}
|
||||
onValueChange={field.onChange}
|
||||
>
|
||||
<FormControl>
|
||||
<SelectTrigger>
|
||||
<SelectValue placeholder={t('Select display mode')} />
|
||||
</SelectTrigger>
|
||||
</FormControl>
|
||||
<SelectContent>
|
||||
<SelectItem value='USD'>{t('USD')}</SelectItem>
|
||||
<SelectItem value='CNY'>{t('CNY')}</SelectItem>
|
||||
<SelectItem value='CUSTOM'>
|
||||
{t('Custom Currency')}
|
||||
</SelectItem>
|
||||
{showTokensOnlyOption && (
|
||||
<SelectItem value='TOKENS'>
|
||||
{t('Tokens Only')}
|
||||
<SelectContent alignItemWithTrigger={false}>
|
||||
<SelectGroup>
|
||||
<SelectItem value='USD'>{t('USD')}</SelectItem>
|
||||
<SelectItem value='CNY'>{t('CNY')}</SelectItem>
|
||||
<SelectItem value='CUSTOM'>
|
||||
{t('Custom Currency')}
|
||||
</SelectItem>
|
||||
)}
|
||||
{showTokensOnlyOption && (
|
||||
<SelectItem value='TOKENS'>
|
||||
{t('Tokens Only')}
|
||||
</SelectItem>
|
||||
)}
|
||||
</SelectGroup>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<FormDescription>
|
||||
|
||||
@ -17,6 +17,7 @@ import { Input } from '@/components/ui/input'
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectGroup,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
@ -133,19 +134,31 @@ export function SystemInfoSection({ defaultValues }: SystemInfoSectionProps) {
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>{t('Frontend Theme')}</FormLabel>
|
||||
<Select onValueChange={field.onChange} value={field.value}>
|
||||
<Select
|
||||
items={[
|
||||
{ value: 'default', label: t('Default (New Frontend)') },
|
||||
{
|
||||
value: 'classic',
|
||||
label: t('Classic (Legacy Frontend)'),
|
||||
},
|
||||
]}
|
||||
onValueChange={field.onChange}
|
||||
value={field.value}
|
||||
>
|
||||
<FormControl>
|
||||
<SelectTrigger className='w-full'>
|
||||
<SelectValue />
|
||||
</SelectTrigger>
|
||||
</FormControl>
|
||||
<SelectContent>
|
||||
<SelectItem value='default'>
|
||||
{t('Default (New Frontend)')}
|
||||
</SelectItem>
|
||||
<SelectItem value='classic'>
|
||||
{t('Classic (Legacy Frontend)')}
|
||||
</SelectItem>
|
||||
<SelectContent alignItemWithTrigger={false}>
|
||||
<SelectGroup>
|
||||
<SelectItem value='default'>
|
||||
{t('Default (New Frontend)')}
|
||||
</SelectItem>
|
||||
<SelectItem value='classic'>
|
||||
{t('Classic (Legacy Frontend)')}
|
||||
</SelectItem>
|
||||
</SelectGroup>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<FormDescription>
|
||||
|
||||
@ -25,6 +25,7 @@ import { Input } from '@/components/ui/input'
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectGroup,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
@ -160,15 +161,24 @@ export function CreemProductDialog({
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>{t('Currency')}</FormLabel>
|
||||
<Select onValueChange={field.onChange} value={field.value}>
|
||||
<Select
|
||||
items={[
|
||||
{ value: 'USD', label: 'USD ($)' },
|
||||
{ value: 'EUR', label: 'EUR (€)' },
|
||||
]}
|
||||
onValueChange={field.onChange}
|
||||
value={field.value}
|
||||
>
|
||||
<FormControl>
|
||||
<SelectTrigger>
|
||||
<SelectValue placeholder={t('Select currency')} />
|
||||
</SelectTrigger>
|
||||
</FormControl>
|
||||
<SelectContent>
|
||||
<SelectItem value='USD'>USD ($)</SelectItem>
|
||||
<SelectItem value='EUR'>EUR (€)</SelectItem>
|
||||
<SelectContent alignItemWithTrigger={false}>
|
||||
<SelectGroup>
|
||||
<SelectItem value='USD'>USD ($)</SelectItem>
|
||||
<SelectItem value='EUR'>EUR (€)</SelectItem>
|
||||
</SelectGroup>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<FormMessage />
|
||||
|
||||
@ -33,6 +33,7 @@ import { Progress } from '@/components/ui/progress'
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectGroup,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
@ -508,6 +509,11 @@ export function PerformanceSection(props: Props) {
|
||||
<FormItem>
|
||||
<FormLabel>{t('Aggregation bucket')}</FormLabel>
|
||||
<Select
|
||||
items={[
|
||||
{ value: 'minute', label: t('1 minute') },
|
||||
{ value: '5min', label: t('5 minutes') },
|
||||
{ value: 'hour', label: t('1 hour') },
|
||||
]}
|
||||
value={field.value}
|
||||
onValueChange={field.onChange}
|
||||
disabled={!perfMetricsEnabled}
|
||||
@ -517,10 +523,12 @@ export function PerformanceSection(props: Props) {
|
||||
<SelectValue />
|
||||
</SelectTrigger>
|
||||
</FormControl>
|
||||
<SelectContent>
|
||||
<SelectItem value='minute'>{t('1 minute')}</SelectItem>
|
||||
<SelectItem value='5min'>{t('5 minutes')}</SelectItem>
|
||||
<SelectItem value='hour'>{t('1 hour')}</SelectItem>
|
||||
<SelectContent alignItemWithTrigger={false}>
|
||||
<SelectGroup>
|
||||
<SelectItem value='minute'>{t('1 minute')}</SelectItem>
|
||||
<SelectItem value='5min'>{t('5 minutes')}</SelectItem>
|
||||
<SelectItem value='hour'>{t('1 hour')}</SelectItem>
|
||||
</SelectGroup>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</FormItem>
|
||||
@ -605,19 +613,25 @@ export function PerformanceSection(props: Props) {
|
||||
<div className='grid gap-1.5'>
|
||||
<Label className='text-xs'>{t('Cleanup Mode')}</Label>
|
||||
<Select
|
||||
items={[
|
||||
{ value: 'by_count', label: t('Retain last N files') },
|
||||
{ value: 'by_days', label: t('Retain last N days') },
|
||||
]}
|
||||
value={logCleanupMode}
|
||||
onValueChange={(v) => v !== null && setLogCleanupMode(v)}
|
||||
>
|
||||
<SelectTrigger className='w-[160px]'>
|
||||
<SelectValue />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value='by_count'>
|
||||
{t('Retain last N files')}
|
||||
</SelectItem>
|
||||
<SelectItem value='by_days'>
|
||||
{t('Retain last N days')}
|
||||
</SelectItem>
|
||||
<SelectContent alignItemWithTrigger={false}>
|
||||
<SelectGroup>
|
||||
<SelectItem value='by_count'>
|
||||
{t('Retain last N files')}
|
||||
</SelectItem>
|
||||
<SelectItem value='by_days'>
|
||||
{t('Retain last N days')}
|
||||
</SelectItem>
|
||||
</SelectGroup>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
|
||||
@ -24,6 +24,7 @@ import { Input } from '@/components/ui/input'
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectGroup,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
@ -224,18 +225,26 @@ export function ChannelSelectorDialog({
|
||||
return (
|
||||
<div className='flex items-center gap-2'>
|
||||
<Select
|
||||
items={[
|
||||
...ENDPOINT_OPTIONS.map((option) => ({
|
||||
value: option.value,
|
||||
label: option.label,
|
||||
})),
|
||||
]}
|
||||
value={endpointType}
|
||||
onValueChange={(v) => v !== null && handleTypeChange(v)}
|
||||
>
|
||||
<SelectTrigger className='h-8 w-32'>
|
||||
<SelectValue />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{ENDPOINT_OPTIONS.map((option) => (
|
||||
<SelectItem key={option.value} value={option.value}>
|
||||
{option.label}
|
||||
</SelectItem>
|
||||
))}
|
||||
<SelectContent alignItemWithTrigger={false}>
|
||||
<SelectGroup>
|
||||
{ENDPOINT_OPTIONS.map((option) => (
|
||||
<SelectItem key={option.value} value={option.value}>
|
||||
{option.label}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectGroup>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
{endpointType === 'custom' && (
|
||||
|
||||
@ -18,6 +18,7 @@ import { Input } from '@/components/ui/input'
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectGroup,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
@ -176,6 +177,38 @@ function GroupSection(props: GroupSectionProps) {
|
||||
{props.items.map((rule) => (
|
||||
<div key={rule._id} className='flex items-center gap-2'>
|
||||
<Select
|
||||
items={[
|
||||
{
|
||||
value: OP_ADD,
|
||||
label: (
|
||||
<StatusBadge
|
||||
label={t(OP_BADGE_MAP[OP_ADD].label)}
|
||||
variant={OP_BADGE_MAP[OP_ADD].variant}
|
||||
copyable={false}
|
||||
/>
|
||||
),
|
||||
},
|
||||
{
|
||||
value: OP_REMOVE,
|
||||
label: (
|
||||
<StatusBadge
|
||||
label={t(OP_BADGE_MAP[OP_REMOVE].label)}
|
||||
variant={OP_BADGE_MAP[OP_REMOVE].variant}
|
||||
copyable={false}
|
||||
/>
|
||||
),
|
||||
},
|
||||
{
|
||||
value: OP_APPEND,
|
||||
label: (
|
||||
<StatusBadge
|
||||
label={t(OP_BADGE_MAP[OP_APPEND].label)}
|
||||
variant={OP_BADGE_MAP[OP_APPEND].variant}
|
||||
copyable={false}
|
||||
/>
|
||||
),
|
||||
},
|
||||
]}
|
||||
value={rule.op}
|
||||
onValueChange={(v) =>
|
||||
v !== null && props.onUpdate(rule._id, 'op', v)
|
||||
@ -190,28 +223,30 @@ function GroupSection(props: GroupSectionProps) {
|
||||
/>
|
||||
</SelectValue>
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value={OP_ADD}>
|
||||
<StatusBadge
|
||||
label={t(OP_BADGE_MAP[OP_ADD].label)}
|
||||
variant={OP_BADGE_MAP[OP_ADD].variant}
|
||||
copyable={false}
|
||||
/>
|
||||
</SelectItem>
|
||||
<SelectItem value={OP_REMOVE}>
|
||||
<StatusBadge
|
||||
label={t(OP_BADGE_MAP[OP_REMOVE].label)}
|
||||
variant={OP_BADGE_MAP[OP_REMOVE].variant}
|
||||
copyable={false}
|
||||
/>
|
||||
</SelectItem>
|
||||
<SelectItem value={OP_APPEND}>
|
||||
<StatusBadge
|
||||
label={t(OP_BADGE_MAP[OP_APPEND].label)}
|
||||
variant={OP_BADGE_MAP[OP_APPEND].variant}
|
||||
copyable={false}
|
||||
/>
|
||||
</SelectItem>
|
||||
<SelectContent alignItemWithTrigger={false}>
|
||||
<SelectGroup>
|
||||
<SelectItem value={OP_ADD}>
|
||||
<StatusBadge
|
||||
label={t(OP_BADGE_MAP[OP_ADD].label)}
|
||||
variant={OP_BADGE_MAP[OP_ADD].variant}
|
||||
copyable={false}
|
||||
/>
|
||||
</SelectItem>
|
||||
<SelectItem value={OP_REMOVE}>
|
||||
<StatusBadge
|
||||
label={t(OP_BADGE_MAP[OP_REMOVE].label)}
|
||||
variant={OP_BADGE_MAP[OP_REMOVE].variant}
|
||||
copyable={false}
|
||||
/>
|
||||
</SelectItem>
|
||||
<SelectItem value={OP_APPEND}>
|
||||
<StatusBadge
|
||||
label={t(OP_BADGE_MAP[OP_APPEND].label)}
|
||||
variant={OP_BADGE_MAP[OP_APPEND].variant}
|
||||
copyable={false}
|
||||
/>
|
||||
</SelectItem>
|
||||
</SelectGroup>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<Input
|
||||
|
||||
@ -27,6 +27,7 @@ import { Label } from '@/components/ui/label'
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectGroup,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
@ -415,6 +416,12 @@ function ConditionRow({ condition, onChange, onRemove }: ConditionRowProps) {
|
||||
return (
|
||||
<div className='flex items-center gap-2'>
|
||||
<Select
|
||||
items={[
|
||||
...CONDITION_INPUT_OPTIONS.map((option) => ({
|
||||
value: option.value,
|
||||
label: t(option.labelKey),
|
||||
})),
|
||||
]}
|
||||
value={condition.var}
|
||||
onValueChange={(value) =>
|
||||
onChange({ ...condition, var: value as TierConditionInput['var'] })
|
||||
@ -427,15 +434,18 @@ function ConditionRow({ condition, onChange, onRemove }: ConditionRowProps) {
|
||||
: condition.var}
|
||||
</SelectValue>
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{CONDITION_INPUT_OPTIONS.map((option) => (
|
||||
<SelectItem key={option.value} value={option.value}>
|
||||
{t(option.labelKey)}
|
||||
</SelectItem>
|
||||
))}
|
||||
<SelectContent alignItemWithTrigger={false}>
|
||||
<SelectGroup>
|
||||
{CONDITION_INPUT_OPTIONS.map((option) => (
|
||||
<SelectItem key={option.value} value={option.value}>
|
||||
{t(option.labelKey)}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectGroup>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<Select
|
||||
items={[...OPS.map((op) => ({ value: op, label: op }))]}
|
||||
value={condition.op}
|
||||
onValueChange={(value) =>
|
||||
onChange({ ...condition, op: value as TierConditionInput['op'] })
|
||||
@ -444,12 +454,14 @@ function ConditionRow({ condition, onChange, onRemove }: ConditionRowProps) {
|
||||
<SelectTrigger className='w-20' size='sm'>
|
||||
<SelectValue />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{OPS.map((op) => (
|
||||
<SelectItem key={op} value={op}>
|
||||
{op}
|
||||
</SelectItem>
|
||||
))}
|
||||
<SelectContent alignItemWithTrigger={false}>
|
||||
<SelectGroup>
|
||||
{OPS.map((op) => (
|
||||
<SelectItem key={op} value={op}>
|
||||
{op}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectGroup>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<DraftNumberInput
|
||||
@ -960,6 +972,12 @@ function RuleConditionRow({
|
||||
const renderTimeCondition = (timeCond: TimeCondition) => (
|
||||
<>
|
||||
<Select
|
||||
items={[
|
||||
...TIME_FUNCS.map((fn) => ({
|
||||
value: fn,
|
||||
label: getTimeFuncLabel(fn),
|
||||
})),
|
||||
]}
|
||||
value={timeCond.timeFunc}
|
||||
onValueChange={(value) =>
|
||||
onChange({ ...timeCond, timeFunc: value as TimeFunc })
|
||||
@ -968,15 +986,23 @@ function RuleConditionRow({
|
||||
<SelectTrigger className='w-32' size='sm'>
|
||||
<SelectValue>{getTimeFuncLabel(timeCond.timeFunc)}</SelectValue>
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{TIME_FUNCS.map((fn) => (
|
||||
<SelectItem key={fn} value={fn}>
|
||||
{getTimeFuncLabel(fn)}
|
||||
</SelectItem>
|
||||
))}
|
||||
<SelectContent alignItemWithTrigger={false}>
|
||||
<SelectGroup>
|
||||
{TIME_FUNCS.map((fn) => (
|
||||
<SelectItem key={fn} value={fn}>
|
||||
{getTimeFuncLabel(fn)}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectGroup>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<Select
|
||||
items={[
|
||||
...COMMON_TIMEZONES.map((tz) => ({
|
||||
value: tz.value,
|
||||
label: tz.label,
|
||||
})),
|
||||
]}
|
||||
value={timeCond.timezone}
|
||||
onValueChange={(value) =>
|
||||
value !== null && onChange({ ...timeCond, timezone: value })
|
||||
@ -988,27 +1014,37 @@ function RuleConditionRow({
|
||||
?.label ?? timeCond.timezone}
|
||||
</SelectValue>
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{COMMON_TIMEZONES.map((tz) => (
|
||||
<SelectItem key={tz.value} value={tz.value}>
|
||||
{tz.label}
|
||||
</SelectItem>
|
||||
))}
|
||||
<SelectContent alignItemWithTrigger={false}>
|
||||
<SelectGroup>
|
||||
{COMMON_TIMEZONES.map((tz) => (
|
||||
<SelectItem key={tz.value} value={tz.value}>
|
||||
{tz.label}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectGroup>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<Select
|
||||
items={[
|
||||
...matchOptions.map((option) => ({
|
||||
value: option.value,
|
||||
label: getMatchLabel(option.value),
|
||||
})),
|
||||
]}
|
||||
value={timeCond.mode}
|
||||
onValueChange={(v) => v !== null && handleModeChange(v)}
|
||||
>
|
||||
<SelectTrigger className='w-32' size='sm'>
|
||||
<SelectValue>{getMatchLabel(timeCond.mode)}</SelectValue>
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{matchOptions.map((option) => (
|
||||
<SelectItem key={option.value} value={option.value}>
|
||||
{getMatchLabel(option.value)}
|
||||
</SelectItem>
|
||||
))}
|
||||
<SelectContent alignItemWithTrigger={false}>
|
||||
<SelectGroup>
|
||||
{matchOptions.map((option) => (
|
||||
<SelectItem key={option.value} value={option.value}>
|
||||
{getMatchLabel(option.value)}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectGroup>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
{timeCond.mode === MATCH_RANGE ? (
|
||||
@ -1055,18 +1091,26 @@ function RuleConditionRow({
|
||||
className='w-44'
|
||||
/>
|
||||
<Select
|
||||
items={[
|
||||
...matchOptions.map((option) => ({
|
||||
value: option.value,
|
||||
label: getMatchLabel(option.value),
|
||||
})),
|
||||
]}
|
||||
value={phCond.mode}
|
||||
onValueChange={(v) => v !== null && handleModeChange(v)}
|
||||
>
|
||||
<SelectTrigger className='w-32' size='sm'>
|
||||
<SelectValue>{getMatchLabel(phCond.mode)}</SelectValue>
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{matchOptions.map((option) => (
|
||||
<SelectItem key={option.value} value={option.value}>
|
||||
{getMatchLabel(option.value)}
|
||||
</SelectItem>
|
||||
))}
|
||||
<SelectContent alignItemWithTrigger={false}>
|
||||
<SelectGroup>
|
||||
{matchOptions.map((option) => (
|
||||
<SelectItem key={option.value} value={option.value}>
|
||||
{getMatchLabel(option.value)}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectGroup>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
{phCond.mode !== MATCH_EXISTS && (
|
||||
@ -1085,16 +1129,23 @@ function RuleConditionRow({
|
||||
return (
|
||||
<div className='flex flex-wrap items-center gap-2'>
|
||||
<Select
|
||||
items={[
|
||||
{ value: SOURCE_PARAM, label: t('Body param') },
|
||||
{ value: SOURCE_HEADER, label: t('Header') },
|
||||
{ value: SOURCE_TIME, label: t('Time') },
|
||||
]}
|
||||
value={condition.source}
|
||||
onValueChange={(v) => v !== null && handleSourceChange(v)}
|
||||
>
|
||||
<SelectTrigger className='w-28' size='sm'>
|
||||
<SelectValue>{sourceLabel}</SelectValue>
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value={SOURCE_PARAM}>{t('Body param')}</SelectItem>
|
||||
<SelectItem value={SOURCE_HEADER}>{t('Header')}</SelectItem>
|
||||
<SelectItem value={SOURCE_TIME}>{t('Time')}</SelectItem>
|
||||
<SelectContent alignItemWithTrigger={false}>
|
||||
<SelectGroup>
|
||||
<SelectItem value={SOURCE_PARAM}>{t('Body param')}</SelectItem>
|
||||
<SelectItem value={SOURCE_HEADER}>{t('Header')}</SelectItem>
|
||||
<SelectItem value={SOURCE_TIME}>{t('Time')}</SelectItem>
|
||||
</SelectGroup>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
{condition.source === SOURCE_TIME
|
||||
@ -1705,15 +1756,21 @@ export const TieredPricingEditor = memo(function TieredPricingEditor({
|
||||
<div className='flex items-center justify-between gap-2'>
|
||||
<Label className='text-xs'>{t('Editor mode')}</Label>
|
||||
<Select
|
||||
items={[
|
||||
{ value: 'visual', label: t('Visual editor') },
|
||||
{ value: 'raw', label: t('Expression editor') },
|
||||
]}
|
||||
value={editorMode}
|
||||
onValueChange={(value) => handleModeChange(value as EditorMode)}
|
||||
>
|
||||
<SelectTrigger className='w-44' size='sm'>
|
||||
<SelectValue />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value='visual'>{t('Visual editor')}</SelectItem>
|
||||
<SelectItem value='raw'>{t('Expression editor')}</SelectItem>
|
||||
<SelectContent alignItemWithTrigger={false}>
|
||||
<SelectGroup>
|
||||
<SelectItem value='visual'>{t('Visual editor')}</SelectItem>
|
||||
<SelectItem value='raw'>{t('Expression editor')}</SelectItem>
|
||||
</SelectGroup>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
|
||||
@ -11,6 +11,7 @@ import { Input } from '@/components/ui/input'
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectGroup,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
@ -212,6 +213,13 @@ export function UpstreamRatioSyncTable({
|
||||
/>
|
||||
</div>
|
||||
<Select
|
||||
items={[
|
||||
{ value: '__all__', label: t('All Types') },
|
||||
...RATIO_TYPE_OPTIONS.map((option) => ({
|
||||
value: option.value,
|
||||
label: t(option.label),
|
||||
})),
|
||||
]}
|
||||
value={ratioTypeFilter}
|
||||
onValueChange={(v) => v !== null && setRatioTypeFilter(v)}
|
||||
disabled={isDisabled}
|
||||
@ -219,13 +227,15 @@ export function UpstreamRatioSyncTable({
|
||||
<SelectTrigger className='w-full sm:w-56'>
|
||||
<SelectValue placeholder={t('Filter by price field')} />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value='__all__'>{t('All Types')}</SelectItem>
|
||||
{RATIO_TYPE_OPTIONS.map((option) => (
|
||||
<SelectItem key={option.value} value={option.value}>
|
||||
{t(option.label)}
|
||||
</SelectItem>
|
||||
))}
|
||||
<SelectContent alignItemWithTrigger={false}>
|
||||
<SelectGroup>
|
||||
<SelectItem value='__all__'>{t('All Types')}</SelectItem>
|
||||
{RATIO_TYPE_OPTIONS.map((option) => (
|
||||
<SelectItem key={option.value} value={option.value}>
|
||||
{t(option.label)}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectGroup>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
|
||||
@ -18,6 +18,7 @@ import { Input } from '@/components/ui/input'
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectGroup,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
@ -242,6 +243,16 @@ export function SSRFSection({ defaultValues }: SSRFSectionProps) {
|
||||
<FormItem>
|
||||
<FormLabel>{t('Domain Filter Mode')}</FormLabel>
|
||||
<Select
|
||||
items={[
|
||||
{
|
||||
value: 'false',
|
||||
label: t('Blacklist (Block listed domains)'),
|
||||
},
|
||||
{
|
||||
value: 'true',
|
||||
label: t('Whitelist (Only allow listed domains)'),
|
||||
},
|
||||
]}
|
||||
onValueChange={(value) => field.onChange(value === 'true')}
|
||||
value={field.value ? 'true' : 'false'}
|
||||
>
|
||||
@ -250,13 +261,15 @@ export function SSRFSection({ defaultValues }: SSRFSectionProps) {
|
||||
<SelectValue />
|
||||
</SelectTrigger>
|
||||
</FormControl>
|
||||
<SelectContent>
|
||||
<SelectItem value='false'>
|
||||
{t('Blacklist (Block listed domains)')}
|
||||
</SelectItem>
|
||||
<SelectItem value='true'>
|
||||
{t('Whitelist (Only allow listed domains)')}
|
||||
</SelectItem>
|
||||
<SelectContent alignItemWithTrigger={false}>
|
||||
<SelectGroup>
|
||||
<SelectItem value='false'>
|
||||
{t('Blacklist (Block listed domains)')}
|
||||
</SelectItem>
|
||||
<SelectItem value='true'>
|
||||
{t('Whitelist (Only allow listed domains)')}
|
||||
</SelectItem>
|
||||
</SelectGroup>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<FormDescription>
|
||||
@ -295,6 +308,16 @@ export function SSRFSection({ defaultValues }: SSRFSectionProps) {
|
||||
<FormItem>
|
||||
<FormLabel>{t('IP Filter Mode')}</FormLabel>
|
||||
<Select
|
||||
items={[
|
||||
{
|
||||
value: 'false',
|
||||
label: t('Blacklist (Block listed IPs)'),
|
||||
},
|
||||
{
|
||||
value: 'true',
|
||||
label: t('Whitelist (Only allow listed IPs)'),
|
||||
},
|
||||
]}
|
||||
onValueChange={(value) => field.onChange(value === 'true')}
|
||||
value={field.value ? 'true' : 'false'}
|
||||
>
|
||||
@ -303,13 +326,15 @@ export function SSRFSection({ defaultValues }: SSRFSectionProps) {
|
||||
<SelectValue />
|
||||
</SelectTrigger>
|
||||
</FormControl>
|
||||
<SelectContent>
|
||||
<SelectItem value='false'>
|
||||
{t('Blacklist (Block listed IPs)')}
|
||||
</SelectItem>
|
||||
<SelectItem value='true'>
|
||||
{t('Whitelist (Only allow listed IPs)')}
|
||||
</SelectItem>
|
||||
<SelectContent alignItemWithTrigger={false}>
|
||||
<SelectGroup>
|
||||
<SelectItem value='false'>
|
||||
{t('Blacklist (Block listed IPs)')}
|
||||
</SelectItem>
|
||||
<SelectItem value='true'>
|
||||
{t('Whitelist (Only allow listed IPs)')}
|
||||
</SelectItem>
|
||||
</SelectGroup>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<FormDescription>
|
||||
|
||||
@ -7,18 +7,19 @@ import { useTranslation } from 'react-i18next'
|
||||
import { useIsAdmin } from '@/hooks/use-admin'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { Input } from '@/components/ui/input'
|
||||
import {
|
||||
Tooltip,
|
||||
TooltipContent,
|
||||
TooltipTrigger,
|
||||
} from '@/components/ui/tooltip'
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectGroup,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
} from '@/components/ui/select'
|
||||
import {
|
||||
Tooltip,
|
||||
TooltipContent,
|
||||
TooltipTrigger,
|
||||
} from '@/components/ui/tooltip'
|
||||
import { DataTableToolbar } from '@/components/data-table'
|
||||
import { LOG_TYPES } from '../constants'
|
||||
import { buildSearchParams } from '../lib/filter'
|
||||
@ -207,6 +208,13 @@ export function CommonLogsFilterBar<TData>(
|
||||
className={inputClass}
|
||||
/>
|
||||
<Select
|
||||
items={[
|
||||
{ value: 'all', label: t('All Types') },
|
||||
...LOG_TYPES.map((type) => ({
|
||||
value: String(type.value),
|
||||
label: t(type.label),
|
||||
})),
|
||||
]}
|
||||
value={logType}
|
||||
onValueChange={(value) => {
|
||||
setLogType(value !== null && isLogTypeValue(value) ? value : '')
|
||||
@ -215,13 +223,15 @@ export function CommonLogsFilterBar<TData>(
|
||||
<SelectTrigger className={inputClass}>
|
||||
<SelectValue placeholder={t('All Types')} />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value='all'>{t('All Types')}</SelectItem>
|
||||
{LOG_TYPES.map((type) => (
|
||||
<SelectItem key={type.value} value={String(type.value)}>
|
||||
{t(type.label)}
|
||||
</SelectItem>
|
||||
))}
|
||||
<SelectContent alignItemWithTrigger={false}>
|
||||
<SelectGroup>
|
||||
<SelectItem value='all'>{t('All Types')}</SelectItem>
|
||||
{LOG_TYPES.map((type) => (
|
||||
<SelectItem key={type.value} value={String(type.value)}>
|
||||
{t(type.label)}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectGroup>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</>
|
||||
|
||||
@ -22,6 +22,7 @@ import { Label } from '@/components/ui/label'
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectGroup,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
@ -201,6 +202,10 @@ export function UsersMutateDrawer({
|
||||
<FormItem>
|
||||
<FormLabel>{t('Role')}</FormLabel>
|
||||
<Select
|
||||
items={[
|
||||
{ value: '1', label: t('Common User') },
|
||||
{ value: '10', label: t('Admin') },
|
||||
]}
|
||||
onValueChange={(value) =>
|
||||
value !== null && field.onChange(parseInt(value))
|
||||
}
|
||||
@ -211,11 +216,13 @@ export function UsersMutateDrawer({
|
||||
<SelectValue placeholder={t('Select a role')} />
|
||||
</SelectTrigger>
|
||||
</FormControl>
|
||||
<SelectContent>
|
||||
<SelectItem value='1'>
|
||||
{t('Common User')}
|
||||
</SelectItem>
|
||||
<SelectItem value='10'>{t('Admin')}</SelectItem>
|
||||
<SelectContent alignItemWithTrigger={false}>
|
||||
<SelectGroup>
|
||||
<SelectItem value='1'>
|
||||
{t('Common User')}
|
||||
</SelectItem>
|
||||
<SelectItem value='10'>{t('Admin')}</SelectItem>
|
||||
</SelectGroup>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<FormDescription>
|
||||
@ -282,6 +289,12 @@ export function UsersMutateDrawer({
|
||||
<FormItem>
|
||||
<FormLabel>{t('Group')}</FormLabel>
|
||||
<Select
|
||||
items={[
|
||||
...groups.map((group) => ({
|
||||
value: group,
|
||||
label: group,
|
||||
})),
|
||||
]}
|
||||
onValueChange={field.onChange}
|
||||
value={field.value}
|
||||
>
|
||||
@ -290,12 +303,14 @@ export function UsersMutateDrawer({
|
||||
<SelectValue placeholder={t('Select a group')} />
|
||||
</SelectTrigger>
|
||||
</FormControl>
|
||||
<SelectContent>
|
||||
{groups.map((group) => (
|
||||
<SelectItem key={group} value={group}>
|
||||
{group}
|
||||
</SelectItem>
|
||||
))}
|
||||
<SelectContent alignItemWithTrigger={false}>
|
||||
<SelectGroup>
|
||||
{groups.map((group) => (
|
||||
<SelectItem key={group} value={group}>
|
||||
{group}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectGroup>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<FormMessage />
|
||||
|
||||
@ -28,6 +28,7 @@ import { ScrollArea } from '@/components/ui/scroll-area'
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectGroup,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
@ -104,6 +105,12 @@ export function BillingHistoryDialog({
|
||||
/>
|
||||
</div>
|
||||
<Select
|
||||
items={[
|
||||
{ value: '10', label: t('10 / page') },
|
||||
{ value: '20', label: t('20 / page') },
|
||||
{ value: '50', label: t('50 / page') },
|
||||
{ value: '100', label: t('100 / page') },
|
||||
]}
|
||||
value={pageSize.toString()}
|
||||
onValueChange={(value) =>
|
||||
value !== null && handlePageSizeChange(parseInt(value))
|
||||
@ -112,11 +119,13 @@ export function BillingHistoryDialog({
|
||||
<SelectTrigger className='h-9 w-[92px] sm:w-32'>
|
||||
<SelectValue />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value='10'>{t('10 / page')}</SelectItem>
|
||||
<SelectItem value='20'>{t('20 / page')}</SelectItem>
|
||||
<SelectItem value='50'>{t('50 / page')}</SelectItem>
|
||||
<SelectItem value='100'>{t('100 / page')}</SelectItem>
|
||||
<SelectContent alignItemWithTrigger={false}>
|
||||
<SelectGroup>
|
||||
<SelectItem value='10'>{t('10 / page')}</SelectItem>
|
||||
<SelectItem value='20'>{t('20 / page')}</SelectItem>
|
||||
<SelectItem value='50'>{t('50 / page')}</SelectItem>
|
||||
<SelectItem value='100'>{t('100 / page')}</SelectItem>
|
||||
</SelectGroup>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
|
||||
@ -10,6 +10,7 @@ import { Progress } from '@/components/ui/progress'
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectGroup,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
@ -276,6 +277,34 @@ export function SubscriptionPlansCard({
|
||||
</div>
|
||||
<div className='flex w-full items-center gap-2 sm:w-auto'>
|
||||
<Select
|
||||
items={[
|
||||
{
|
||||
value: 'subscription_first',
|
||||
label: (
|
||||
<>
|
||||
{getBillingPreferenceLabel('subscription_first', t)}
|
||||
{disablePref ? ` (${t('No Active')})` : ''}
|
||||
</>
|
||||
),
|
||||
},
|
||||
{
|
||||
value: 'wallet_first',
|
||||
label: getBillingPreferenceLabel('wallet_first', t),
|
||||
},
|
||||
{
|
||||
value: 'subscription_only',
|
||||
label: (
|
||||
<>
|
||||
{getBillingPreferenceLabel('subscription_only', t)}
|
||||
{disablePref ? ` (${t('No Active')})` : ''}
|
||||
</>
|
||||
),
|
||||
},
|
||||
{
|
||||
value: 'wallet_only',
|
||||
label: getBillingPreferenceLabel('wallet_only', t),
|
||||
},
|
||||
]}
|
||||
value={displayPref}
|
||||
onValueChange={(v) => v !== null && handlePreferenceChange(v)}
|
||||
>
|
||||
@ -284,21 +313,29 @@ export function SubscriptionPlansCard({
|
||||
{getBillingPreferenceLabel(displayPref, t)}
|
||||
</SelectValue>
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value='subscription_first' disabled={disablePref}>
|
||||
{getBillingPreferenceLabel('subscription_first', t)}
|
||||
{disablePref ? ` (${t('No Active')})` : ''}
|
||||
</SelectItem>
|
||||
<SelectItem value='wallet_first'>
|
||||
{getBillingPreferenceLabel('wallet_first', t)}
|
||||
</SelectItem>
|
||||
<SelectItem value='subscription_only' disabled={disablePref}>
|
||||
{getBillingPreferenceLabel('subscription_only', t)}
|
||||
{disablePref ? ` (${t('No Active')})` : ''}
|
||||
</SelectItem>
|
||||
<SelectItem value='wallet_only'>
|
||||
{getBillingPreferenceLabel('wallet_only', t)}
|
||||
</SelectItem>
|
||||
<SelectContent alignItemWithTrigger={false}>
|
||||
<SelectGroup>
|
||||
<SelectItem
|
||||
value='subscription_first'
|
||||
disabled={disablePref}
|
||||
>
|
||||
{getBillingPreferenceLabel('subscription_first', t)}
|
||||
{disablePref ? ` (${t('No Active')})` : ''}
|
||||
</SelectItem>
|
||||
<SelectItem value='wallet_first'>
|
||||
{getBillingPreferenceLabel('wallet_first', t)}
|
||||
</SelectItem>
|
||||
<SelectItem
|
||||
value='subscription_only'
|
||||
disabled={disablePref}
|
||||
>
|
||||
{getBillingPreferenceLabel('subscription_only', t)}
|
||||
{disablePref ? ` (${t('No Active')})` : ''}
|
||||
</SelectItem>
|
||||
<SelectItem value='wallet_only'>
|
||||
{getBillingPreferenceLabel('wallet_only', t)}
|
||||
</SelectItem>
|
||||
</SelectGroup>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<Button
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user