From 0ea7de7d31d3a958a60e318be198960bf66de5c0 Mon Sep 17 00:00:00 2001 From: andwati Date: Tue, 18 Aug 2026 14:18:39 +0300 Subject: [PATCH] fix: assign tags created from the project dialog The tag dialog's form is nested inside the project dialog's form in the React tree, and React propagates events along the React tree rather than the DOM tree, so submitting the tag form also submitted the project form. The project was created immediately with no tags and the dialog closed before more than one tag could be picked. Stop propagation in the tag form's onSubmit, and select the new tag in the selector so it is included when the project is saved. Fixes #5117 --- .../dashboard/settings/tags/handle-tag.tsx | 23 ++++++++++++++++--- .../components/shared/tag-selector.tsx | 8 ++++++- 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/apps/dokploy/components/dashboard/settings/tags/handle-tag.tsx b/apps/dokploy/components/dashboard/settings/tags/handle-tag.tsx index 343e0f93b..bb26ce863 100644 --- a/apps/dokploy/components/dashboard/settings/tags/handle-tag.tsx +++ b/apps/dokploy/components/dashboard/settings/tags/handle-tag.tsx @@ -53,9 +53,14 @@ type Tag = z.infer; interface HandleTagProps { tagId?: string; + /** + * Called with the new tag's id after it is created, so callers embedding + * this dialog (e.g. the tag selector) can select the tag right away. + */ + onCreated?: (tagId: string) => void; } -export const HandleTag = ({ tagId }: HandleTagProps) => { +export const HandleTag = ({ tagId, onCreated }: HandleTagProps) => { const utils = api.useUtils(); const [isOpen, setIsOpen] = useState(false); const colorInputRef = useRef(null); @@ -101,8 +106,11 @@ export const HandleTag = ({ tagId }: HandleTagProps) => { color: data.color, tagId: tagId || "", }) - .then(async () => { + .then(async (result) => { await utils.tag.all.invalidate(); + if (!tagId && result?.tagId) { + onCreated?.(result.tagId); + } toast.success(tagId ? "Tag Updated" : "Tag Created"); setIsOpen(false); form.reset(); @@ -139,9 +147,18 @@ export const HandleTag = ({ tagId }: HandleTagProps) => { {isError && {error?.message}}
+ {/* + * This dialog can be rendered inside another form (e.g. the tag + * selector in the project dialog). React propagates events through the + * React tree, not the DOM tree, so without stopPropagation submitting + * this form would also submit the outer one. + */} { + e.stopPropagation(); + form.handleSubmit(onSubmit)(e); + }} className="grid w-full gap-4" >
- + { + if (!selectedTags.includes(tagId)) { + onTagsChange([...selectedTags, tagId]); + } + }} + />