From b28bac6bb742080f48b94924c9130c76d3c7e161 Mon Sep 17 00:00:00 2001 From: Naiyuan Qing <145280634+NevilleQingNY@users.noreply.github.com> Date: Wed, 1 Apr 2026 22:24:35 +0800 Subject: [PATCH] Revert "feat: add global issue search" --- .../(dashboard)/_components/app-sidebar.tsx | 32 ++-- apps/web/features/modals/registry.tsx | 3 - apps/web/features/modals/search-issues.tsx | 143 ------------------ apps/web/features/modals/store.ts | 2 +- apps/web/shared/api/client.ts | 1 - apps/web/shared/types/api.ts | 1 - server/internal/handler/issue.go | 5 - server/pkg/db/generated/issue.sql.go | 3 - server/pkg/db/queries/issue.sql | 1 - 9 files changed, 11 insertions(+), 180 deletions(-) delete mode 100644 apps/web/features/modals/search-issues.tsx diff --git a/apps/web/app/(dashboard)/_components/app-sidebar.tsx b/apps/web/app/(dashboard)/_components/app-sidebar.tsx index 123c1466..7657d039 100644 --- a/apps/web/app/(dashboard)/_components/app-sidebar.tsx +++ b/apps/web/app/(dashboard)/_components/app-sidebar.tsx @@ -15,7 +15,6 @@ import { BookOpenText, SquarePen, CircleUser, - Search, } from "lucide-react"; import { WorkspaceAvatar } from "@/features/workspace"; import { useIssueDraftStore } from "@/features/issues/stores/draft-store"; @@ -156,27 +155,16 @@ export function AppSidebar() { -
- - useModalStore.getState().open("search-issues")} - > - - - Search issues - - - useModalStore.getState().open("create-issue")} - > - - - - New issue - -
+ + useModalStore.getState().open("create-issue")} + > + + + + New issue + diff --git a/apps/web/features/modals/registry.tsx b/apps/web/features/modals/registry.tsx index 02b60c3d..faf2e63a 100644 --- a/apps/web/features/modals/registry.tsx +++ b/apps/web/features/modals/registry.tsx @@ -3,7 +3,6 @@ import { useModalStore } from "./store"; import { CreateWorkspaceModal } from "./create-workspace"; import { CreateIssueModal } from "./create-issue"; -import { SearchIssuesModal } from "./search-issues"; export function ModalRegistry() { const modal = useModalStore((s) => s.modal); @@ -15,8 +14,6 @@ export function ModalRegistry() { return ; case "create-issue": return ; - case "search-issues": - return ; default: return null; } diff --git a/apps/web/features/modals/search-issues.tsx b/apps/web/features/modals/search-issues.tsx deleted file mode 100644 index d8740591..00000000 --- a/apps/web/features/modals/search-issues.tsx +++ /dev/null @@ -1,143 +0,0 @@ -"use client"; - -import { useState, useEffect, useRef, useCallback } from "react"; -import { useRouter } from "next/navigation"; -import { - CommandDialog, - Command, - CommandInput, - CommandList, - CommandEmpty, - CommandGroup, - CommandItem, -} from "@/components/ui/command"; -import { Skeleton } from "@/components/ui/skeleton"; -import { StatusIcon } from "@/features/issues/components"; -import { api } from "@/shared/api"; -import type { Issue } from "@/shared/types"; - -function SearchSkeleton() { - return ( -
- {Array.from({ length: 5 }, (_, i) => ( -
- - - -
- ))} -
- ); -} - -export function SearchIssuesModal({ onClose }: { onClose: () => void }) { - const router = useRouter(); - const [query, setQuery] = useState(""); - const [results, setResults] = useState([]); - const [loading, setLoading] = useState(false); - const debounceRef = useRef>(null); - const composingRef = useRef(false); - - const search = useCallback(async (q: string) => { - if (!q.trim()) { - setResults([]); - setLoading(false); - return; - } - setLoading(true); - try { - const res = await api.listIssues({ search: q.trim(), limit: 20 }); - setResults(res.issues); - } catch { - setResults([]); - } finally { - setLoading(false); - } - }, []); - - const scheduleSearch = useCallback( - (q: string) => { - if (debounceRef.current) clearTimeout(debounceRef.current); - if (q.trim()) setLoading(true); - debounceRef.current = setTimeout(() => search(q), 300); - }, - [search] - ); - - useEffect(() => { - return () => { - if (debounceRef.current) clearTimeout(debounceRef.current); - }; - }, []); - - const handleValueChange = (value: string) => { - setQuery(value); - if (!composingRef.current) { - scheduleSearch(value); - } - }; - - const handleCompositionStart = () => { - composingRef.current = true; - }; - - const handleCompositionEnd = (e: React.CompositionEvent) => { - composingRef.current = false; - scheduleSearch((e.target as HTMLInputElement).value); - }; - - const handleSelect = (issue: Issue) => { - onClose(); - router.push(`/issues/${issue.id}`); - }; - - return ( - { - if (!open) onClose(); - }} - title="Search Issues" - description="Search issues by title" - className="top-[min(33%,12rem)]" - > - - - - {!query.trim() ? ( -
- Type to search issues by title -
- ) : loading ? ( - - ) : ( - <> - No issues found - - {results.map((issue) => ( - handleSelect(issue)} - > - - {issue.title} - - {issue.identifier} - - - ))} - - - )} -
-
-
- ); -} diff --git a/apps/web/features/modals/store.ts b/apps/web/features/modals/store.ts index 0a5a946d..f720be43 100644 --- a/apps/web/features/modals/store.ts +++ b/apps/web/features/modals/store.ts @@ -2,7 +2,7 @@ import { create } from "zustand"; -type ModalType = "create-workspace" | "create-issue" | "search-issues" | null; +type ModalType = "create-workspace" | "create-issue" | null; interface ModalStore { modal: ModalType; diff --git a/apps/web/shared/api/client.ts b/apps/web/shared/api/client.ts index 603be220..65004b34 100644 --- a/apps/web/shared/api/client.ts +++ b/apps/web/shared/api/client.ts @@ -163,7 +163,6 @@ export class ApiClient { if (params?.status) search.set("status", params.status); if (params?.priority) search.set("priority", params.priority); if (params?.assignee_id) search.set("assignee_id", params.assignee_id); - if (params?.search) search.set("search", params.search); return this.fetch(`/api/issues?${search}`); } diff --git a/apps/web/shared/types/api.ts b/apps/web/shared/types/api.ts index a06b3fdb..cdeeae4e 100644 --- a/apps/web/shared/types/api.ts +++ b/apps/web/shared/types/api.ts @@ -31,7 +31,6 @@ export interface ListIssuesParams { status?: IssueStatus; priority?: IssuePriority; assignee_id?: string; - search?: string; } export interface ListIssuesResponse { diff --git a/server/internal/handler/issue.go b/server/internal/handler/issue.go index 64123151..0c5a0d6a 100644 --- a/server/internal/handler/issue.go +++ b/server/internal/handler/issue.go @@ -99,10 +99,6 @@ func (h *Handler) ListIssues(w http.ResponseWriter, r *http.Request) { if a := r.URL.Query().Get("assignee_id"); a != "" { assigneeFilter = parseUUID(a) } - var searchFilter pgtype.Text - if s := r.URL.Query().Get("search"); s != "" { - searchFilter = pgtype.Text{String: s, Valid: true} - } issues, err := h.Queries.ListIssues(ctx, db.ListIssuesParams{ WorkspaceID: parseUUID(workspaceID), @@ -111,7 +107,6 @@ func (h *Handler) ListIssues(w http.ResponseWriter, r *http.Request) { Status: statusFilter, Priority: priorityFilter, AssigneeID: assigneeFilter, - Search: searchFilter, }) if err != nil { writeError(w, http.StatusInternalServerError, "failed to list issues") diff --git a/server/pkg/db/generated/issue.sql.go b/server/pkg/db/generated/issue.sql.go index 208a3800..f899eb6e 100644 --- a/server/pkg/db/generated/issue.sql.go +++ b/server/pkg/db/generated/issue.sql.go @@ -195,7 +195,6 @@ WHERE workspace_id = $1 AND ($4::text IS NULL OR status = $4) AND ($5::text IS NULL OR priority = $5) AND ($6::uuid IS NULL OR assignee_id = $6) - AND ($7::text IS NULL OR title ILIKE '%' || $7 || '%') ORDER BY position ASC, created_at DESC LIMIT $2 OFFSET $3 ` @@ -207,7 +206,6 @@ type ListIssuesParams struct { Status pgtype.Text `json:"status"` Priority pgtype.Text `json:"priority"` AssigneeID pgtype.UUID `json:"assignee_id"` - Search pgtype.Text `json:"search"` } func (q *Queries) ListIssues(ctx context.Context, arg ListIssuesParams) ([]Issue, error) { @@ -218,7 +216,6 @@ func (q *Queries) ListIssues(ctx context.Context, arg ListIssuesParams) ([]Issue arg.Status, arg.Priority, arg.AssigneeID, - arg.Search, ) if err != nil { return nil, err diff --git a/server/pkg/db/queries/issue.sql b/server/pkg/db/queries/issue.sql index 3082abab..edc229c3 100644 --- a/server/pkg/db/queries/issue.sql +++ b/server/pkg/db/queries/issue.sql @@ -4,7 +4,6 @@ WHERE workspace_id = $1 AND (sqlc.narg('status')::text IS NULL OR status = sqlc.narg('status')) AND (sqlc.narg('priority')::text IS NULL OR priority = sqlc.narg('priority')) AND (sqlc.narg('assignee_id')::uuid IS NULL OR assignee_id = sqlc.narg('assignee_id')) - AND (sqlc.narg('search')::text IS NULL OR title ILIKE '%' || sqlc.narg('search') || '%') ORDER BY position ASC, created_at DESC LIMIT $2 OFFSET $3;