Migrate SidePanel state to Zustand (#799)

Co-authored-by: hardiknai-techm <HN00734461@TechMahindra.com>
This commit is contained in:
Steve Faulkner 2021-05-27 16:07:07 -05:00 committed by GitHub
parent e41b52e265
commit 481ff9e7fe
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
60 changed files with 288 additions and 598 deletions

View File

@ -111,9 +111,6 @@ src/Explorer/OpenActionsStubs.ts
src/Explorer/Panes/AddDatabasePane.ts src/Explorer/Panes/AddDatabasePane.ts
src/Explorer/Panes/AddDatabasePane.test.ts src/Explorer/Panes/AddDatabasePane.test.ts
src/Explorer/Panes/BrowseQueriesPane.ts src/Explorer/Panes/BrowseQueriesPane.ts
src/Explorer/Panes/ContextualPaneBase.ts
# src/Explorer/Panes/GraphStylingPane.ts
# src/Explorer/Panes/NewVertexPane.ts
src/Explorer/Panes/RenewAdHocAccessPane.ts src/Explorer/Panes/RenewAdHocAccessPane.ts
src/Explorer/Panes/SetupNotebooksPane.ts src/Explorer/Panes/SetupNotebooksPane.ts
src/Explorer/Panes/SwitchDirectoryPane.ts src/Explorer/Panes/SwitchDirectoryPane.ts

View File

@ -31,7 +31,6 @@ exports[`SettingsComponent renders 1`] = `
"_isInitializingNotebooks": false, "_isInitializingNotebooks": false,
"_resetNotebookWorkspace": [Function], "_resetNotebookWorkspace": [Function],
"canSaveQueries": [Function], "canSaveQueries": [Function],
"closeSidePanel": undefined,
"collapsedResourceTreeWidth": 36, "collapsedResourceTreeWidth": 36,
"commandBarComponentAdapter": CommandBarComponentAdapter { "commandBarComponentAdapter": CommandBarComponentAdapter {
"container": [Circular], "container": [Circular],
@ -56,7 +55,6 @@ exports[`SettingsComponent renders 1`] = `
"notebookServerInfo": [Function], "notebookServerInfo": [Function],
"onRefreshDatabasesKeyPress": [Function], "onRefreshDatabasesKeyPress": [Function],
"onRefreshResourcesClick": [Function], "onRefreshResourcesClick": [Function],
"openSidePanel": undefined,
"provideFeedbackEmail": [Function], "provideFeedbackEmail": [Function],
"queriesClient": QueriesClient { "queriesClient": QueriesClient {
"container": [Circular], "container": [Circular],
@ -81,7 +79,6 @@ exports[`SettingsComponent renders 1`] = `
"selectedDatabaseId": [Function], "selectedDatabaseId": [Function],
"selectedNode": [Function], "selectedNode": [Function],
"setInProgressConsoleDataIdToBeDeleted": undefined, "setInProgressConsoleDataIdToBeDeleted": undefined,
"setIsNotificationConsoleExpanded": undefined,
"setNotificationConsoleData": undefined, "setNotificationConsoleData": undefined,
"sparkClusterConnectionInfo": [Function], "sparkClusterConnectionInfo": [Function],
"splitter": Splitter { "splitter": Splitter {
@ -124,7 +121,6 @@ exports[`SettingsComponent renders 1`] = `
"_isInitializingNotebooks": false, "_isInitializingNotebooks": false,
"_resetNotebookWorkspace": [Function], "_resetNotebookWorkspace": [Function],
"canSaveQueries": [Function], "canSaveQueries": [Function],
"closeSidePanel": undefined,
"collapsedResourceTreeWidth": 36, "collapsedResourceTreeWidth": 36,
"commandBarComponentAdapter": CommandBarComponentAdapter { "commandBarComponentAdapter": CommandBarComponentAdapter {
"container": [Circular], "container": [Circular],
@ -149,7 +145,6 @@ exports[`SettingsComponent renders 1`] = `
"notebookServerInfo": [Function], "notebookServerInfo": [Function],
"onRefreshDatabasesKeyPress": [Function], "onRefreshDatabasesKeyPress": [Function],
"onRefreshResourcesClick": [Function], "onRefreshResourcesClick": [Function],
"openSidePanel": undefined,
"provideFeedbackEmail": [Function], "provideFeedbackEmail": [Function],
"queriesClient": QueriesClient { "queriesClient": QueriesClient {
"container": [Circular], "container": [Circular],
@ -174,7 +169,6 @@ exports[`SettingsComponent renders 1`] = `
"selectedDatabaseId": [Function], "selectedDatabaseId": [Function],
"selectedNode": [Function], "selectedNode": [Function],
"setInProgressConsoleDataIdToBeDeleted": undefined, "setInProgressConsoleDataIdToBeDeleted": undefined,
"setIsNotificationConsoleExpanded": undefined,
"setNotificationConsoleData": undefined, "setNotificationConsoleData": undefined,
"sparkClusterConnectionInfo": [Function], "sparkClusterConnectionInfo": [Function],
"splitter": Splitter { "splitter": Splitter {
@ -230,7 +224,6 @@ exports[`SettingsComponent renders 1`] = `
"_isInitializingNotebooks": false, "_isInitializingNotebooks": false,
"_resetNotebookWorkspace": [Function], "_resetNotebookWorkspace": [Function],
"canSaveQueries": [Function], "canSaveQueries": [Function],
"closeSidePanel": undefined,
"collapsedResourceTreeWidth": 36, "collapsedResourceTreeWidth": 36,
"commandBarComponentAdapter": CommandBarComponentAdapter { "commandBarComponentAdapter": CommandBarComponentAdapter {
"container": [Circular], "container": [Circular],
@ -255,7 +248,6 @@ exports[`SettingsComponent renders 1`] = `
"notebookServerInfo": [Function], "notebookServerInfo": [Function],
"onRefreshDatabasesKeyPress": [Function], "onRefreshDatabasesKeyPress": [Function],
"onRefreshResourcesClick": [Function], "onRefreshResourcesClick": [Function],
"openSidePanel": undefined,
"provideFeedbackEmail": [Function], "provideFeedbackEmail": [Function],
"queriesClient": QueriesClient { "queriesClient": QueriesClient {
"container": [Circular], "container": [Circular],
@ -280,7 +272,6 @@ exports[`SettingsComponent renders 1`] = `
"selectedDatabaseId": [Function], "selectedDatabaseId": [Function],
"selectedNode": [Function], "selectedNode": [Function],
"setInProgressConsoleDataIdToBeDeleted": undefined, "setInProgressConsoleDataIdToBeDeleted": undefined,
"setIsNotificationConsoleExpanded": undefined,
"setNotificationConsoleData": undefined, "setNotificationConsoleData": undefined,
"sparkClusterConnectionInfo": [Function], "sparkClusterConnectionInfo": [Function],
"splitter": Splitter { "splitter": Splitter {
@ -323,7 +314,6 @@ exports[`SettingsComponent renders 1`] = `
"_isInitializingNotebooks": false, "_isInitializingNotebooks": false,
"_resetNotebookWorkspace": [Function], "_resetNotebookWorkspace": [Function],
"canSaveQueries": [Function], "canSaveQueries": [Function],
"closeSidePanel": undefined,
"collapsedResourceTreeWidth": 36, "collapsedResourceTreeWidth": 36,
"commandBarComponentAdapter": CommandBarComponentAdapter { "commandBarComponentAdapter": CommandBarComponentAdapter {
"container": [Circular], "container": [Circular],
@ -348,7 +338,6 @@ exports[`SettingsComponent renders 1`] = `
"notebookServerInfo": [Function], "notebookServerInfo": [Function],
"onRefreshDatabasesKeyPress": [Function], "onRefreshDatabasesKeyPress": [Function],
"onRefreshResourcesClick": [Function], "onRefreshResourcesClick": [Function],
"openSidePanel": undefined,
"provideFeedbackEmail": [Function], "provideFeedbackEmail": [Function],
"queriesClient": QueriesClient { "queriesClient": QueriesClient {
"container": [Circular], "container": [Circular],
@ -373,7 +362,6 @@ exports[`SettingsComponent renders 1`] = `
"selectedDatabaseId": [Function], "selectedDatabaseId": [Function],
"selectedNode": [Function], "selectedNode": [Function],
"setInProgressConsoleDataIdToBeDeleted": undefined, "setInProgressConsoleDataIdToBeDeleted": undefined,
"setIsNotificationConsoleExpanded": undefined,
"setNotificationConsoleData": undefined, "setNotificationConsoleData": undefined,
"sparkClusterConnectionInfo": [Function], "sparkClusterConnectionInfo": [Function],
"splitter": Splitter { "splitter": Splitter {

View File

@ -18,6 +18,7 @@ import { configContext, Platform } from "../ConfigContext";
import * as DataModels from "../Contracts/DataModels"; import * as DataModels from "../Contracts/DataModels";
import * as ViewModels from "../Contracts/ViewModels"; import * as ViewModels from "../Contracts/ViewModels";
import { GitHubOAuthService } from "../GitHub/GitHubOAuthService"; import { GitHubOAuthService } from "../GitHub/GitHubOAuthService";
import { useSidePanel } from "../hooks/useSidePanel";
import { IGalleryItem, JunoClient } from "../Juno/JunoClient"; import { IGalleryItem, JunoClient } from "../Juno/JunoClient";
import { NotebookWorkspaceManager } from "../NotebookWorkspaceManager/NotebookWorkspaceManager"; import { NotebookWorkspaceManager } from "../NotebookWorkspaceManager/NotebookWorkspaceManager";
import { RouteHandler } from "../RouteHandlers/RouteHandler"; import { RouteHandler } from "../RouteHandlers/RouteHandler";
@ -53,7 +54,6 @@ import { DeleteCollectionConfirmationPane } from "./Panes/DeleteCollectionConfir
import { DeleteDatabaseConfirmationPanel } from "./Panes/DeleteDatabaseConfirmationPanel"; import { DeleteDatabaseConfirmationPanel } from "./Panes/DeleteDatabaseConfirmationPanel";
import { ExecuteSprocParamsPane } from "./Panes/ExecuteSprocParamsPane/ExecuteSprocParamsPane"; import { ExecuteSprocParamsPane } from "./Panes/ExecuteSprocParamsPane/ExecuteSprocParamsPane";
import { GitHubReposPanel } from "./Panes/GitHubReposPanel/GitHubReposPanel"; import { GitHubReposPanel } from "./Panes/GitHubReposPanel/GitHubReposPanel";
import { LoadQueryPane } from "./Panes/LoadQueryPane/LoadQueryPane";
import { SaveQueryPane } from "./Panes/SaveQueryPane/SaveQueryPane"; import { SaveQueryPane } from "./Panes/SaveQueryPane/SaveQueryPane";
import { SettingsPane } from "./Panes/SettingsPane/SettingsPane"; import { SettingsPane } from "./Panes/SettingsPane/SettingsPane";
import { SetupNoteBooksPanel } from "./Panes/SetupNotebooksPanel/SetupNotebooksPanel"; import { SetupNoteBooksPanel } from "./Panes/SetupNotebooksPanel/SetupNotebooksPanel";
@ -81,11 +81,8 @@ BindingHandlersRegisterer.registerBindingHandlers();
var tmp = ComponentRegisterer; var tmp = ComponentRegisterer;
export interface ExplorerParams { export interface ExplorerParams {
setIsNotificationConsoleExpanded: (isExpanded: boolean) => void;
setNotificationConsoleData: (consoleData: ConsoleData) => void; setNotificationConsoleData: (consoleData: ConsoleData) => void;
setInProgressConsoleDataIdToBeDeleted: (id: string) => void; setInProgressConsoleDataIdToBeDeleted: (id: string) => void;
openSidePanel: (headerText: string, panelContent: JSX.Element, onClose?: () => void) => void;
closeSidePanel: () => void;
tabsManager: TabsManager; tabsManager: TabsManager;
} }
@ -100,15 +97,9 @@ export default class Explorer {
public tableDataClient: TableDataClient; public tableDataClient: TableDataClient;
public splitter: Splitter; public splitter: Splitter;
// Notification Console
private setIsNotificationConsoleExpanded: (isExpanded: boolean) => void;
private setNotificationConsoleData: (consoleData: ConsoleData) => void; private setNotificationConsoleData: (consoleData: ConsoleData) => void;
private setInProgressConsoleDataIdToBeDeleted: (id: string) => void; private setInProgressConsoleDataIdToBeDeleted: (id: string) => void;
// Panes
public openSidePanel: (headerText: string, panelContent: JSX.Element, onClose?: () => void) => void;
public closeSidePanel: () => void;
// Resource Tree // Resource Tree
public databases: ko.ObservableArray<ViewModels.Database>; public databases: ko.ObservableArray<ViewModels.Database>;
public selectedDatabaseId: ko.Computed<string>; public selectedDatabaseId: ko.Computed<string>;
@ -159,11 +150,8 @@ export default class Explorer {
private static readonly MaxNbDatabasesToAutoExpand = 5; private static readonly MaxNbDatabasesToAutoExpand = 5;
constructor(params?: ExplorerParams) { constructor(params?: ExplorerParams) {
this.setIsNotificationConsoleExpanded = params?.setIsNotificationConsoleExpanded;
this.setNotificationConsoleData = params?.setNotificationConsoleData; this.setNotificationConsoleData = params?.setNotificationConsoleData;
this.setInProgressConsoleDataIdToBeDeleted = params?.setInProgressConsoleDataIdToBeDeleted; this.setInProgressConsoleDataIdToBeDeleted = params?.setInProgressConsoleDataIdToBeDeleted;
this.openSidePanel = params?.openSidePanel;
this.closeSidePanel = params?.closeSidePanel;
const startKey: number = TelemetryProcessor.traceStart(Action.InitializeDataExplorer, { const startKey: number = TelemetryProcessor.traceStart(Action.InitializeDataExplorer, {
dataExplorerArea: Constants.Areas.ResourceTree, dataExplorerArea: Constants.Areas.ResourceTree,
@ -483,14 +471,6 @@ export default class Explorer {
this.setInProgressConsoleDataIdToBeDeleted(id); this.setInProgressConsoleDataIdToBeDeleted(id);
} }
public expandConsole(): void {
this.setIsNotificationConsoleExpanded(true);
}
public collapseConsole(): void {
this.setIsNotificationConsoleExpanded(false);
}
public refreshDatabaseForResourceToken(): Q.Promise<any> { public refreshDatabaseForResourceToken(): Q.Promise<any> {
const databaseId = this.resourceTokenDatabaseId(); const databaseId = this.resourceTokenDatabaseId();
const collectionId = this.resourceTokenCollectionId(); const collectionId = this.resourceTokenCollectionId();
@ -1136,12 +1116,12 @@ export default class Explorer {
if (openedNotebookTabs.length > 0) { if (openedNotebookTabs.length > 0) {
this.showOkModalDialog("Unable to rename file", "This file is being edited. Please close the tab and try again."); this.showOkModalDialog("Unable to rename file", "This file is being edited. Please close the tab and try again.");
} else { } else {
this.openSidePanel( useSidePanel.getState().openSidePanel(
"Rename Notebook", "Rename Notebook",
<StringInputPane <StringInputPane
explorer={this} explorer={this}
closePanel={() => { closePanel={() => {
this.closeSidePanel(); useSidePanel.getState().closeSidePanel();
this.resourceTree.triggerRender(); this.resourceTree.triggerRender();
}} }}
inputLabel="Enter new notebook name" inputLabel="Enter new notebook name"
@ -1167,12 +1147,12 @@ export default class Explorer {
throw new Error(error); throw new Error(error);
} }
this.openSidePanel( useSidePanel.getState().openSidePanel(
"Create new directory", "Create new directory",
<StringInputPane <StringInputPane
explorer={this} explorer={this}
closePanel={() => { closePanel={() => {
this.closeSidePanel(); useSidePanel.getState().closeSidePanel();
this.resourceTree.triggerRender(); this.resourceTree.triggerRender();
}} }}
errorMessage="Could not create directory " errorMessage="Could not create directory "
@ -1561,160 +1541,115 @@ export default class Explorer {
return false; return false;
}); });
} }
public openDeleteCollectionConfirmationPane(): void { public openDeleteCollectionConfirmationPane(): void {
this.openSidePanel( useSidePanel
"Delete " + getCollectionName(), .getState()
<DeleteCollectionConfirmationPane explorer={this} closePanel={this.closeSidePanel} /> .openSidePanel("Delete " + getCollectionName(), <DeleteCollectionConfirmationPane explorer={this} />);
);
} }
public openDeleteDatabaseConfirmationPane(): void { public openDeleteDatabaseConfirmationPane(): void {
this.openSidePanel( useSidePanel
"Delete " + getDatabaseName(), .getState()
<DeleteDatabaseConfirmationPanel .openSidePanel(
explorer={this} "Delete " + getDatabaseName(),
openNotificationConsole={() => this.expandConsole()} <DeleteDatabaseConfirmationPanel explorer={this} selectedDatabase={this.findSelectedDatabase()} />
closePanel={this.closeSidePanel} );
selectedDatabase={this.findSelectedDatabase()}
/>
);
} }
public openUploadItemsPanePane(): void { public openUploadItemsPanePane(): void {
this.openSidePanel("Upload " + getUploadName(), <UploadItemsPane explorer={this} />); useSidePanel.getState().openSidePanel("Upload " + getUploadName(), <UploadItemsPane explorer={this} />);
} }
public openSettingPane(): void {
this.openSidePanel(
"Setting",
<SettingsPane expandConsole={() => this.expandConsole()} closePanel={this.closeSidePanel} />
);
}
public openExecuteSprocParamsPanel(storedProcedure: StoredProcedure): void { public openExecuteSprocParamsPanel(storedProcedure: StoredProcedure): void {
this.openSidePanel( useSidePanel
"Input parameters", .getState()
<ExecuteSprocParamsPane .openSidePanel("Input parameters", <ExecuteSprocParamsPane storedProcedure={storedProcedure} />);
storedProcedure={storedProcedure}
expandConsole={() => this.expandConsole()}
closePanel={() => this.closeSidePanel()}
/>
);
} }
public async openAddCollectionPanel(databaseId?: string): Promise<void> { public async openAddCollectionPanel(databaseId?: string): Promise<void> {
await this.loadDatabaseOffers(); await this.loadDatabaseOffers();
this.openSidePanel( useSidePanel
"New " + getCollectionName(), .getState()
<AddCollectionPanel .openSidePanel("New " + getCollectionName(), <AddCollectionPanel explorer={this} databaseId={databaseId} />);
explorer={this}
closePanel={() => this.closeSidePanel()}
openNotificationConsole={() => this.expandConsole()}
databaseId={databaseId}
/>
);
} }
public openAddDatabasePane(): void { public openAddDatabasePane(): void {
this.openSidePanel( useSidePanel.getState().openSidePanel("New " + getDatabaseName(), <AddDatabasePanel explorer={this} />);
"New " + getDatabaseName(),
<AddDatabasePanel
explorer={this}
openNotificationConsole={() => this.expandConsole()}
closePanel={this.closeSidePanel}
/>
);
} }
public openBrowseQueriesPanel(): void { public openBrowseQueriesPanel(): void {
this.openSidePanel("Open Saved Queries", <BrowseQueriesPane explorer={this} closePanel={this.closeSidePanel} />); useSidePanel.getState().openSidePanel("Open Saved Queries", <BrowseQueriesPane explorer={this} />);
}
public openLoadQueryPanel(): void {
this.openSidePanel("Load Query", <LoadQueryPane explorer={this} closePanel={() => this.closeSidePanel()} />);
} }
public openSaveQueryPanel(): void { public openSaveQueryPanel(): void {
this.openSidePanel("Save Query", <SaveQueryPane explorer={this} closePanel={() => this.closeSidePanel()} />); useSidePanel.getState().openSidePanel("Save Query", <SaveQueryPane explorer={this} />);
} }
public openUploadFilePanel(parent?: NotebookContentItem): void { public openUploadFilePanel(parent?: NotebookContentItem): void {
parent = parent || this.resourceTree.myNotebooksContentRoot; parent = parent || this.resourceTree.myNotebooksContentRoot;
this.openSidePanel( useSidePanel
"Upload file to notebook server", .getState()
<UploadFilePane .openSidePanel(
expandConsole={() => this.expandConsole()} "Upload file to notebook server",
closePanel={this.closeSidePanel} <UploadFilePane uploadFile={(name: string, content: string) => this.uploadFile(name, content, parent)} />
uploadFile={(name: string, content: string) => this.uploadFile(name, content, parent)} );
/>
);
} }
public openCassandraAddCollectionPane(): void { public openCassandraAddCollectionPane(): void {
this.openSidePanel( useSidePanel
"Add Table", .getState()
<CassandraAddCollectionPane .openSidePanel(
explorer={this} "Add Table",
closePanel={() => this.closeSidePanel()} <CassandraAddCollectionPane explorer={this} cassandraApiClient={new CassandraAPIDataClient()} />
cassandraApiClient={new CassandraAPIDataClient()} );
/>
);
} }
public openGitHubReposPanel(header: string, junoClient?: JunoClient): void { public openGitHubReposPanel(header: string, junoClient?: JunoClient): void {
this.openSidePanel( useSidePanel
header, .getState()
<GitHubReposPanel .openSidePanel(
explorer={this} header,
closePanel={this.closeSidePanel} <GitHubReposPanel
gitHubClientProp={this.notebookManager.gitHubClient} explorer={this}
junoClientProp={junoClient} gitHubClientProp={this.notebookManager.gitHubClient}
openNotificationConsole={() => this.expandConsole()} junoClientProp={junoClient}
/> />
); );
} }
public openAddTableEntityPanel(queryTablesTab: QueryTablesTab, tableEntityListViewModel: TableListViewModal): void { public openAddTableEntityPanel(queryTablesTab: QueryTablesTab, tableEntityListViewModel: TableListViewModal): void {
this.openSidePanel( useSidePanel
"Add Table Entity", .getState()
<AddTableEntityPanel .openSidePanel(
explorer={this} "Add Table Entity",
closePanel={this.closeSidePanel} <AddTableEntityPanel
queryTablesTab={queryTablesTab} tableDataClient={this.tableDataClient}
tableEntityListViewModel={tableEntityListViewModel} queryTablesTab={queryTablesTab}
cassandraApiClient={new CassandraAPIDataClient()} tableEntityListViewModel={tableEntityListViewModel}
/> cassandraApiClient={new CassandraAPIDataClient()}
); />
);
} }
public openSetupNotebooksPanel(title: string, description: string): void { public openSetupNotebooksPanel(title: string, description: string): void {
this.openSidePanel( useSidePanel
title, .getState()
<SetupNoteBooksPanel .openSidePanel(title, <SetupNoteBooksPanel explorer={this} panelTitle={title} panelDescription={description} />);
explorer={this}
closePanel={this.closeSidePanel}
openNotificationConsole={() => this.expandConsole()}
panelTitle={title}
panelDescription={description}
/>
);
} }
public openEditTableEntityPanel(queryTablesTab: QueryTablesTab, tableEntityListViewModel: TableListViewModal): void { public openEditTableEntityPanel(queryTablesTab: QueryTablesTab, tableEntityListViewModel: TableListViewModal): void {
this.openSidePanel( useSidePanel
"Edit Table Entity", .getState()
<EditTableEntityPanel .openSidePanel(
explorer={this} "Edit Table Entity",
closePanel={this.closeSidePanel} <EditTableEntityPanel
queryTablesTab={queryTablesTab} tableDataClient={this.tableDataClient}
tableEntityListViewModel={tableEntityListViewModel} queryTablesTab={queryTablesTab}
cassandraApiClient={new CassandraAPIDataClient()} tableEntityListViewModel={tableEntityListViewModel}
/> cassandraApiClient={new CassandraAPIDataClient()}
); />
);
} }
public openTableSelectQueryPanel(queryViewModal: QueryViewModel): void { public openTableSelectQueryPanel(queryViewModal: QueryViewModel): void {
this.openSidePanel( useSidePanel.getState().openSidePanel("Select Column", <TableQuerySelectPanel queryViewModel={queryViewModal} />);
"Select Column", }
<TableQuerySelectPanel explorer={this} closePanel={this.closeSidePanel} queryViewModel={queryViewModal} /> public openSettingPane(): void {
); useSidePanel.getState().openSidePanel("Settings", <SettingsPane />);
} }
} }

View File

@ -21,11 +21,13 @@ import { AuthType } from "../../../AuthType";
import * as Constants from "../../../Common/Constants"; import * as Constants from "../../../Common/Constants";
import { configContext, Platform } from "../../../ConfigContext"; import { configContext, Platform } from "../../../ConfigContext";
import * as ViewModels from "../../../Contracts/ViewModels"; import * as ViewModels from "../../../Contracts/ViewModels";
import { useSidePanel } from "../../../hooks/useSidePanel";
import { userContext } from "../../../UserContext"; import { userContext } from "../../../UserContext";
import { getCollectionName, getDatabaseName } from "../../../Utils/APITypeUtils"; import { getCollectionName, getDatabaseName } from "../../../Utils/APITypeUtils";
import { CommandButtonComponentProps } from "../../Controls/CommandButton/CommandButtonComponent"; import { CommandButtonComponentProps } from "../../Controls/CommandButton/CommandButtonComponent";
import Explorer from "../../Explorer"; import Explorer from "../../Explorer";
import { OpenFullScreen } from "../../OpenFullScreen"; import { OpenFullScreen } from "../../OpenFullScreen";
import { LoadQueryPane } from "../../Panes/LoadQueryPane/LoadQueryPane";
let counter = 0; let counter = 0;
@ -152,7 +154,7 @@ export function createControlCommandBarButtons(container: Explorer): CommandButt
{ {
iconSrc: SettingsIcon, iconSrc: SettingsIcon,
iconAlt: "Settings", iconAlt: "Settings",
onCommandClick: () => container.openSettingPane(), onCommandClick: container.openSettingPane,
commandButtonLabel: undefined, commandButtonLabel: undefined,
ariaLabel: "Settings", ariaLabel: "Settings",
tooltipText: "Settings", tooltipText: "Settings",
@ -167,7 +169,7 @@ export function createControlCommandBarButtons(container: Explorer): CommandButt
iconSrc: OpenInTabIcon, iconSrc: OpenInTabIcon,
iconAlt: label, iconAlt: label,
onCommandClick: () => { onCommandClick: () => {
container.openSidePanel("Open Full Screen", <OpenFullScreen />); useSidePanel.getState().openSidePanel("Open Full Screen", <OpenFullScreen />);
}, },
commandButtonLabel: undefined, commandButtonLabel: undefined,
ariaLabel: label, ariaLabel: label,
@ -408,7 +410,7 @@ function createOpenQueryFromDiskButton(container: Explorer): CommandButtonCompon
return { return {
iconSrc: OpenQueryFromDiskIcon, iconSrc: OpenQueryFromDiskIcon,
iconAlt: label, iconAlt: label,
onCommandClick: () => container.openLoadQueryPanel(), onCommandClick: () => useSidePanel.getState().openSidePanel("Load Query", <LoadQueryPane explorer={container} />),
commandButtonLabel: label, commandButtonLabel: label,
ariaLabel: label, ariaLabel: label,
hasPopup: true, hasPopup: true,

View File

@ -15,6 +15,7 @@ import LoadingIcon from "../../../../images/loading.svg";
import ChevronDownIcon from "../../../../images/QueryBuilder/CollapseChevronDown_16x.png"; import ChevronDownIcon from "../../../../images/QueryBuilder/CollapseChevronDown_16x.png";
import ChevronUpIcon from "../../../../images/QueryBuilder/CollapseChevronUp_16x.png"; import ChevronUpIcon from "../../../../images/QueryBuilder/CollapseChevronUp_16x.png";
import { ClientDefaults, KeyCodes } from "../../../Common/Constants"; import { ClientDefaults, KeyCodes } from "../../../Common/Constants";
import { useNotificationConsole } from "../../../hooks/useNotificationConsole";
import { userContext } from "../../../UserContext"; import { userContext } from "../../../UserContext";
/** /**
@ -321,3 +322,23 @@ const PrPreview = (props: { pr: string }) => {
</> </>
); );
}; };
export const NotificationConsole: React.FC<
Pick<NotificationConsoleComponentProps, "consoleData" | "inProgressConsoleDataIdToBeDeleted">
> = ({
consoleData,
inProgressConsoleDataIdToBeDeleted,
}: Pick<NotificationConsoleComponentProps, "consoleData" | "inProgressConsoleDataIdToBeDeleted">) => {
const setIsExpanded = useNotificationConsole((state) => state.setIsExpanded);
const isExpanded = useNotificationConsole((state) => state.isExpanded);
// TODO Refactor NotificationConsoleComponent into a functional component and remove this wrapper
// This component only exists so we can use hooks and pass them down to a non-functional component
return (
<NotificationConsoleComponent
consoleData={consoleData}
inProgressConsoleDataIdToBeDeleted={inProgressConsoleDataIdToBeDeleted}
isConsoleExpanded={isExpanded}
setIsConsoleExpanded={setIsExpanded}
/>
);
};

View File

@ -14,13 +14,13 @@ import { MemoryUsageInfo } from "../../Contracts/DataModels";
import { GitHubClient } from "../../GitHub/GitHubClient"; import { GitHubClient } from "../../GitHub/GitHubClient";
import { GitHubContentProvider } from "../../GitHub/GitHubContentProvider"; import { GitHubContentProvider } from "../../GitHub/GitHubContentProvider";
import { GitHubOAuthService } from "../../GitHub/GitHubOAuthService"; import { GitHubOAuthService } from "../../GitHub/GitHubOAuthService";
import { useSidePanel } from "../../hooks/useSidePanel";
import { JunoClient } from "../../Juno/JunoClient"; import { JunoClient } from "../../Juno/JunoClient";
import { Action, ActionModifiers } from "../../Shared/Telemetry/TelemetryConstants"; import { Action, ActionModifiers } from "../../Shared/Telemetry/TelemetryConstants";
import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor"; import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
import { userContext } from "../../UserContext"; import { userContext } from "../../UserContext";
import { getFullName } from "../../Utils/UserUtils"; import { getFullName } from "../../Utils/UserUtils";
import Explorer from "../Explorer"; import Explorer from "../Explorer";
import { ContextualPaneBase } from "../Panes/ContextualPaneBase";
import { CopyNotebookPane } from "../Panes/CopyNotebookPane/CopyNotebookPane"; import { CopyNotebookPane } from "../Panes/CopyNotebookPane/CopyNotebookPane";
import { PublishNotebookPane } from "../Panes/PublishNotebookPane/PublishNotebookPane"; import { PublishNotebookPane } from "../Panes/PublishNotebookPane/PublishNotebookPane";
import { ResourceTreeAdapter } from "../Tree/ResourceTreeAdapter"; import { ResourceTreeAdapter } from "../Tree/ResourceTreeAdapter";
@ -56,8 +56,6 @@ export default class NotebookManager {
public gitHubOAuthService: GitHubOAuthService; public gitHubOAuthService: GitHubOAuthService;
public gitHubClient: GitHubClient; public gitHubClient: GitHubClient;
public gitHubReposPane: ContextualPaneBase;
public initialize(params: NotebookManagerOptions): void { public initialize(params: NotebookManagerOptions): void {
this.params = params; this.params = params;
this.junoClient = new JunoClient(); this.junoClient = new JunoClient();
@ -98,7 +96,7 @@ export default class NotebookManager {
this.gitHubOAuthService.getTokenObservable().subscribe((token) => { this.gitHubOAuthService.getTokenObservable().subscribe((token) => {
this.gitHubClient.setToken(token?.access_token); this.gitHubClient.setToken(token?.access_token);
if (this?.gitHubOAuthService.isLoggedIn()) { if (this?.gitHubOAuthService.isLoggedIn()) {
this.params.container.closeSidePanel(); useSidePanel.getState().closeSidePanel();
this.params.container.openGitHubReposPanel("Manager GitHub settings", this.junoClient); this.params.container.openGitHubReposPanel("Manager GitHub settings", this.junoClient);
} }
@ -127,37 +125,37 @@ export default class NotebookManager {
onTakeSnapshot: (request: SnapshotRequest) => void, onTakeSnapshot: (request: SnapshotRequest) => void,
onClosePanel: () => void onClosePanel: () => void
): Promise<void> { ): Promise<void> {
const explorer = this.params.container; useSidePanel
explorer.openSidePanel( .getState()
"Publish Notebook", .openSidePanel(
<PublishNotebookPane "Publish Notebook",
explorer={this.params.container} <PublishNotebookPane
junoClient={this.junoClient} explorer={this.params.container}
closePanel={this.params.container.closeSidePanel} junoClient={this.junoClient}
openNotificationConsole={this.params.container.expandConsole} name={name}
name={name} author={getFullName()}
author={getFullName()} notebookContent={content}
notebookContent={content} notebookContentRef={notebookContentRef}
notebookContentRef={notebookContentRef} onTakeSnapshot={onTakeSnapshot}
onTakeSnapshot={onTakeSnapshot} />,
/>, onClosePanel
onClosePanel );
);
} }
public openCopyNotebookPane(name: string, content: string): void { public openCopyNotebookPane(name: string, content: string): void {
const { container } = this.params; const { container } = this.params;
container.openSidePanel( useSidePanel
"Copy Notebook", .getState()
<CopyNotebookPane .openSidePanel(
container={container} "Copy Notebook",
closePanel={container.closeSidePanel} <CopyNotebookPane
junoClient={this.junoClient} container={container}
gitHubOAuthService={this.gitHubOAuthService} junoClient={this.junoClient}
name={name} gitHubOAuthService={this.gitHubOAuthService}
content={content} name={name}
/> content={content}
); />
);
} }
// Octokit's error handler uses any // Octokit's error handler uses any

View File

@ -20,6 +20,7 @@ import { getErrorMessage, getErrorStack } from "../../Common/ErrorHandlingUtils"
import { configContext, Platform } from "../../ConfigContext"; import { configContext, Platform } from "../../ConfigContext";
import * as DataModels from "../../Contracts/DataModels"; import * as DataModels from "../../Contracts/DataModels";
import { SubscriptionType } from "../../Contracts/SubscriptionType"; import { SubscriptionType } from "../../Contracts/SubscriptionType";
import { useSidePanel } from "../../hooks/useSidePanel";
import { CollectionCreation } from "../../Shared/Constants"; import { CollectionCreation } from "../../Shared/Constants";
import { Action } from "../../Shared/Telemetry/TelemetryConstants"; import { Action } from "../../Shared/Telemetry/TelemetryConstants";
import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor"; import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
@ -36,8 +37,6 @@ import { PanelLoadingScreen } from "./PanelLoadingScreen";
export interface AddCollectionPanelProps { export interface AddCollectionPanelProps {
explorer: Explorer; explorer: Explorer;
closePanel: () => void;
openNotificationConsole: () => void;
databaseId?: string; databaseId?: string;
} }
@ -133,7 +132,6 @@ export class AddCollectionPanel extends React.Component<AddCollectionPanelProps,
message={this.state.errorMessage} message={this.state.errorMessage}
messageType="error" messageType="error"
showErrorDetails={this.state.showErrorDetails} showErrorDetails={this.state.showErrorDetails}
openNotificationConsole={this.props.openNotificationConsole}
/> />
)} )}
@ -142,7 +140,6 @@ export class AddCollectionPanel extends React.Component<AddCollectionPanelProps,
message={getUpsellMessage(userContext.portalEnv, true, this.props.explorer.isFirstResourceCreated(), true)} message={getUpsellMessage(userContext.portalEnv, true, this.props.explorer.isFirstResourceCreated(), true)}
messageType="info" messageType="info"
showErrorDetails={false} showErrorDetails={false}
openNotificationConsole={this.props.openNotificationConsole}
link={Constants.Urls.freeTierInformation} link={Constants.Urls.freeTierInformation}
linkText="Learn more" linkText="Learn more"
/> />
@ -1062,7 +1059,7 @@ export class AddCollectionPanel extends React.Component<AddCollectionPanelProps,
this.setState({ isExecuting: false }); this.setState({ isExecuting: false });
this.props.explorer.refreshAllDatabases(); this.props.explorer.refreshAllDatabases();
TelemetryProcessor.traceSuccess(Action.CreateCollection, telemetryData, startKey); TelemetryProcessor.traceSuccess(Action.CreateCollection, telemetryData, startKey);
this.props.closePanel(); useSidePanel.getState().closeSidePanel();
} catch (error) { } catch (error) {
const errorMessage: string = getErrorMessage(error); const errorMessage: string = getErrorMessage(error);
this.setState({ isExecuting: false, errorMessage, showErrorDetails: true }); this.setState({ isExecuting: false, errorMessage, showErrorDetails: true });

View File

@ -6,6 +6,7 @@ import { getErrorMessage, getErrorStack } from "../../../Common/ErrorHandlingUti
import { InfoTooltip } from "../../../Common/Tooltip/InfoTooltip"; import { InfoTooltip } from "../../../Common/Tooltip/InfoTooltip";
import * as DataModels from "../../../Contracts/DataModels"; import * as DataModels from "../../../Contracts/DataModels";
import { SubscriptionType } from "../../../Contracts/SubscriptionType"; import { SubscriptionType } from "../../../Contracts/SubscriptionType";
import { useSidePanel } from "../../../hooks/useSidePanel";
import * as SharedConstants from "../../../Shared/Constants"; import * as SharedConstants from "../../../Shared/Constants";
import { Action, ActionModifiers } from "../../../Shared/Telemetry/TelemetryConstants"; import { Action, ActionModifiers } from "../../../Shared/Telemetry/TelemetryConstants";
import * as TelemetryProcessor from "../../../Shared/Telemetry/TelemetryProcessor"; import * as TelemetryProcessor from "../../../Shared/Telemetry/TelemetryProcessor";
@ -20,15 +21,12 @@ import { RightPaneForm, RightPaneFormProps } from "../RightPaneForm/RightPaneFor
export interface AddDatabasePaneProps { export interface AddDatabasePaneProps {
explorer: Explorer; explorer: Explorer;
closePanel: () => void;
openNotificationConsole: () => void;
} }
export const AddDatabasePanel: FunctionComponent<AddDatabasePaneProps> = ({ export const AddDatabasePanel: FunctionComponent<AddDatabasePaneProps> = ({
explorer: container, explorer: container,
closePanel,
openNotificationConsole,
}: AddDatabasePaneProps) => { }: AddDatabasePaneProps) => {
const closeSidePanel = useSidePanel((state) => state.closeSidePanel);
let throughput: number; let throughput: number;
let isAutoscaleSelected: boolean; let isAutoscaleSelected: boolean;
let isCostAcknowledged: boolean; let isCostAcknowledged: boolean;
@ -114,7 +112,7 @@ export const AddDatabasePanel: FunctionComponent<AddDatabasePaneProps> = ({
const _onCreateDatabaseSuccess = (offerThroughput: number, startKey: number): void => { const _onCreateDatabaseSuccess = (offerThroughput: number, startKey: number): void => {
setIsExecuting(false); setIsExecuting(false);
closePanel(); closeSidePanel();
container.refreshAllDatabases(); container.refreshAllDatabases();
const addDatabasePaneSuccessMessage = { const addDatabasePaneSuccessMessage = {
...addDatabasePaneMessage, ...addDatabasePaneMessage,
@ -163,7 +161,6 @@ export const AddDatabasePanel: FunctionComponent<AddDatabasePaneProps> = ({
); );
const props: RightPaneFormProps = { const props: RightPaneFormProps = {
expandConsole: openNotificationConsole,
formError: formErrors, formError: formErrors,
isExecuting, isExecuting,
submitButtonText: "OK", submitButtonText: "OK",
@ -177,7 +174,6 @@ export const AddDatabasePanel: FunctionComponent<AddDatabasePaneProps> = ({
message={getUpsellMessage(userContext.portalEnv, true, container.isFirstResourceCreated(), true)} message={getUpsellMessage(userContext.portalEnv, true, container.isFirstResourceCreated(), true)}
messageType="info" messageType="info"
showErrorDetails={false} showErrorDetails={false}
openNotificationConsole={openNotificationConsole}
link={Constants.Urls.freeTierInformation} link={Constants.Urls.freeTierInformation}
linkText="Learn more" linkText="Learn more"
/> />

View File

@ -2,7 +2,6 @@
exports[`AddDatabasePane Pane should render Default properly 1`] = ` exports[`AddDatabasePane Pane should render Default properly 1`] = `
<RightPaneForm <RightPaneForm
expandConsole={[Function]}
formError="" formError=""
isExecuting={false} isExecuting={false}
onSubmit={[Function]} onSubmit={[Function]}

View File

@ -3,6 +3,7 @@ import { Areas } from "../../../Common/Constants";
import { logError } from "../../../Common/Logger"; import { logError } from "../../../Common/Logger";
import { Query } from "../../../Contracts/DataModels"; import { Query } from "../../../Contracts/DataModels";
import { Collection } from "../../../Contracts/ViewModels"; import { Collection } from "../../../Contracts/ViewModels";
import { useSidePanel } from "../../../hooks/useSidePanel";
import { Action, ActionModifiers } from "../../../Shared/Telemetry/TelemetryConstants"; import { Action, ActionModifiers } from "../../../Shared/Telemetry/TelemetryConstants";
import { trace } from "../../../Shared/Telemetry/TelemetryProcessor"; import { trace } from "../../../Shared/Telemetry/TelemetryProcessor";
import { userContext } from "../../../UserContext"; import { userContext } from "../../../UserContext";
@ -15,13 +16,12 @@ import QueryTab from "../../Tabs/QueryTab";
interface BrowseQueriesPaneProps { interface BrowseQueriesPaneProps {
explorer: Explorer; explorer: Explorer;
closePanel: () => void;
} }
export const BrowseQueriesPane: FunctionComponent<BrowseQueriesPaneProps> = ({ export const BrowseQueriesPane: FunctionComponent<BrowseQueriesPaneProps> = ({
explorer, explorer,
closePanel,
}: BrowseQueriesPaneProps): JSX.Element => { }: BrowseQueriesPaneProps): JSX.Element => {
const closeSidePanel = useSidePanel((state) => state.closeSidePanel);
const loadSavedQuery = (savedQuery: Query): void => { const loadSavedQuery = (savedQuery: Query): void => {
const selectedCollection: Collection = explorer && explorer.findSelectedCollection(); const selectedCollection: Collection = explorer && explorer.findSelectedCollection();
if (!selectedCollection) { if (!selectedCollection) {
@ -43,7 +43,7 @@ export const BrowseQueriesPane: FunctionComponent<BrowseQueriesPaneProps> = ({
queryName: savedQuery.queryName, queryName: savedQuery.queryName,
paneTitle: "Open Saved Queries", paneTitle: "Open Saved Queries",
}); });
closePanel(); closeSidePanel();
}; };
const props: QueriesGridComponentProps = { const props: QueriesGridComponentProps = {

View File

@ -6,6 +6,7 @@ import { getErrorMessage, getErrorStack } from "../../../Common/ErrorHandlingUti
import { InfoTooltip } from "../../../Common/Tooltip/InfoTooltip"; import { InfoTooltip } from "../../../Common/Tooltip/InfoTooltip";
import * as DataModels from "../../../Contracts/DataModels"; import * as DataModels from "../../../Contracts/DataModels";
import * as ViewModels from "../../../Contracts/ViewModels"; import * as ViewModels from "../../../Contracts/ViewModels";
import { useSidePanel } from "../../../hooks/useSidePanel";
import * as AddCollectionUtility from "../../../Shared/AddCollectionUtility"; import * as AddCollectionUtility from "../../../Shared/AddCollectionUtility";
import * as SharedConstants from "../../../Shared/Constants"; import * as SharedConstants from "../../../Shared/Constants";
import { Action, ActionModifiers } from "../../../Shared/Telemetry/TelemetryConstants"; import { Action, ActionModifiers } from "../../../Shared/Telemetry/TelemetryConstants";
@ -19,15 +20,14 @@ import { RightPaneForm, RightPaneFormProps } from "../RightPaneForm/RightPaneFor
export interface CassandraAddCollectionPaneProps { export interface CassandraAddCollectionPaneProps {
explorer: Explorer; explorer: Explorer;
closePanel: () => void;
cassandraApiClient: CassandraAPIDataClient; cassandraApiClient: CassandraAPIDataClient;
} }
export const CassandraAddCollectionPane: FunctionComponent<CassandraAddCollectionPaneProps> = ({ export const CassandraAddCollectionPane: FunctionComponent<CassandraAddCollectionPaneProps> = ({
explorer: container, explorer: container,
closePanel,
cassandraApiClient, cassandraApiClient,
}: CassandraAddCollectionPaneProps) => { }: CassandraAddCollectionPaneProps) => {
const closeSidePanel = useSidePanel((state) => state.closeSidePanel);
const throughputDefaults = userContext.collectionCreationDefaults.throughput; const throughputDefaults = userContext.collectionCreationDefaults.throughput;
const [createTableQuery, setCreateTableQuery] = useState<string>("CREATE TABLE "); const [createTableQuery, setCreateTableQuery] = useState<string>("CREATE TABLE ");
const [keyspaceId, setKeyspaceId] = useState<string>(""); const [keyspaceId, setKeyspaceId] = useState<string>("");
@ -241,7 +241,7 @@ export const CassandraAddCollectionPane: FunctionComponent<CassandraAddCollectio
} }
container.refreshAllDatabases(); container.refreshAllDatabases();
setIsExecuting(false); setIsExecuting(false);
closePanel(); closeSidePanel();
TelemetryProcessor.traceSuccess(Action.CreateCollection, addCollectionPaneStartMessage, startKey); TelemetryProcessor.traceSuccess(Action.CreateCollection, addCollectionPaneStartMessage, startKey);
} catch (error) { } catch (error) {
@ -261,7 +261,6 @@ export const CassandraAddCollectionPane: FunctionComponent<CassandraAddCollectio
}; };
const props: RightPaneFormProps = { const props: RightPaneFormProps = {
expandConsole: () => container.expandConsole(),
formError: formErrors, formError: formErrors,
isExecuting, isExecuting,
submitButtonText: "Apply", submitButtonText: "Apply",

View File

@ -2,7 +2,6 @@
exports[`CassandraAddCollectionPane Pane should render Default properly 1`] = ` exports[`CassandraAddCollectionPane Pane should render Default properly 1`] = `
<RightPaneForm <RightPaneForm
expandConsole={[Function]}
formError="" formError=""
onSubmit={[Function]} onSubmit={[Function]}
submitButtonText="Apply" submitButtonText="Apply"

View File

@ -1,126 +0,0 @@
import * as ko from "knockout";
import * as ViewModels from "../../Contracts/ViewModels";
import * as Constants from "../../Common/Constants";
import { Action, ActionModifiers } from "../../Shared/Telemetry/TelemetryConstants";
import { KeyCodes } from "../../Common/Constants";
import { WaitsForTemplateViewModel } from "../WaitsForTemplateViewModel";
import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
import Explorer from "../Explorer";
// TODO: Use specific actions for logging telemetry data
export abstract class ContextualPaneBase extends WaitsForTemplateViewModel {
private initalFocusedElement: HTMLElement | undefined;
public id: string;
public container: Explorer;
public firstFieldHasFocus: ko.Observable<boolean>;
public formErrorsDetails: ko.Observable<string>;
public formErrors: ko.Observable<string>;
public title: ko.Observable<string>;
public visible: ko.Observable<boolean>;
public isExecuting: ko.Observable<boolean>;
constructor(options: ViewModels.PaneOptions) {
super();
this.id = options.id;
this.container = options.container;
this.visible = options.visible || ko.observable(false);
this.firstFieldHasFocus = ko.observable<boolean>(false);
this.formErrors = ko.observable<string>();
this.title = ko.observable<string>();
this.formErrorsDetails = ko.observable<string>();
this.isExecuting = ko.observable<boolean>(false);
}
public cancel() {
this.close();
this.container.isAccountReady() &&
TelemetryProcessor.trace(Action.ContextualPane, ActionModifiers.Close, {
dataExplorerArea: Constants.Areas.ContextualPane,
paneTitle: this.title(),
});
}
public close() {
this.visible(false);
this.isExecuting(false);
this.resetData();
this.resetFocus();
}
public open() {
this.initalFocusedElement = document.activeElement as HTMLElement;
this.visible(true);
this.firstFieldHasFocus(true);
this.resizePane();
this.container.isAccountReady() &&
TelemetryProcessor.trace(Action.ContextualPane, ActionModifiers.Open, {
dataExplorerArea: Constants.Areas.ContextualPane,
paneTitle: this.title(),
});
}
public resetData() {
this.firstFieldHasFocus(false);
this.formErrors(null);
this.formErrorsDetails(null);
}
public showErrorDetails() {
this.container.expandConsole();
}
public submit() {
this.close();
event.stopPropagation();
this.container.isAccountReady() &&
TelemetryProcessor.trace(Action.ContextualPane, ActionModifiers.Submit, {
dataExplorerArea: Constants.Areas.ContextualPane,
paneTitle: this.title(),
});
}
public onCloseKeyPress(source: any, event: KeyboardEvent): boolean {
if (event.keyCode === KeyCodes.Enter || event.keyCode === KeyCodes.Space) {
this.close();
event.stopPropagation();
return false;
}
return true;
}
public onPaneKeyDown(source: any, event: KeyboardEvent): boolean {
if (event.keyCode === KeyCodes.Escape) {
this.close();
event.stopPropagation();
return false;
}
return true;
}
public onSubmitKeyPress(source: any, event: KeyboardEvent): boolean {
if (event.keyCode === KeyCodes.Enter || event.keyCode === KeyCodes.Space) {
this.submit();
event.stopPropagation();
return false;
}
return true;
}
private resizePane(): void {
const paneElement: HTMLElement = document.getElementById(this.id);
const notificationConsoleElement: HTMLElement = document.getElementById("explorerNotificationConsole");
const newPaneElementHeight = window.innerHeight - $(notificationConsoleElement).height();
$(paneElement).height(newPaneElementHeight);
}
private resetFocus(): void {
if (this.initalFocusedElement) {
this.initalFocusedElement.focus();
this.initalFocusedElement = undefined;
}
}
}

View File

@ -3,6 +3,7 @@ import React, { FormEvent, FunctionComponent, useEffect, useState } from "react"
import { HttpStatusCodes } from "../../../Common/Constants"; import { HttpStatusCodes } from "../../../Common/Constants";
import { getErrorMessage, handleError } from "../../../Common/ErrorHandlingUtils"; import { getErrorMessage, handleError } from "../../../Common/ErrorHandlingUtils";
import { GitHubOAuthService } from "../../../GitHub/GitHubOAuthService"; import { GitHubOAuthService } from "../../../GitHub/GitHubOAuthService";
import { useSidePanel } from "../../../hooks/useSidePanel";
import { IPinnedRepo, JunoClient } from "../../../Juno/JunoClient"; import { IPinnedRepo, JunoClient } from "../../../Juno/JunoClient";
import * as GitHubUtils from "../../../Utils/GitHubUtils"; import * as GitHubUtils from "../../../Utils/GitHubUtils";
import * as NotificationConsoleUtils from "../../../Utils/NotificationConsoleUtils"; import * as NotificationConsoleUtils from "../../../Utils/NotificationConsoleUtils";
@ -26,7 +27,6 @@ export interface CopyNotebookPanelProps {
container: Explorer; container: Explorer;
junoClient: JunoClient; junoClient: JunoClient;
gitHubOAuthService: GitHubOAuthService; gitHubOAuthService: GitHubOAuthService;
closePanel: () => void;
} }
export const CopyNotebookPane: FunctionComponent<CopyNotebookPanelProps> = ({ export const CopyNotebookPane: FunctionComponent<CopyNotebookPanelProps> = ({
@ -35,8 +35,8 @@ export const CopyNotebookPane: FunctionComponent<CopyNotebookPanelProps> = ({
container, container,
junoClient, junoClient,
gitHubOAuthService, gitHubOAuthService,
closePanel,
}: CopyNotebookPanelProps) => { }: CopyNotebookPanelProps) => {
const closeSidePanel = useSidePanel((state) => state.closeSidePanel);
const [isExecuting, setIsExecuting] = useState<boolean>(); const [isExecuting, setIsExecuting] = useState<boolean>();
const [formError, setFormError] = useState<string>(""); const [formError, setFormError] = useState<string>("");
const [pinnedRepos, setPinnedRepos] = useState<IPinnedRepo[]>(); const [pinnedRepos, setPinnedRepos] = useState<IPinnedRepo[]>();
@ -84,7 +84,7 @@ export const CopyNotebookPane: FunctionComponent<CopyNotebookPanelProps> = ({
} }
NotificationConsoleUtils.logConsoleInfo(`Successfully copied ${name} to ${destination}`); NotificationConsoleUtils.logConsoleInfo(`Successfully copied ${name} to ${destination}`);
closePanel(); closeSidePanel();
} catch (error) { } catch (error) {
const errorMessage = getErrorMessage(error); const errorMessage = getErrorMessage(error);
setFormError(`Failed to copy ${name} to ${destination}`); setFormError(`Failed to copy ${name} to ${destination}`);
@ -130,7 +130,6 @@ export const CopyNotebookPane: FunctionComponent<CopyNotebookPanelProps> = ({
isExecuting: isExecuting, isExecuting: isExecuting,
submitButtonText: "OK", submitButtonText: "OK",
onSubmit: () => submit(), onSubmit: () => submit(),
expandConsole: () => container.expandConsole(),
}; };
const copyNotebookPaneProps: CopyNotebookPaneProps = { const copyNotebookPaneProps: CopyNotebookPaneProps = {

View File

@ -5,6 +5,7 @@ import { deleteCollection } from "../../../Common/dataAccess/deleteCollection";
import DeleteFeedback from "../../../Common/DeleteFeedback"; import DeleteFeedback from "../../../Common/DeleteFeedback";
import { getErrorMessage, getErrorStack } from "../../../Common/ErrorHandlingUtils"; import { getErrorMessage, getErrorStack } from "../../../Common/ErrorHandlingUtils";
import { Collection } from "../../../Contracts/ViewModels"; import { Collection } from "../../../Contracts/ViewModels";
import { useSidePanel } from "../../../hooks/useSidePanel";
import { DefaultExperienceUtility } from "../../../Shared/DefaultExperienceUtility"; import { DefaultExperienceUtility } from "../../../Shared/DefaultExperienceUtility";
import { Action, ActionModifiers } from "../../../Shared/Telemetry/TelemetryConstants"; import { Action, ActionModifiers } from "../../../Shared/Telemetry/TelemetryConstants";
import * as TelemetryProcessor from "../../../Shared/Telemetry/TelemetryProcessor"; import * as TelemetryProcessor from "../../../Shared/Telemetry/TelemetryProcessor";
@ -15,13 +16,12 @@ import Explorer from "../../Explorer";
import { RightPaneForm, RightPaneFormProps } from "../RightPaneForm/RightPaneForm"; import { RightPaneForm, RightPaneFormProps } from "../RightPaneForm/RightPaneForm";
export interface DeleteCollectionConfirmationPaneProps { export interface DeleteCollectionConfirmationPaneProps {
explorer: Explorer; explorer: Explorer;
closePanel: () => void;
} }
export const DeleteCollectionConfirmationPane: FunctionComponent<DeleteCollectionConfirmationPaneProps> = ({ export const DeleteCollectionConfirmationPane: FunctionComponent<DeleteCollectionConfirmationPaneProps> = ({
explorer, explorer,
closePanel,
}: DeleteCollectionConfirmationPaneProps) => { }: DeleteCollectionConfirmationPaneProps) => {
const closeSidePanel = useSidePanel((state) => state.closeSidePanel);
const [deleteCollectionFeedback, setDeleteCollectionFeedback] = useState<string>(""); const [deleteCollectionFeedback, setDeleteCollectionFeedback] = useState<string>("");
const [inputCollectionName, setInputCollectionName] = useState<string>(""); const [inputCollectionName, setInputCollectionName] = useState<string>("");
const [formError, setFormError] = useState<string>(""); const [formError, setFormError] = useState<string>("");
@ -79,7 +79,7 @@ export const DeleteCollectionConfirmationPane: FunctionComponent<DeleteCollectio
}); });
} }
closePanel(); closeSidePanel();
} catch (error) { } catch (error) {
const errorMessage = getErrorMessage(error); const errorMessage = getErrorMessage(error);
@ -102,7 +102,6 @@ export const DeleteCollectionConfirmationPane: FunctionComponent<DeleteCollectio
isExecuting, isExecuting,
submitButtonText: "OK", submitButtonText: "OK",
onSubmit, onSubmit,
expandConsole: () => explorer.expandConsole(),
}; };
return ( return (
<RightPaneForm {...props}> <RightPaneForm {...props}>

View File

@ -16,7 +16,6 @@ exports[`Delete Collection Confirmation Pane submit() should call delete collect
} }
> >
<RightPaneForm <RightPaneForm
expandConsole={[Function]}
formError="" formError=""
isExecuting={false} isExecuting={false}
onSubmit={[Function]} onSubmit={[Function]}

View File

@ -6,6 +6,7 @@ import { deleteDatabase } from "../../Common/dataAccess/deleteDatabase";
import DeleteFeedback from "../../Common/DeleteFeedback"; import DeleteFeedback from "../../Common/DeleteFeedback";
import { getErrorMessage, getErrorStack } from "../../Common/ErrorHandlingUtils"; import { getErrorMessage, getErrorStack } from "../../Common/ErrorHandlingUtils";
import { Collection, Database } from "../../Contracts/ViewModels"; import { Collection, Database } from "../../Contracts/ViewModels";
import { useSidePanel } from "../../hooks/useSidePanel";
import { DefaultExperienceUtility } from "../../Shared/DefaultExperienceUtility"; import { DefaultExperienceUtility } from "../../Shared/DefaultExperienceUtility";
import { Action, ActionModifiers } from "../../Shared/Telemetry/TelemetryConstants"; import { Action, ActionModifiers } from "../../Shared/Telemetry/TelemetryConstants";
import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor"; import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
@ -17,17 +18,14 @@ import { RightPaneForm, RightPaneFormProps } from "./RightPaneForm/RightPaneForm
interface DeleteDatabaseConfirmationPanelProps { interface DeleteDatabaseConfirmationPanelProps {
explorer: Explorer; explorer: Explorer;
closePanel: () => void;
openNotificationConsole: () => void;
selectedDatabase: Database; selectedDatabase: Database;
} }
export const DeleteDatabaseConfirmationPanel: FunctionComponent<DeleteDatabaseConfirmationPanelProps> = ({ export const DeleteDatabaseConfirmationPanel: FunctionComponent<DeleteDatabaseConfirmationPanelProps> = ({
explorer, explorer,
openNotificationConsole,
closePanel,
selectedDatabase, selectedDatabase,
}: DeleteDatabaseConfirmationPanelProps): JSX.Element => { }: DeleteDatabaseConfirmationPanelProps): JSX.Element => {
const closeSidePanel = useSidePanel((state) => state.closeSidePanel);
const [isLoading, { setTrue: setLoadingTrue, setFalse: setLoadingFalse }] = useBoolean(false); const [isLoading, { setTrue: setLoadingTrue, setFalse: setLoadingFalse }] = useBoolean(false);
const [formError, setFormError] = useState<string>(""); const [formError, setFormError] = useState<string>("");
@ -51,7 +49,7 @@ export const DeleteDatabaseConfirmationPanel: FunctionComponent<DeleteDatabaseCo
try { try {
await deleteDatabase(selectedDatabase.id()); await deleteDatabase(selectedDatabase.id());
closePanel(); closeSidePanel();
explorer.refreshAllDatabases(); explorer.refreshAllDatabases();
explorer.tabsManager.closeTabsByComparator((tab) => tab.node?.id() === selectedDatabase.id()); explorer.tabsManager.closeTabsByComparator((tab) => tab.node?.id() === selectedDatabase.id());
explorer.selectedNode(undefined); explorer.selectedNode(undefined);
@ -111,7 +109,6 @@ export const DeleteDatabaseConfirmationPanel: FunctionComponent<DeleteDatabaseCo
isExecuting: isLoading, isExecuting: isLoading,
submitButtonText: "OK", submitButtonText: "OK",
onSubmit: () => submit(), onSubmit: () => submit(),
expandConsole: openNotificationConsole,
}; };
const errorProps: PanelInfoErrorProps = { const errorProps: PanelInfoErrorProps = {

View File

@ -2,15 +2,14 @@ import { IDropdownOption, IImageProps, Image, Stack, Text } from "@fluentui/reac
import { useBoolean } from "@fluentui/react-hooks"; import { useBoolean } from "@fluentui/react-hooks";
import React, { FunctionComponent, useState } from "react"; import React, { FunctionComponent, useState } from "react";
import AddPropertyIcon from "../../../../images/Add-property.svg"; import AddPropertyIcon from "../../../../images/Add-property.svg";
import { useSidePanel } from "../../../hooks/useSidePanel";
import { logConsoleError } from "../../../Utils/NotificationConsoleUtils"; import { logConsoleError } from "../../../Utils/NotificationConsoleUtils";
import StoredProcedure from "../../Tree/StoredProcedure"; import StoredProcedure from "../../Tree/StoredProcedure";
import { RightPaneForm, RightPaneFormProps } from "../RightPaneForm/RightPaneForm"; import { RightPaneForm, RightPaneFormProps } from "../RightPaneForm/RightPaneForm";
import { InputParameter } from "./InputParameter"; import { InputParameter } from "./InputParameter";
interface ExecuteSprocParamsPaneProps { interface ExecuteSprocParamsPaneProps {
expandConsole: () => void;
storedProcedure: StoredProcedure; storedProcedure: StoredProcedure;
closePanel: () => void;
} }
const imageProps: IImageProps = { const imageProps: IImageProps = {
@ -24,10 +23,9 @@ interface UnwrappedExecuteSprocParam {
} }
export const ExecuteSprocParamsPane: FunctionComponent<ExecuteSprocParamsPaneProps> = ({ export const ExecuteSprocParamsPane: FunctionComponent<ExecuteSprocParamsPaneProps> = ({
expandConsole,
storedProcedure, storedProcedure,
closePanel,
}: ExecuteSprocParamsPaneProps): JSX.Element => { }: ExecuteSprocParamsPaneProps): JSX.Element => {
const closeSidePanel = useSidePanel((state) => state.closeSidePanel);
const [isLoading, { setTrue: setLoadingTrue, setFalse: setLoadingFalse }] = useBoolean(false); const [isLoading, { setTrue: setLoadingTrue, setFalse: setLoadingFalse }] = useBoolean(false);
const [paramKeyValues, setParamKeyValues] = useState<UnwrappedExecuteSprocParam[]>([{ key: "string", text: "" }]); const [paramKeyValues, setParamKeyValues] = useState<UnwrappedExecuteSprocParam[]>([{ key: "string", text: "" }]);
const [partitionValue, setPartitionValue] = useState<string>(); // Defaulting to undefined here is important. It is not the same partition key as "" const [partitionValue, setPartitionValue] = useState<string>(); // Defaulting to undefined here is important. It is not the same partition key as ""
@ -76,7 +74,7 @@ export const ExecuteSprocParamsPane: FunctionComponent<ExecuteSprocParamsPanePro
}); });
storedProcedure.execute(sprocParams, partitionKey === "custom" ? JSON.parse(partitionValue) : partitionValue); storedProcedure.execute(sprocParams, partitionKey === "custom" ? JSON.parse(partitionValue) : partitionValue);
setLoadingFalse(); setLoadingFalse();
closePanel(); closeSidePanel();
}; };
const deleteParamAtIndex = (indexToRemove: number): void => { const deleteParamAtIndex = (indexToRemove: number): void => {
@ -114,7 +112,6 @@ export const ExecuteSprocParamsPane: FunctionComponent<ExecuteSprocParamsPanePro
}; };
const props: RightPaneFormProps = { const props: RightPaneFormProps = {
expandConsole,
formError: formError, formError: formError,
isExecuting: isLoading, isExecuting: isLoading,
submitButtonText: "Execute", submitButtonText: "Execute",

View File

@ -7,7 +7,6 @@ exports[`Excute Sproc Param Pane should render Default properly 1`] = `
storedProcedure={Object {}} storedProcedure={Object {}}
> >
<RightPaneForm <RightPaneForm
expandConsole={[Function]}
formError="" formError=""
isExecuting={false} isExecuting={false}
onSubmit={[Function]} onSubmit={[Function]}

View File

@ -2,6 +2,7 @@ import React from "react";
import { Areas, HttpStatusCodes } from "../../../Common/Constants"; import { Areas, HttpStatusCodes } from "../../../Common/Constants";
import { handleError } from "../../../Common/ErrorHandlingUtils"; import { handleError } from "../../../Common/ErrorHandlingUtils";
import { GitHubClient, IGitHubPageInfo, IGitHubRepo } from "../../../GitHub/GitHubClient"; import { GitHubClient, IGitHubPageInfo, IGitHubRepo } from "../../../GitHub/GitHubClient";
import { useSidePanel } from "../../../hooks/useSidePanel";
import { IPinnedRepo, JunoClient } from "../../../Juno/JunoClient"; import { IPinnedRepo, JunoClient } from "../../../Juno/JunoClient";
import { Action, ActionModifiers } from "../../../Shared/Telemetry/TelemetryConstants"; import { Action, ActionModifiers } from "../../../Shared/Telemetry/TelemetryConstants";
import * as TelemetryProcessor from "../../../Shared/Telemetry/TelemetryProcessor"; import * as TelemetryProcessor from "../../../Shared/Telemetry/TelemetryProcessor";
@ -21,10 +22,8 @@ import { PanelLoadingScreen } from "../PanelLoadingScreen";
interface IGitHubReposPanelProps { interface IGitHubReposPanelProps {
explorer: Explorer; explorer: Explorer;
closePanel: () => void;
gitHubClientProp: GitHubClient; gitHubClientProp: GitHubClient;
junoClientProp: JunoClient; junoClientProp: JunoClient;
openNotificationConsole: () => void;
} }
interface IGitHubReposPanelState { interface IGitHubReposPanelState {
@ -91,7 +90,7 @@ export class GitHubReposPanel extends React.Component<IGitHubReposPanelProps, IG
}, },
resetConnection: (): void => this.setup(true), resetConnection: (): void => this.setup(true),
onOkClick: (): Promise<void> => this.submit(), onOkClick: (): Promise<void> => this.submit(),
onCancelClick: (): void => this.props.closePanel(), onCancelClick: (): void => useSidePanel.getState().closeSidePanel(),
}, },
}; };
this.gitHubClient = this.props.gitHubClientProp; this.gitHubClient = this.props.gitHubClientProp;
@ -439,7 +438,6 @@ export class GitHubReposPanel extends React.Component<IGitHubReposPanelProps, IG
message={this.state.errorMessage} message={this.state.errorMessage}
messageType="error" messageType="error"
showErrorDetails={this.state.showErrorDetails} showErrorDetails={this.state.showErrorDetails}
openNotificationConsole={this.props.openNotificationConsole}
/> />
)} )}
<div className="panelMainContent" style={ContentMainStyle}> <div className="panelMainContent" style={ContentMainStyle}>

View File

@ -20,7 +20,6 @@ exports[`GitHub Repos Panel should render Default properly 1`] = `
"_isInitializingNotebooks": false, "_isInitializingNotebooks": false,
"_resetNotebookWorkspace": [Function], "_resetNotebookWorkspace": [Function],
"canSaveQueries": [Function], "canSaveQueries": [Function],
"closeSidePanel": undefined,
"collapsedResourceTreeWidth": 36, "collapsedResourceTreeWidth": 36,
"commandBarComponentAdapter": CommandBarComponentAdapter { "commandBarComponentAdapter": CommandBarComponentAdapter {
"container": [Circular], "container": [Circular],
@ -45,7 +44,6 @@ exports[`GitHub Repos Panel should render Default properly 1`] = `
"notebookServerInfo": [Function], "notebookServerInfo": [Function],
"onRefreshDatabasesKeyPress": [Function], "onRefreshDatabasesKeyPress": [Function],
"onRefreshResourcesClick": [Function], "onRefreshResourcesClick": [Function],
"openSidePanel": undefined,
"provideFeedbackEmail": [Function], "provideFeedbackEmail": [Function],
"queriesClient": QueriesClient { "queriesClient": QueriesClient {
"container": [Circular], "container": [Circular],
@ -70,7 +68,6 @@ exports[`GitHub Repos Panel should render Default properly 1`] = `
"selectedDatabaseId": [Function], "selectedDatabaseId": [Function],
"selectedNode": [Function], "selectedNode": [Function],
"setInProgressConsoleDataIdToBeDeleted": undefined, "setInProgressConsoleDataIdToBeDeleted": undefined,
"setIsNotificationConsoleExpanded": undefined,
"setNotificationConsoleData": undefined, "setNotificationConsoleData": undefined,
"sparkClusterConnectionInfo": [Function], "sparkClusterConnectionInfo": [Function],
"splitter": Splitter { "splitter": Splitter {

View File

@ -1,25 +1,26 @@
import React, { FunctionComponent } from "react"; import React, { FunctionComponent } from "react";
import * as ViewModels from "../../../Contracts/ViewModels"; import * as ViewModels from "../../../Contracts/ViewModels";
import { useSidePanel } from "../../../hooks/useSidePanel";
import { GraphStyleComponent } from "../../Graph/GraphStyleComponent/GraphStyleComponent"; import { GraphStyleComponent } from "../../Graph/GraphStyleComponent/GraphStyleComponent";
import { IGraphConfig } from "../../Tabs/GraphTab"; import { IGraphConfig } from "../../Tabs/GraphTab";
import { PanelFooterComponent } from "../PanelFooterComponent"; import { PanelFooterComponent } from "../PanelFooterComponent";
interface GraphStylingProps { interface GraphStylingProps {
closePanel: () => void;
igraphConfigUiData: ViewModels.IGraphConfigUiData; igraphConfigUiData: ViewModels.IGraphConfigUiData;
igraphConfig: IGraphConfig; igraphConfig: IGraphConfig;
getValues: (igraphConfig?: IGraphConfig) => void; getValues: (igraphConfig?: IGraphConfig) => void;
} }
export const GraphStylingPanel: FunctionComponent<GraphStylingProps> = ({ export const GraphStylingPanel: FunctionComponent<GraphStylingProps> = ({
closePanel,
igraphConfigUiData, igraphConfigUiData,
igraphConfig, igraphConfig,
getValues, getValues,
}: GraphStylingProps): JSX.Element => { }: GraphStylingProps): JSX.Element => {
const closeSidePanel = useSidePanel((state) => state.closeSidePanel);
const buttonLabel = "Ok"; const buttonLabel = "Ok";
const submit = () => { const submit = () => {
closePanel(); closeSidePanel();
}; };
return ( return (

View File

@ -4,6 +4,7 @@ import React, { FunctionComponent, useState } from "react";
import folderIcon from "../../../../images/folder_16x16.svg"; import folderIcon from "../../../../images/folder_16x16.svg";
import { logError } from "../../../Common/Logger"; import { logError } from "../../../Common/Logger";
import { Collection } from "../../../Contracts/ViewModels"; import { Collection } from "../../../Contracts/ViewModels";
import { useSidePanel } from "../../../hooks/useSidePanel";
import { userContext } from "../../../UserContext"; import { userContext } from "../../../UserContext";
import { logConsoleError, logConsoleInfo, logConsoleProgress } from "../../../Utils/NotificationConsoleUtils"; import { logConsoleError, logConsoleInfo, logConsoleProgress } from "../../../Utils/NotificationConsoleUtils";
import Explorer from "../../Explorer"; import Explorer from "../../Explorer";
@ -12,13 +13,10 @@ import { RightPaneForm, RightPaneFormProps } from "../RightPaneForm/RightPaneFor
interface LoadQueryPaneProps { interface LoadQueryPaneProps {
explorer: Explorer; explorer: Explorer;
closePanel: () => void;
} }
export const LoadQueryPane: FunctionComponent<LoadQueryPaneProps> = ({ export const LoadQueryPane: FunctionComponent<LoadQueryPaneProps> = ({ explorer }: LoadQueryPaneProps): JSX.Element => {
explorer, const closeSidePanel = useSidePanel((state) => state.closeSidePanel);
closePanel,
}: LoadQueryPaneProps): JSX.Element => {
const [isLoading, { setTrue: setLoadingTrue, setFalse: setLoadingFalse }] = useBoolean(false); const [isLoading, { setTrue: setLoadingTrue, setFalse: setLoadingFalse }] = useBoolean(false);
const [formError, setFormError] = useState<string>(""); const [formError, setFormError] = useState<string>("");
const [selectedFileName, setSelectedFileName] = useState<string>(""); const [selectedFileName, setSelectedFileName] = useState<string>("");
@ -51,7 +49,7 @@ export const LoadQueryPane: FunctionComponent<LoadQueryPaneProps> = ({
try { try {
await loadQueryFromFile(file); await loadQueryFromFile(file);
logConsoleInfo(`Successfully loaded query from file ${file.name}`); logConsoleInfo(`Successfully loaded query from file ${file.name}`);
closePanel(); closeSidePanel();
setLoadingFalse(); setLoadingFalse();
} catch (error) { } catch (error) {
setLoadingFalse(); setLoadingFalse();
@ -89,7 +87,6 @@ export const LoadQueryPane: FunctionComponent<LoadQueryPaneProps> = ({
isExecuting: isLoading, isExecuting: isLoading,
submitButtonText: "Load", submitButtonText: "Load",
onSubmit: () => submit(), onSubmit: () => submit(),
expandConsole: () => explorer.expandConsole(),
}; };
return ( return (

View File

@ -2,7 +2,6 @@
exports[`Load Query Pane should render Default properly 1`] = ` exports[`Load Query Pane should render Default properly 1`] = `
<RightPaneForm <RightPaneForm
expandConsole={[Function]}
formError="" formError=""
isExecuting={false} isExecuting={false}
onSubmit={[Function]} onSubmit={[Function]}

View File

@ -36,14 +36,7 @@ describe("New Vertex Panel", () => {
it("should call form submit method", () => { it("should call form submit method", () => {
const onSubmitSpy = jest.fn(); const onSubmitSpy = jest.fn();
const newWrapper = mount( const newWrapper = mount(<NewVertexPanel partitionKeyPropertyProp={undefined} onSubmit={onSubmitSpy} />);
<NewVertexPanel
explorer={fakeExplorer}
partitionKeyPropertyProp={undefined}
openNotificationConsole={(): void => undefined}
onSubmit={onSubmitSpy}
/>
);
//eslint-disable-next-line //eslint-disable-next-line
newWrapper.find("form").simulate("submit", { preventDefault: () => {} }); newWrapper.find("form").simulate("submit", { preventDefault: () => {} });
@ -61,14 +54,7 @@ describe("New Vertex Panel", () => {
const result = onSubmitSpy(fakeNewVertexData, onErrorSpy, onSuccessSpy); const result = onSubmitSpy(fakeNewVertexData, onErrorSpy, onSuccessSpy);
const newWrapper = mount( const newWrapper = mount(<NewVertexPanel partitionKeyPropertyProp={undefined} onSubmit={onSubmitSpy} />);
<NewVertexPanel
explorer={fakeExplorer}
partitionKeyPropertyProp={undefined}
openNotificationConsole={(): void => undefined}
onSubmit={onSubmitSpy}
/>
);
//eslint-disable-next-line //eslint-disable-next-line
newWrapper.find("form").simulate("submit", { preventDefault: () => {} }); newWrapper.find("form").simulate("submit", { preventDefault: () => {} });

View File

@ -1,21 +1,17 @@
import { useBoolean } from "@fluentui/react-hooks"; import { useBoolean } from "@fluentui/react-hooks";
import React, { FunctionComponent, useState } from "react"; import React, { FunctionComponent, useState } from "react";
import * as ViewModels from "../../../Contracts/ViewModels"; import * as ViewModels from "../../../Contracts/ViewModels";
import Explorer from "../../Explorer"; import { useSidePanel } from "../../../hooks/useSidePanel";
import { NewVertexComponent } from "../../Graph/NewVertexComponent/NewVertexComponent"; import { NewVertexComponent } from "../../Graph/NewVertexComponent/NewVertexComponent";
import { RightPaneForm, RightPaneFormProps } from "../RightPaneForm/RightPaneForm"; import { RightPaneForm, RightPaneFormProps } from "../RightPaneForm/RightPaneForm";
export interface INewVertexPanelProps { export interface INewVertexPanelProps {
explorer: Explorer;
partitionKeyPropertyProp: string; partitionKeyPropertyProp: string;
onSubmit: (result: ViewModels.NewVertexData, onError: (errorMsg: string) => void, onSuccess: () => void) => void; onSubmit: (result: ViewModels.NewVertexData, onError: (errorMsg: string) => void, onSuccess: () => void) => void;
openNotificationConsole: () => void;
} }
export const NewVertexPanel: FunctionComponent<INewVertexPanelProps> = ({ export const NewVertexPanel: FunctionComponent<INewVertexPanelProps> = ({
explorer,
partitionKeyPropertyProp, partitionKeyPropertyProp,
onSubmit, onSubmit,
openNotificationConsole,
}: INewVertexPanelProps): JSX.Element => { }: INewVertexPanelProps): JSX.Element => {
let newVertexDataValue: ViewModels.NewVertexData; let newVertexDataValue: ViewModels.NewVertexData;
const [errorMessage, setErrorMessage] = useState<string>(""); const [errorMessage, setErrorMessage] = useState<string>("");
@ -33,10 +29,10 @@ export const NewVertexPanel: FunctionComponent<INewVertexPanelProps> = ({
setErrorMessage(errorMsg); setErrorMessage(errorMsg);
setLoadingFalse(); setLoadingFalse();
}; };
const closeSidePanel = useSidePanel((state) => state.closeSidePanel);
const onSuccess = () => { const onSuccess = () => {
setLoadingFalse(); setLoadingFalse();
explorer.closeSidePanel(); closeSidePanel();
}; };
const onChange = (newVertexData: ViewModels.NewVertexData) => { const onChange = (newVertexData: ViewModels.NewVertexData) => {
@ -47,7 +43,6 @@ export const NewVertexPanel: FunctionComponent<INewVertexPanelProps> = ({
isExecuting: isLoading, isExecuting: isLoading,
submitButtonText: "OK", submitButtonText: "OK",
onSubmit: () => submit(), onSubmit: () => submit(),
expandConsole: openNotificationConsole,
}; };
return ( return (

View File

@ -2,7 +2,6 @@
exports[`New Vertex Panel should render default property 1`] = ` exports[`New Vertex Panel should render default property 1`] = `
<RightPaneForm <RightPaneForm
expandConsole={[Function]}
formError="" formError=""
isExecuting={false} isExecuting={false}
onSubmit={[Function]} onSubmit={[Function]}

View File

@ -9,7 +9,6 @@ describe("PaneContainerComponent test", () => {
panelContent: <div></div>, panelContent: <div></div>,
isOpen: true, isOpen: true,
isConsoleExpanded: false, isConsoleExpanded: false,
closePanel: undefined,
}; };
const wrapper = shallow(<PanelContainerComponent {...panelContainerProps} />); const wrapper = shallow(<PanelContainerComponent {...panelContainerProps} />);
expect(wrapper).toMatchSnapshot(); expect(wrapper).toMatchSnapshot();
@ -21,7 +20,6 @@ describe("PaneContainerComponent test", () => {
panelContent: undefined, panelContent: undefined,
isOpen: true, isOpen: true,
isConsoleExpanded: false, isConsoleExpanded: false,
closePanel: undefined,
}; };
const wrapper = shallow(<PanelContainerComponent {...panelContainerProps} />); const wrapper = shallow(<PanelContainerComponent {...panelContainerProps} />);
expect(wrapper).toMatchSnapshot(); expect(wrapper).toMatchSnapshot();
@ -33,7 +31,6 @@ describe("PaneContainerComponent test", () => {
panelContent: <div></div>, panelContent: <div></div>,
isOpen: true, isOpen: true,
isConsoleExpanded: true, isConsoleExpanded: true,
closePanel: undefined,
}; };
const wrapper = shallow(<PanelContainerComponent {...panelContainerProps} />); const wrapper = shallow(<PanelContainerComponent {...panelContainerProps} />);
expect(wrapper).toMatchSnapshot(); expect(wrapper).toMatchSnapshot();

View File

@ -1,12 +1,13 @@
import { IPanelProps, IRenderFunction, Panel, PanelType } from "@fluentui/react"; import { IPanelProps, IRenderFunction, Panel, PanelType } from "@fluentui/react";
import * as React from "react"; import * as React from "react";
import { useNotificationConsole } from "../../hooks/useNotificationConsole";
import { useSidePanel } from "../../hooks/useSidePanel";
export interface PanelContainerProps { export interface PanelContainerProps {
headerText: string; headerText: string;
panelContent: JSX.Element; panelContent: JSX.Element;
isConsoleExpanded: boolean; isConsoleExpanded: boolean;
isOpen: boolean; isOpen: boolean;
closePanel: () => void;
panelWidth?: string; panelWidth?: string;
onRenderNavigationContent?: IRenderFunction<IPanelProps>; onRenderNavigationContent?: IRenderFunction<IPanelProps>;
} }
@ -69,7 +70,7 @@ export class PanelContainerComponent extends React.Component<PanelContainerProps
if ((ev.target as HTMLElement).id === "notificationConsoleHeader") { if ((ev.target as HTMLElement).id === "notificationConsoleHeader") {
ev.preventDefault(); ev.preventDefault();
} else { } else {
this.props.closePanel(); useSidePanel.getState().closeSidePanel();
} }
}; };
@ -81,3 +82,24 @@ export class PanelContainerComponent extends React.Component<PanelContainerProps
return panelHeight + "px"; return panelHeight + "px";
}; };
} }
export const SidePanel: React.FC = () => {
const isConsoleExpanded = useNotificationConsole((state) => state.isExpanded);
const { isOpen, panelContent, headerText } = useSidePanel((state) => {
return {
isOpen: state.isOpen,
panelContent: state.panelContent,
headerText: state.headerText,
};
});
// TODO Refactor PanelContainerComponent into a functional component and remove this wrapper
// This component only exists so we can use hooks and pass them down to a non-functional component
return (
<PanelContainerComponent
isOpen={isOpen}
panelContent={panelContent}
headerText={headerText}
isConsoleExpanded={isConsoleExpanded}
/>
);
};

View File

@ -1,5 +1,6 @@
import { Icon, Link, Stack, Text } from "@fluentui/react"; import { Icon, Link, Stack, Text } from "@fluentui/react";
import React from "react"; import React from "react";
import { useNotificationConsole } from "../../hooks/useNotificationConsole";
export interface PanelInfoErrorProps { export interface PanelInfoErrorProps {
message: string; message: string;
@ -7,7 +8,6 @@ export interface PanelInfoErrorProps {
showErrorDetails: boolean; showErrorDetails: boolean;
link?: string; link?: string;
linkText?: string; linkText?: string;
openNotificationConsole?: () => void;
formError?: boolean; formError?: boolean;
} }
@ -17,8 +17,9 @@ export const PanelInfoErrorComponent: React.FunctionComponent<PanelInfoErrorProp
showErrorDetails, showErrorDetails,
link, link,
linkText, linkText,
openNotificationConsole,
}: PanelInfoErrorProps): JSX.Element => { }: PanelInfoErrorProps): JSX.Element => {
const expandConsole = useNotificationConsole((state) => state.expandConsole);
let icon: JSX.Element = <Icon iconName="InfoSolid" className="panelLargeInfoIcon" aria-label="Infomation" />; let icon: JSX.Element = <Icon iconName="InfoSolid" className="panelLargeInfoIcon" aria-label="Infomation" />;
if (messageType === "error") { if (messageType === "error") {
icon = <Icon iconName="StatusErrorFull" className="panelErrorIcon" aria-label="error" />; icon = <Icon iconName="StatusErrorFull" className="panelErrorIcon" aria-label="error" />;
@ -41,7 +42,7 @@ export const PanelInfoErrorComponent: React.FunctionComponent<PanelInfoErrorProp
)} )}
</Text> </Text>
{showErrorDetails && ( {showErrorDetails && (
<a className="paneErrorLink" role="link" onClick={openNotificationConsole}> <a className="paneErrorLink" role="link" onClick={expandConsole}>
More details More details
</a> </a>
)} )}

View File

@ -3,6 +3,7 @@ import React, { FunctionComponent, useEffect, useState } from "react";
import { HttpStatusCodes } from "../../../Common/Constants"; import { HttpStatusCodes } from "../../../Common/Constants";
import { getErrorMessage, getErrorStack, handleError } from "../../../Common/ErrorHandlingUtils"; import { getErrorMessage, getErrorStack, handleError } from "../../../Common/ErrorHandlingUtils";
import { useNotebookSnapshotStore } from "../../../hooks/useNotebookSnapshotStore"; import { useNotebookSnapshotStore } from "../../../hooks/useNotebookSnapshotStore";
import { useSidePanel } from "../../../hooks/useSidePanel";
import { JunoClient } from "../../../Juno/JunoClient"; import { JunoClient } from "../../../Juno/JunoClient";
import { Action } from "../../../Shared/Telemetry/TelemetryConstants"; import { Action } from "../../../Shared/Telemetry/TelemetryConstants";
import { traceFailure, traceStart, traceSuccess } from "../../../Shared/Telemetry/TelemetryProcessor"; import { traceFailure, traceStart, traceSuccess } from "../../../Shared/Telemetry/TelemetryProcessor";
@ -17,8 +18,6 @@ import { PublishNotebookPaneComponent, PublishNotebookPaneProps } from "./Publis
export interface PublishNotebookPaneAProps { export interface PublishNotebookPaneAProps {
explorer: Explorer; explorer: Explorer;
closePanel: () => void;
openNotificationConsole: () => void;
junoClient: JunoClient; junoClient: JunoClient;
name: string; name: string;
author: string; author: string;
@ -29,13 +28,14 @@ export interface PublishNotebookPaneAProps {
export const PublishNotebookPane: FunctionComponent<PublishNotebookPaneAProps> = ({ export const PublishNotebookPane: FunctionComponent<PublishNotebookPaneAProps> = ({
explorer: container, explorer: container,
junoClient, junoClient,
closePanel,
name, name,
author, author,
notebookContent, notebookContent,
notebookContentRef, notebookContentRef,
onTakeSnapshot, onTakeSnapshot,
}: PublishNotebookPaneAProps): JSX.Element => { }: PublishNotebookPaneAProps): JSX.Element => {
const closeSidePanel = useSidePanel((state) => state.closeSidePanel);
const [isCodeOfConductAccepted, setIsCodeOfConductAccepted] = useState<boolean>(false); const [isCodeOfConductAccepted, setIsCodeOfConductAccepted] = useState<boolean>(false);
const [content, setContent] = useState<string>(""); const [content, setContent] = useState<string>("");
const [formError, setFormError] = useState<string>(""); const [formError, setFormError] = useState<string>("");
@ -152,7 +152,7 @@ export const PublishNotebookPane: FunctionComponent<PublishNotebookPaneAProps> =
clearPublishingMessage(); clearPublishingMessage();
setIsExecuting(false); setIsExecuting(false);
} }
closePanel(); closeSidePanel();
}; };
const createFormError = (formError: string, formErrorDetail: string, area: string): void => { const createFormError = (formError: string, formErrorDetail: string, area: string): void => {
@ -171,7 +171,6 @@ export const PublishNotebookPane: FunctionComponent<PublishNotebookPaneAProps> =
isExecuting: isExecuting, isExecuting: isExecuting,
submitButtonText: "Publish", submitButtonText: "Publish",
onSubmit: () => submit(), onSubmit: () => submit(),
expandConsole: () => container.expandConsole(),
isSubmitButtonHidden: !isCodeOfConductAccepted, isSubmitButtonHidden: !isCodeOfConductAccepted,
}; };

View File

@ -4,7 +4,6 @@ import { PanelInfoErrorComponent } from "../PanelInfoErrorComponent";
import { PanelLoadingScreen } from "../PanelLoadingScreen"; import { PanelLoadingScreen } from "../PanelLoadingScreen";
export interface RightPaneFormProps { export interface RightPaneFormProps {
expandConsole: () => void;
formError: string; formError: string;
isExecuting: boolean; isExecuting: boolean;
onSubmit: () => void; onSubmit: () => void;
@ -14,7 +13,6 @@ export interface RightPaneFormProps {
} }
export const RightPaneForm: FunctionComponent<RightPaneFormProps> = ({ export const RightPaneForm: FunctionComponent<RightPaneFormProps> = ({
expandConsole,
formError, formError,
isExecuting, isExecuting,
onSubmit, onSubmit,
@ -30,14 +28,7 @@ export const RightPaneForm: FunctionComponent<RightPaneFormProps> = ({
return ( return (
<> <>
<form className="panelFormWrapper" onSubmit={handleOnSubmit}> <form className="panelFormWrapper" onSubmit={handleOnSubmit}>
{formError && ( {formError && <PanelInfoErrorComponent messageType="error" message={formError} showErrorDetails={true} />}
<PanelInfoErrorComponent
messageType="error"
message={formError}
showErrorDetails={true}
openNotificationConsole={expandConsole}
/>
)}
{children} {children}
{!isSubmitButtonHidden && <PanelFooterComponent buttonLabel={submitButtonText} />} {!isSubmitButtonHidden && <PanelFooterComponent buttonLabel={submitButtonText} />}
</form> </form>

View File

@ -4,6 +4,7 @@ import React, { FunctionComponent, useState } from "react";
import { Areas, SavedQueries } from "../../../Common/Constants"; import { Areas, SavedQueries } from "../../../Common/Constants";
import { getErrorMessage, getErrorStack } from "../../../Common/ErrorHandlingUtils"; import { getErrorMessage, getErrorStack } from "../../../Common/ErrorHandlingUtils";
import { Query } from "../../../Contracts/DataModels"; import { Query } from "../../../Contracts/DataModels";
import { useSidePanel } from "../../../hooks/useSidePanel";
import { Action } from "../../../Shared/Telemetry/TelemetryConstants"; import { Action } from "../../../Shared/Telemetry/TelemetryConstants";
import { traceFailure, traceStart, traceSuccess } from "../../../Shared/Telemetry/TelemetryProcessor"; import { traceFailure, traceStart, traceSuccess } from "../../../Shared/Telemetry/TelemetryProcessor";
import { logConsoleError } from "../../../Utils/NotificationConsoleUtils"; import { logConsoleError } from "../../../Utils/NotificationConsoleUtils";
@ -13,13 +14,10 @@ import { RightPaneForm, RightPaneFormProps } from "../RightPaneForm/RightPaneFor
interface SaveQueryPaneProps { interface SaveQueryPaneProps {
explorer: Explorer; explorer: Explorer;
closePanel: () => void;
} }
export const SaveQueryPane: FunctionComponent<SaveQueryPaneProps> = ({ export const SaveQueryPane: FunctionComponent<SaveQueryPaneProps> = ({ explorer }: SaveQueryPaneProps): JSX.Element => {
explorer, const closeSidePanel = useSidePanel((state) => state.closeSidePanel);
closePanel,
}: SaveQueryPaneProps): JSX.Element => {
const [isLoading, { setTrue: setLoadingTrue, setFalse: setLoadingFalse }] = useBoolean(false); const [isLoading, { setTrue: setLoadingTrue, setFalse: setLoadingFalse }] = useBoolean(false);
const [formError, setFormError] = useState<string>(""); const [formError, setFormError] = useState<string>("");
const [queryName, setQueryName] = useState<string>(""); const [queryName, setQueryName] = useState<string>("");
@ -71,7 +69,7 @@ export const SaveQueryPane: FunctionComponent<SaveQueryPaneProps> = ({
}, },
startKey startKey
); );
closePanel(); closeSidePanel();
} catch (error) { } catch (error) {
setLoadingFalse(); setLoadingFalse();
const errorMessage = getErrorMessage(error); const errorMessage = getErrorMessage(error);
@ -128,7 +126,6 @@ export const SaveQueryPane: FunctionComponent<SaveQueryPaneProps> = ({
}; };
const props: RightPaneFormProps = { const props: RightPaneFormProps = {
expandConsole: () => explorer.expandConsole(),
formError: formError, formError: formError,
isExecuting: isLoading, isExecuting: isLoading,
submitButtonText: canSaveQueries() ? "Save" : "Complete setup", submitButtonText: canSaveQueries() ? "Save" : "Complete setup",

View File

@ -2,7 +2,6 @@
exports[`Save Query Pane should render Default properly 1`] = ` exports[`Save Query Pane should render Default properly 1`] = `
<RightPaneForm <RightPaneForm
expandConsole={[Function]}
formError="" formError=""
isExecuting={false} isExecuting={false}
onSubmit={[Function]} onSubmit={[Function]}

View File

@ -3,13 +3,10 @@ import React from "react";
import { DatabaseAccount } from "../../../Contracts/DataModels"; import { DatabaseAccount } from "../../../Contracts/DataModels";
import { updateUserContext } from "../../../UserContext"; import { updateUserContext } from "../../../UserContext";
import { SettingsPane } from "./SettingsPane"; import { SettingsPane } from "./SettingsPane";
const props = {
expandConsole: (): void => undefined,
closePanel: (): void => undefined,
};
describe("Settings Pane", () => { describe("Settings Pane", () => {
it("should render Default properly", () => { it("should render Default properly", () => {
const wrapper = shallow(<SettingsPane {...props} />); const wrapper = shallow(<SettingsPane />);
expect(wrapper).toMatchSnapshot(); expect(wrapper).toMatchSnapshot();
}); });
@ -21,7 +18,7 @@ describe("Settings Pane", () => {
}, },
} as DatabaseAccount, } as DatabaseAccount,
}); });
const wrapper = shallow(<SettingsPane {...props} />); const wrapper = shallow(<SettingsPane />);
expect(wrapper).toMatchSnapshot(); expect(wrapper).toMatchSnapshot();
}); });
}); });

View File

@ -3,21 +3,15 @@ import React, { FunctionComponent, MouseEvent, useState } from "react";
import * as Constants from "../../../Common/Constants"; import * as Constants from "../../../Common/Constants";
import { InfoTooltip } from "../../../Common/Tooltip/InfoTooltip"; import { InfoTooltip } from "../../../Common/Tooltip/InfoTooltip";
import { configContext } from "../../../ConfigContext"; import { configContext } from "../../../ConfigContext";
import { useSidePanel } from "../../../hooks/useSidePanel";
import { LocalStorageUtility, StorageKey } from "../../../Shared/StorageUtility"; import { LocalStorageUtility, StorageKey } from "../../../Shared/StorageUtility";
import * as StringUtility from "../../../Shared/StringUtility"; import * as StringUtility from "../../../Shared/StringUtility";
import { userContext } from "../../../UserContext"; import { userContext } from "../../../UserContext";
import { logConsoleInfo } from "../../../Utils/NotificationConsoleUtils"; import { logConsoleInfo } from "../../../Utils/NotificationConsoleUtils";
import { RightPaneForm, RightPaneFormProps } from "../RightPaneForm/RightPaneForm"; import { RightPaneForm, RightPaneFormProps } from "../RightPaneForm/RightPaneForm";
export interface SettingsPaneProps { export const SettingsPane: FunctionComponent = () => {
expandConsole: () => void; const closeSidePanel = useSidePanel((state) => state.closeSidePanel);
closePanel: () => void;
}
export const SettingsPane: FunctionComponent<SettingsPaneProps> = ({
expandConsole,
closePanel,
}: SettingsPaneProps) => {
const [isExecuting, setIsExecuting] = useState<boolean>(false); const [isExecuting, setIsExecuting] = useState<boolean>(false);
const [pageOption, setPageOption] = useState<string>( const [pageOption, setPageOption] = useState<string>(
LocalStorageUtility.getEntryNumber(StorageKey.ActualItemPerPage) === Constants.Queries.unlimitedItemsPerPage LocalStorageUtility.getEntryNumber(StorageKey.ActualItemPerPage) === Constants.Queries.unlimitedItemsPerPage
@ -88,7 +82,7 @@ export const SettingsPane: FunctionComponent<SettingsPaneProps> = ({
logConsoleInfo( logConsoleInfo(
`Updated query setting to ${LocalStorageUtility.getEntryString(StorageKey.SetPartitionKeyUndefined)}` `Updated query setting to ${LocalStorageUtility.getEntryString(StorageKey.SetPartitionKeyUndefined)}`
); );
closePanel(); closeSidePanel();
e.preventDefault(); e.preventDefault();
}; };
@ -101,7 +95,6 @@ export const SettingsPane: FunctionComponent<SettingsPaneProps> = ({
}; };
const genericPaneProps: RightPaneFormProps = { const genericPaneProps: RightPaneFormProps = {
expandConsole,
formError: "", formError: "",
isExecuting, isExecuting,
submitButtonText: "Apply", submitButtonText: "Apply",

View File

@ -2,7 +2,6 @@
exports[`Settings Pane should render Default properly 1`] = ` exports[`Settings Pane should render Default properly 1`] = `
<RightPaneForm <RightPaneForm
expandConsole={[Function]}
formError="" formError=""
isExecuting={false} isExecuting={false}
onSubmit={[Function]} onSubmit={[Function]}
@ -149,7 +148,6 @@ exports[`Settings Pane should render Default properly 1`] = `
exports[`Settings Pane should render Gremlin properly 1`] = ` exports[`Settings Pane should render Gremlin properly 1`] = `
<RightPaneForm <RightPaneForm
expandConsole={[Function]}
formError="" formError=""
isExecuting={false} isExecuting={false}
onSubmit={[Function]} onSubmit={[Function]}

View File

@ -3,6 +3,7 @@ import { useBoolean } from "@fluentui/react-hooks";
import React, { FunctionComponent, KeyboardEvent, useState } from "react"; import React, { FunctionComponent, KeyboardEvent, useState } from "react";
import { Areas, NormalizedEventKey } from "../../../Common/Constants"; import { Areas, NormalizedEventKey } from "../../../Common/Constants";
import { getErrorMessage, getErrorStack } from "../../../Common/ErrorHandlingUtils"; import { getErrorMessage, getErrorStack } from "../../../Common/ErrorHandlingUtils";
import { useSidePanel } from "../../../hooks/useSidePanel";
import { Action } from "../../../Shared/Telemetry/TelemetryConstants"; import { Action } from "../../../Shared/Telemetry/TelemetryConstants";
import * as TelemetryProcessor from "../../../Shared/Telemetry/TelemetryProcessor"; import * as TelemetryProcessor from "../../../Shared/Telemetry/TelemetryProcessor";
import { userContext } from "../../../UserContext"; import { userContext } from "../../../UserContext";
@ -12,20 +13,17 @@ import { PanelInfoErrorComponent } from "../PanelInfoErrorComponent";
import { PanelLoadingScreen } from "../PanelLoadingScreen"; import { PanelLoadingScreen } from "../PanelLoadingScreen";
interface SetupNoteBooksPanelProps { interface SetupNoteBooksPanelProps {
explorer: Explorer; explorer: Explorer;
closePanel: () => void;
openNotificationConsole: () => void;
panelTitle: string; panelTitle: string;
panelDescription: string; panelDescription: string;
} }
export const SetupNoteBooksPanel: FunctionComponent<SetupNoteBooksPanelProps> = ({ export const SetupNoteBooksPanel: FunctionComponent<SetupNoteBooksPanelProps> = ({
explorer, explorer,
closePanel,
openNotificationConsole,
panelTitle, panelTitle,
panelDescription, panelDescription,
}: SetupNoteBooksPanelProps): JSX.Element => { }: SetupNoteBooksPanelProps): JSX.Element => {
const title = panelTitle; const closeSidePanel = useSidePanel((state) => state.closeSidePanel);
const description = panelDescription; const description = panelDescription;
const [isLoading, { setTrue: setLoadingTrue, setFalse: setLoadingFalse }] = useBoolean(false); const [isLoading, { setTrue: setLoadingTrue, setFalse: setLoadingFalse }] = useBoolean(false);
const [errorMessage, setErrorMessage] = useState<string>(""); const [errorMessage, setErrorMessage] = useState<string>("");
@ -51,7 +49,7 @@ export const SetupNoteBooksPanel: FunctionComponent<SetupNoteBooksPanelProps> =
const startKey: number = TelemetryProcessor.traceStart(Action.CreateNotebookWorkspace, { const startKey: number = TelemetryProcessor.traceStart(Action.CreateNotebookWorkspace, {
dataExplorerArea: Areas.ContextualPane, dataExplorerArea: Areas.ContextualPane,
paneTitle: title, paneTitle: panelTitle,
}); });
const clear = NotificationConsoleUtils.logConsoleProgress("Creating a new default notebook workspace"); const clear = NotificationConsoleUtils.logConsoleProgress("Creating a new default notebook workspace");
@ -64,13 +62,13 @@ export const SetupNoteBooksPanel: FunctionComponent<SetupNoteBooksPanelProps> =
); );
explorer.isAccountReady.valueHasMutated(); // re-trigger init notebooks explorer.isAccountReady.valueHasMutated(); // re-trigger init notebooks
closePanel(); closeSidePanel();
TelemetryProcessor.traceSuccess( TelemetryProcessor.traceSuccess(
Action.CreateNotebookWorkspace, Action.CreateNotebookWorkspace,
{ {
dataExplorerArea: Areas.ContextualPane, dataExplorerArea: Areas.ContextualPane,
paneTitle: title, paneTitle: panelTitle,
}, },
startKey startKey
); );
@ -81,7 +79,7 @@ export const SetupNoteBooksPanel: FunctionComponent<SetupNoteBooksPanelProps> =
Action.CreateNotebookWorkspace, Action.CreateNotebookWorkspace,
{ {
dataExplorerArea: Areas.ContextualPane, dataExplorerArea: Areas.ContextualPane,
paneTitle: title, paneTitle: panelTitle,
error: errorMessage, error: errorMessage,
errorStack: getErrorStack(error), errorStack: getErrorStack(error),
}, },
@ -99,12 +97,7 @@ export const SetupNoteBooksPanel: FunctionComponent<SetupNoteBooksPanelProps> =
return ( return (
<form className="panelFormWrapper"> <form className="panelFormWrapper">
{errorMessage && ( {errorMessage && (
<PanelInfoErrorComponent <PanelInfoErrorComponent message={errorMessage} messageType="error" showErrorDetails={showErrorDetails} />
message={errorMessage}
messageType="error"
showErrorDetails={showErrorDetails}
openNotificationConsole={openNotificationConsole}
/>
)} )}
<div className="panelMainContent"> <div className="panelMainContent">
<div className="pkPadding"> <div className="pkPadding">

View File

@ -89,7 +89,6 @@ export const StringInputPane: FunctionComponent<StringInputPanelProps> = ({
isExecuting: isExecuting, isExecuting: isExecuting,
submitButtonText: submitButtonLabel, submitButtonText: submitButtonLabel,
onSubmit: submit, onSubmit: submit,
expandConsole: () => container.expandConsole(),
}; };
return ( return (
<RightPaneForm {...props}> <RightPaneForm {...props}>

View File

@ -10,7 +10,6 @@ exports[`StringInput Pane should render Create new directory properly 1`] = `
"_isInitializingNotebooks": false, "_isInitializingNotebooks": false,
"_resetNotebookWorkspace": [Function], "_resetNotebookWorkspace": [Function],
"canSaveQueries": [Function], "canSaveQueries": [Function],
"closeSidePanel": undefined,
"collapsedResourceTreeWidth": 36, "collapsedResourceTreeWidth": 36,
"commandBarComponentAdapter": CommandBarComponentAdapter { "commandBarComponentAdapter": CommandBarComponentAdapter {
"container": [Circular], "container": [Circular],
@ -35,7 +34,6 @@ exports[`StringInput Pane should render Create new directory properly 1`] = `
"notebookServerInfo": [Function], "notebookServerInfo": [Function],
"onRefreshDatabasesKeyPress": [Function], "onRefreshDatabasesKeyPress": [Function],
"onRefreshResourcesClick": [Function], "onRefreshResourcesClick": [Function],
"openSidePanel": undefined,
"provideFeedbackEmail": [Function], "provideFeedbackEmail": [Function],
"queriesClient": QueriesClient { "queriesClient": QueriesClient {
"container": [Circular], "container": [Circular],
@ -60,7 +58,6 @@ exports[`StringInput Pane should render Create new directory properly 1`] = `
"selectedDatabaseId": [Function], "selectedDatabaseId": [Function],
"selectedNode": [Function], "selectedNode": [Function],
"setInProgressConsoleDataIdToBeDeleted": undefined, "setInProgressConsoleDataIdToBeDeleted": undefined,
"setIsNotificationConsoleExpanded": undefined,
"setNotificationConsoleData": undefined, "setNotificationConsoleData": undefined,
"sparkClusterConnectionInfo": [Function], "sparkClusterConnectionInfo": [Function],
"splitter": Splitter { "splitter": Splitter {
@ -97,7 +94,6 @@ exports[`StringInput Pane should render Create new directory properly 1`] = `
successMessage="Created directory " successMessage="Created directory "
> >
<RightPaneForm <RightPaneForm
expandConsole={[Function]}
formError="" formError=""
isExecuting={false} isExecuting={false}
onSubmit={[Function]} onSubmit={[Function]}

View File

@ -1,23 +1,20 @@
import { mount } from "enzyme"; import { mount } from "enzyme";
import * as ko from "knockout"; import * as ko from "knockout";
import React from "react"; import React from "react";
import Explorer from "../../Explorer";
import TableListViewModal from "../../Tables/DataTable/TableEntityListViewModel"; import TableListViewModal from "../../Tables/DataTable/TableEntityListViewModel";
import * as Entities from "../../Tables/Entities"; import * as Entities from "../../Tables/Entities";
import { CassandraAPIDataClient } from "../../Tables/TableDataClient"; import { CassandraAPIDataClient, TablesAPIDataClient } from "../../Tables/TableDataClient";
import QueryTablesTab from "../../Tabs/QueryTablesTab"; import QueryTablesTab from "../../Tabs/QueryTablesTab";
import { AddTableEntityPanel } from "./AddTableEntityPanel"; import { AddTableEntityPanel } from "./AddTableEntityPanel";
describe("Excute Add Table Entity Pane", () => { describe("Excute Add Table Entity Pane", () => {
const fakeExplorer = {} as Explorer;
const fakeQueryTablesTab = {} as QueryTablesTab; const fakeQueryTablesTab = {} as QueryTablesTab;
const fakeTableEntityListViewModel = {} as TableListViewModal; const fakeTableEntityListViewModel = {} as TableListViewModal;
const fakeCassandraApiClient = {} as CassandraAPIDataClient; const fakeCassandraApiClient = {} as CassandraAPIDataClient;
fakeTableEntityListViewModel.items = ko.observableArray<Entities.ITableEntity>(); fakeTableEntityListViewModel.items = ko.observableArray<Entities.ITableEntity>();
fakeTableEntityListViewModel.headers = []; fakeTableEntityListViewModel.headers = [];
const props = { const props = {
explorer: fakeExplorer, tableDataClient: new TablesAPIDataClient(),
closePanel: (): void => undefined,
queryTablesTab: fakeQueryTablesTab, queryTablesTab: fakeQueryTablesTab,
tableEntityListViewModel: fakeTableEntityListViewModel, tableEntityListViewModel: fakeTableEntityListViewModel,
cassandraApiClient: fakeCassandraApiClient, cassandraApiClient: fakeCassandraApiClient,

View File

@ -5,13 +5,13 @@ import * as _ from "underscore";
import AddPropertyIcon from "../../../../images/Add-property.svg"; import AddPropertyIcon from "../../../../images/Add-property.svg";
import RevertBackIcon from "../../../../images/RevertBack.svg"; import RevertBackIcon from "../../../../images/RevertBack.svg";
import { TableEntity } from "../../../Common/TableEntity"; import { TableEntity } from "../../../Common/TableEntity";
import { useSidePanel } from "../../../hooks/useSidePanel";
import { userContext } from "../../../UserContext"; import { userContext } from "../../../UserContext";
import Explorer from "../../Explorer";
import * as TableConstants from "../../Tables/Constants"; import * as TableConstants from "../../Tables/Constants";
import * as DataTableUtilities from "../../Tables/DataTable/DataTableUtilities"; import * as DataTableUtilities from "../../Tables/DataTable/DataTableUtilities";
import TableEntityListViewModel from "../../Tables/DataTable/TableEntityListViewModel"; import TableEntityListViewModel from "../../Tables/DataTable/TableEntityListViewModel";
import * as Entities from "../../Tables/Entities"; import * as Entities from "../../Tables/Entities";
import { CassandraAPIDataClient, CassandraTableKey } from "../../Tables/TableDataClient"; import { CassandraAPIDataClient, CassandraTableKey, TableDataClient } from "../../Tables/TableDataClient";
import * as TableEntityProcessor from "../../Tables/TableEntityProcessor"; import * as TableEntityProcessor from "../../Tables/TableEntityProcessor";
import * as Utilities from "../../Tables/Utilities"; import * as Utilities from "../../Tables/Utilities";
import QueryTablesTab from "../../Tabs/QueryTablesTab"; import QueryTablesTab from "../../Tabs/QueryTablesTab";
@ -37,8 +37,7 @@ import {
} from "./Validators/EntityTableHelper"; } from "./Validators/EntityTableHelper";
interface AddTableEntityPanelProps { interface AddTableEntityPanelProps {
explorer: Explorer; tableDataClient: TableDataClient;
closePanel: () => void;
queryTablesTab: QueryTablesTab; queryTablesTab: QueryTablesTab;
tableEntityListViewModel: TableEntityListViewModel; tableEntityListViewModel: TableEntityListViewModel;
cassandraApiClient: CassandraAPIDataClient; cassandraApiClient: CassandraAPIDataClient;
@ -57,12 +56,12 @@ interface EntityRowType {
} }
export const AddTableEntityPanel: FunctionComponent<AddTableEntityPanelProps> = ({ export const AddTableEntityPanel: FunctionComponent<AddTableEntityPanelProps> = ({
explorer, tableDataClient,
closePanel,
queryTablesTab, queryTablesTab,
tableEntityListViewModel, tableEntityListViewModel,
cassandraApiClient, cassandraApiClient,
}: AddTableEntityPanelProps): JSX.Element => { }: AddTableEntityPanelProps): JSX.Element => {
const closeSidePanel = useSidePanel((state) => state.closeSidePanel);
const [entities, setEntities] = useState<EntityRowType[]>([]); const [entities, setEntities] = useState<EntityRowType[]>([]);
const [selectedRow, setSelectedRow] = useState<number>(0); const [selectedRow, setSelectedRow] = useState<number>(0);
const [entityAttributeValue, setEntityAttributeValue] = useState<string>(""); const [entityAttributeValue, setEntityAttributeValue] = useState<string>("");
@ -106,15 +105,12 @@ export const AddTableEntityPanel: FunctionComponent<AddTableEntityPanelProps> =
event.preventDefault(); event.preventDefault();
const entity: Entities.ITableEntity = entityFromAttributes(entities); const entity: Entities.ITableEntity = entityFromAttributes(entities);
const newEntity: Entities.ITableEntity = await explorer.tableDataClient.createDocument( const newEntity: Entities.ITableEntity = await tableDataClient.createDocument(queryTablesTab.collection, entity);
queryTablesTab.collection,
entity
);
await tableEntityListViewModel.addEntityToCache(newEntity); await tableEntityListViewModel.addEntityToCache(newEntity);
if (!tryInsertNewHeaders(tableEntityListViewModel, newEntity)) { if (!tryInsertNewHeaders(tableEntityListViewModel, newEntity)) {
tableEntityListViewModel.redrawTableThrottled(); tableEntityListViewModel.redrawTableThrottled();
} }
closePanel(); closeSidePanel();
}; };
const tryInsertNewHeaders = (viewModel: TableEntityListViewModel, newEntity: Entities.ITableEntity): boolean => { const tryInsertNewHeaders = (viewModel: TableEntityListViewModel, newEntity: Entities.ITableEntity): boolean => {
@ -296,7 +292,6 @@ export const AddTableEntityPanel: FunctionComponent<AddTableEntityPanelProps> =
}} }}
/> />
} }
closePanel={() => closePanel()}
isConsoleExpanded={false} isConsoleExpanded={false}
/> />
); );
@ -308,7 +303,6 @@ export const AddTableEntityPanel: FunctionComponent<AddTableEntityPanelProps> =
panelWidth="700px" panelWidth="700px"
isOpen={true} isOpen={true}
panelContent={renderPanelContent()} panelContent={renderPanelContent()}
closePanel={() => closePanel()}
isConsoleExpanded={false} isConsoleExpanded={false}
/> />
); );

View File

@ -1,15 +1,13 @@
import { mount } from "enzyme"; import { mount } from "enzyme";
import * as ko from "knockout"; import * as ko from "knockout";
import React from "react"; import React from "react";
import Explorer from "../../Explorer";
import TableListViewModal from "../../Tables/DataTable/TableEntityListViewModel"; import TableListViewModal from "../../Tables/DataTable/TableEntityListViewModel";
import * as Entities from "../../Tables/Entities"; import * as Entities from "../../Tables/Entities";
import { CassandraAPIDataClient } from "../../Tables/TableDataClient"; import { CassandraAPIDataClient, TablesAPIDataClient } from "../../Tables/TableDataClient";
import QueryTablesTab from "../../Tabs/QueryTablesTab"; import QueryTablesTab from "../../Tabs/QueryTablesTab";
import { EditTableEntityPanel } from "./EditTableEntityPanel"; import { EditTableEntityPanel } from "./EditTableEntityPanel";
describe("Excute Edit Table Entity Pane", () => { describe("Excute Edit Table Entity Pane", () => {
const fakeExplorer = {} as Explorer;
const fakeQueryTablesTab = {} as QueryTablesTab; const fakeQueryTablesTab = {} as QueryTablesTab;
const fakeTableEntityListViewModel = {} as TableListViewModal; const fakeTableEntityListViewModel = {} as TableListViewModal;
fakeTableEntityListViewModel.items = ko.observableArray<Entities.ITableEntity>(); fakeTableEntityListViewModel.items = ko.observableArray<Entities.ITableEntity>();
@ -18,8 +16,7 @@ describe("Excute Edit Table Entity Pane", () => {
fakeTableEntityListViewModel.selected = ko.observableArray<Entities.ITableEntity>([{}]); fakeTableEntityListViewModel.selected = ko.observableArray<Entities.ITableEntity>([{}]);
const props = { const props = {
explorer: fakeExplorer, tableDataClient: new TablesAPIDataClient(),
closePanel: (): void => undefined,
queryTablesTab: fakeQueryTablesTab, queryTablesTab: fakeQueryTablesTab,
tableEntityListViewModel: fakeTableEntityListViewModel, tableEntityListViewModel: fakeTableEntityListViewModel,
cassandraApiClient: fakeCassandraApiClient, cassandraApiClient: fakeCassandraApiClient,

View File

@ -5,13 +5,13 @@ import * as _ from "underscore";
import AddPropertyIcon from "../../../../images/Add-property.svg"; import AddPropertyIcon from "../../../../images/Add-property.svg";
import RevertBackIcon from "../../../../images/RevertBack.svg"; import RevertBackIcon from "../../../../images/RevertBack.svg";
import { TableEntity } from "../../../Common/TableEntity"; import { TableEntity } from "../../../Common/TableEntity";
import { useSidePanel } from "../../../hooks/useSidePanel";
import { userContext } from "../../../UserContext"; import { userContext } from "../../../UserContext";
import Explorer from "../../Explorer";
import * as TableConstants from "../../Tables/Constants"; import * as TableConstants from "../../Tables/Constants";
import * as DataTableUtilities from "../../Tables/DataTable/DataTableUtilities"; import * as DataTableUtilities from "../../Tables/DataTable/DataTableUtilities";
import TableEntityListViewModel from "../../Tables/DataTable/TableEntityListViewModel"; import TableEntityListViewModel from "../../Tables/DataTable/TableEntityListViewModel";
import * as Entities from "../../Tables/Entities"; import * as Entities from "../../Tables/Entities";
import { CassandraAPIDataClient } from "../../Tables/TableDataClient"; import { CassandraAPIDataClient, TableDataClient } from "../../Tables/TableDataClient";
import * as TableEntityProcessor from "../../Tables/TableEntityProcessor"; import * as TableEntityProcessor from "../../Tables/TableEntityProcessor";
import QueryTablesTab from "../../Tabs/QueryTablesTab"; import QueryTablesTab from "../../Tabs/QueryTablesTab";
import { PanelContainerComponent } from "../PanelContainerComponent"; import { PanelContainerComponent } from "../PanelContainerComponent";
@ -34,8 +34,7 @@ import {
} from "./Validators/EntityTableHelper"; } from "./Validators/EntityTableHelper";
interface EditTableEntityPanelProps { interface EditTableEntityPanelProps {
explorer: Explorer; tableDataClient: TableDataClient;
closePanel: () => void;
queryTablesTab: QueryTablesTab; queryTablesTab: QueryTablesTab;
tableEntityListViewModel: TableEntityListViewModel; tableEntityListViewModel: TableEntityListViewModel;
cassandraApiClient: CassandraAPIDataClient; cassandraApiClient: CassandraAPIDataClient;
@ -55,12 +54,12 @@ interface EntityRowType {
} }
export const EditTableEntityPanel: FunctionComponent<EditTableEntityPanelProps> = ({ export const EditTableEntityPanel: FunctionComponent<EditTableEntityPanelProps> = ({
explorer, tableDataClient,
closePanel,
queryTablesTab, queryTablesTab,
tableEntityListViewModel, tableEntityListViewModel,
cassandraApiClient, cassandraApiClient,
}: EditTableEntityPanelProps): JSX.Element => { }: EditTableEntityPanelProps): JSX.Element => {
const closeSidePanel = useSidePanel((state) => state.closeSidePanel);
const [entities, setEntities] = useState<EntityRowType[]>([]); const [entities, setEntities] = useState<EntityRowType[]>([]);
const [selectedRow, setSelectedRow] = useState<number>(0); const [selectedRow, setSelectedRow] = useState<number>(0);
const [entityAttributeValue, setEntityAttributeValue] = useState<string>(""); const [entityAttributeValue, setEntityAttributeValue] = useState<string>("");
@ -197,9 +196,9 @@ export const EditTableEntityPanel: FunctionComponent<EditTableEntityPanelProps>
} }
event.preventDefault(); event.preventDefault();
const entity: Entities.ITableEntity = entityFromAttributes(entities); const entity: Entities.ITableEntity = entityFromAttributes(entities);
const tableDataClient = userContext.apiType === "Cassandra" ? cassandraApiClient : explorer.tableDataClient; const newTableDataClient = userContext.apiType === "Cassandra" ? cassandraApiClient : tableDataClient;
const originalDocumentData = userContext.apiType === "Cassandra" ? originalDocument[0] : originalDocument; const originalDocumentData = userContext.apiType === "Cassandra" ? originalDocument[0] : originalDocument;
const newEntity: Entities.ITableEntity = await tableDataClient.updateDocument( const newEntity: Entities.ITableEntity = await newTableDataClient.updateDocument(
queryTablesTab.collection, queryTablesTab.collection,
originalDocumentData, originalDocumentData,
entity entity
@ -210,7 +209,7 @@ export const EditTableEntityPanel: FunctionComponent<EditTableEntityPanelProps>
} }
tableEntityListViewModel.selected.removeAll(); tableEntityListViewModel.selected.removeAll();
tableEntityListViewModel.selected.push(newEntity); tableEntityListViewModel.selected.push(newEntity);
closePanel(); closeSidePanel();
}; };
const tryInsertNewHeaders = (viewModel: TableEntityListViewModel, newEntity: Entities.ITableEntity): boolean => { const tryInsertNewHeaders = (viewModel: TableEntityListViewModel, newEntity: Entities.ITableEntity): boolean => {
@ -391,7 +390,6 @@ export const EditTableEntityPanel: FunctionComponent<EditTableEntityPanelProps>
}} }}
/> />
} }
closePanel={() => closePanel()}
isConsoleExpanded={false} isConsoleExpanded={false}
/> />
); );
@ -403,7 +401,6 @@ export const EditTableEntityPanel: FunctionComponent<EditTableEntityPanelProps>
panelWidth="700px" panelWidth="700px"
isOpen={true} isOpen={true}
panelContent={renderPanelContent()} panelContent={renderPanelContent()}
closePanel={() => closePanel()}
isConsoleExpanded={false} isConsoleExpanded={false}
/> />
); );

View File

@ -1,14 +1,12 @@
import { Checkbox, Text } from "@fluentui/react"; import { Checkbox, Text } from "@fluentui/react";
import React, { FunctionComponent, useEffect, useState } from "react"; import React, { FunctionComponent, useEffect, useState } from "react";
import { useSidePanel } from "../../../../hooks/useSidePanel";
import { userContext } from "../../../../UserContext"; import { userContext } from "../../../../UserContext";
import Explorer from "../../../Explorer";
import * as Constants from "../../../Tables/Constants"; import * as Constants from "../../../Tables/Constants";
import QueryViewModel from "../../../Tables/QueryBuilder/QueryViewModel"; import QueryViewModel from "../../../Tables/QueryBuilder/QueryViewModel";
import { RightPaneForm, RightPaneFormProps } from "../../RightPaneForm/RightPaneForm"; import { RightPaneForm, RightPaneFormProps } from "../../RightPaneForm/RightPaneForm";
interface TableQuerySelectPanelProps { interface TableQuerySelectPanelProps {
explorer: Explorer;
closePanel: () => void;
queryViewModel: QueryViewModel; queryViewModel: QueryViewModel;
} }
@ -19,10 +17,10 @@ interface ISelectColumn {
} }
export const TableQuerySelectPanel: FunctionComponent<TableQuerySelectPanelProps> = ({ export const TableQuerySelectPanel: FunctionComponent<TableQuerySelectPanelProps> = ({
explorer,
closePanel,
queryViewModel, queryViewModel,
}: TableQuerySelectPanelProps): JSX.Element => { }: TableQuerySelectPanelProps): JSX.Element => {
const closeSidePanel = useSidePanel((state) => state.closeSidePanel);
const [columnOptions, setColumnOptions] = useState<ISelectColumn[]>([ const [columnOptions, setColumnOptions] = useState<ISelectColumn[]>([
{ columnName: "", selected: true, editable: false }, { columnName: "", selected: true, editable: false },
]); ]);
@ -31,7 +29,7 @@ export const TableQuerySelectPanel: FunctionComponent<TableQuerySelectPanelProps
const onSubmit = (): void => { const onSubmit = (): void => {
queryViewModel.selectText(getParameters()); queryViewModel.selectText(getParameters());
queryViewModel.getSelectMessage(); queryViewModel.getSelectMessage();
closePanel(); closeSidePanel();
}; };
const props: RightPaneFormProps = { const props: RightPaneFormProps = {
@ -39,7 +37,6 @@ export const TableQuerySelectPanel: FunctionComponent<TableQuerySelectPanelProps
isExecuting: false, isExecuting: false,
submitButtonText: "OK", submitButtonText: "OK",
onSubmit, onSubmit,
expandConsole: () => explorer.expandConsole(),
}; };
const handleClick = (isChecked: boolean, selectedColumn: string): void => { const handleClick = (isChecked: boolean, selectedColumn: string): void => {

View File

@ -11,7 +11,6 @@ exports[`Table query select Panel should render Default properly 1`] = `
} }
> >
<RightPaneForm <RightPaneForm
expandConsole={[Function]}
formError="" formError=""
isExecuting={false} isExecuting={false}
onSubmit={[Function]} onSubmit={[Function]}

View File

@ -3,9 +3,8 @@
exports[`Excute Add Table Entity Pane should render Default properly 1`] = ` exports[`Excute Add Table Entity Pane should render Default properly 1`] = `
<AddTableEntityPanel <AddTableEntityPanel
cassandraApiClient={Object {}} cassandraApiClient={Object {}}
closePanel={[Function]}
explorer={Object {}}
queryTablesTab={Object {}} queryTablesTab={Object {}}
tableDataClient={TablesAPIDataClient {}}
tableEntityListViewModel={ tableEntityListViewModel={
Object { Object {
"headers": Array [], "headers": Array [],
@ -14,7 +13,6 @@ exports[`Excute Add Table Entity Pane should render Default properly 1`] = `
} }
> >
<PanelContainerComponent <PanelContainerComponent
closePanel={[Function]}
headerText="Add Table Row" headerText="Add Table Row"
isConsoleExpanded={false} isConsoleExpanded={false}
isOpen={true} isOpen={true}

View File

@ -3,9 +3,8 @@
exports[`Excute Edit Table Entity Pane should render Default properly 1`] = ` exports[`Excute Edit Table Entity Pane should render Default properly 1`] = `
<EditTableEntityPanel <EditTableEntityPanel
cassandraApiClient={Object {}} cassandraApiClient={Object {}}
closePanel={[Function]}
explorer={Object {}}
queryTablesTab={Object {}} queryTablesTab={Object {}}
tableDataClient={TablesAPIDataClient {}}
tableEntityListViewModel={ tableEntityListViewModel={
Object { Object {
"headers": Array [], "headers": Array [],
@ -15,7 +14,6 @@ exports[`Excute Edit Table Entity Pane should render Default properly 1`] = `
} }
> >
<PanelContainerComponent <PanelContainerComponent
closePanel={[Function]}
headerText="Edit Table Entity" headerText="Edit Table Entity"
isConsoleExpanded={false} isConsoleExpanded={false}
isOpen={true} isOpen={true}

View File

@ -1,20 +1,16 @@
import React, { ChangeEvent, FunctionComponent, useState } from "react"; import React, { ChangeEvent, FunctionComponent, useState } from "react";
import { Upload } from "../../../Common/Upload/Upload"; import { Upload } from "../../../Common/Upload/Upload";
import { useSidePanel } from "../../../hooks/useSidePanel";
import { logConsoleError, logConsoleInfo, logConsoleProgress } from "../../../Utils/NotificationConsoleUtils"; import { logConsoleError, logConsoleInfo, logConsoleProgress } from "../../../Utils/NotificationConsoleUtils";
import { NotebookContentItem } from "../../Notebook/NotebookContentItem"; import { NotebookContentItem } from "../../Notebook/NotebookContentItem";
import { RightPaneForm, RightPaneFormProps } from "../RightPaneForm/RightPaneForm"; import { RightPaneForm, RightPaneFormProps } from "../RightPaneForm/RightPaneForm";
export interface UploadFilePanelProps { export interface UploadFilePanelProps {
expandConsole: () => void;
closePanel: () => void;
uploadFile: (name: string, content: string) => Promise<NotebookContentItem>; uploadFile: (name: string, content: string) => Promise<NotebookContentItem>;
} }
export const UploadFilePane: FunctionComponent<UploadFilePanelProps> = ({ export const UploadFilePane: FunctionComponent<UploadFilePanelProps> = ({ uploadFile }: UploadFilePanelProps) => {
expandConsole, const closeSidePanel = useSidePanel((state) => state.closeSidePanel);
closePanel,
uploadFile,
}: UploadFilePanelProps) => {
const extensions: string = undefined; //ex. ".ipynb" const extensions: string = undefined; //ex. ".ipynb"
const errorMessage = "Could not upload file"; const errorMessage = "Could not upload file";
const inProgressMessage = "Uploading file to notebook server"; const inProgressMessage = "Uploading file to notebook server";
@ -42,7 +38,7 @@ export const UploadFilePane: FunctionComponent<UploadFilePanelProps> = ({
.then( .then(
() => { () => {
logConsoleInfo(`${successMessage} ${file.name}`); logConsoleInfo(`${successMessage} ${file.name}`);
closePanel(); closeSidePanel();
}, },
(error: string) => { (error: string) => {
setFormErrors(errorMessage); setFormErrors(errorMessage);
@ -79,7 +75,6 @@ export const UploadFilePane: FunctionComponent<UploadFilePanelProps> = ({
}; };
const props: RightPaneFormProps = { const props: RightPaneFormProps = {
expandConsole,
formError: formErrors, formError: formErrors,
isExecuting: isExecuting, isExecuting: isExecuting,
submitButtonText: "Upload", submitButtonText: "Upload",

View File

@ -4,7 +4,6 @@ import Explorer from "../../Explorer";
import { UploadItemsPane } from "./UploadItemsPane"; import { UploadItemsPane } from "./UploadItemsPane";
const props = { const props = {
explorer: new Explorer(), explorer: new Explorer(),
closePanel: (): void => undefined,
}; };
describe("Upload Items Pane", () => { describe("Upload Items Pane", () => {
it("should render Default properly", () => { it("should render Default properly", () => {

View File

@ -26,7 +26,6 @@ export const UploadItemsPane: FunctionComponent<UploadItemsPaneProps> = ({ explo
} }
const selectedCollection = explorer.findSelectedCollection(); const selectedCollection = explorer.findSelectedCollection();
setIsExecuting(true); setIsExecuting(true);
selectedCollection selectedCollection
@ -51,7 +50,6 @@ export const UploadItemsPane: FunctionComponent<UploadItemsPaneProps> = ({ explo
}; };
const props: RightPaneFormProps = { const props: RightPaneFormProps = {
expandConsole: () => explorer.expandConsole(),
formError, formError,
isExecuting: isExecuting, isExecuting: isExecuting,
submitButtonText: "Upload", submitButtonText: "Upload",

View File

@ -2,7 +2,6 @@
exports[`Upload Items Pane should render Default properly 1`] = ` exports[`Upload Items Pane should render Default properly 1`] = `
<RightPaneForm <RightPaneForm
expandConsole={[Function]}
formError="" formError=""
onSubmit={[Function]} onSubmit={[Function]}
submitButtonText="Upload" submitButtonText="Upload"

View File

@ -8,7 +8,6 @@ exports[`Delete Database Confirmation Pane submit() Should call delete database
"_isInitializingNotebooks": false, "_isInitializingNotebooks": false,
"_resetNotebookWorkspace": [Function], "_resetNotebookWorkspace": [Function],
"canSaveQueries": [Function], "canSaveQueries": [Function],
"closeSidePanel": undefined,
"collapsedResourceTreeWidth": 36, "collapsedResourceTreeWidth": 36,
"commandBarComponentAdapter": CommandBarComponentAdapter { "commandBarComponentAdapter": CommandBarComponentAdapter {
"container": [Circular], "container": [Circular],
@ -36,7 +35,6 @@ exports[`Delete Database Confirmation Pane submit() Should call delete database
"notebookServerInfo": [Function], "notebookServerInfo": [Function],
"onRefreshDatabasesKeyPress": [Function], "onRefreshDatabasesKeyPress": [Function],
"onRefreshResourcesClick": [Function], "onRefreshResourcesClick": [Function],
"openSidePanel": undefined,
"provideFeedbackEmail": [Function], "provideFeedbackEmail": [Function],
"queriesClient": QueriesClient { "queriesClient": QueriesClient {
"container": [Circular], "container": [Circular],
@ -62,7 +60,6 @@ exports[`Delete Database Confirmation Pane submit() Should call delete database
"selectedDatabaseId": [Function], "selectedDatabaseId": [Function],
"selectedNode": [Function], "selectedNode": [Function],
"setInProgressConsoleDataIdToBeDeleted": undefined, "setInProgressConsoleDataIdToBeDeleted": undefined,
"setIsNotificationConsoleExpanded": undefined,
"setNotificationConsoleData": undefined, "setNotificationConsoleData": undefined,
"sparkClusterConnectionInfo": [Function], "sparkClusterConnectionInfo": [Function],
"splitter": Splitter { "splitter": Splitter {
@ -92,7 +89,6 @@ exports[`Delete Database Confirmation Pane submit() Should call delete database
} }
> >
<RightPaneForm <RightPaneForm
expandConsole={[Function]}
formError="" formError=""
isExecuting={false} isExecuting={false}
onSubmit={[Function]} onSubmit={[Function]}

View File

@ -4,6 +4,7 @@ import NewVertexIcon from "../../../images/NewVertex.svg";
import StyleIcon from "../../../images/Style.svg"; import StyleIcon from "../../../images/Style.svg";
import { DatabaseAccount } from "../../Contracts/DataModels"; import { DatabaseAccount } from "../../Contracts/DataModels";
import * as ViewModels from "../../Contracts/ViewModels"; import * as ViewModels from "../../Contracts/ViewModels";
import { useSidePanel } from "../../hooks/useSidePanel";
import { CommandButtonComponentProps } from "../Controls/CommandButton/CommandButtonComponent"; import { CommandButtonComponentProps } from "../Controls/CommandButton/CommandButtonComponent";
import { import {
GraphAccessor, GraphAccessor,
@ -11,9 +12,6 @@ import {
GraphExplorerError, GraphExplorerError,
GraphExplorerProps, GraphExplorerProps,
} from "../Graph/GraphExplorerComponent/GraphExplorer"; } from "../Graph/GraphExplorerComponent/GraphExplorer";
// import { GraphAccessor, GraphExplorer, GraphExplorerError } from "../Graph/GraphExplorerComponent/GraphExplorer";
// import { GraphExplorerAdapter } from "../Graph/GraphExplorerComponent/GraphExplorerAdapter";
import { ContextualPaneBase } from "../Panes/ContextualPaneBase";
import { GraphStylingPanel } from "../Panes/GraphStylingPanel/GraphStylingPanel"; import { GraphStylingPanel } from "../Panes/GraphStylingPanel/GraphStylingPanel";
import { NewVertexPanel } from "../Panes/NewVertexPanel/NewVertexPanel"; import { NewVertexPanel } from "../Panes/NewVertexPanel/NewVertexPanel";
import TabsBase from "./TabsBase"; import TabsBase from "./TabsBase";
@ -71,7 +69,6 @@ export default class GraphTab extends TabsBase {
private isFilterQueryLoading: ko.Observable<boolean>; private isFilterQueryLoading: ko.Observable<boolean>;
private isValidQuery: ko.Observable<boolean>; private isValidQuery: ko.Observable<boolean>;
private collectionPartitionKeyProperty: string; private collectionPartitionKeyProperty: string;
private contextualPane: ContextualPaneBase;
public graphExplorer: GraphExplorer; public graphExplorer: GraphExplorer;
public options: GraphTabOptions; public options: GraphTabOptions;
constructor(options: GraphTabOptions) { constructor(options: GraphTabOptions) {
@ -159,12 +156,10 @@ export default class GraphTab extends TabsBase {
/* Command bar */ /* Command bar */
private showNewVertexEditor(): void { private showNewVertexEditor(): void {
this.collection.container.openSidePanel( useSidePanel.getState().openSidePanel(
"New Vertex", "New Vertex",
<NewVertexPanel <NewVertexPanel
explorer={this.collection.container}
partitionKeyPropertyProp={this.collectionPartitionKeyProperty} partitionKeyPropertyProp={this.collectionPartitionKeyProperty}
openNotificationConsole={() => this.collection.container.expandConsole()}
onSubmit={( onSubmit={(
result: ViewModels.NewVertexData, result: ViewModels.NewVertexData,
onError: (errorMessage: string) => void, onError: (errorMessage: string) => void,
@ -173,7 +168,7 @@ export default class GraphTab extends TabsBase {
this.graphAccessor.addVertex(result).then( this.graphAccessor.addVertex(result).then(
() => { () => {
onSuccess(); onSuccess();
this.contextualPane.cancel(); useSidePanel.getState().closeSidePanel();
}, },
(error: GraphExplorerError) => { (error: GraphExplorerError) => {
onError(error.title); onError(error.title);
@ -184,10 +179,9 @@ export default class GraphTab extends TabsBase {
); );
} }
public openStyling(): void { public openStyling(): void {
this.collection.container.openSidePanel( useSidePanel.getState().openSidePanel(
"Graph Style", "Graph Style",
<GraphStylingPanel <GraphStylingPanel
closePanel={this.collection.container.closeSidePanel}
igraphConfigUiData={this.igraphConfigUiData} igraphConfigUiData={this.igraphConfigUiData}
igraphConfig={this.igraphConfig} igraphConfig={this.igraphConfig}
getValues={(igraphConfig?: IGraphConfig): void => { getValues={(igraphConfig?: IGraphConfig): void => {

View File

@ -10,6 +10,7 @@ import { MinimalQueryIterator } from "../../Common/IteratorUtilities";
import { Splitter, SplitterBounds, SplitterDirection } from "../../Common/Splitter"; import { Splitter, SplitterBounds, SplitterDirection } from "../../Common/Splitter";
import * as DataModels from "../../Contracts/DataModels"; import * as DataModels from "../../Contracts/DataModels";
import * as ViewModels from "../../Contracts/ViewModels"; import * as ViewModels from "../../Contracts/ViewModels";
import { useNotificationConsole } from "../../hooks/useNotificationConsole";
import { Action } from "../../Shared/Telemetry/TelemetryConstants"; import { Action } from "../../Shared/Telemetry/TelemetryConstants";
import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor"; import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
import { userContext } from "../../UserContext"; import { userContext } from "../../UserContext";
@ -198,7 +199,7 @@ export default class QueryTab extends TabsBase implements ViewModels.WaitsForTem
} }
public onErrorDetailsClick = (src: any, event: MouseEvent): boolean => { public onErrorDetailsClick = (src: any, event: MouseEvent): boolean => {
this.collection && this.collection.container.expandConsole(); useNotificationConsole.getState().expandConsole();
return false; return false;
}; };

View File

@ -9,6 +9,7 @@ import { updateStoredProcedure } from "../../Common/dataAccess/updateStoredProce
import editable from "../../Common/EditableUtility"; import editable from "../../Common/EditableUtility";
import { getErrorMessage, getErrorStack } from "../../Common/ErrorHandlingUtils"; import { getErrorMessage, getErrorStack } from "../../Common/ErrorHandlingUtils";
import * as ViewModels from "../../Contracts/ViewModels"; import * as ViewModels from "../../Contracts/ViewModels";
import { useNotificationConsole } from "../../hooks/useNotificationConsole";
import { Action } from "../../Shared/Telemetry/TelemetryConstants"; import { Action } from "../../Shared/Telemetry/TelemetryConstants";
import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor"; import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
import { CommandButtonComponentProps } from "../Controls/CommandButton/CommandButtonComponent"; import { CommandButtonComponentProps } from "../Controls/CommandButton/CommandButtonComponent";
@ -136,7 +137,7 @@ export default class StoredProcedureTab extends ScriptTabBase {
} }
public onErrorDetailsClick = (src: any, event: MouseEvent): boolean => { public onErrorDetailsClick = (src: any, event: MouseEvent): boolean => {
this.collection && this.collection.container.expandConsole(); useNotificationConsole.getState().expandConsole();
return false; return false;
}; };

View File

@ -3,6 +3,7 @@ import * as Constants from "../../Common/Constants";
import * as ThemeUtility from "../../Common/ThemeUtility"; import * as ThemeUtility from "../../Common/ThemeUtility";
import * as DataModels from "../../Contracts/DataModels"; import * as DataModels from "../../Contracts/DataModels";
import * as ViewModels from "../../Contracts/ViewModels"; import * as ViewModels from "../../Contracts/ViewModels";
import { useNotificationConsole } from "../../hooks/useNotificationConsole";
import { RouteHandler } from "../../RouteHandlers/RouteHandler"; import { RouteHandler } from "../../RouteHandlers/RouteHandler";
import { Action, ActionModifiers } from "../../Shared/Telemetry/TelemetryConstants"; import { Action, ActionModifiers } from "../../Shared/Telemetry/TelemetryConstants";
import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor"; import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
@ -122,8 +123,8 @@ export default class TabsBase extends WaitsForTemplateViewModel {
} }
public onErrorDetailsClick = (src: any, event: MouseEvent): boolean => { public onErrorDetailsClick = (src: any, event: MouseEvent): boolean => {
this.collection?.container?.expandConsole(); useNotificationConsole.getState().expandConsole();
this.database?.container?.expandConsole(); useNotificationConsole.getState().expandConsole();
return false; return false;
}; };

View File

@ -39,16 +39,15 @@ import "./Explorer/Graph/GraphExplorerComponent/graphExplorer.less";
import "./Explorer/Menus/CommandBar/CommandBarComponent.less"; import "./Explorer/Menus/CommandBar/CommandBarComponent.less";
import "./Explorer/Menus/CommandBar/MemoryTrackerComponent.less"; import "./Explorer/Menus/CommandBar/MemoryTrackerComponent.less";
import "./Explorer/Menus/NotificationConsole/NotificationConsole.less"; import "./Explorer/Menus/NotificationConsole/NotificationConsole.less";
import { NotificationConsoleComponent } from "./Explorer/Menus/NotificationConsole/NotificationConsoleComponent"; import { NotificationConsole } from "./Explorer/Menus/NotificationConsole/NotificationConsoleComponent";
import "./Explorer/Panes/PanelComponent.less"; import "./Explorer/Panes/PanelComponent.less";
import { PanelContainerComponent } from "./Explorer/Panes/PanelContainerComponent"; import { SidePanel } from "./Explorer/Panes/PanelContainerComponent";
import { SplashScreen } from "./Explorer/SplashScreen/SplashScreen"; import { SplashScreen } from "./Explorer/SplashScreen/SplashScreen";
import "./Explorer/SplashScreen/SplashScreen.less"; import "./Explorer/SplashScreen/SplashScreen.less";
import "./Explorer/Tabs/QueryTab.less"; import "./Explorer/Tabs/QueryTab.less";
import { Tabs } from "./Explorer/Tabs/Tabs"; import { Tabs } from "./Explorer/Tabs/Tabs";
import { useConfig } from "./hooks/useConfig"; import { useConfig } from "./hooks/useConfig";
import { useKnockoutExplorer } from "./hooks/useKnockoutExplorer"; import { useKnockoutExplorer } from "./hooks/useKnockoutExplorer";
import { useSidePanel } from "./hooks/useSidePanel";
import { useTabs } from "./hooks/useTabs"; import { useTabs } from "./hooks/useTabs";
import "./Libs/jquery"; import "./Libs/jquery";
import "./Shared/appInsights"; import "./Shared/appInsights";
@ -56,21 +55,16 @@ import "./Shared/appInsights";
initializeIcons(); initializeIcons();
const App: React.FunctionComponent = () => { const App: React.FunctionComponent = () => {
const [isNotificationConsoleExpanded, setIsNotificationConsoleExpanded] = useState(false);
const [notificationConsoleData, setNotificationConsoleData] = useState(undefined); const [notificationConsoleData, setNotificationConsoleData] = useState(undefined);
//TODO: Refactor so we don't need to pass the id to remove a console data //TODO: Refactor so we don't need to pass the id to remove a console data
const [inProgressConsoleDataIdToBeDeleted, setInProgressConsoleDataIdToBeDeleted] = useState(""); const [inProgressConsoleDataIdToBeDeleted, setInProgressConsoleDataIdToBeDeleted] = useState("");
const [isLeftPaneExpanded, setIsLeftPaneExpanded] = useState<boolean>(true); const [isLeftPaneExpanded, setIsLeftPaneExpanded] = useState<boolean>(true);
const { isPanelOpen, panelContent, headerText, openSidePanel, closeSidePanel } = useSidePanel();
const { tabs, activeTab, tabsManager } = useTabs(); const { tabs, activeTab, tabsManager } = useTabs();
const explorerParams: ExplorerParams = { const explorerParams: ExplorerParams = {
setIsNotificationConsoleExpanded,
setNotificationConsoleData, setNotificationConsoleData,
setInProgressConsoleDataIdToBeDeleted, setInProgressConsoleDataIdToBeDeleted,
openSidePanel,
closeSidePanel,
tabsManager, tabsManager,
}; };
@ -125,21 +119,13 @@ const App: React.FunctionComponent = () => {
aria-label="Notification console" aria-label="Notification console"
id="explorerNotificationConsole" id="explorerNotificationConsole"
> >
<NotificationConsoleComponent <NotificationConsole
isConsoleExpanded={isNotificationConsoleExpanded}
consoleData={notificationConsoleData} consoleData={notificationConsoleData}
inProgressConsoleDataIdToBeDeleted={inProgressConsoleDataIdToBeDeleted} inProgressConsoleDataIdToBeDeleted={inProgressConsoleDataIdToBeDeleted}
setIsConsoleExpanded={setIsNotificationConsoleExpanded}
/> />
</div> </div>
</div> </div>
<PanelContainerComponent <SidePanel />
isOpen={isPanelOpen}
panelContent={panelContent}
headerText={headerText}
closePanel={closeSidePanel}
isConsoleExpanded={isNotificationConsoleExpanded}
/>
<Dialog /> <Dialog />
</div> </div>
); );

View File

@ -0,0 +1,14 @@
import create, { UseStore } from "zustand";
export interface NotificationConsoleState {
isExpanded: boolean;
expandConsole: () => void;
// TODO Remove this method. Add a `closeConsole` method instead
setIsExpanded: (isExpanded: boolean) => void;
}
export const useNotificationConsole: UseStore<NotificationConsoleState> = create((set) => ({
isExpanded: false,
expandConsole: () => set((state) => ({ ...state, isExpanded: true })),
setIsExpanded: (isExpanded) => set((state) => ({ ...state, isExpanded })),
}));

View File

@ -1,35 +1,15 @@
import { useState } from "react"; import create, { UseStore } from "zustand";
export interface SidePanelHooks { export interface SidePanelState {
isPanelOpen: boolean; isOpen: boolean;
panelContent: JSX.Element; panelContent?: JSX.Element;
headerText: string; headerText?: string;
openSidePanel: (headerText: string, panelContent: JSX.Element, onClose?: () => void) => void; openSidePanel: (headerText: string, panelContent: JSX.Element, onClose?: () => void) => void;
closeSidePanel: () => void; closeSidePanel: () => void;
} }
export const useSidePanel = (): SidePanelHooks => { export const useSidePanel: UseStore<SidePanelState> = create((set) => ({
const [isPanelOpen, setIsPanelOpen] = useState<boolean>(false); isOpen: false,
const [panelContent, setPanelContent] = useState<JSX.Element>(); openSidePanel: (headerText, panelContent) => set((state) => ({ ...state, headerText, panelContent, isOpen: true })),
const [headerText, setHeaderText] = useState<string>(); closeSidePanel: () => set((state) => ({ ...state, isOpen: false })),
const [onCloseCallback, setOnCloseCallback] = useState<{ callback: () => void }>(); }));
const openSidePanel = (headerText: string, panelContent: JSX.Element, onClose?: () => void): void => {
setHeaderText(headerText);
setPanelContent(panelContent);
setIsPanelOpen(true);
!!onClose && setOnCloseCallback({ callback: onClose });
};
const closeSidePanel = (): void => {
setHeaderText("");
setPanelContent(undefined);
setIsPanelOpen(false);
if (onCloseCallback) {
onCloseCallback.callback();
setOnCloseCallback(undefined);
}
};
return { isPanelOpen, panelContent, headerText, openSidePanel, closeSidePanel };
};