diff --git a/ui/src/components/IssueProperties.tsx b/ui/src/components/IssueProperties.tsx index 053e8e424b..0e92861134 100644 --- a/ui/src/components/IssueProperties.tsx +++ b/ui/src/components/IssueProperties.tsx @@ -119,7 +119,7 @@ function PropertyPicker({ - + {children} diff --git a/ui/src/components/NewIssueDialog.tsx b/ui/src/components/NewIssueDialog.tsx index 727a54e650..a7afbfe165 100644 --- a/ui/src/components/NewIssueDialog.tsx +++ b/ui/src/components/NewIssueDialog.tsx @@ -306,6 +306,9 @@ export function NewIssueDialog() { // Popover states const [statusOpen, setStatusOpen] = useState(false); const [priorityOpen, setPriorityOpen] = useState(false); + const [labelsOpen, setLabelsOpen] = useState(false); + const [labelSearch, setLabelSearch] = useState(""); + const [selectedLabelIds, setSelectedLabelIds] = useState([]); const [moreOpen, setMoreOpen] = useState(false); const [companyOpen, setCompanyOpen] = useState(false); const descriptionEditorRef = useRef(null); @@ -324,6 +327,12 @@ export function NewIssueDialog() { queryFn: () => projectsApi.list(effectiveCompanyId!), enabled: !!effectiveCompanyId && newIssueOpen, }); + + const { data: labels } = useQuery({ + queryKey: queryKeys.issues.labels(effectiveCompanyId!), + queryFn: () => issuesApi.listLabels(effectiveCompanyId!), + enabled: !!effectiveCompanyId && newIssueOpen, + }); const { data: reusableExecutionWorkspaces } = useQuery({ queryKey: queryKeys.executionWorkspaces.list(effectiveCompanyId!, { projectId, @@ -675,6 +684,7 @@ export function NewIssueDialog() { ? { executionWorkspaceId: selectedExecutionWorkspaceId } : {}), ...(executionWorkspaceSettings ? { executionWorkspaceSettings } : {}), + ...(selectedLabelIds.length > 0 ? { labelIds: selectedLabelIds } : {}), }); } @@ -1392,11 +1402,51 @@ export function NewIssueDialog() { - {/* Labels chip (placeholder) */} - + {/* Labels chip */} + { setLabelsOpen(open); if (!open) setLabelSearch(""); }}> + + + + + setLabelSearch(e.target.value)} + autoFocus + /> +
+ {(labels ?? []) + .filter((l) => !labelSearch.trim() || l.name.toLowerCase().includes(labelSearch.toLowerCase())) + .map((label) => { + const selected = selectedLabelIds.includes(label.id); + return ( + + ); + })} + {(labels ?? []).length === 0 && ( +

No labels defined.

+ )} +
+
+