From b6d576b7b62ad6a38d45240cbe1120d55fd88cf7 Mon Sep 17 00:00:00 2001 From: Predrag Klepic <60631598+Klepic95@users.noreply.github.com> Date: Mon, 10 Jul 2023 09:14:14 +0200 Subject: [PATCH] [Query Copilot] Resource tree styling and New query button (#1519) * Styling implemented related with the work item * Sample container New query button implementation * Fixing related with the not rendering Sample Data * Fix race condition when rendering sample data resource tree * Remove export keyword for updateContextForSampleData * Copilot New Query should open Copilot tab * showing buttons in sample command bar --------- Co-authored-by: Predrag Klepic Co-authored-by: Victor Meng --- src/Explorer/ContextMenuButtonFactory.tsx | 16 ++++++++ .../Controls/Accordion/AccordionComponent.tsx | 8 +++- src/Explorer/Tree/ResourceTree.tsx | 12 +++++- src/Explorer/Tree/SampleDataTree.tsx | 37 ++++++++++++++++--- src/hooks/useKnockoutExplorer.ts | 11 +++--- 5 files changed, 70 insertions(+), 14 deletions(-) diff --git a/src/Explorer/ContextMenuButtonFactory.tsx b/src/Explorer/ContextMenuButtonFactory.tsx index 55d0e0917..2439a1691 100644 --- a/src/Explorer/ContextMenuButtonFactory.tsx +++ b/src/Explorer/ContextMenuButtonFactory.tsx @@ -1,3 +1,4 @@ +import { ReactTabKind, useTabs } from "hooks/useTabs"; import React from "react"; import AddCollectionIcon from "../../images/AddCollection.svg"; import AddSqlQueryIcon from "../../images/AddSqlQuery_16x16.svg"; @@ -140,6 +141,21 @@ export const createCollectionContextMenuButton = ( return items; }; +export const createSampleCollectionContextMenuButton = ( + selectedCollection: ViewModels.CollectionBase +): TreeNodeMenuItem[] => { + const items: TreeNodeMenuItem[] = []; + if (userContext.apiType === "SQL") { + items.push({ + iconSrc: AddSqlQueryIcon, + onClick: () => selectedCollection && useTabs.getState().openAndActivateReactTab(ReactTabKind.QueryCopilot), + label: "New SQL Query", + }); + } + + return items; +}; + export const createStoreProcedureContextMenuItems = ( container: Explorer, storedProcedure: StoredProcedure diff --git a/src/Explorer/Controls/Accordion/AccordionComponent.tsx b/src/Explorer/Controls/Accordion/AccordionComponent.tsx index ae858a6fa..cf70acc91 100644 --- a/src/Explorer/Controls/Accordion/AccordionComponent.tsx +++ b/src/Explorer/Controls/Accordion/AccordionComponent.tsx @@ -25,6 +25,7 @@ export class AccordionComponent extends React.Component export interface AccordionItemComponentProps { title: string; isExpanded?: boolean; + styles?: React.CSSProperties; } interface AccordionItemComponentState { @@ -53,6 +54,7 @@ export class AccordionItemComponent extends React.Component
@@ -60,7 +62,11 @@ export class AccordionItemComponent extends React.Component
- + {this.props.children}
diff --git a/src/Explorer/Tree/ResourceTree.tsx b/src/Explorer/Tree/ResourceTree.tsx index 6a25f742b..d9036fc79 100644 --- a/src/Explorer/Tree/ResourceTree.tsx +++ b/src/Explorer/Tree/ResourceTree.tsx @@ -790,7 +790,11 @@ export const ResourceTree: React.FC = ({ container }: Resourc {!isNotebookEnabled && isSampleDataEnabled && ( <> - + @@ -804,7 +808,11 @@ export const ResourceTree: React.FC = ({ container }: Resourc {isNotebookEnabled && isSampleDataEnabled && ( <> - + diff --git a/src/Explorer/Tree/SampleDataTree.tsx b/src/Explorer/Tree/SampleDataTree.tsx index 1b4ad7f5f..ca9a76cd3 100644 --- a/src/Explorer/Tree/SampleDataTree.tsx +++ b/src/Explorer/Tree/SampleDataTree.tsx @@ -1,7 +1,12 @@ +import { useCommandBar } from "Explorer/Menus/CommandBar/CommandBarComponentAdapter"; +import TabsBase from "Explorer/Tabs/TabsBase"; +import { useSelectedNode } from "Explorer/useSelectedNode"; +import { useTabs } from "hooks/useTabs"; import React, { useEffect, useState } from "react"; import CosmosDBIcon from "../../../images/Azure-Cosmos-DB.svg"; import CollectionIcon from "../../../images/tree-collection.svg"; import * as ViewModels from "../../Contracts/ViewModels"; +import * as ResourceTreeContextMenuButtonFactory from "../ContextMenuButtonFactory"; import { TreeComponent, TreeNode } from "../Controls/TreeComponent/TreeComponent"; export const SampleDataTree = ({ @@ -15,14 +20,36 @@ export const SampleDataTree = ({ if (sampleDataResourceTokenCollection) { const updatedSampleTree: TreeNode = { label: sampleDataResourceTokenCollection.databaseId, - isExpanded: true, + isExpanded: false, iconSrc: CosmosDBIcon, + className: "databaseHeader", children: [ { label: sampleDataResourceTokenCollection.id(), iconSrc: CollectionIcon, - isExpanded: true, - className: "collectionHeader", + isExpanded: false, + className: "dataResourceTree", + contextMenu: ResourceTreeContextMenuButtonFactory.createSampleCollectionContextMenuButton( + sampleDataResourceTokenCollection + ), + onClick: () => { + // Rewritten version of expandCollapseCollection + useSelectedNode.getState().setSelectedNode(sampleDataResourceTokenCollection); + useCommandBar.getState().setContextButtons([]); + useTabs().refreshActiveTab( + (tab: TabsBase) => + tab.collection?.id() === sampleDataResourceTokenCollection.id() && + tab.collection.databaseId === sampleDataResourceTokenCollection.databaseId + ); + }, + isSelected: () => + useSelectedNode + .getState() + .isDataNodeSelected( + sampleDataResourceTokenCollection.databaseId, + sampleDataResourceTokenCollection.id() + ), + onContextMenuOpen: () => useSelectedNode.getState().setSelectedNode(sampleDataResourceTokenCollection), children: [ { label: "Items", @@ -35,7 +62,5 @@ export const SampleDataTree = ({ } }, [sampleDataResourceTokenCollection]); - return ( - - ); + return ; }; diff --git a/src/hooks/useKnockoutExplorer.ts b/src/hooks/useKnockoutExplorer.ts index a87f61cba..5eebd408f 100644 --- a/src/hooks/useKnockoutExplorer.ts +++ b/src/hooks/useKnockoutExplorer.ts @@ -62,10 +62,6 @@ export function useKnockoutExplorer(platform: Platform): Explorer { setExplorer(explorer); } } - - if (userContext.features.enableCopilot) { - await updateContextForSampleData(); - } }; effect(); }, [platform]); @@ -73,6 +69,9 @@ export function useKnockoutExplorer(platform: Platform): Explorer { useEffect(() => { if (explorer) { applyExplorerBindings(explorer); + if (userContext.features.enableCopilot) { + updateContextForSampleData(explorer); + } } }, [explorer]); @@ -415,7 +414,7 @@ interface PortalMessage { inputs?: DataExplorerInputsFrame; } -async function updateContextForSampleData(): Promise { +async function updateContextForSampleData(explorer: Explorer): Promise { if (!userContext.features.enableCopilot) { return; } @@ -435,6 +434,8 @@ async function updateContextForSampleData(): Promise { const data: SampledataconnectionResponse = await response.json(); const sampleDataConnectionInfo = parseResourceTokenConnectionString(data.connectionString); updateUserContext({ sampleDataConnectionInfo }); + + await explorer.refreshSampleData(); } interface SampledataconnectionResponse {