From 1e5fbd378f7515ee25813c78eb60935bb9207ecd Mon Sep 17 00:00:00 2001 From: Tim Raderschad Date: Wed, 7 Aug 2024 23:03:51 +0200 Subject: [PATCH] feat(web): add flag search --- apps/web/package.json | 1 + apps/web/src/components/FlagPage.tsx | 89 +++++++++++++++++++--------- pnpm-lock.yaml | 8 +++ 3 files changed, 69 insertions(+), 29 deletions(-) diff --git a/apps/web/package.json b/apps/web/package.json index ba8d2ccf..0a3cb602 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -81,6 +81,7 @@ "csstype": "^3.1.2", "dayjs": "^1.11.7", "framer-motion": "^10.12.7", + "fuse.js": "^7.0.0", "hono": "^4.2.7", "immer": "^9.0.21", "ioredis": "^5.4.1", diff --git a/apps/web/src/components/FlagPage.tsx b/apps/web/src/components/FlagPage.tsx index 6e71a2a2..e8cc50ab 100644 --- a/apps/web/src/components/FlagPage.tsx +++ b/apps/web/src/components/FlagPage.tsx @@ -14,8 +14,8 @@ import { Modal } from "components/Modal"; import { Tooltip, TooltipContent, TooltipTrigger } from "components/Tooltip"; import { Input } from "components/ui/input"; import { useProjectId } from "lib/hooks/useProjectId"; -import { EditIcon, FileEditIcon, TrashIcon } from "lucide-react"; -import { useState } from "react"; +import { EditIcon, FileEditIcon, Search, TrashIcon } from "lucide-react"; +import { useMemo, useState } from "react"; import { toast } from "react-hot-toast"; import { AiOutlinePlus } from "react-icons/ai"; import { BiInfoCircle } from "react-icons/bi"; @@ -23,6 +23,7 @@ import { BsThreeDotsVertical } from "react-icons/bs"; import type { appRouter } from "server/trpc/router/_app"; import { trpc } from "utils/trpc"; import { Button } from "./ui/button"; +import Fuse from "fuse.js"; const EditTitleModal = ({ flagId, @@ -165,11 +166,28 @@ export const FeatureFlagPageContent = ({ action: "editDescription" | "editName" | "delete"; } | null>(null); + const [flags, setFlags] = useState(data.flags); + const [isCreateEnvironmentModalOpen, setIsCreateEnvironmentModalOpen] = useState(false); const projectId = useProjectId(); + const fuse = useMemo( + () => new Fuse(data.flags, { keys: ["name"] }), + [data.flags] + ); + + const onSearch = (query: string) => { + if (!query) { + setFlags(data.flags); + return; + } + + const results = fuse.search(query); + setFlags(results.map((result) => result.item)); + }; + const activeFlag = data.flags.find((flag) => flag.id === activeFlagInfo?.id); if (data.environments.length === 0) @@ -199,36 +217,49 @@ export const FeatureFlagPageContent = ({ return ( <>
-
- - - setIsCreateFlagModalOpen(false)} - projectId={projectId} - isRemoteConfig={type === "Remote Config"} - /> - setIsCreateEnvironmentModalOpen(false)} - projectId={projectId} - /> +
+
+
+ + onSearch(e.target.value)} + /> +
+
+
+ + + setIsCreateFlagModalOpen(false)} + projectId={projectId} + isRemoteConfig={type === "Remote Config"} + /> + setIsCreateEnvironmentModalOpen(false)} + projectId={projectId} + /> +
- {data.flags.map((currentFlag) => { + {flags.map((currentFlag) => { return (
=10'} + dev: false + /gauge@3.0.2: resolution: {integrity: sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==} engines: {node: '>=10'}