fix: use shared tags field component

This commit is contained in:
Julian Sommer
2026-08-18 12:27:54 +10:00
parent d620569adb
commit 3a3740a6de
16 changed files with 29 additions and 106 deletions
+1 -1
View File
@@ -1,2 +1,2 @@
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/_id42.js","assets/compiler-runtime.js","assets/QueryClientProvider.js","assets/useQuery.js","assets/useBaseQuery.js","assets/useSuspenseQuery.js","assets/useNavigate.js","assets/useStore.js","assets/back-link.js","assets/link.js","assets/createLucideIcon.js","assets/cli-command-panel.js","assets/cluster-config.js","assets/hex-encoding.js","assets/check.js","assets/chevron-down.js","assets/copy.js","assets/button.js","assets/dist.js","assets/use-copy-to-clipboard.js","assets/input.js","assets/createBaseUIEventDetails.js","assets/useRegisterFieldControl.js","assets/useControlled.js","assets/field.js","assets/ec2.js","assets/queryOptions.js","assets/awsClient.js","assets/index.browser.js","assets/rds.js","assets/rds2.js","assets/useMutation.js","assets/rds3.js","assets/zod.js","assets/error-banner.js","assets/page-heading.js","assets/form-actions.js","assets/detail-row.js","assets/system-managed.js","assets/system-image-required.js","assets/rotate-cw.js","assets/triangle-alert.js","assets/picker-notice.js","assets/security-group-checkboxes.js","assets/select.js","assets/useValueAsRef.js","assets/useScrollLock.js","assets/useCompositeListItem.js","assets/tags-field-array.js","assets/plus.js","assets/trash-2.js"])))=>i.map(i=>d[i]);
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/_id42.js","assets/compiler-runtime.js","assets/QueryClientProvider.js","assets/useQuery.js","assets/useBaseQuery.js","assets/useSuspenseQuery.js","assets/useNavigate.js","assets/useStore.js","assets/back-link.js","assets/link.js","assets/createLucideIcon.js","assets/cli-command-panel.js","assets/cluster-config.js","assets/hex-encoding.js","assets/check.js","assets/chevron-down.js","assets/copy.js","assets/button.js","assets/dist.js","assets/use-copy-to-clipboard.js","assets/input.js","assets/createBaseUIEventDetails.js","assets/useRegisterFieldControl.js","assets/useControlled.js","assets/field.js","assets/ec2.js","assets/queryOptions.js","assets/awsClient.js","assets/index.browser.js","assets/rds.js","assets/rds2.js","assets/useMutation.js","assets/rds3.js","assets/zod.js","assets/error-banner.js","assets/page-heading.js","assets/form-actions.js","assets/detail-row.js","assets/system-managed.js","assets/tags-field-array.js","assets/plus.js","assets/trash-2.js","assets/system-image-required.js","assets/rotate-cw.js","assets/triangle-alert.js","assets/picker-notice.js","assets/security-group-checkboxes.js","assets/select.js","assets/useValueAsRef.js","assets/useScrollLock.js","assets/useCompositeListItem.js"])))=>i.map(i=>d[i]);
import{n as e,t}from"./lazyRouteComponent.js";import{rt as n}from"./cluster-config.js";import{o as r,w as i}from"./ec2.js";import{d as a,h as o,i as s,o as c}from"./rds3.js";var l=e(`/_auth/rds/(snapshots)/restore-db-instance-from-db-snapshot/$id`)({loader:async({context:e,params:t})=>{await Promise.all([e.queryClient.ensureQueryData(s(decodeURIComponent(t.id))),e.queryClient.ensureQueryData(c),e.queryClient.ensureQueryData(o),e.queryClient.ensureQueryData(a),e.queryClient.ensureQueryData(i),e.queryClient.ensureQueryData(r)])},head:({params:e})=>({meta:[{title:`Restore ${decodeURIComponent(e.id)} | RDS | Mulga`}]}),component:t(()=>n(()=>import(`./_id42.js`),__vite__mapDeps([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50])),`component`)});export{l as t};
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1,9 +1,8 @@
import type { Vpc } from "@aws-sdk/client-ec2"
import { Plus, Trash2 } from "lucide-react"
import type { UseFormReturn } from "react-hook-form"
import { Controller, useWatch } from "react-hook-form"
import { Button } from "@/components/ui/button"
import { TagsFieldArray } from "@/components/tags-field-array"
import {
Collapsible,
CollapsibleContent,
@@ -45,10 +44,8 @@ export function TargetGroupForm({
control,
register,
setValue,
getValues,
formState: { errors },
} = form
const tags = useWatch({ control, name: "tags" })
const protocol = useWatch({ control, name: "protocol" })
// Path + Matcher only apply to HTTP(S) health checks; L4 target groups (TCP/
// UDP/TLS) use a TCP health check that has neither.
@@ -277,41 +274,7 @@ export function TargetGroupForm({
</CollapsibleContent>
</Collapsible>
<Field>
<FieldTitle>Tags</FieldTitle>
<div className="space-y-2">
{tags.map((_, index) => (
<div className="flex items-center gap-2" key={index}>
<Input placeholder="Key" {...register(`tags.${index}.key`)} />
<Input placeholder="Value" {...register(`tags.${index}.value`)} />
<Button
onClick={() =>
setValue(
"tags",
getValues("tags").filter((__, i) => i !== index),
)
}
size="icon"
type="button"
variant="ghost"
>
<Trash2 className="size-3.5" />
</Button>
</div>
))}
<Button
onClick={() =>
setValue("tags", [...getValues("tags"), { key: "", value: "" }])
}
size="sm"
type="button"
variant="outline"
>
<Plus className="size-3.5" />
Add tag
</Button>
</div>
</Field>
<TagsFieldArray control={control} name="tags" />
</>
)
}
@@ -18,8 +18,8 @@ interface TagsFieldArrayProps<T extends FieldValues> {
name: ArrayPath<T>
}
// The key/value rows every RDS create form carries. Keyed by useFieldArray's
// own id so removing a row does not shuffle the values of the ones below it.
// The key/value tag rows a create form carries. Keyed by useFieldArray's own
// id so removing a row does not shuffle the values of the ones below it.
export function TagsFieldArray<T extends FieldValues>({
control,
name,
@@ -2,7 +2,6 @@ import type { Subnet, Vpc } from "@aws-sdk/client-ec2"
import { zodResolver } from "@hookform/resolvers/zod"
import { useSuspenseQuery } from "@tanstack/react-query"
import { useNavigate } from "@tanstack/react-router"
import { Plus, Trash2 } from "lucide-react"
import { useState } from "react"
import { Controller, useForm, useWatch } from "react-hook-form"
@@ -17,6 +16,7 @@ import { TargetGroupForm } from "@/components/elbv2/target-group-form"
import { ErrorBanner } from "@/components/error-banner"
import { FormActions } from "@/components/form-actions"
import { PageHeading } from "@/components/page-heading"
import { TagsFieldArray } from "@/components/tags-field-array"
import { Button } from "@/components/ui/button"
import { Field, FieldError, FieldTitle } from "@/components/ui/field"
import { Input } from "@/components/ui/input"
@@ -186,7 +186,6 @@ export function CreateLoadBalancerPage() {
const lbType = useWatch({ control, name: "type" })
const listenerProtocol = useWatch({ control, name: "listener.protocol" })
const tgMode = useWatch({ control, name: "listener.targetGroupMode" })
const tags = useWatch({ control, name: "tags" })
const isNlb = lbType === "network"
const isSecure = isSecureProtocol(listenerProtocol)
@@ -535,44 +534,7 @@ export function CreateLoadBalancerPage() {
</Field>
)}
<Field>
<FieldTitle>Tags</FieldTitle>
<div className="space-y-2">
{tags.map((_, index) => (
<div className="flex items-center gap-2" key={index}>
<Input placeholder="Key" {...register(`tags.${index}.key`)} />
<Input
placeholder="Value"
{...register(`tags.${index}.value`)}
/>
<Button
onClick={() =>
setValue(
"tags",
getValues("tags").filter((__, i) => i !== index),
)
}
size="icon"
type="button"
variant="ghost"
>
<Trash2 className="size-3.5" />
</Button>
</div>
))}
<Button
onClick={() =>
setValue("tags", [...getValues("tags"), { key: "", value: "" }])
}
size="sm"
type="button"
variant="outline"
>
<Plus className="size-3.5" />
Add tag
</Button>
</div>
</Field>
<TagsFieldArray control={control} name="tags" />
<div className="space-y-4 rounded-md border bg-card p-4">
<h2 className="text-sm font-semibold">
@@ -20,6 +20,7 @@ import { ErrorBanner } from "@/components/error-banner"
import { FormActions } from "@/components/form-actions"
import { PageHeading } from "@/components/page-heading"
import { SystemImageRequired } from "@/components/system-image-required"
import { TagsFieldArray } from "@/components/tags-field-array"
import {
Field,
FieldDescription,
@@ -68,7 +69,6 @@ import {
securityGroupIdsForVpc,
securityGroupsForVpc,
} from "../../-components/security-group-checkboxes"
import { TagsFieldArray } from "../../-components/tags-field-array"
// The retention the backend applies when a create names none.
const DEFAULT_BACKUP_RETENTION_DAYS = 7
@@ -13,6 +13,7 @@ import {
import { ErrorBanner } from "@/components/error-banner"
import { FormActions } from "@/components/form-actions"
import { PageHeading } from "@/components/page-heading"
import { TagsFieldArray } from "@/components/tags-field-array"
import {
Field,
FieldDescription,
@@ -34,8 +35,6 @@ import {
createDBParameterGroupSchema,
} from "@/types/rds"
import { TagsFieldArray } from "../../-components/tags-field-array"
export function CreateDBParameterGroupPage() {
const navigate = useNavigate()
const createGroup = useCreateDBParameterGroup()
@@ -3,6 +3,7 @@ import { useQuery } from "@tanstack/react-query"
import { useState } from "react"
import { useForm } from "react-hook-form"
import { TagsFieldArray } from "@/components/tags-field-array"
import {
AlertDialog,
AlertDialogContent,
@@ -35,7 +36,6 @@ import {
} from "@/types/rds"
import { PickerNoticeText, pickerNotice } from "../../-components/picker-notice"
import { TagsFieldArray } from "../../-components/tags-field-array"
interface CreateDBSnapshotDialogProps {
open: boolean
@@ -22,6 +22,7 @@ import { ErrorBanner } from "@/components/error-banner"
import { FormActions } from "@/components/form-actions"
import { PageHeading } from "@/components/page-heading"
import { SystemImageRequired } from "@/components/system-image-required"
import { TagsFieldArray } from "@/components/tags-field-array"
import {
Field,
FieldDescription,
@@ -61,7 +62,6 @@ import {
securityGroupIdsForVpc,
securityGroupsForVpc,
} from "../../-components/security-group-checkboxes"
import { TagsFieldArray } from "../../-components/tags-field-array"
interface Props {
dbSnapshotIdentifier: string
@@ -14,6 +14,7 @@ import {
import { ErrorBanner } from "@/components/error-banner"
import { FormActions } from "@/components/form-actions"
import { PageHeading } from "@/components/page-heading"
import { TagsFieldArray } from "@/components/tags-field-array"
import {
Field,
FieldDescription,
@@ -30,8 +31,6 @@ import {
MAX_SUBNETS_PER_GROUP,
} from "@/types/rds"
import { TagsFieldArray } from "../../-components/tags-field-array"
function subnetLabel(subnet: Subnet): string {
const name = getNameTag(subnet.Tags)
const parts = [subnet.CidrBlock, subnet.AvailabilityZone, name].filter(