From ab219d5a3f8f230fdf1ffa8aba0621cffd1f57e4 Mon Sep 17 00:00:00 2001 From: nishthaAhujaa Date: Fri, 2 Jan 2026 15:53:32 +0530 Subject: [PATCH] implemented search bar --- src/Explorer/Tree/ResourceTree.tsx | 45 +++++++++++++++++--------- src/Explorer/Tree/treeNodeUtil.test.ts | 9 +++--- src/Explorer/Tree/treeNodeUtil.tsx | 8 ++++- src/Explorer/useDatabases.ts | 4 +++ 4 files changed, 45 insertions(+), 21 deletions(-) diff --git a/src/Explorer/Tree/ResourceTree.tsx b/src/Explorer/Tree/ResourceTree.tsx index 2405be01e..9b87187f9 100644 --- a/src/Explorer/Tree/ResourceTree.tsx +++ b/src/Explorer/Tree/ResourceTree.tsx @@ -1,5 +1,5 @@ -import { Tree, TreeItemValue, TreeOpenChangeData, TreeOpenChangeEvent } from "@fluentui/react-components"; -import { Home16Regular } from "@fluentui/react-icons"; +import { Input, Tree, TreeItemValue, TreeOpenChangeData, TreeOpenChangeEvent } from "@fluentui/react-components"; +import { Home16Regular, Search20Regular } from "@fluentui/react-icons"; import { AuthType } from "AuthType"; import { useTreeStyles } from "Explorer/Controls/TreeComponent/Styles"; import { TreeNode, TreeNodeComponent } from "Explorer/Controls/TreeComponent/TreeNodeComponent"; @@ -55,6 +55,8 @@ export const ResourceTree: React.FC = ({ explorer }: Resource sampleDataResourceTokenCollection: state.sampleDataResourceTokenCollection, })); const databasesFetchedSuccessfully = useDatabases((state) => state.databasesFetchedSuccessfully); + const searchText = useDatabases((state) => state.searchText); + const setSearchText = useDatabases((state) => state.setSearchText); const { isCopilotEnabled, isCopilotSampleDBEnabled } = useQueryCopilot((state) => ({ isCopilotEnabled: state.copilotEnabled, isCopilotSampleDBEnabled: state.copilotSampleDBEnabled, @@ -63,8 +65,8 @@ export const ResourceTree: React.FC = ({ explorer }: Resource const databaseTreeNodes = useMemo(() => { return userContext.authType === AuthType.ResourceToken ? createResourceTokenTreeNodes(resourceTokenCollection) - : createDatabaseTreeNodes(explorer, isNotebookEnabled, databases, refreshActiveTab); - }, [resourceTokenCollection, databases, isNotebookEnabled, refreshActiveTab]); + : createDatabaseTreeNodes(explorer, isNotebookEnabled, databases, refreshActiveTab, searchText); + }, [resourceTokenCollection, databases, isNotebookEnabled, refreshActiveTab, searchText]); const isSampleDataEnabled = isCopilotEnabled && @@ -81,19 +83,19 @@ export const ResourceTree: React.FC = ({ explorer }: Resource const headerNodes: TreeNode[] = isFabricMirrored() ? [] : [ - { - id: "home", - iconSrc: , - label: "Home", - isSelected: () => - useSelectedNode.getState().selectedNode === undefined && - useTabs.getState().activeReactTab === ReactTabKind.Home, - onClick: () => { - useSelectedNode.getState().setSelectedNode(undefined); - useTabs.getState().openAndActivateReactTab(ReactTabKind.Home); - }, + { + id: "home", + iconSrc: , + label: "Home", + isSelected: () => + useSelectedNode.getState().selectedNode === undefined && + useTabs.getState().activeReactTab === ReactTabKind.Home, + onClick: () => { + useSelectedNode.getState().setSelectedNode(undefined); + useTabs.getState().openAndActivateReactTab(ReactTabKind.Home); }, - ]; + }, + ]; const rootNodes: TreeNode[] = useMemo(() => { if (sampleDataNodes.length > 0) { @@ -154,6 +156,17 @@ export const ResourceTree: React.FC = ({ explorer }: Resource return (
+ {userContext.authType !== AuthType.ResourceToken && databases.length > 0 && ( +
+ setSearchText(data?.value || "")} + size="small" + contentBefore={} + /> +
+ )} { }, } as never, }); - nodes = createDatabaseTreeNodes(explorer, false, useDatabases.getState().databases, refreshActiveTab); + nodes = createDatabaseTreeNodes(explorer, false, useDatabases.getState().databases, refreshActiveTab, ""); }); it("creates expected tree", () => { @@ -445,6 +445,7 @@ describe("createDatabaseTreeNodes", () => { isNotebookEnabled, useDatabases.getState().databases, refreshActiveTab, + "", ); expect(nodes).toMatchSnapshot(); }, @@ -455,7 +456,7 @@ describe("createDatabaseTreeNodes", () => { // The goal is to cover some key behaviors like loading child nodes, opening tabs/side panels, etc. it("adds new collections to database as they appear", () => { - const nodes = createDatabaseTreeNodes(explorer, false, useDatabases.getState().databases, refreshActiveTab); + const nodes = createDatabaseTreeNodes(explorer, false, useDatabases.getState().databases, refreshActiveTab, ""); const giganticDbNode = nodes.find((node) => node.label === giganticDb.id()); expect(giganticDbNode).toBeDefined(); expect(giganticDbNode.children.map((node) => node.label)).toStrictEqual(["schemaCollection", "load more"]); @@ -487,7 +488,7 @@ describe("createDatabaseTreeNodes", () => { }, } as unknown as DataModels.DatabaseAccount, }); - nodes = createDatabaseTreeNodes(explorer, false, useDatabases.getState().databases, refreshActiveTab); + nodes = createDatabaseTreeNodes(explorer, false, useDatabases.getState().databases, refreshActiveTab, ""); standardDbNode = nodes.find((node) => node.label === standardDb.id()); sharedDbNode = nodes.find((node) => node.label === sharedDb.id()); giganticDbNode = nodes.find((node) => node.label === giganticDb.id()); @@ -642,7 +643,7 @@ describe("createDatabaseTreeNodes", () => { setup(); // Rebuild the nodes after changing the user/config context. - nodes = createDatabaseTreeNodes(explorer, false, useDatabases.getState().databases, refreshActiveTab); + nodes = createDatabaseTreeNodes(explorer, false, useDatabases.getState().databases, refreshActiveTab, ""); standardDbNode = nodes.find((node) => node.label === standardDb.id()); standardCollectionNode = standardDbNode.children.find((node) => node.label === standardCollection.id()); diff --git a/src/Explorer/Tree/treeNodeUtil.tsx b/src/Explorer/Tree/treeNodeUtil.tsx index 04eafed3f..63aefcd28 100644 --- a/src/Explorer/Tree/treeNodeUtil.tsx +++ b/src/Explorer/Tree/treeNodeUtil.tsx @@ -131,8 +131,14 @@ export const createDatabaseTreeNodes = ( isNotebookEnabled: boolean, databases: ViewModels.Database[], refreshActiveTab: (comparator: (tab: TabsBase) => boolean) => void, + searchText = "", ): TreeNode[] => { - const databaseTreeNodes: TreeNode[] = databases.map((database: ViewModels.Database) => { + // Filter databases based on search text + const filteredDatabases = searchText + ? databases.filter((db) => db.id().toLowerCase().includes(searchText.toLowerCase())) + : databases; + + const databaseTreeNodes: TreeNode[] = filteredDatabases.map((database: ViewModels.Database) => { const buildDatabaseChildNodes = (databaseNode: TreeNode) => { databaseNode.children = []; if (database.isDatabaseShared() && configContext.platform !== Platform.Fabric) { diff --git a/src/Explorer/useDatabases.ts b/src/Explorer/useDatabases.ts index b6420647e..3a5a98469 100644 --- a/src/Explorer/useDatabases.ts +++ b/src/Explorer/useDatabases.ts @@ -10,6 +10,8 @@ interface DatabasesState { resourceTokenCollection: ViewModels.CollectionBase; sampleDataResourceTokenCollection: ViewModels.CollectionBase; databasesFetchedSuccessfully: boolean; // Track if last database fetch was successful + searchText: string; + setSearchText: (searchText: string) => void; updateDatabase: (database: ViewModels.Database) => void; addDatabases: (databases: ViewModels.Database[]) => void; deleteDatabase: (database: ViewModels.Database) => void; @@ -32,6 +34,8 @@ export const useDatabases: UseStore = create((set, get) => ({ resourceTokenCollection: undefined, sampleDataResourceTokenCollection: undefined, databasesFetchedSuccessfully: false, + searchText: "", + setSearchText: (searchText: string) => set({ searchText }), updateDatabase: (updatedDatabase: ViewModels.Database) => set((state) => { const updatedDatabases = state.databases.map((database: ViewModels.Database) => {