refactor: Simplify HealthCheckConfigFields component structure and enhance layout by integrating className prop for better styling flexibility, while maintaining functionality for load balancing and health check configurations
Build, Test, and Push CFDM Docker Image / test (push) Successful in 4m9s
Build, Test, and Push CFDM Docker Image / build-and-push (push) Successful in 2m18s
Build, Test, and Push CFDM Docker Image / update-wiki (push) Successful in 5s
Build, Test, and Push CFDM Docker Image / create-release (push) Has been skipped
Build, Test, and Push CFDM Docker Image / test (push) Successful in 4m9s
Build, Test, and Push CFDM Docker Image / build-and-push (push) Successful in 2m18s
Build, Test, and Push CFDM Docker Image / update-wiki (push) Successful in 5s
Build, Test, and Push CFDM Docker Image / create-release (push) Has been skipped
This commit is contained in:
@@ -10,6 +10,7 @@ import {
|
|||||||
} from '@cfdm/ui/components/select'
|
} from '@cfdm/ui/components/select'
|
||||||
import { Switch } from '@cfdm/ui/components/switch'
|
import { Switch } from '@cfdm/ui/components/switch'
|
||||||
import { Label } from '@cfdm/ui/components/label'
|
import { Label } from '@cfdm/ui/components/label'
|
||||||
|
import { cn } from '@cfdm/ui/lib/utils'
|
||||||
|
|
||||||
export type LbMode = 'round_robin' | 'failover' | 'weighted'
|
export type LbMode = 'round_robin' | 'failover' | 'weighted'
|
||||||
export type HealthCheckType = 'tcp' | 'http'
|
export type HealthCheckType = 'tcp' | 'http'
|
||||||
@@ -46,6 +47,7 @@ interface HealthCheckConfigFieldsProps {
|
|||||||
lbModeOptions?: { value: string; label: string }[]
|
lbModeOptions?: { value: string; label: string }[]
|
||||||
idPrefix?: string
|
idPrefix?: string
|
||||||
showLbMode?: boolean
|
showLbMode?: boolean
|
||||||
|
className?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export function HealthCheckConfigFields({
|
export function HealthCheckConfigFields({
|
||||||
@@ -55,13 +57,16 @@ export function HealthCheckConfigFields({
|
|||||||
lbModeOptions = defaultLbModeOptions,
|
lbModeOptions = defaultLbModeOptions,
|
||||||
idPrefix = 'health',
|
idPrefix = 'health',
|
||||||
showLbMode = true,
|
showLbMode = true,
|
||||||
|
className,
|
||||||
}: HealthCheckConfigFieldsProps) {
|
}: HealthCheckConfigFieldsProps) {
|
||||||
function patch(next: Partial<LbAndHealthConfig>) {
|
function patch(next: Partial<LbAndHealthConfig>) {
|
||||||
onChange({ ...value, ...next })
|
onChange({ ...value, ...next })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const isHttp = value.type === 'http'
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<AppFieldGroup>
|
<div className={cn('flex flex-col gap-4', className)}>
|
||||||
{showLbMode && (
|
{showLbMode && (
|
||||||
<FormFieldSimple label={lbModeLabel} htmlFor={`${idPrefix}-lb-mode`}>
|
<FormFieldSimple label={lbModeLabel} htmlFor={`${idPrefix}-lb-mode`}>
|
||||||
<Select
|
<Select
|
||||||
@@ -95,99 +100,115 @@ export function HealthCheckConfigFields({
|
|||||||
</div>
|
</div>
|
||||||
</FormFieldSimple>
|
</FormFieldSimple>
|
||||||
|
|
||||||
<FormFieldSimple label="Тип проверки" htmlFor={`${idPrefix}-type`}>
|
{value.enabled && (
|
||||||
<Select
|
<div className="rounded-md border border-border bg-muted/30 p-4">
|
||||||
value={value.type}
|
<p className="mb-3 text-sm font-medium text-foreground">
|
||||||
onValueChange={(v) => patch({ type: (v ?? 'tcp') as HealthCheckType })}
|
Параметры проверки
|
||||||
>
|
</p>
|
||||||
<SelectTrigger id={`${idPrefix}-type`} className="w-full">
|
<AppFieldGroup>
|
||||||
<SelectValue placeholder="Тип" />
|
<FormFieldSimple label="Тип проверки" htmlFor={`${idPrefix}-type`}>
|
||||||
</SelectTrigger>
|
<Select
|
||||||
<SelectContent>
|
value={value.type}
|
||||||
{healthCheckTypes.map((item) => (
|
onValueChange={(v) => patch({ type: (v ?? 'tcp') as HealthCheckType })}
|
||||||
<SelectItem key={item.value} value={item.value}>
|
>
|
||||||
{item.label}
|
<SelectTrigger id={`${idPrefix}-type`} className="w-full">
|
||||||
</SelectItem>
|
<SelectValue placeholder="Тип" />
|
||||||
))}
|
</SelectTrigger>
|
||||||
</SelectContent>
|
<SelectContent>
|
||||||
</Select>
|
{healthCheckTypes.map((item) => (
|
||||||
</FormFieldSimple>
|
<SelectItem key={item.value} value={item.value}>
|
||||||
|
{item.label}
|
||||||
|
</SelectItem>
|
||||||
|
))}
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
</FormFieldSimple>
|
||||||
|
|
||||||
<FormFieldSimple label="Порт" htmlFor={`${idPrefix}-port`}>
|
<FormFieldSimple label="Порт" htmlFor={`${idPrefix}-port`}>
|
||||||
<AppInput
|
<AppInput
|
||||||
id={`${idPrefix}-port`}
|
id={`${idPrefix}-port`}
|
||||||
type="number"
|
type="number"
|
||||||
inputMode="numeric"
|
inputMode="numeric"
|
||||||
placeholder="80"
|
placeholder="80"
|
||||||
value={value.port ?? ''}
|
value={value.port ?? ''}
|
||||||
onChange={(e) =>
|
onChange={(e) =>
|
||||||
patch({ port: e.target.value === '' ? null : Number(e.target.value) })
|
patch({ port: e.target.value === '' ? null : Number(e.target.value) })
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
</FormFieldSimple>
|
</FormFieldSimple>
|
||||||
|
|
||||||
<FormFieldSimple label="HTTP path (для типа HTTP)" htmlFor={`${idPrefix}-path`}>
|
{isHttp && (
|
||||||
<AppInput
|
<FormFieldSimple
|
||||||
id={`${idPrefix}-path`}
|
label="HTTP path"
|
||||||
placeholder="/health"
|
htmlFor={`${idPrefix}-path`}
|
||||||
value={value.path ?? ''}
|
>
|
||||||
onChange={(e) =>
|
<AppInput
|
||||||
patch({ path: e.target.value === '' ? null : e.target.value })
|
id={`${idPrefix}-path`}
|
||||||
}
|
placeholder="/health"
|
||||||
/>
|
value={value.path ?? ''}
|
||||||
</FormFieldSimple>
|
onChange={(e) =>
|
||||||
|
patch({ path: e.target.value === '' ? null : e.target.value })
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</FormFieldSimple>
|
||||||
|
)}
|
||||||
|
|
||||||
<FormFieldSimple
|
{isHttp && (
|
||||||
label="Ожидаемый HTTP-статус"
|
<FormFieldSimple
|
||||||
htmlFor={`${idPrefix}-status`}
|
label="Ожидаемый HTTP-статус"
|
||||||
>
|
htmlFor={`${idPrefix}-status`}
|
||||||
<AppInput
|
>
|
||||||
id={`${idPrefix}-status`}
|
<AppInput
|
||||||
type="number"
|
id={`${idPrefix}-status`}
|
||||||
inputMode="numeric"
|
type="number"
|
||||||
placeholder="200"
|
inputMode="numeric"
|
||||||
value={value.expected_status ?? ''}
|
placeholder="200"
|
||||||
onChange={(e) =>
|
value={value.expected_status ?? ''}
|
||||||
patch({
|
onChange={(e) =>
|
||||||
expected_status:
|
patch({
|
||||||
e.target.value === '' ? null : Number(e.target.value),
|
expected_status:
|
||||||
})
|
e.target.value === '' ? null : Number(e.target.value),
|
||||||
}
|
})
|
||||||
/>
|
}
|
||||||
</FormFieldSimple>
|
/>
|
||||||
|
</FormFieldSimple>
|
||||||
|
)}
|
||||||
|
|
||||||
<div className="grid grid-cols-2 gap-4">
|
<div className="grid grid-cols-2 gap-4">
|
||||||
<FormFieldSimple label="Интервал, сек" htmlFor={`${idPrefix}-interval`}>
|
<FormFieldSimple label="Интервал, сек" htmlFor={`${idPrefix}-interval`}>
|
||||||
<AppInput
|
<AppInput
|
||||||
id={`${idPrefix}-interval`}
|
id={`${idPrefix}-interval`}
|
||||||
type="number"
|
type="number"
|
||||||
inputMode="numeric"
|
inputMode="numeric"
|
||||||
placeholder="30"
|
placeholder="30"
|
||||||
value={value.interval_sec}
|
value={value.interval_sec}
|
||||||
onChange={(e) =>
|
onChange={(e) =>
|
||||||
patch({
|
patch({
|
||||||
interval_sec:
|
interval_sec:
|
||||||
e.target.value === '' ? 30 : Number(e.target.value),
|
e.target.value === '' ? 30 : Number(e.target.value),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
</FormFieldSimple>
|
</FormFieldSimple>
|
||||||
<FormFieldSimple label="Таймаут, мс" htmlFor={`${idPrefix}-timeout`}>
|
<FormFieldSimple label="Таймаут, мс" htmlFor={`${idPrefix}-timeout`}>
|
||||||
<AppInput
|
<AppInput
|
||||||
id={`${idPrefix}-timeout`}
|
id={`${idPrefix}-timeout`}
|
||||||
type="number"
|
type="number"
|
||||||
inputMode="numeric"
|
inputMode="numeric"
|
||||||
placeholder="3000"
|
placeholder="3000"
|
||||||
value={value.timeout_ms}
|
value={value.timeout_ms}
|
||||||
onChange={(e) =>
|
onChange={(e) =>
|
||||||
patch({
|
patch({
|
||||||
timeout_ms:
|
timeout_ms:
|
||||||
e.target.value === '' ? 3000 : Number(e.target.value),
|
e.target.value === '' ? 3000 : Number(e.target.value),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
</FormFieldSimple>
|
</FormFieldSimple>
|
||||||
</div>
|
</div>
|
||||||
</AppFieldGroup>
|
</AppFieldGroup>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -295,12 +295,6 @@ export function ServiceEditSheet({
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleBindingLbModeChange(index: number, lbMode: LbMode) {
|
|
||||||
setBindings((current) =>
|
|
||||||
current.map((item, i) => (i === index ? { ...item, lb_mode: lbMode } : item)),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
function handleBindingMetaChange(
|
function handleBindingMetaChange(
|
||||||
index: number,
|
index: number,
|
||||||
ip: string,
|
ip: string,
|
||||||
@@ -604,54 +598,29 @@ export function ServiceEditSheet({
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
{showLbBlock && (
|
{showLbBlock && (
|
||||||
<Accordion>
|
<Accordion defaultValue={[`lb-${index}`]}>
|
||||||
<AccordionItem value={`lb-${index}`}>
|
<AccordionItem value={`lb-${index}`}>
|
||||||
<AccordionTrigger>
|
<AccordionTrigger>
|
||||||
Балансировка и Health-check (multi-A)
|
Балансировка и Health-check (multi-A)
|
||||||
</AccordionTrigger>
|
</AccordionTrigger>
|
||||||
<AccordionContent>
|
<AccordionContent>
|
||||||
<AppFieldGroup>
|
<HealthCheckConfigFields
|
||||||
<AppField>
|
value={{
|
||||||
<AppFieldLabel htmlFor={`binding-lb-mode-${index}`}>
|
lb_mode: binding.lb_mode,
|
||||||
Режим балансировки
|
enabled: binding.health.enabled,
|
||||||
</AppFieldLabel>
|
type: binding.health.type,
|
||||||
<Select
|
port: binding.health.port,
|
||||||
value={binding.lb_mode}
|
path: binding.health.path,
|
||||||
onValueChange={(value) =>
|
expected_status: binding.health.expected_status,
|
||||||
handleBindingLbModeChange(
|
interval_sec: binding.health.interval_sec,
|
||||||
index,
|
timeout_ms: binding.health.timeout_ms,
|
||||||
(value ?? 'round_robin') as LbMode,
|
}}
|
||||||
)
|
onChange={(next) =>
|
||||||
}
|
handleBindingHealthChange(index, next)
|
||||||
>
|
}
|
||||||
<SelectTrigger id={`binding-lb-mode-${index}`} className="w-full">
|
lbModeLabel="Режим балансировки"
|
||||||
<SelectValue />
|
idPrefix={`binding-${index}-health`}
|
||||||
</SelectTrigger>
|
/>
|
||||||
<SelectContent>
|
|
||||||
<SelectItem value="round_robin">Round Robin</SelectItem>
|
|
||||||
<SelectItem value="failover">Failover (приоритет)</SelectItem>
|
|
||||||
<SelectItem value="weighted">Weighted (веса)</SelectItem>
|
|
||||||
</SelectContent>
|
|
||||||
</Select>
|
|
||||||
</AppField>
|
|
||||||
<HealthCheckConfigFields
|
|
||||||
value={{
|
|
||||||
lb_mode: binding.lb_mode,
|
|
||||||
enabled: binding.health.enabled,
|
|
||||||
type: binding.health.type,
|
|
||||||
port: binding.health.port,
|
|
||||||
path: binding.health.path,
|
|
||||||
expected_status: binding.health.expected_status,
|
|
||||||
interval_sec: binding.health.interval_sec,
|
|
||||||
timeout_ms: binding.health.timeout_ms,
|
|
||||||
}}
|
|
||||||
onChange={(next) =>
|
|
||||||
handleBindingHealthChange(index, next)
|
|
||||||
}
|
|
||||||
showLbMode={false}
|
|
||||||
idPrefix={`binding-${index}-health`}
|
|
||||||
/>
|
|
||||||
</AppFieldGroup>
|
|
||||||
</AccordionContent>
|
</AccordionContent>
|
||||||
</AccordionItem>
|
</AccordionItem>
|
||||||
</Accordion>
|
</Accordion>
|
||||||
|
|||||||
@@ -29,7 +29,6 @@ import {
|
|||||||
AccordionItem,
|
AccordionItem,
|
||||||
AccordionTrigger,
|
AccordionTrigger,
|
||||||
} from '@cfdm/ui/components/accordion'
|
} from '@cfdm/ui/components/accordion'
|
||||||
import { Separator } from '@cfdm/ui/components/separator'
|
|
||||||
|
|
||||||
const groupTypes = [
|
const groupTypes = [
|
||||||
{ value: 'vpn', label: 'VPN' },
|
{ value: 'vpn', label: 'VPN' },
|
||||||
@@ -201,22 +200,19 @@ export function ServiceGroupEditSheet({
|
|||||||
</AppFieldGroup>
|
</AppFieldGroup>
|
||||||
|
|
||||||
{hasDomain && (
|
{hasDomain && (
|
||||||
<>
|
<Accordion defaultValue={['lb-health']}>
|
||||||
<Separator />
|
<AccordionItem value="lb-health">
|
||||||
<Accordion>
|
<AccordionTrigger>Балансировка и Health-check</AccordionTrigger>
|
||||||
<AccordionItem value="lb-health">
|
<AccordionContent>
|
||||||
<AccordionTrigger>Балансировка и Health-check</AccordionTrigger>
|
<HealthCheckConfigFields
|
||||||
<AccordionContent>
|
value={lbHealth}
|
||||||
<HealthCheckConfigFields
|
onChange={setLbHealth}
|
||||||
value={lbHealth}
|
lbModeLabel="Режим балансировки общего домена"
|
||||||
onChange={setLbHealth}
|
idPrefix="group-lb-health"
|
||||||
lbModeLabel="Режим балансировки общего домена"
|
/>
|
||||||
idPrefix="group-lb-health"
|
</AccordionContent>
|
||||||
/>
|
</AccordionItem>
|
||||||
</AccordionContent>
|
</Accordion>
|
||||||
</AccordionItem>
|
|
||||||
</Accordion>
|
|
||||||
</>
|
|
||||||
)}
|
)}
|
||||||
</FormSheet>
|
</FormSheet>
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user