From b875407d49679a54b9f4f13477de2e44f203e94e Mon Sep 17 00:00:00 2001 From: Steve Faulkner Date: Fri, 28 May 2021 15:20:59 -0500 Subject: [PATCH] Pure React Command Bar (#828) --- src/Contracts/ViewModels.ts | 2 - .../Settings/SettingsComponent.test.tsx | 1 - .../Controls/Settings/SettingsComponent.tsx | 5 +- .../SettingsComponent.test.tsx.snap | 24 --- src/Explorer/Explorer.tsx | 19 +-- .../CommandBar/CommandBarComponentAdapter.tsx | 147 +++++++----------- .../GitHubReposPanel.test.tsx.snap | 6 - .../StringInputPane.test.tsx.snap | 6 - ...eteDatabaseConfirmationPanel.test.tsx.snap | 6 - src/Explorer/Tabs/DocumentsTab.test.ts | 7 - src/Explorer/Tabs/QueryTab.test.ts | 2 - src/Explorer/Tabs/TabsBase.ts | 3 +- src/Explorer/Tabs/TabsManager.test.ts | 2 - src/Explorer/Tree/Collection.ts | 14 +- src/Explorer/Tree/Database.ts | 1 - src/Explorer/Tree/ResourceTokenCollection.ts | 9 +- .../Tree/ResourceTreeAdapter.test.tsx | 11 +- src/Explorer/Tree/ResourceTreeAdapter.tsx | 5 +- ...sourceTreeAdapterForResourceToken.test.tsx | 10 +- .../ResourceTreeAdapterForResourceToken.tsx | 15 +- src/Explorer/Tree/StoredProcedure.ts | 2 - src/Explorer/Tree/Trigger.ts | 2 - src/Explorer/Tree/UserDefinedFunction.ts | 2 - src/Main.tsx | 3 +- 24 files changed, 93 insertions(+), 211 deletions(-) diff --git a/src/Contracts/ViewModels.ts b/src/Contracts/ViewModels.ts index 25df44c7f..c44a86041 100644 --- a/src/Contracts/ViewModels.ts +++ b/src/Contracts/ViewModels.ts @@ -5,7 +5,6 @@ import { TriggerDefinition, UserDefinedFunctionDefinition, } from "@azure/cosmos"; -import { CommandButtonComponentProps } from "../Explorer/Controls/CommandButton/CommandButtonComponent"; import Explorer from "../Explorer/Explorer"; import { ConsoleData } from "../Explorer/Menus/NotificationConsole/NotificationConsoleComponent"; import { CassandraTableKey, CassandraTableKeys } from "../Explorer/Tables/TableDataClient"; @@ -277,7 +276,6 @@ export interface TabOptions { title: string; tabPath: string; hashLocation: string; - onUpdateTabsButtons: (buttons: CommandButtonComponentProps[]) => void; isTabsContentExpanded?: ko.Observable; onLoadStartKey?: number; diff --git a/src/Explorer/Controls/Settings/SettingsComponent.test.tsx b/src/Explorer/Controls/Settings/SettingsComponent.test.tsx index 33a7ca84d..e4cee955c 100644 --- a/src/Explorer/Controls/Settings/SettingsComponent.test.tsx +++ b/src/Explorer/Controls/Settings/SettingsComponent.test.tsx @@ -39,7 +39,6 @@ describe("SettingsComponent", () => { tabPath: "", node: undefined, hashLocation: "settings", - onUpdateTabsButtons: undefined, }), }; diff --git a/src/Explorer/Controls/Settings/SettingsComponent.tsx b/src/Explorer/Controls/Settings/SettingsComponent.tsx index 2559c17a6..f2ba989ff 100644 --- a/src/Explorer/Controls/Settings/SettingsComponent.tsx +++ b/src/Explorer/Controls/Settings/SettingsComponent.tsx @@ -18,6 +18,7 @@ import { MongoDBCollectionResource, MongoIndex } from "../../../Utils/arm/genera import * as AutoPilotUtils from "../../../Utils/AutoPilotUtils"; import { CommandButtonComponentProps } from "../../Controls/CommandButton/CommandButtonComponent"; import Explorer from "../../Explorer"; +import { useCommandBar } from "../../Menus/CommandBar/CommandBarComponentAdapter"; import { SettingsTabV2 } from "../../Tabs/SettingsTabV2"; import "./SettingsComponent.less"; import { mongoIndexingPolicyAADError } from "./SettingsRenderUtils"; @@ -222,13 +223,13 @@ export class SettingsComponent extends React.Component { if (tabs.length === 0) { this.selectedNode(undefined); - this.onUpdateTabsButtons([]); + useCommandBar.getState().setContextButtons([]); } }); @@ -322,8 +318,6 @@ export default class Explorer { break; } - this.commandBarComponentAdapter = new CommandBarComponentAdapter(this); - this._initSettings(); TelemetryProcessor.traceSuccess( @@ -786,10 +780,6 @@ export default class Explorer { ); } - public onUpdateTabsButtons(buttons: CommandButtonComponentProps[]): void { - this.commandBarComponentAdapter.onUpdateTabsButtons(buttons); - } - private refreshAndExpandNewDatabases(newDatabases: ViewModels.Database[]): Q.Promise { // we reload collections for all databases so the resource tree reflects any collection-level changes // i.e addition of stored procedures, etc. @@ -1081,7 +1071,6 @@ export default class Explorer { hashLocation: "notebooks", isTabsContentExpanded: ko.observable(true), onLoadStartKey: null, - onUpdateTabsButtons: this.onUpdateTabsButtons, container: this, notebookContentItem, }; @@ -1416,7 +1405,6 @@ export default class Explorer { hashLocation: `${hashLocation} ${index}`, isTabsContentExpanded: ko.observable(true), onLoadStartKey: null, - onUpdateTabsButtons: this.onUpdateTabsButtons, container: this, kind: kind, }); @@ -1447,7 +1435,6 @@ export default class Explorer { title: title, tabPath: title, hashLocation: hashLocation, - onUpdateTabsButtons: this.onUpdateTabsButtons, onLoadStartKey: null, isTabsContentExpanded: ko.observable(true), }, @@ -1478,7 +1465,7 @@ export default class Explorer { if (activeTab) { activeTab.onActivate(); // TODO only update tabs buttons? } else { - this.onUpdateTabsButtons([]); + useCommandBar.getState().setContextButtons([]); } } diff --git a/src/Explorer/Menus/CommandBar/CommandBarComponentAdapter.tsx b/src/Explorer/Menus/CommandBar/CommandBarComponentAdapter.tsx index d4e4c444d..efaa5a3dd 100644 --- a/src/Explorer/Menus/CommandBar/CommandBarComponentAdapter.tsx +++ b/src/Explorer/Menus/CommandBar/CommandBarComponentAdapter.tsx @@ -3,100 +3,71 @@ * If the component signals a change through the callback passed in the properties, it must render the React component when appropriate * and update any knockout observables passed from the parent. */ -import { CommandBar, ICommandBarItemProps } from "@fluentui/react"; -import * as ko from "knockout"; +import { CommandBar as FluentCommandBar, ICommandBarItemProps } from "@fluentui/react"; import * as React from "react"; -import { ReactAdapter } from "../../../Bindings/ReactBindingHandler"; +import create, { UseStore } from "zustand"; import { StyleConstants } from "../../../Common/Constants"; import * as ViewModels from "../../../Contracts/ViewModels"; -import { userContext } from "../../../UserContext"; +import { useObservable } from "../../../hooks/useObservable"; import { CommandButtonComponentProps } from "../../Controls/CommandButton/CommandButtonComponent"; import Explorer from "../../Explorer"; import * as CommandBarComponentButtonFactory from "./CommandBarComponentButtonFactory"; import * as CommandBarUtil from "./CommandBarUtil"; -export class CommandBarComponentAdapter implements ReactAdapter { - public parameters: ko.Observable; - public container: Explorer; - private tabsButtons: CommandButtonComponentProps[]; - private isNotebookTabActive: ko.Computed; - - constructor(container: Explorer) { - this.container = container; - this.tabsButtons = []; - this.isNotebookTabActive = ko.computed( - () => container.tabsManager.activeTab()?.tabKind === ViewModels.CollectionTabKind.NotebookV2 - ); - - // These are the parameters watched by the react binding that will trigger a renderComponent() if one of the ko mutates - const toWatch = [ - container.isDatabaseNodeOrNoneSelected, - container.isDatabaseNodeSelected, - container.isNoneSelected, - container.isResourceTokenCollectionNodeSelected, - container.isHostedDataExplorerEnabled, - container.isSynapseLinkUpdating, - userContext?.databaseAccount, - this.isNotebookTabActive, - container.isServerlessEnabled, - ]; - - ko.computed(() => ko.toJSON(toWatch)).subscribe(() => this.triggerRender()); - this.parameters = ko.observable(Date.now()); - } - - public onUpdateTabsButtons(buttons: CommandButtonComponentProps[]): void { - this.tabsButtons = buttons; - this.triggerRender(); - } - - public renderComponent(): JSX.Element { - const backgroundColor = StyleConstants.BaseLight; - - const staticButtons = CommandBarComponentButtonFactory.createStaticCommandBarButtons(this.container); - const contextButtons = (this.tabsButtons || []).concat( - CommandBarComponentButtonFactory.createContextCommandBarButtons(this.container) - ); - const controlButtons = CommandBarComponentButtonFactory.createControlCommandBarButtons(this.container); - - const uiFabricStaticButtons = CommandBarUtil.convertButton(staticButtons, backgroundColor); - if (this.tabsButtons && this.tabsButtons.length > 0) { - uiFabricStaticButtons.forEach((btn: ICommandBarItemProps) => (btn.iconOnly = true)); - } - - const uiFabricTabsButtons: ICommandBarItemProps[] = CommandBarUtil.convertButton(contextButtons, backgroundColor); - - if (uiFabricTabsButtons.length > 0) { - uiFabricStaticButtons.push(CommandBarUtil.createDivider("commandBarDivider")); - } - - const uiFabricControlButtons = CommandBarUtil.convertButton(controlButtons, backgroundColor); - uiFabricControlButtons.forEach((btn: ICommandBarItemProps) => (btn.iconOnly = true)); - - if (this.isNotebookTabActive()) { - uiFabricControlButtons.unshift( - CommandBarUtil.createMemoryTracker("memoryTracker", this.container.memoryUsageInfo) - ); - } - - return ( - -
- -
-
- ); - } - - private triggerRender() { - window.requestAnimationFrame(() => this.parameters(Date.now())); - } +interface Props { + container: Explorer; } + +export interface CommandBarStore { + contextButtons: CommandButtonComponentProps[]; + setContextButtons: (contextButtons: CommandButtonComponentProps[]) => void; +} + +export const useCommandBar: UseStore = create((set) => ({ + contextButtons: [], + setContextButtons: (contextButtons: CommandButtonComponentProps[]) => set((state) => ({ ...state, contextButtons })), +})); + +export const CommandBar: React.FC = ({ container }: Props) => { + useObservable(container.selectedNode); + const buttons = useCommandBar((state) => state.contextButtons); + const backgroundColor = StyleConstants.BaseLight; + + const staticButtons = CommandBarComponentButtonFactory.createStaticCommandBarButtons(container); + const contextButtons = (buttons || []).concat( + CommandBarComponentButtonFactory.createContextCommandBarButtons(container) + ); + const controlButtons = CommandBarComponentButtonFactory.createControlCommandBarButtons(container); + + const uiFabricStaticButtons = CommandBarUtil.convertButton(staticButtons, backgroundColor); + if (buttons && buttons.length > 0) { + uiFabricStaticButtons.forEach((btn: ICommandBarItemProps) => (btn.iconOnly = true)); + } + + const uiFabricTabsButtons: ICommandBarItemProps[] = CommandBarUtil.convertButton(contextButtons, backgroundColor); + + if (uiFabricTabsButtons.length > 0) { + uiFabricStaticButtons.push(CommandBarUtil.createDivider("commandBarDivider")); + } + + const uiFabricControlButtons = CommandBarUtil.convertButton(controlButtons, backgroundColor); + uiFabricControlButtons.forEach((btn: ICommandBarItemProps) => (btn.iconOnly = true)); + + if (container.tabsManager.activeTab()?.tabKind === ViewModels.CollectionTabKind.NotebookV2) { + uiFabricControlButtons.unshift(CommandBarUtil.createMemoryTracker("memoryTracker", container.memoryUsageInfo)); + } + + return ( +
+ +
+ ); +}; diff --git a/src/Explorer/Panes/GitHubReposPanel/__snapshots__/GitHubReposPanel.test.tsx.snap b/src/Explorer/Panes/GitHubReposPanel/__snapshots__/GitHubReposPanel.test.tsx.snap index 200772d5a..6ef9c40b0 100644 --- a/src/Explorer/Panes/GitHubReposPanel/__snapshots__/GitHubReposPanel.test.tsx.snap +++ b/src/Explorer/Panes/GitHubReposPanel/__snapshots__/GitHubReposPanel.test.tsx.snap @@ -21,12 +21,6 @@ exports[`GitHub Repos Panel should render Default properly 1`] = ` "_resetNotebookWorkspace": [Function], "canSaveQueries": [Function], "collapsedResourceTreeWidth": 36, - "commandBarComponentAdapter": CommandBarComponentAdapter { - "container": [Circular], - "isNotebookTabActive": [Function], - "parameters": [Function], - "tabsButtons": Array [], - }, "databases": [Function], "isAccountReady": [Function], "isFixedCollectionWithSharedThroughputSupported": [Function], diff --git a/src/Explorer/Panes/StringInputPane/__snapshots__/StringInputPane.test.tsx.snap b/src/Explorer/Panes/StringInputPane/__snapshots__/StringInputPane.test.tsx.snap index 760e170ee..6a5f4cf63 100644 --- a/src/Explorer/Panes/StringInputPane/__snapshots__/StringInputPane.test.tsx.snap +++ b/src/Explorer/Panes/StringInputPane/__snapshots__/StringInputPane.test.tsx.snap @@ -11,12 +11,6 @@ exports[`StringInput Pane should render Create new directory properly 1`] = ` "_resetNotebookWorkspace": [Function], "canSaveQueries": [Function], "collapsedResourceTreeWidth": 36, - "commandBarComponentAdapter": CommandBarComponentAdapter { - "container": [Circular], - "isNotebookTabActive": [Function], - "parameters": [Function], - "tabsButtons": Array [], - }, "databases": [Function], "isAccountReady": [Function], "isFixedCollectionWithSharedThroughputSupported": [Function], diff --git a/src/Explorer/Panes/__snapshots__/DeleteDatabaseConfirmationPanel.test.tsx.snap b/src/Explorer/Panes/__snapshots__/DeleteDatabaseConfirmationPanel.test.tsx.snap index 16399ce3c..8c41ea2b1 100644 --- a/src/Explorer/Panes/__snapshots__/DeleteDatabaseConfirmationPanel.test.tsx.snap +++ b/src/Explorer/Panes/__snapshots__/DeleteDatabaseConfirmationPanel.test.tsx.snap @@ -9,12 +9,6 @@ exports[`Delete Database Confirmation Pane submit() Should call delete database "_resetNotebookWorkspace": [Function], "canSaveQueries": [Function], "collapsedResourceTreeWidth": 36, - "commandBarComponentAdapter": CommandBarComponentAdapter { - "container": [Circular], - "isNotebookTabActive": [Function], - "parameters": [Function], - "tabsButtons": Array [], - }, "databases": [Function], "isAccountReady": [Function], "isFixedCollectionWithSharedThroughputSupported": [Function], diff --git a/src/Explorer/Tabs/DocumentsTab.test.ts b/src/Explorer/Tabs/DocumentsTab.test.ts index 6321a4afb..bd7018000 100644 --- a/src/Explorer/Tabs/DocumentsTab.test.ts +++ b/src/Explorer/Tabs/DocumentsTab.test.ts @@ -2,7 +2,6 @@ import * as ko from "knockout"; import { DatabaseAccount } from "../../Contracts/DataModels"; import * as ViewModels from "../../Contracts/ViewModels"; import { updateUserContext } from "../../UserContext"; -import { CommandButtonComponentProps } from "../Controls/CommandButton/CommandButtonComponent"; import Explorer from "../Explorer"; import DocumentId from "../Tree/DocumentId"; import DocumentsTab from "./DocumentsTab"; @@ -17,7 +16,6 @@ describe("Documents tab", () => { title: "", tabPath: "", hashLocation: "", - onUpdateTabsButtons: (buttons: CommandButtonComponentProps[]): void => {}, }); expect(documentsTab.buildQuery("")).toContain("select"); @@ -93,7 +91,6 @@ describe("Documents tab", () => { title: "", tabPath: "", hashLocation: "", - onUpdateTabsButtons: (buttons: CommandButtonComponentProps[]): void => {}, }); expect(documentsTab.showPartitionKey).toBe(false); @@ -108,7 +105,6 @@ describe("Documents tab", () => { title: "", tabPath: "", hashLocation: "", - onUpdateTabsButtons: (buttons: CommandButtonComponentProps[]): void => {}, }); expect(documentsTab.showPartitionKey).toBe(false); @@ -123,7 +119,6 @@ describe("Documents tab", () => { title: "", tabPath: "", hashLocation: "", - onUpdateTabsButtons: (buttons: CommandButtonComponentProps[]): void => {}, }); expect(documentsTab.showPartitionKey).toBe(true); @@ -141,7 +136,6 @@ describe("Documents tab", () => { title: "", tabPath: "", hashLocation: "", - onUpdateTabsButtons: (buttons: CommandButtonComponentProps[]): void => {}, }); expect(documentsTab.showPartitionKey).toBe(false); @@ -156,7 +150,6 @@ describe("Documents tab", () => { title: "", tabPath: "", hashLocation: "", - onUpdateTabsButtons: (buttons: CommandButtonComponentProps[]): void => {}, }); expect(documentsTab.showPartitionKey).toBe(true); diff --git a/src/Explorer/Tabs/QueryTab.test.ts b/src/Explorer/Tabs/QueryTab.test.ts index c146f6d6f..f112db091 100644 --- a/src/Explorer/Tabs/QueryTab.test.ts +++ b/src/Explorer/Tabs/QueryTab.test.ts @@ -2,7 +2,6 @@ import * as ko from "knockout"; import { DatabaseAccount } from "../../Contracts/DataModels"; import * as ViewModels from "../../Contracts/ViewModels"; import { updateUserContext } from "../../UserContext"; -import { CommandButtonComponentProps } from "../Controls/CommandButton/CommandButtonComponent"; import Explorer from "../Explorer"; import QueryTab from "./QueryTab"; @@ -26,7 +25,6 @@ describe("Query Tab", () => { title: "", tabPath: "", hashLocation: "", - onUpdateTabsButtons: (buttons: CommandButtonComponentProps[]): void => {}, }); } diff --git a/src/Explorer/Tabs/TabsBase.ts b/src/Explorer/Tabs/TabsBase.ts index 1f0dbc3bb..2130a6715 100644 --- a/src/Explorer/Tabs/TabsBase.ts +++ b/src/Explorer/Tabs/TabsBase.ts @@ -9,6 +9,7 @@ import { Action, ActionModifiers } from "../../Shared/Telemetry/TelemetryConstan import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor"; import { CommandButtonComponentProps } from "../Controls/CommandButton/CommandButtonComponent"; import Explorer from "../Explorer"; +import { useCommandBar } from "../Menus/CommandBar/CommandBarComponentAdapter"; import { WaitsForTemplateViewModel } from "../WaitsForTemplateViewModel"; import { TabsManager } from "./TabsManager"; @@ -163,7 +164,7 @@ export default class TabsBase extends WaitsForTemplateViewModel { protected updateNavbarWithTabsButtons = (): void => { if (this.isActive()) { - this.getContainer().onUpdateTabsButtons(this.getTabsButtons()); + useCommandBar.getState().setContextButtons(this.getTabsButtons()); } }; } diff --git a/src/Explorer/Tabs/TabsManager.test.ts b/src/Explorer/Tabs/TabsManager.test.ts index e8bf95f22..7f4509a2f 100644 --- a/src/Explorer/Tabs/TabsManager.test.ts +++ b/src/Explorer/Tabs/TabsManager.test.ts @@ -52,7 +52,6 @@ describe("Tabs manager tests", () => { title: "", tabPath: "", hashLocation: "", - onUpdateTabsButtons: undefined, }); documentsTab = new DocumentsTab({ @@ -63,7 +62,6 @@ describe("Tabs manager tests", () => { title: "", tabPath: "", hashLocation: "", - onUpdateTabsButtons: undefined, }); // make sure tabs have different tabId diff --git a/src/Explorer/Tree/Collection.ts b/src/Explorer/Tree/Collection.ts index 5ec6c2803..ffd236573 100644 --- a/src/Explorer/Tree/Collection.ts +++ b/src/Explorer/Tree/Collection.ts @@ -21,6 +21,7 @@ import { userContext } from "../../UserContext"; import { SqlTriggerResource } from "../../Utils/arm/generatedClients/cosmos/types"; import { logConsoleInfo } from "../../Utils/NotificationConsoleUtils"; import Explorer from "../Explorer"; +import { useCommandBar } from "../Menus/CommandBar/CommandBarComponentAdapter"; import { CassandraAPIDataClient, CassandraTableKey, CassandraTableKeys } from "../Tables/TableDataClient"; import ConflictsTab from "../Tabs/ConflictsTab"; import DocumentsTab from "../Tabs/DocumentsTab"; @@ -221,7 +222,7 @@ export default class Collection implements ViewModels.Collection { } else { this.expandCollection(); } - this.container.onUpdateTabsButtons([]); + useCommandBar.getState().setContextButtons([]); this.container.tabsManager.refreshActiveTab( (tab) => tab.collection && tab.collection.databaseId === this.databaseId && tab.collection.id() === this.id() ); @@ -299,7 +300,6 @@ export default class Collection implements ViewModels.Collection { tabPath: `${this.databaseId}>${this.id()}>Documents`, hashLocation: `${Constants.HashRoutePrefixes.collectionsWithIds(this.databaseId, this.id())}/documents`, onLoadStartKey: startKey, - onUpdateTabsButtons: this.container.onUpdateTabsButtons, }); this.container.tabsManager.activateNewTab(documentsTab); @@ -346,7 +346,6 @@ export default class Collection implements ViewModels.Collection { tabPath: `${this.databaseId}>${this.id()}>Conflicts`, hashLocation: `${Constants.HashRoutePrefixes.collectionsWithIds(this.databaseId, this.id())}/conflicts`, onLoadStartKey: startKey, - onUpdateTabsButtons: this.container.onUpdateTabsButtons, }); this.container.tabsManager.activateNewTab(conflictsTab); @@ -401,7 +400,6 @@ export default class Collection implements ViewModels.Collection { node: this, hashLocation: `${Constants.HashRoutePrefixes.collectionsWithIds(this.databaseId, this.id())}/entities`, onLoadStartKey: startKey, - onUpdateTabsButtons: this.container.onUpdateTabsButtons, }); this.container.tabsManager.activateNewTab(queryTablesTab); @@ -454,7 +452,6 @@ export default class Collection implements ViewModels.Collection { databaseId: this.databaseId, isTabsContentExpanded: this.container.isTabsContentExpanded, onLoadStartKey: startKey, - onUpdateTabsButtons: this.container.onUpdateTabsButtons, }); this.container.tabsManager.activateNewTab(graphTab); @@ -501,7 +498,6 @@ export default class Collection implements ViewModels.Collection { node: this, hashLocation: `${Constants.HashRoutePrefixes.collectionsWithIds(this.databaseId, this.id())}/mongoDocuments`, onLoadStartKey: startKey, - onUpdateTabsButtons: this.container.onUpdateTabsButtons, }); this.container.tabsManager.activateNewTab(mongoDocumentsTab); } @@ -547,7 +543,6 @@ export default class Collection implements ViewModels.Collection { node: this, hashLocation: `${Constants.HashRoutePrefixes.collectionsWithIds(this.databaseId, this.id())}/schemaAnalyzer`, onLoadStartKey: startKey, - onUpdateTabsButtons: this.container.onUpdateTabsButtons, }) ); }; @@ -587,7 +582,6 @@ export default class Collection implements ViewModels.Collection { collection: this, node: this, hashLocation: `${Constants.HashRoutePrefixes.collectionsWithIds(this.databaseId, this.id())}/settings`, - onUpdateTabsButtons: this.container.onUpdateTabsButtons, }; let settingsTabV2 = matchingTabs && (matchingTabs[0] as CollectionSettingsTabV2); @@ -632,7 +626,6 @@ export default class Collection implements ViewModels.Collection { queryText: queryText, partitionKey: collection.partitionKey, onLoadStartKey: startKey, - onUpdateTabsButtons: this.container.onUpdateTabsButtons, }); this.container.tabsManager.activateNewTab(queryTab); @@ -660,7 +653,6 @@ export default class Collection implements ViewModels.Collection { hashLocation: `${Constants.HashRoutePrefixes.collectionsWithIds(this.databaseId, this.id())}/mongoQuery`, partitionKey: collection.partitionKey, onLoadStartKey: startKey, - onUpdateTabsButtons: this.container.onUpdateTabsButtons, }); this.container.tabsManager.activateNewTab(mongoQueryTab); @@ -692,7 +684,6 @@ export default class Collection implements ViewModels.Collection { databaseId: this.databaseId, isTabsContentExpanded: this.container.isTabsContentExpanded, onLoadStartKey: startKey, - onUpdateTabsButtons: this.container.onUpdateTabsButtons, }); this.container.tabsManager.activateNewTab(graphTab); @@ -707,7 +698,6 @@ export default class Collection implements ViewModels.Collection { collection: this, node: this, hashLocation: `${Constants.HashRoutePrefixes.collectionsWithIds(this.databaseId, this.id())}/mongoShell`, - onUpdateTabsButtons: this.container.onUpdateTabsButtons, }); this.container.tabsManager.activateNewTab(mongoShellTab); diff --git a/src/Explorer/Tree/Database.ts b/src/Explorer/Tree/Database.ts index f9cc2e605..1730b48a3 100644 --- a/src/Explorer/Tree/Database.ts +++ b/src/Explorer/Tree/Database.ts @@ -81,7 +81,6 @@ export default class Database implements ViewModels.Database { database: this, hashLocation: `${Constants.HashRoutePrefixes.databasesWithId(this.id())}/settings`, onLoadStartKey: startKey, - onUpdateTabsButtons: this.container.onUpdateTabsButtons, }; settingsTab = new DatabaseSettingsTabV2(tabOptions); settingsTab.pendingNotification(pendingNotification); diff --git a/src/Explorer/Tree/ResourceTokenCollection.ts b/src/Explorer/Tree/ResourceTokenCollection.ts index dbc5ac060..08dae8ca9 100644 --- a/src/Explorer/Tree/ResourceTokenCollection.ts +++ b/src/Explorer/Tree/ResourceTokenCollection.ts @@ -3,13 +3,12 @@ import * as Constants from "../../Common/Constants"; import * as DataModels from "../../Contracts/DataModels"; import * as ViewModels from "../../Contracts/ViewModels"; import { Action, ActionModifiers } from "../../Shared/Telemetry/TelemetryConstants"; -import DocumentId from "./DocumentId"; -import DocumentsTab from "../Tabs/DocumentsTab"; -import Q from "q"; -import QueryTab from "../Tabs/QueryTab"; import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor"; import Explorer from "../Explorer"; +import DocumentsTab from "../Tabs/DocumentsTab"; +import QueryTab from "../Tabs/QueryTab"; import TabsBase from "../Tabs/TabsBase"; +import DocumentId from "./DocumentId"; export default class ResourceTokenCollection implements ViewModels.CollectionBase { public nodeKind: string; @@ -96,7 +95,6 @@ export default class ResourceTokenCollection implements ViewModels.CollectionBas partitionKey: collection.partitionKey, resourceTokenPartitionKey: this.container.resourceTokenPartitionKey(), onLoadStartKey: startKey, - onUpdateTabsButtons: this.container.onUpdateTabsButtons, }); this.container.tabsManager.activateNewTab(queryTab); @@ -143,7 +141,6 @@ export default class ResourceTokenCollection implements ViewModels.CollectionBas tabPath: `${this.databaseId}>${this.id()}>Documents`, hashLocation: `${Constants.HashRoutePrefixes.collectionsWithIds(this.databaseId, this.id())}/documents`, onLoadStartKey: startKey, - onUpdateTabsButtons: this.container.onUpdateTabsButtons, }); this.container.tabsManager.activateNewTab(documentsTab); diff --git a/src/Explorer/Tree/ResourceTreeAdapter.test.tsx b/src/Explorer/Tree/ResourceTreeAdapter.test.tsx index a161eaf1d..e796dc305 100644 --- a/src/Explorer/Tree/ResourceTreeAdapter.test.tsx +++ b/src/Explorer/Tree/ResourceTreeAdapter.test.tsx @@ -1,12 +1,12 @@ +import { shallow } from "enzyme"; import * as ko from "knockout"; +import React from "react"; import * as DataModels from "../../Contracts/DataModels"; import * as ViewModels from "../../Contracts/ViewModels"; -import React from "react"; -import { ResourceTreeAdapter } from "./ResourceTreeAdapter"; -import { shallow } from "enzyme"; -import { TreeComponent, TreeNode, TreeComponentProps } from "../Controls/TreeComponent/TreeComponent"; +import { TreeComponent, TreeComponentProps, TreeNode } from "../Controls/TreeComponent/TreeComponent"; import Explorer from "../Explorer"; import Collection from "./Collection"; +import { ResourceTreeAdapter } from "./ResourceTreeAdapter"; const schema: DataModels.ISchema = { id: "fakeSchemaId", @@ -211,9 +211,6 @@ const schema: DataModels.ISchema = { const createMockContainer = (): Explorer => { const mockContainer = new Explorer(); mockContainer.selectedNode = ko.observable(); - mockContainer.onUpdateTabsButtons = () => { - return; - }; return mockContainer; }; diff --git a/src/Explorer/Tree/ResourceTreeAdapter.tsx b/src/Explorer/Tree/ResourceTreeAdapter.tsx index f06187564..7a8633209 100644 --- a/src/Explorer/Tree/ResourceTreeAdapter.tsx +++ b/src/Explorer/Tree/ResourceTreeAdapter.tsx @@ -27,6 +27,7 @@ import { ResourceTreeContextMenuButtonFactory } from "../ContextMenuButtonFactor import { AccordionComponent, AccordionItemComponent } from "../Controls/Accordion/AccordionComponent"; import { TreeComponent, TreeNode, TreeNodeMenuItem } from "../Controls/TreeComponent/TreeComponent"; import Explorer from "../Explorer"; +import { useCommandBar } from "../Menus/CommandBar/CommandBarComponentAdapter"; import { mostRecentActivity } from "../MostRecentActivity/MostRecentActivity"; import { NotebookContentItem, NotebookContentItemType } from "../Notebook/NotebookContentItem"; import { NotebookUtil } from "../Notebook/NotebookUtil"; @@ -211,7 +212,7 @@ export class ResourceTreeAdapter implements ReactAdapter { } databaseNode.isLoading = false; database.selectDatabase(); - this.container.onUpdateTabsButtons([]); + useCommandBar.getState().setContextButtons([]); this.container.tabsManager.refreshActiveTab((tab: TabsBase) => tab.collection?.databaseId === database.id()); }, onContextMenuOpen: () => this.container.selectedNode(database), @@ -330,7 +331,7 @@ export class ResourceTreeAdapter implements ReactAdapter { onClick: () => { // Rewritten version of expandCollapseCollection this.container.selectedNode(collection); - this.container.onUpdateTabsButtons([]); + useCommandBar.getState().setContextButtons([]); this.container.tabsManager.refreshActiveTab( (tab: TabsBase) => tab.collection?.id() === collection.id() && tab.collection.databaseId === collection.databaseId diff --git a/src/Explorer/Tree/ResourceTreeAdapterForResourceToken.test.tsx b/src/Explorer/Tree/ResourceTreeAdapterForResourceToken.test.tsx index 9398747fa..40ac991b6 100644 --- a/src/Explorer/Tree/ResourceTreeAdapterForResourceToken.test.tsx +++ b/src/Explorer/Tree/ResourceTreeAdapterForResourceToken.test.tsx @@ -1,19 +1,17 @@ +import { shallow } from "enzyme"; import * as ko from "knockout"; -import * as MostRecentActivity from "../MostRecentActivity/MostRecentActivity"; +import React from "react"; import * as DataModels from "../../Contracts/DataModels"; import * as ViewModels from "../../Contracts/ViewModels"; -import React from "react"; +import { TreeComponent, TreeComponentProps, TreeNode } from "../Controls/TreeComponent/TreeComponent"; +import Explorer from "../Explorer"; import ResourceTokenCollection from "./ResourceTokenCollection"; import { ResourceTreeAdapterForResourceToken } from "./ResourceTreeAdapterForResourceToken"; -import { shallow } from "enzyme"; -import { TreeComponent, TreeNode, TreeComponentProps } from "../Controls/TreeComponent/TreeComponent"; -import Explorer from "../Explorer"; const createMockContainer = (): Explorer => { let mockContainer = {} as Explorer; mockContainer.resourceTokenCollection = createMockCollection(mockContainer); mockContainer.selectedNode = ko.observable(); - mockContainer.onUpdateTabsButtons = () => {}; return mockContainer; }; diff --git a/src/Explorer/Tree/ResourceTreeAdapterForResourceToken.tsx b/src/Explorer/Tree/ResourceTreeAdapterForResourceToken.tsx index 2c106e6f9..72ac21af7 100644 --- a/src/Explorer/Tree/ResourceTreeAdapterForResourceToken.tsx +++ b/src/Explorer/Tree/ResourceTreeAdapterForResourceToken.tsx @@ -1,13 +1,14 @@ import * as ko from "knockout"; -import { mostRecentActivity } from "../MostRecentActivity/MostRecentActivity"; import * as React from "react"; -import * as ViewModels from "../../Contracts/ViewModels"; -import { NotebookContentItem } from "../Notebook/NotebookContentItem"; -import { ReactAdapter } from "../../Bindings/ReactBindingHandler"; -import { TreeComponent, TreeNode } from "../Controls/TreeComponent/TreeComponent"; import CollectionIcon from "../../../images/tree-collection.svg"; -import Explorer from "../Explorer"; +import { ReactAdapter } from "../../Bindings/ReactBindingHandler"; +import * as ViewModels from "../../Contracts/ViewModels"; import { userContext } from "../../UserContext"; +import { TreeComponent, TreeNode } from "../Controls/TreeComponent/TreeComponent"; +import Explorer from "../Explorer"; +import { useCommandBar } from "../Menus/CommandBar/CommandBarComponentAdapter"; +import { mostRecentActivity } from "../MostRecentActivity/MostRecentActivity"; +import { NotebookContentItem } from "../Notebook/NotebookContentItem"; export class ResourceTreeAdapterForResourceToken implements ReactAdapter { public parameters: ko.Observable; @@ -59,7 +60,7 @@ export class ResourceTreeAdapterForResourceToken implements ReactAdapter { onClick: () => { // Rewritten version of expandCollapseCollection this.container.selectedNode(collection); - this.container.onUpdateTabsButtons([]); + useCommandBar.getState().setContextButtons([]); this.container.tabsManager.refreshActiveTab( (tab) => tab.collection?.id() === collection.id() && tab.collection.databaseId === collection.databaseId ); diff --git a/src/Explorer/Tree/StoredProcedure.ts b/src/Explorer/Tree/StoredProcedure.ts index e85a39391..9f491287c 100644 --- a/src/Explorer/Tree/StoredProcedure.ts +++ b/src/Explorer/Tree/StoredProcedure.ts @@ -76,7 +76,6 @@ export default class StoredProcedure { collection: source, node: source, hashLocation: `${Constants.HashRoutePrefixes.collectionsWithIds(source.databaseId, source.id())}/sproc`, - onUpdateTabsButtons: source.container.onUpdateTabsButtons, }); source.container.tabsManager.activateNewTab(storedProcedureTab); @@ -122,7 +121,6 @@ export default class StoredProcedure { this.collection.databaseId, this.collection.id() )}/sprocs/${this.id()}`, - onUpdateTabsButtons: this.container.onUpdateTabsButtons, }); this.container.tabsManager.activateNewTab(storedProcedureTab); diff --git a/src/Explorer/Tree/Trigger.ts b/src/Explorer/Tree/Trigger.ts index 5f6e0b877..21f69741d 100644 --- a/src/Explorer/Tree/Trigger.ts +++ b/src/Explorer/Tree/Trigger.ts @@ -58,7 +58,6 @@ export default class Trigger { collection: source, node: source, hashLocation: `${Constants.HashRoutePrefixes.collectionsWithIds(source.databaseId, source.id())}/trigger`, - onUpdateTabsButtons: source.container.onUpdateTabsButtons, }); source.container.tabsManager.activateNewTab(triggerTab); @@ -97,7 +96,6 @@ export default class Trigger { this.collection.databaseId, this.collection.id() )}/triggers/${this.id()}`, - onUpdateTabsButtons: this.container.onUpdateTabsButtons, }); this.container.tabsManager.activateNewTab(triggerTab); diff --git a/src/Explorer/Tree/UserDefinedFunction.ts b/src/Explorer/Tree/UserDefinedFunction.ts index 270afe34f..cbd37ecd6 100644 --- a/src/Explorer/Tree/UserDefinedFunction.ts +++ b/src/Explorer/Tree/UserDefinedFunction.ts @@ -44,7 +44,6 @@ export default class UserDefinedFunction { collection: source, node: source, hashLocation: `${Constants.HashRoutePrefixes.collectionsWithIds(source.databaseId, source.id())}/udf`, - onUpdateTabsButtons: source.container.onUpdateTabsButtons, }); source.container.tabsManager.activateNewTab(userDefinedFunctionTab); @@ -81,7 +80,6 @@ export default class UserDefinedFunction { this.collection.databaseId, this.collection.id() )}/udfs/${this.id()}`, - onUpdateTabsButtons: this.container.onUpdateTabsButtons, }); this.container.tabsManager.activateNewTab(userDefinedFunctionTab); diff --git a/src/Main.tsx b/src/Main.tsx index d8244ec2b..bf6f1643f 100644 --- a/src/Main.tsx +++ b/src/Main.tsx @@ -37,6 +37,7 @@ import "./Explorer/Controls/TreeComponent/treeComponent.less"; import { ExplorerParams } from "./Explorer/Explorer"; import "./Explorer/Graph/GraphExplorerComponent/graphExplorer.less"; import "./Explorer/Menus/CommandBar/CommandBarComponent.less"; +import { CommandBar } from "./Explorer/Menus/CommandBar/CommandBarComponentAdapter"; import "./Explorer/Menus/CommandBar/MemoryTrackerComponent.less"; import "./Explorer/Menus/NotificationConsole/NotificationConsole.less"; import { NotificationConsole } from "./Explorer/Menus/NotificationConsole/NotificationConsoleComponent"; @@ -88,7 +89,7 @@ const App: React.FunctionComponent = () => {
{/* Main Command Bar - Start */} -
+ {/* Collections Tree and Tabs - Begin */}
{/* Collections Tree - Start */}