quality / commitlint (push) Skipped
CD / update-wiki (push) Successful in 6s
quality / changes (push) Successful in 5s
quality / api (push) Skipped
quality / docker-check (push) Skipped
quality / web (push) Successful in 52s
CD / quality (push) Successful in 1m1s
CD / publish (push) Successful in 1m36s
- Added a common FQDN input field in the ServiceEditSheet to streamline domain management for services. - Updated binding handling to synchronize the common domain across service bindings. - Improved the ServiceKanbanCard to display both common domain and IP addresses for better visibility. - Refactored the ServiceFqdnList to support customizable text classes and added a new ServiceIpList component for IP display. This commit enhances the user experience by simplifying domain management and improving the display of service information.
150 lines
4.2 KiB
TypeScript
150 lines
4.2 KiB
TypeScript
import { useEffect } from 'react'
|
|
import { useForm, Controller } from 'react-hook-form'
|
|
import { zodResolver } from '@hookform/resolvers/zod'
|
|
import {
|
|
createServiceGroupSchema,
|
|
type CreateServiceGroupInput,
|
|
type ServiceGroup,
|
|
} from '@/lib/schemas'
|
|
import type { z } from 'zod'
|
|
import { FormSheet } from '@/components/form-sheet'
|
|
import { FormFieldSimple } from '@/components/form-field'
|
|
import { LoadingButton } from '@/components/loading-button'
|
|
import { AppFieldGroup } from '@/components/app-field'
|
|
import { AppInput } from '@/components/app-input'
|
|
import {
|
|
Select,
|
|
SelectContent,
|
|
SelectItem,
|
|
SelectTrigger,
|
|
SelectValue,
|
|
} from '@cfdm/ui/components/select'
|
|
|
|
const groupTypes = [
|
|
{ value: 'vpn', label: 'VPN' },
|
|
{ value: 'network', label: 'Сеть' },
|
|
{ value: 'internet', label: 'Интернет' },
|
|
{ value: 'bgp', label: 'BGP' },
|
|
{ value: 'custom', label: 'Другое' },
|
|
] as const
|
|
|
|
type ServiceGroupFormValues = z.input<typeof createServiceGroupSchema>
|
|
|
|
interface ServiceGroupEditSheetProps {
|
|
mode: 'create' | 'edit'
|
|
group: ServiceGroup | null
|
|
open: boolean
|
|
isSaving: boolean
|
|
onOpenChange: (open: boolean) => void
|
|
onCreate?: (body: CreateServiceGroupInput) => void
|
|
onSave?: (id: number, body: CreateServiceGroupInput) => void
|
|
}
|
|
|
|
export function ServiceGroupEditSheet({
|
|
mode,
|
|
group,
|
|
open,
|
|
isSaving,
|
|
onOpenChange,
|
|
onCreate,
|
|
onSave,
|
|
}: ServiceGroupEditSheetProps) {
|
|
const form = useForm<ServiceGroupFormValues>({
|
|
resolver: zodResolver(createServiceGroupSchema),
|
|
defaultValues: {
|
|
name: '',
|
|
type: 'custom',
|
|
domain: null,
|
|
},
|
|
})
|
|
|
|
useEffect(() => {
|
|
if (!open) return
|
|
if (mode === 'edit' && group) {
|
|
form.reset({
|
|
name: group.name,
|
|
type: group.type,
|
|
domain: null,
|
|
})
|
|
} else {
|
|
form.reset({ name: '', type: 'custom', domain: null })
|
|
}
|
|
}, [open, mode, group, form])
|
|
|
|
function handleSubmit(values: ServiceGroupFormValues) {
|
|
const body: CreateServiceGroupInput = {
|
|
name: values.name,
|
|
type: values.type ?? 'custom',
|
|
icon: values.icon,
|
|
domain: null,
|
|
}
|
|
if (mode === 'create') {
|
|
onCreate?.(body)
|
|
} else if (group) {
|
|
onSave?.(group.id, body)
|
|
}
|
|
}
|
|
|
|
return (
|
|
<FormSheet<ServiceGroupFormValues>
|
|
open={open}
|
|
onOpenChange={onOpenChange}
|
|
title={mode === 'create' ? 'Новая группа сервисов' : 'Редактировать группу'}
|
|
description="Группа нужна только для сортировки каталога. Общий домен и IP задаются у каждого сервиса."
|
|
form={form}
|
|
onSubmit={handleSubmit}
|
|
contentClassName="gap-6"
|
|
footer={
|
|
<LoadingButton
|
|
type="submit"
|
|
className="w-full"
|
|
isLoading={isSaving}
|
|
loadingLabel="Сохранение…"
|
|
>
|
|
{mode === 'create' ? 'Создать' : 'Сохранить'}
|
|
</LoadingButton>
|
|
}
|
|
>
|
|
<AppFieldGroup>
|
|
<FormFieldSimple
|
|
label="Название"
|
|
htmlFor="group-name"
|
|
error={form.formState.errors.name}
|
|
>
|
|
<AppInput
|
|
id="group-name"
|
|
placeholder="VPN"
|
|
{...form.register('name')}
|
|
aria-invalid={!!form.formState.errors.name}
|
|
/>
|
|
</FormFieldSimple>
|
|
<FormFieldSimple label="Тип" htmlFor="group-type">
|
|
<Controller
|
|
control={form.control}
|
|
name="type"
|
|
render={({ field }) => (
|
|
<Select
|
|
value={field.value}
|
|
onValueChange={(value) =>
|
|
field.onChange(value as CreateServiceGroupInput['type'])
|
|
}
|
|
>
|
|
<SelectTrigger id="group-type">
|
|
<SelectValue placeholder="Выберите тип" />
|
|
</SelectTrigger>
|
|
<SelectContent>
|
|
{groupTypes.map((item) => (
|
|
<SelectItem key={item.value} value={item.value}>
|
|
{item.label}
|
|
</SelectItem>
|
|
))}
|
|
</SelectContent>
|
|
</Select>
|
|
)}
|
|
/>
|
|
</FormFieldSimple>
|
|
</AppFieldGroup>
|
|
</FormSheet>
|
|
)
|
|
}
|