mirror of
https://github.com/QuantumNous/new-api.git
synced 2026-09-07 01:56:53 +00:00
perf(web): improve dialog sizing and footer layout
- migrate frontend dialogs to the shared footer API so actions stay separated from scrollable body content. - tune dialog dimensions for model analytics, prefill groups, billing history, channel model sync, and related workflows. - update channel terminology and dialog action translations across supported locales.
This commit is contained in:
+117
-123
@@ -22,14 +22,6 @@ import { useForm } from 'react-hook-form'
|
||||
import { zodResolver } from '@hookform/resolvers/zod'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogDescription,
|
||||
DialogFooter,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
} from '@/components/ui/dialog'
|
||||
import {
|
||||
Form,
|
||||
FormControl,
|
||||
@@ -40,6 +32,7 @@ import {
|
||||
FormMessage,
|
||||
} from '@/components/ui/form'
|
||||
import { Input } from '@/components/ui/input'
|
||||
import { Dialog } from '@/components/dialog'
|
||||
|
||||
const rateLimitDialogSchema = z.object({
|
||||
groupName: z.string().min(1, 'Group name is required'),
|
||||
@@ -55,6 +48,8 @@ const rateLimitDialogSchema = z.object({
|
||||
|
||||
type RateLimitDialogFormValues = z.infer<typeof rateLimitDialogSchema>
|
||||
|
||||
const RATE_LIMIT_FORM_ID = 'rate-limit-form'
|
||||
|
||||
export type RateLimitEntryData = {
|
||||
groupName: string
|
||||
maxRequests: number
|
||||
@@ -105,126 +100,125 @@ export function RateLimitDialog({
|
||||
}
|
||||
|
||||
return (
|
||||
<Dialog open={open} onOpenChange={onOpenChange}>
|
||||
<DialogContent className='sm:max-w-[500px]'>
|
||||
<DialogHeader>
|
||||
<DialogTitle>
|
||||
{isEditMode
|
||||
? t('Edit group rate limit')
|
||||
: t('Add group rate limit')}
|
||||
</DialogTitle>
|
||||
<DialogDescription>
|
||||
{t('Configure rate limiting rules for a specific user group.')}
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
|
||||
<Form {...form}>
|
||||
<form
|
||||
onSubmit={form.handleSubmit(handleSubmit)}
|
||||
className='space-y-4'
|
||||
<Dialog
|
||||
open={open}
|
||||
onOpenChange={onOpenChange}
|
||||
title={
|
||||
isEditMode ? t('Edit group rate limit') : t('Add group rate limit')
|
||||
}
|
||||
description={t(
|
||||
'Configure rate limiting rules for a specific user group.'
|
||||
)}
|
||||
contentClassName='sm:max-w-[500px]'
|
||||
contentHeight='auto'
|
||||
bodyClassName='space-y-4'
|
||||
footer={
|
||||
<>
|
||||
<Button
|
||||
type='button'
|
||||
variant='outline'
|
||||
onClick={() => onOpenChange(false)}
|
||||
>
|
||||
<FormField
|
||||
control={form.control}
|
||||
name='groupName'
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>{t('Group Name')}</FormLabel>
|
||||
<FormControl>
|
||||
{t('Cancel')}
|
||||
</Button>
|
||||
<Button type='submit' form={RATE_LIMIT_FORM_ID}>
|
||||
{isEditMode ? t('Update') : t('Add')}
|
||||
</Button>
|
||||
</>
|
||||
}
|
||||
>
|
||||
<Form {...form}>
|
||||
<form
|
||||
id={RATE_LIMIT_FORM_ID}
|
||||
onSubmit={form.handleSubmit(handleSubmit)}
|
||||
className='space-y-4'
|
||||
>
|
||||
<FormField
|
||||
control={form.control}
|
||||
name='groupName'
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>{t('Group Name')}</FormLabel>
|
||||
<FormControl>
|
||||
<Input
|
||||
placeholder={t('e.g., default, vip, premium')}
|
||||
{...field}
|
||||
disabled={isEditMode}
|
||||
/>
|
||||
</FormControl>
|
||||
<FormDescription>
|
||||
{isEditMode
|
||||
? t('Group name cannot be changed when editing.')
|
||||
: t('Unique identifier for this group.')}
|
||||
</FormDescription>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
|
||||
<FormField
|
||||
control={form.control}
|
||||
name='maxRequests'
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>{t('Max Requests (including failures)')}</FormLabel>
|
||||
<FormControl>
|
||||
<div className='flex items-center gap-2'>
|
||||
<Input
|
||||
placeholder={t('e.g., default, vip, premium')}
|
||||
type='number'
|
||||
min={0}
|
||||
max={2147483647}
|
||||
step={1}
|
||||
{...field}
|
||||
disabled={isEditMode}
|
||||
onChange={(e) =>
|
||||
field.onChange(parseInt(e.target.value) || 0)
|
||||
}
|
||||
/>
|
||||
</FormControl>
|
||||
<FormDescription>
|
||||
{isEditMode
|
||||
? t('Group name cannot be changed when editing.')
|
||||
: t('Unique identifier for this group.')}
|
||||
</FormDescription>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
<span className='text-muted-foreground text-sm'>
|
||||
{t('times')}
|
||||
</span>
|
||||
</div>
|
||||
</FormControl>
|
||||
<FormDescription>
|
||||
{t('Total requests allowed per period. 0 = unlimited.')}
|
||||
</FormDescription>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
|
||||
<FormField
|
||||
control={form.control}
|
||||
name='maxRequests'
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>
|
||||
{t('Max Requests (including failures)')}
|
||||
</FormLabel>
|
||||
<FormControl>
|
||||
<div className='flex items-center gap-2'>
|
||||
<Input
|
||||
type='number'
|
||||
min={0}
|
||||
max={2147483647}
|
||||
step={1}
|
||||
{...field}
|
||||
onChange={(e) =>
|
||||
field.onChange(parseInt(e.target.value) || 0)
|
||||
}
|
||||
/>
|
||||
<span className='text-muted-foreground text-sm'>
|
||||
{t('times')}
|
||||
</span>
|
||||
</div>
|
||||
</FormControl>
|
||||
<FormDescription>
|
||||
{t('Total requests allowed per period. 0 = unlimited.')}
|
||||
</FormDescription>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
|
||||
<FormField
|
||||
control={form.control}
|
||||
name='maxSuccess'
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>{t('Max Successful Requests')}</FormLabel>
|
||||
<FormControl>
|
||||
<div className='flex items-center gap-2'>
|
||||
<Input
|
||||
type='number'
|
||||
min={1}
|
||||
max={2147483647}
|
||||
step={1}
|
||||
{...field}
|
||||
onChange={(e) =>
|
||||
field.onChange(parseInt(e.target.value) || 1)
|
||||
}
|
||||
/>
|
||||
<span className='text-muted-foreground text-sm'>
|
||||
{t('times')}
|
||||
</span>
|
||||
</div>
|
||||
</FormControl>
|
||||
<FormDescription>
|
||||
{t('Only successful requests count toward this limit.')}
|
||||
</FormDescription>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
|
||||
<DialogFooter>
|
||||
<Button
|
||||
type='button'
|
||||
variant='outline'
|
||||
onClick={() => onOpenChange(false)}
|
||||
>
|
||||
{t('Cancel')}
|
||||
</Button>
|
||||
<Button type='submit'>
|
||||
{isEditMode ? t('Update') : t('Add')}
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
</form>
|
||||
</Form>
|
||||
</DialogContent>
|
||||
<FormField
|
||||
control={form.control}
|
||||
name='maxSuccess'
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>{t('Max Successful Requests')}</FormLabel>
|
||||
<FormControl>
|
||||
<div className='flex items-center gap-2'>
|
||||
<Input
|
||||
type='number'
|
||||
min={1}
|
||||
max={2147483647}
|
||||
step={1}
|
||||
{...field}
|
||||
onChange={(e) =>
|
||||
field.onChange(parseInt(e.target.value) || 1)
|
||||
}
|
||||
/>
|
||||
<span className='text-muted-foreground text-sm'>
|
||||
{t('times')}
|
||||
</span>
|
||||
</div>
|
||||
</FormControl>
|
||||
<FormDescription>
|
||||
{t('Only successful requests count toward this limit.')}
|
||||
</FormDescription>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</form>
|
||||
</Form>
|
||||
</Dialog>
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user