mirror of
https://github.com/Azure/cosmos-explorer.git
synced 2024-11-25 06:56:38 +00:00
Remove some Notebooks code (#1832)
* Remove onNewNotebookClicked, openUploadFilePanel functions and UploadFilePane. * Remove resetNotebookWorkspace function. * Remove Notebooks related resource tree node generation. * Fix test snapshots.
This commit is contained in:
parent
298197b1b8
commit
6ebc48ad28
@ -30,7 +30,6 @@ exports[`SettingsComponent renders 1`] = `
|
|||||||
"conflictResolutionPolicy": [Function],
|
"conflictResolutionPolicy": [Function],
|
||||||
"container": Explorer {
|
"container": Explorer {
|
||||||
"_isInitializingNotebooks": false,
|
"_isInitializingNotebooks": false,
|
||||||
"_resetNotebookWorkspace": [Function],
|
|
||||||
"isFixedCollectionWithSharedThroughputSupported": [Function],
|
"isFixedCollectionWithSharedThroughputSupported": [Function],
|
||||||
"isTabsContentExpanded": [Function],
|
"isTabsContentExpanded": [Function],
|
||||||
"onRefreshDatabasesKeyPress": [Function],
|
"onRefreshDatabasesKeyPress": [Function],
|
||||||
@ -108,7 +107,6 @@ exports[`SettingsComponent renders 1`] = `
|
|||||||
"conflictResolutionPolicy": [Function],
|
"conflictResolutionPolicy": [Function],
|
||||||
"container": Explorer {
|
"container": Explorer {
|
||||||
"_isInitializingNotebooks": false,
|
"_isInitializingNotebooks": false,
|
||||||
"_resetNotebookWorkspace": [Function],
|
|
||||||
"isFixedCollectionWithSharedThroughputSupported": [Function],
|
"isFixedCollectionWithSharedThroughputSupported": [Function],
|
||||||
"isTabsContentExpanded": [Function],
|
"isTabsContentExpanded": [Function],
|
||||||
"onRefreshDatabasesKeyPress": [Function],
|
"onRefreshDatabasesKeyPress": [Function],
|
||||||
@ -225,7 +223,6 @@ exports[`SettingsComponent renders 1`] = `
|
|||||||
"conflictResolutionPolicy": [Function],
|
"conflictResolutionPolicy": [Function],
|
||||||
"container": Explorer {
|
"container": Explorer {
|
||||||
"_isInitializingNotebooks": false,
|
"_isInitializingNotebooks": false,
|
||||||
"_resetNotebookWorkspace": [Function],
|
|
||||||
"isFixedCollectionWithSharedThroughputSupported": [Function],
|
"isFixedCollectionWithSharedThroughputSupported": [Function],
|
||||||
"isTabsContentExpanded": [Function],
|
"isTabsContentExpanded": [Function],
|
||||||
"onRefreshDatabasesKeyPress": [Function],
|
"onRefreshDatabasesKeyPress": [Function],
|
||||||
@ -272,7 +269,6 @@ exports[`SettingsComponent renders 1`] = `
|
|||||||
explorer={
|
explorer={
|
||||||
Explorer {
|
Explorer {
|
||||||
"_isInitializingNotebooks": false,
|
"_isInitializingNotebooks": false,
|
||||||
"_resetNotebookWorkspace": [Function],
|
|
||||||
"isFixedCollectionWithSharedThroughputSupported": [Function],
|
"isFixedCollectionWithSharedThroughputSupported": [Function],
|
||||||
"isTabsContentExpanded": [Function],
|
"isTabsContentExpanded": [Function],
|
||||||
"onRefreshDatabasesKeyPress": [Function],
|
"onRefreshDatabasesKeyPress": [Function],
|
||||||
|
@ -38,7 +38,6 @@ import { fromContentUri, toRawContentUri } from "../Utils/GitHubUtils";
|
|||||||
import * as NotificationConsoleUtils from "../Utils/NotificationConsoleUtils";
|
import * as NotificationConsoleUtils from "../Utils/NotificationConsoleUtils";
|
||||||
import { logConsoleError, logConsoleInfo, logConsoleProgress } from "../Utils/NotificationConsoleUtils";
|
import { logConsoleError, logConsoleInfo, logConsoleProgress } from "../Utils/NotificationConsoleUtils";
|
||||||
import { update } from "../Utils/arm/generatedClients/cosmos/databaseAccounts";
|
import { update } from "../Utils/arm/generatedClients/cosmos/databaseAccounts";
|
||||||
import { listByDatabaseAccount } from "../Utils/arm/generatedClients/cosmosNotebooks/notebookWorkspaces";
|
|
||||||
import { useSidePanel } from "../hooks/useSidePanel";
|
import { useSidePanel } from "../hooks/useSidePanel";
|
||||||
import { useTabs } from "../hooks/useTabs";
|
import { useTabs } from "../hooks/useTabs";
|
||||||
import "./ComponentRegisterer";
|
import "./ComponentRegisterer";
|
||||||
@ -56,7 +55,6 @@ import { AddCollectionPanel } from "./Panes/AddCollectionPanel";
|
|||||||
import { CassandraAddCollectionPane } from "./Panes/CassandraAddCollectionPane/CassandraAddCollectionPane";
|
import { CassandraAddCollectionPane } from "./Panes/CassandraAddCollectionPane/CassandraAddCollectionPane";
|
||||||
import { ExecuteSprocParamsPane } from "./Panes/ExecuteSprocParamsPane/ExecuteSprocParamsPane";
|
import { ExecuteSprocParamsPane } from "./Panes/ExecuteSprocParamsPane/ExecuteSprocParamsPane";
|
||||||
import { StringInputPane } from "./Panes/StringInputPane/StringInputPane";
|
import { StringInputPane } from "./Panes/StringInputPane/StringInputPane";
|
||||||
import { UploadFilePane } from "./Panes/UploadFilePane/UploadFilePane";
|
|
||||||
import { UploadItemsPane } from "./Panes/UploadItemsPane/UploadItemsPane";
|
import { UploadItemsPane } from "./Panes/UploadItemsPane/UploadItemsPane";
|
||||||
import { CassandraAPIDataClient, TableDataClient, TablesAPIDataClient } from "./Tables/TableDataClient";
|
import { CassandraAPIDataClient, TableDataClient, TablesAPIDataClient } from "./Tables/TableDataClient";
|
||||||
import NotebookV2Tab, { NotebookTabOptions } from "./Tabs/NotebookV2Tab";
|
import NotebookV2Tab, { NotebookTabOptions } from "./Tabs/NotebookV2Tab";
|
||||||
@ -510,104 +508,6 @@ export default class Explorer {
|
|||||||
.then((memoryUsageInfo) => useNotebook.getState().setMemoryUsageInfo(memoryUsageInfo));
|
.then((memoryUsageInfo) => useNotebook.getState().setMemoryUsageInfo(memoryUsageInfo));
|
||||||
}
|
}
|
||||||
|
|
||||||
public resetNotebookWorkspace(): void {
|
|
||||||
if (!useNotebook.getState().isNotebookEnabled || !this.notebookManager?.notebookClient) {
|
|
||||||
handleError(
|
|
||||||
"Attempt to reset notebook workspace, but notebook is not enabled",
|
|
||||||
"Explorer/resetNotebookWorkspace",
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const dialogContent = useNotebook.getState().isPhoenixNotebooks
|
|
||||||
? "Notebooks saved in the temporary workspace will be deleted. Do you want to proceed?"
|
|
||||||
: "This lets you keep your notebook files and the workspace will be restored to default. Proceed anyway?";
|
|
||||||
|
|
||||||
const resetConfirmationDialogProps: DialogProps = {
|
|
||||||
isModal: true,
|
|
||||||
title: "Reset Workspace",
|
|
||||||
subText: dialogContent,
|
|
||||||
primaryButtonText: "OK",
|
|
||||||
secondaryButtonText: "Cancel",
|
|
||||||
onPrimaryButtonClick: this._resetNotebookWorkspace,
|
|
||||||
onSecondaryButtonClick: () => useDialog.getState().closeDialog(),
|
|
||||||
};
|
|
||||||
useDialog.getState().openDialog(resetConfirmationDialogProps);
|
|
||||||
}
|
|
||||||
|
|
||||||
private async _containsDefaultNotebookWorkspace(databaseAccount: DataModels.DatabaseAccount): Promise<boolean> {
|
|
||||||
if (!databaseAccount) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
const { value: workspaces } = await listByDatabaseAccount(
|
|
||||||
userContext.subscriptionId,
|
|
||||||
userContext.resourceGroup,
|
|
||||||
userContext.databaseAccount.name,
|
|
||||||
);
|
|
||||||
return workspaces && workspaces.length > 0 && workspaces.some((workspace) => workspace.name === "default");
|
|
||||||
} catch (error) {
|
|
||||||
Logger.logError(getErrorMessage(error), "Explorer/_containsDefaultNotebookWorkspace");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private _resetNotebookWorkspace = async () => {
|
|
||||||
useDialog.getState().closeDialog();
|
|
||||||
const clearInProgressMessage = logConsoleProgress("Resetting notebook workspace");
|
|
||||||
let connectionStatus: ContainerConnectionInfo;
|
|
||||||
try {
|
|
||||||
const notebookServerInfo = useNotebook.getState().notebookServerInfo;
|
|
||||||
if (!notebookServerInfo || !notebookServerInfo.notebookServerEndpoint) {
|
|
||||||
const error = "No server endpoint detected";
|
|
||||||
Logger.logError(error, "NotebookContainerClient/resetWorkspace");
|
|
||||||
logConsoleError(error);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
TelemetryProcessor.traceStart(Action.PhoenixResetWorkspace, {
|
|
||||||
dataExplorerArea: Areas.Notebook,
|
|
||||||
});
|
|
||||||
if (useNotebook.getState().isPhoenixNotebooks) {
|
|
||||||
useTabs.getState().closeAllNotebookTabs(true);
|
|
||||||
connectionStatus = {
|
|
||||||
status: ConnectionStatusType.Connecting,
|
|
||||||
};
|
|
||||||
useNotebook.getState().setConnectionInfo(connectionStatus);
|
|
||||||
}
|
|
||||||
const connectionInfo = await this.notebookManager?.notebookClient.resetWorkspace();
|
|
||||||
if (connectionInfo?.status !== HttpStatusCodes.OK) {
|
|
||||||
throw new Error(`Reset Workspace: Received status code- ${connectionInfo?.status}`);
|
|
||||||
}
|
|
||||||
if (!connectionInfo?.data?.phoenixServiceUrl) {
|
|
||||||
throw new Error(`Reset Workspace: PhoenixServiceUrl is invalid!`);
|
|
||||||
}
|
|
||||||
if (useNotebook.getState().isPhoenixNotebooks) {
|
|
||||||
await this.setNotebookInfo(true, connectionInfo, connectionStatus);
|
|
||||||
useNotebook.getState().setIsRefreshed(!useNotebook.getState().isRefreshed);
|
|
||||||
}
|
|
||||||
logConsoleInfo("Successfully reset notebook workspace");
|
|
||||||
TelemetryProcessor.traceSuccess(Action.PhoenixResetWorkspace, {
|
|
||||||
dataExplorerArea: Areas.Notebook,
|
|
||||||
});
|
|
||||||
} catch (error) {
|
|
||||||
logConsoleError(`Failed to reset notebook workspace: ${error}`);
|
|
||||||
TelemetryProcessor.traceFailure(Action.PhoenixResetWorkspace, {
|
|
||||||
dataExplorerArea: Areas.Notebook,
|
|
||||||
error: getErrorMessage(error),
|
|
||||||
errorStack: getErrorStack(error),
|
|
||||||
});
|
|
||||||
if (useNotebook.getState().isPhoenixNotebooks) {
|
|
||||||
connectionStatus = {
|
|
||||||
status: ConnectionStatusType.Failed,
|
|
||||||
};
|
|
||||||
useNotebook.getState().resetContainerConnection(connectionStatus);
|
|
||||||
useNotebook.getState().setIsRefreshed(!useNotebook.getState().isRefreshed);
|
|
||||||
}
|
|
||||||
throw error;
|
|
||||||
} finally {
|
|
||||||
clearInProgressMessage();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
private getDeltaDatabases(
|
private getDeltaDatabases(
|
||||||
updatedDatabaseList: DataModels.Database[],
|
updatedDatabaseList: DataModels.Database[],
|
||||||
databases: ViewModels.Database[],
|
databases: ViewModels.Database[],
|
||||||
@ -1010,92 +910,6 @@ export default class Explorer {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* This creates a new notebook file, then opens the notebook
|
|
||||||
*/
|
|
||||||
public async onNewNotebookClicked(parent?: NotebookContentItem, isGithubTree?: boolean): Promise<void> {
|
|
||||||
if (!useNotebook.getState().isNotebookEnabled || !this.notebookManager?.notebookContentClient) {
|
|
||||||
const error = "Attempt to create new notebook, but notebook is not enabled";
|
|
||||||
handleError(error, "Explorer/onNewNotebookClicked");
|
|
||||||
throw new Error(error);
|
|
||||||
}
|
|
||||||
if (useNotebook.getState().isPhoenixNotebooks) {
|
|
||||||
if (isGithubTree) {
|
|
||||||
await this.allocateContainer(PoolIdType.DefaultPoolId);
|
|
||||||
parent = parent || this.resourceTree.myNotebooksContentRoot;
|
|
||||||
this.createNewNoteBook(parent, isGithubTree);
|
|
||||||
} else {
|
|
||||||
useDialog.getState().showOkCancelModalDialog(
|
|
||||||
Notebook.newNotebookModalTitle,
|
|
||||||
undefined,
|
|
||||||
"Create",
|
|
||||||
async () => {
|
|
||||||
await this.allocateContainer(PoolIdType.DefaultPoolId);
|
|
||||||
parent = parent || this.resourceTree.myNotebooksContentRoot;
|
|
||||||
this.createNewNoteBook(parent, isGithubTree);
|
|
||||||
},
|
|
||||||
"Cancel",
|
|
||||||
undefined,
|
|
||||||
this.getNewNoteWarningText(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
parent = parent || this.resourceTree.myNotebooksContentRoot;
|
|
||||||
this.createNewNoteBook(parent, isGithubTree);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private getNewNoteWarningText(): JSX.Element {
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<p>{Notebook.newNotebookModalContent1}</p>
|
|
||||||
<br />
|
|
||||||
<p>
|
|
||||||
{Notebook.newNotebookModalContent2}
|
|
||||||
<Link href={Notebook.cosmosNotebookHomePageUrl} target="_blank">
|
|
||||||
{Notebook.learnMore}
|
|
||||||
</Link>
|
|
||||||
</p>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
private createNewNoteBook(parent?: NotebookContentItem, isGithubTree?: boolean): void {
|
|
||||||
const clearInProgressMessage = logConsoleProgress(`Creating new notebook in ${parent.path}`);
|
|
||||||
const startKey: number = TelemetryProcessor.traceStart(Action.CreateNewNotebook, {
|
|
||||||
dataExplorerArea: Constants.Areas.Notebook,
|
|
||||||
});
|
|
||||||
|
|
||||||
this.notebookManager?.notebookContentClient
|
|
||||||
.createNewNotebookFile(parent, isGithubTree)
|
|
||||||
.then((newFile: NotebookContentItem) => {
|
|
||||||
logConsoleInfo(`Successfully created: ${newFile.name}`);
|
|
||||||
TelemetryProcessor.traceSuccess(
|
|
||||||
Action.CreateNewNotebook,
|
|
||||||
{
|
|
||||||
dataExplorerArea: Constants.Areas.Notebook,
|
|
||||||
},
|
|
||||||
startKey,
|
|
||||||
);
|
|
||||||
return this.openNotebook(newFile);
|
|
||||||
})
|
|
||||||
.then(() => this.resourceTree.triggerRender())
|
|
||||||
.catch((error) => {
|
|
||||||
const errorMessage = `Failed to create a new notebook: ${getErrorMessage(error)}`;
|
|
||||||
logConsoleError(errorMessage);
|
|
||||||
TelemetryProcessor.traceFailure(
|
|
||||||
Action.CreateNewNotebook,
|
|
||||||
{
|
|
||||||
dataExplorerArea: Constants.Areas.Notebook,
|
|
||||||
error: errorMessage,
|
|
||||||
errorStack: getErrorStack(error),
|
|
||||||
},
|
|
||||||
startKey,
|
|
||||||
);
|
|
||||||
})
|
|
||||||
.finally(clearInProgressMessage);
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Delete this function when ResourceTreeAdapter is removed.
|
// TODO: Delete this function when ResourceTreeAdapter is removed.
|
||||||
public async refreshContentItem(item: NotebookContentItem): Promise<void> {
|
public async refreshContentItem(item: NotebookContentItem): Promise<void> {
|
||||||
if (!useNotebook.getState().isNotebookEnabled || !this.notebookManager?.notebookContentClient) {
|
if (!useNotebook.getState().isNotebookEnabled || !this.notebookManager?.notebookContentClient) {
|
||||||
@ -1130,10 +944,6 @@ export default class Explorer {
|
|||||||
let title: string;
|
let title: string;
|
||||||
|
|
||||||
switch (kind) {
|
switch (kind) {
|
||||||
case ViewModels.TerminalKind.Default:
|
|
||||||
title = "Terminal";
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ViewModels.TerminalKind.Mongo:
|
case ViewModels.TerminalKind.Mongo:
|
||||||
title = "Mongo Shell";
|
title = "Mongo Shell";
|
||||||
break;
|
break;
|
||||||
@ -1287,36 +1097,6 @@ export default class Explorer {
|
|||||||
.openSidePanel("Input parameters", <ExecuteSprocParamsPane storedProcedure={storedProcedure} />);
|
.openSidePanel("Input parameters", <ExecuteSprocParamsPane storedProcedure={storedProcedure} />);
|
||||||
}
|
}
|
||||||
|
|
||||||
public openUploadFilePanel(parent?: NotebookContentItem): void {
|
|
||||||
if (useNotebook.getState().isPhoenixNotebooks) {
|
|
||||||
useDialog.getState().showOkCancelModalDialog(
|
|
||||||
Notebook.newNotebookUploadModalTitle,
|
|
||||||
undefined,
|
|
||||||
"Upload",
|
|
||||||
async () => {
|
|
||||||
await this.allocateContainer(PoolIdType.DefaultPoolId);
|
|
||||||
parent = parent || this.resourceTree.myNotebooksContentRoot;
|
|
||||||
this.uploadFilePanel(parent);
|
|
||||||
},
|
|
||||||
"Cancel",
|
|
||||||
undefined,
|
|
||||||
this.getNewNoteWarningText(),
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
parent = parent || this.resourceTree.myNotebooksContentRoot;
|
|
||||||
this.uploadFilePanel(parent);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private uploadFilePanel(parent?: NotebookContentItem): void {
|
|
||||||
useSidePanel
|
|
||||||
.getState()
|
|
||||||
.openSidePanel(
|
|
||||||
"Upload file to notebook server",
|
|
||||||
<UploadFilePane uploadFile={(name: string, content: string) => this.uploadFile(name, content, parent)} />,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public getDownloadModalConent(fileName: string): JSX.Element {
|
public getDownloadModalConent(fileName: string): JSX.Element {
|
||||||
if (useNotebook.getState().isPhoenixNotebooks) {
|
if (useNotebook.getState().isPhoenixNotebooks) {
|
||||||
return (
|
return (
|
||||||
|
@ -18,7 +18,6 @@ exports[`GitHub Repos Panel should render Default properly 1`] = `
|
|||||||
Object {
|
Object {
|
||||||
"container": Explorer {
|
"container": Explorer {
|
||||||
"_isInitializingNotebooks": false,
|
"_isInitializingNotebooks": false,
|
||||||
"_resetNotebookWorkspace": [Function],
|
|
||||||
"isFixedCollectionWithSharedThroughputSupported": [Function],
|
"isFixedCollectionWithSharedThroughputSupported": [Function],
|
||||||
"isTabsContentExpanded": [Function],
|
"isTabsContentExpanded": [Function],
|
||||||
"onRefreshDatabasesKeyPress": [Function],
|
"onRefreshDatabasesKeyPress": [Function],
|
||||||
|
@ -8,7 +8,6 @@ exports[`StringInput Pane should render Create new directory properly 1`] = `
|
|||||||
explorer={
|
explorer={
|
||||||
Explorer {
|
Explorer {
|
||||||
"_isInitializingNotebooks": false,
|
"_isInitializingNotebooks": false,
|
||||||
"_resetNotebookWorkspace": [Function],
|
|
||||||
"isFixedCollectionWithSharedThroughputSupported": [Function],
|
"isFixedCollectionWithSharedThroughputSupported": [Function],
|
||||||
"isTabsContentExpanded": [Function],
|
"isTabsContentExpanded": [Function],
|
||||||
"onRefreshDatabasesKeyPress": [Function],
|
"onRefreshDatabasesKeyPress": [Function],
|
||||||
|
@ -1,91 +0,0 @@
|
|||||||
import { Upload } from "Common/Upload/Upload";
|
|
||||||
import { useSidePanel } from "hooks/useSidePanel";
|
|
||||||
import React, { ChangeEvent, FunctionComponent, useState } from "react";
|
|
||||||
import { logConsoleError, logConsoleInfo, logConsoleProgress } from "Utils/NotificationConsoleUtils";
|
|
||||||
import { NotebookContentItem } from "../../Notebook/NotebookContentItem";
|
|
||||||
import { RightPaneForm, RightPaneFormProps } from "../RightPaneForm/RightPaneForm";
|
|
||||||
|
|
||||||
export interface UploadFilePanelProps {
|
|
||||||
uploadFile: (name: string, content: string) => Promise<NotebookContentItem>;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const UploadFilePane: FunctionComponent<UploadFilePanelProps> = ({ uploadFile }: UploadFilePanelProps) => {
|
|
||||||
const closeSidePanel = useSidePanel((state) => state.closeSidePanel);
|
|
||||||
const extensions: string = undefined; //ex. ".ipynb"
|
|
||||||
const errorMessage = "Could not upload file";
|
|
||||||
const inProgressMessage = "Uploading file to notebook server";
|
|
||||||
const successMessage = "Successfully uploaded file to notebook server";
|
|
||||||
|
|
||||||
const [files, setFiles] = useState<FileList>();
|
|
||||||
const [formErrors, setFormErrors] = useState<string>("");
|
|
||||||
const [isExecuting, setIsExecuting] = useState<boolean>(false);
|
|
||||||
|
|
||||||
const submit = () => {
|
|
||||||
setFormErrors("");
|
|
||||||
if (!files || files.length === 0) {
|
|
||||||
setFormErrors("No file specified. Please input a file.");
|
|
||||||
logConsoleError(`${errorMessage} -- No file specified. Please input a file.`);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const file: File = files.item(0);
|
|
||||||
|
|
||||||
const clearMessage = logConsoleProgress(`${inProgressMessage}: ${file.name}`);
|
|
||||||
|
|
||||||
setIsExecuting(true);
|
|
||||||
|
|
||||||
onSubmit(files.item(0))
|
|
||||||
.then(
|
|
||||||
() => {
|
|
||||||
logConsoleInfo(`${successMessage} ${file.name}`);
|
|
||||||
closeSidePanel();
|
|
||||||
},
|
|
||||||
(error: string) => {
|
|
||||||
setFormErrors(errorMessage);
|
|
||||||
logConsoleError(`${errorMessage} ${file.name}: ${error}`);
|
|
||||||
},
|
|
||||||
)
|
|
||||||
.finally(() => {
|
|
||||||
setIsExecuting(false);
|
|
||||||
clearMessage();
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const updateSelectedFiles = (event: ChangeEvent<HTMLInputElement>): void => {
|
|
||||||
setFiles(event.target.files);
|
|
||||||
};
|
|
||||||
|
|
||||||
const onSubmit = async (file: File): Promise<NotebookContentItem> => {
|
|
||||||
const readFileAsText = (inputFile: File): Promise<string> => {
|
|
||||||
const reader = new FileReader();
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
reader.onerror = () => {
|
|
||||||
reader.abort();
|
|
||||||
reject(`Problem parsing file: ${inputFile}`);
|
|
||||||
};
|
|
||||||
reader.onload = () => {
|
|
||||||
resolve(reader.result as string);
|
|
||||||
};
|
|
||||||
reader.readAsText(inputFile);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const fileContent = await readFileAsText(file);
|
|
||||||
return uploadFile(file.name, fileContent);
|
|
||||||
};
|
|
||||||
|
|
||||||
const props: RightPaneFormProps = {
|
|
||||||
formError: formErrors,
|
|
||||||
isExecuting: isExecuting,
|
|
||||||
submitButtonText: "Upload",
|
|
||||||
onSubmit: submit,
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<RightPaneForm {...props}>
|
|
||||||
<div className="paneMainContent">
|
|
||||||
<Upload label="Select file to upload" accept={extensions} onUpload={updateSelectedFiles} />
|
|
||||||
</div>
|
|
||||||
</RightPaneForm>
|
|
||||||
);
|
|
||||||
};
|
|
@ -23,7 +23,6 @@ exports[`Query copilot tab snapshot test should render with initial input 1`] =
|
|||||||
explorer={
|
explorer={
|
||||||
Explorer {
|
Explorer {
|
||||||
"_isInitializingNotebooks": false,
|
"_isInitializingNotebooks": false,
|
||||||
"_resetNotebookWorkspace": [Function],
|
|
||||||
"isFixedCollectionWithSharedThroughputSupported": [Function],
|
"isFixedCollectionWithSharedThroughputSupported": [Function],
|
||||||
"isTabsContentExpanded": [Function],
|
"isTabsContentExpanded": [Function],
|
||||||
"onRefreshDatabasesKeyPress": [Function],
|
"onRefreshDatabasesKeyPress": [Function],
|
||||||
|
@ -25,7 +25,6 @@ import * as React from "react";
|
|||||||
import ConnectIcon from "../../../images/Connect_color.svg";
|
import ConnectIcon from "../../../images/Connect_color.svg";
|
||||||
import ContainersIcon from "../../../images/Containers.svg";
|
import ContainersIcon from "../../../images/Containers.svg";
|
||||||
import LinkIcon from "../../../images/Link_blue.svg";
|
import LinkIcon from "../../../images/Link_blue.svg";
|
||||||
import NotebookColorIcon from "../../../images/Notebooks.svg";
|
|
||||||
import PowerShellIcon from "../../../images/PowerShell.svg";
|
import PowerShellIcon from "../../../images/PowerShell.svg";
|
||||||
import CopilotIcon from "../../../images/QueryCopilotNewLogo.svg";
|
import CopilotIcon from "../../../images/QueryCopilotNewLogo.svg";
|
||||||
import QuickStartIcon from "../../../images/Quickstart_Lightning.svg";
|
import QuickStartIcon from "../../../images/Quickstart_Lightning.svg";
|
||||||
@ -410,14 +409,6 @@ export class SplashScreen extends React.Component<SplashScreenProps> {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
heroes.push(launchQuickstartBtn);
|
heroes.push(launchQuickstartBtn);
|
||||||
} else if (useNotebook.getState().isPhoenixNotebooks) {
|
|
||||||
const newNotebookBtn = {
|
|
||||||
iconSrc: NotebookColorIcon,
|
|
||||||
title: "New notebook",
|
|
||||||
description: "Visualize your data stored in Azure Cosmos DB",
|
|
||||||
onClick: () => this.container.onNewNotebookClicked(),
|
|
||||||
};
|
|
||||||
heroes.push(newNotebookBtn);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
heroes.push(this.getShellCard());
|
heroes.push(this.getShellCard());
|
||||||
|
@ -1,11 +1,9 @@
|
|||||||
import { Callout, DirectionalHint, ICalloutProps, ILinkProps, Link, Stack, Text } from "@fluentui/react";
|
|
||||||
import { SampleDataTree } from "Explorer/Tree/SampleDataTree";
|
import { SampleDataTree } from "Explorer/Tree/SampleDataTree";
|
||||||
import { getItemName } from "Utils/APITypeUtils";
|
import { getItemName } from "Utils/APITypeUtils";
|
||||||
import { useQueryCopilot } from "hooks/useQueryCopilot";
|
import { useQueryCopilot } from "hooks/useQueryCopilot";
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import shallow from "zustand/shallow";
|
import shallow from "zustand/shallow";
|
||||||
import CosmosDBIcon from "../../../images/Azure-Cosmos-DB.svg";
|
import CosmosDBIcon from "../../../images/Azure-Cosmos-DB.svg";
|
||||||
import GalleryIcon from "../../../images/GalleryIcon.svg";
|
|
||||||
import DeleteIcon from "../../../images/delete.svg";
|
import DeleteIcon from "../../../images/delete.svg";
|
||||||
import CopyIcon from "../../../images/notebook/Notebook-copy.svg";
|
import CopyIcon from "../../../images/notebook/Notebook-copy.svg";
|
||||||
import NewNotebookIcon from "../../../images/notebook/Notebook-new.svg";
|
import NewNotebookIcon from "../../../images/notebook/Notebook-new.svg";
|
||||||
@ -14,17 +12,14 @@ import FileIcon from "../../../images/notebook/file-cosmos.svg";
|
|||||||
import PublishIcon from "../../../images/notebook/publish_content.svg";
|
import PublishIcon from "../../../images/notebook/publish_content.svg";
|
||||||
import RefreshIcon from "../../../images/refresh-cosmos.svg";
|
import RefreshIcon from "../../../images/refresh-cosmos.svg";
|
||||||
import CollectionIcon from "../../../images/tree-collection.svg";
|
import CollectionIcon from "../../../images/tree-collection.svg";
|
||||||
import { Areas, ConnectionStatusType, Notebook } from "../../Common/Constants";
|
|
||||||
import { isPublicInternetAccessAllowed } from "../../Common/DatabaseAccountUtility";
|
import { isPublicInternetAccessAllowed } from "../../Common/DatabaseAccountUtility";
|
||||||
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 { LocalStorageUtility, StorageKey } from "../../Shared/StorageUtility";
|
|
||||||
import { Action, ActionModifiers, Source } from "../../Shared/Telemetry/TelemetryConstants";
|
import { Action, ActionModifiers, Source } 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 { isServerlessAccount } from "../../Utils/CapabilityUtils";
|
import { isServerlessAccount } from "../../Utils/CapabilityUtils";
|
||||||
import * as GitHubUtils from "../../Utils/GitHubUtils";
|
import * as GitHubUtils from "../../Utils/GitHubUtils";
|
||||||
import { useSidePanel } from "../../hooks/useSidePanel";
|
|
||||||
import { useTabs } from "../../hooks/useTabs";
|
import { useTabs } from "../../hooks/useTabs";
|
||||||
import * as ResourceTreeContextMenuButtonFactory from "../ContextMenuButtonFactory";
|
import * as ResourceTreeContextMenuButtonFactory from "../ContextMenuButtonFactory";
|
||||||
import { AccordionComponent, AccordionItemComponent } from "../Controls/Accordion/AccordionComponent";
|
import { AccordionComponent, AccordionItemComponent } from "../Controls/Accordion/AccordionComponent";
|
||||||
@ -36,7 +31,6 @@ import { mostRecentActivity } from "../MostRecentActivity/MostRecentActivity";
|
|||||||
import { NotebookContentItem, NotebookContentItemType } from "../Notebook/NotebookContentItem";
|
import { NotebookContentItem, NotebookContentItemType } from "../Notebook/NotebookContentItem";
|
||||||
import { NotebookUtil } from "../Notebook/NotebookUtil";
|
import { NotebookUtil } from "../Notebook/NotebookUtil";
|
||||||
import { useNotebook } from "../Notebook/useNotebook";
|
import { useNotebook } from "../Notebook/useNotebook";
|
||||||
import { GitHubReposPanel } from "../Panes/GitHubReposPanel/GitHubReposPanel";
|
|
||||||
import TabsBase from "../Tabs/TabsBase";
|
import TabsBase from "../Tabs/TabsBase";
|
||||||
import { useDatabases } from "../useDatabases";
|
import { useDatabases } from "../useDatabases";
|
||||||
import { useSelectedNode } from "../useSelectedNode";
|
import { useSelectedNode } from "../useSelectedNode";
|
||||||
@ -75,152 +69,6 @@ export const ResourceTree: React.FC<ResourceTreeProps> = ({ container }: Resourc
|
|||||||
configContext.platform !== Platform.Fabric && (userContext.apiType === "SQL" || userContext.apiType === "Gremlin");
|
configContext.platform !== Platform.Fabric && (userContext.apiType === "SQL" || userContext.apiType === "Gremlin");
|
||||||
const pseudoDirPath = "PsuedoDir";
|
const pseudoDirPath = "PsuedoDir";
|
||||||
|
|
||||||
const buildGalleryCallout = (): JSX.Element => {
|
|
||||||
if (
|
|
||||||
LocalStorageUtility.hasItem(StorageKey.GalleryCalloutDismissed) &&
|
|
||||||
LocalStorageUtility.getEntryBoolean(StorageKey.GalleryCalloutDismissed)
|
|
||||||
) {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
const calloutProps: ICalloutProps = {
|
|
||||||
calloutMaxWidth: 350,
|
|
||||||
ariaLabel: "New gallery",
|
|
||||||
role: "alertdialog",
|
|
||||||
gapSpace: 0,
|
|
||||||
target: ".galleryHeader",
|
|
||||||
directionalHint: DirectionalHint.leftTopEdge,
|
|
||||||
onDismiss: () => {
|
|
||||||
LocalStorageUtility.setEntryBoolean(StorageKey.GalleryCalloutDismissed, true);
|
|
||||||
},
|
|
||||||
setInitialFocus: true,
|
|
||||||
};
|
|
||||||
|
|
||||||
const openGalleryProps: ILinkProps = {
|
|
||||||
onClick: () => {
|
|
||||||
LocalStorageUtility.setEntryBoolean(StorageKey.GalleryCalloutDismissed, true);
|
|
||||||
container.openGallery();
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Callout {...calloutProps}>
|
|
||||||
<Stack tokens={{ childrenGap: 10, padding: 20 }}>
|
|
||||||
<Text variant="xLarge" block>
|
|
||||||
New gallery
|
|
||||||
</Text>
|
|
||||||
<Text block>
|
|
||||||
Sample notebooks are now combined in gallery. View and try out samples provided by Microsoft and other
|
|
||||||
contributors.
|
|
||||||
</Text>
|
|
||||||
<Link {...openGalleryProps}>Open gallery</Link>
|
|
||||||
</Stack>
|
|
||||||
</Callout>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const buildNotebooksTree = (): TreeNode => {
|
|
||||||
const notebooksTree: TreeNode = {
|
|
||||||
label: undefined,
|
|
||||||
isExpanded: true,
|
|
||||||
children: [],
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!useNotebook.getState().isPhoenixNotebooks) {
|
|
||||||
notebooksTree.children.push(buildNotebooksTemporarilyDownTree());
|
|
||||||
} else {
|
|
||||||
if (galleryContentRoot) {
|
|
||||||
notebooksTree.children.push(buildGalleryNotebooksTree());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (
|
|
||||||
myNotebooksContentRoot &&
|
|
||||||
useNotebook.getState().isPhoenixNotebooks &&
|
|
||||||
useNotebook.getState().connectionInfo.status === ConnectionStatusType.Connected
|
|
||||||
) {
|
|
||||||
notebooksTree.children.push(buildMyNotebooksTree());
|
|
||||||
}
|
|
||||||
if (container.notebookManager?.gitHubOAuthService.isLoggedIn()) {
|
|
||||||
// collapse all other notebook nodes
|
|
||||||
notebooksTree.children.forEach((node) => (node.isExpanded = false));
|
|
||||||
notebooksTree.children.push(buildGitHubNotebooksTree(true));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return notebooksTree;
|
|
||||||
};
|
|
||||||
|
|
||||||
const buildNotebooksTemporarilyDownTree = (): TreeNode => {
|
|
||||||
return {
|
|
||||||
label: Notebook.temporarilyDownMsg,
|
|
||||||
className: "clickDisabled",
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
const buildGalleryNotebooksTree = (): TreeNode => {
|
|
||||||
return {
|
|
||||||
label: "Gallery",
|
|
||||||
iconSrc: GalleryIcon,
|
|
||||||
className: "notebookHeader galleryHeader",
|
|
||||||
onClick: () => container.openGallery(),
|
|
||||||
isSelected: () => activeTab?.tabKind === ViewModels.CollectionTabKind.Gallery,
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
const buildMyNotebooksTree = (): TreeNode => {
|
|
||||||
const myNotebooksTree: TreeNode = buildNotebookDirectoryNode(
|
|
||||||
myNotebooksContentRoot,
|
|
||||||
(item: NotebookContentItem) => {
|
|
||||||
container.openNotebook(item);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
myNotebooksTree.isExpanded = true;
|
|
||||||
myNotebooksTree.isAlphaSorted = true;
|
|
||||||
// Remove "Delete" menu item from context menu
|
|
||||||
myNotebooksTree.contextMenu = myNotebooksTree.contextMenu.filter((menuItem) => menuItem.label !== "Delete");
|
|
||||||
return myNotebooksTree;
|
|
||||||
};
|
|
||||||
|
|
||||||
const buildGitHubNotebooksTree = (isConnected: boolean): TreeNode => {
|
|
||||||
const gitHubNotebooksTree: TreeNode = buildNotebookDirectoryNode(
|
|
||||||
gitHubNotebooksContentRoot,
|
|
||||||
(item: NotebookContentItem) => {
|
|
||||||
container.openNotebook(item);
|
|
||||||
},
|
|
||||||
true,
|
|
||||||
);
|
|
||||||
const manageGitContextMenu: TreeNodeMenuItem[] = [
|
|
||||||
{
|
|
||||||
label: "Manage GitHub settings",
|
|
||||||
onClick: () =>
|
|
||||||
useSidePanel
|
|
||||||
.getState()
|
|
||||||
.openSidePanel(
|
|
||||||
"Manage GitHub settings",
|
|
||||||
<GitHubReposPanel
|
|
||||||
explorer={container}
|
|
||||||
gitHubClientProp={container.notebookManager.gitHubClient}
|
|
||||||
junoClientProp={container.notebookManager.junoClient}
|
|
||||||
/>,
|
|
||||||
),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "Disconnect from GitHub",
|
|
||||||
onClick: () => {
|
|
||||||
TelemetryProcessor.trace(Action.NotebooksGitHubDisconnect, ActionModifiers.Mark, {
|
|
||||||
dataExplorerArea: Areas.Notebook,
|
|
||||||
});
|
|
||||||
container.notebookManager?.gitHubOAuthService.logout();
|
|
||||||
},
|
|
||||||
},
|
|
||||||
];
|
|
||||||
gitHubNotebooksTree.contextMenu = manageGitContextMenu;
|
|
||||||
gitHubNotebooksTree.isExpanded = true;
|
|
||||||
gitHubNotebooksTree.isAlphaSorted = true;
|
|
||||||
|
|
||||||
return gitHubNotebooksTree;
|
|
||||||
};
|
|
||||||
|
|
||||||
const buildChildNodes = (
|
const buildChildNodes = (
|
||||||
item: NotebookContentItem,
|
item: NotebookContentItem,
|
||||||
onFileClick: (item: NotebookContentItem) => void,
|
onFileClick: (item: NotebookContentItem) => void,
|
||||||
@ -373,11 +221,6 @@ export const ResourceTree: React.FC<ResourceTreeProps> = ({ container }: Resourc
|
|||||||
iconSrc: NewNotebookIcon,
|
iconSrc: NewNotebookIcon,
|
||||||
onClick: () => container.onCreateDirectory(item, isGithubTree),
|
onClick: () => container.onCreateDirectory(item, isGithubTree),
|
||||||
},
|
},
|
||||||
{
|
|
||||||
label: "Upload File",
|
|
||||||
iconSrc: NewNotebookIcon,
|
|
||||||
onClick: () => container.openUploadFilePanel(item),
|
|
||||||
},
|
|
||||||
];
|
];
|
||||||
|
|
||||||
//disallow renaming of temporary notebook workspace
|
//disallow renaming of temporary notebook workspace
|
||||||
@ -782,8 +625,6 @@ export const ResourceTree: React.FC<ResourceTreeProps> = ({ container }: Resourc
|
|||||||
<TreeComponent className="dataResourceTree" rootNode={dataRootNode} />
|
<TreeComponent className="dataResourceTree" rootNode={dataRootNode} />
|
||||||
</AccordionItemComponent>
|
</AccordionItemComponent>
|
||||||
</AccordionComponent>
|
</AccordionComponent>
|
||||||
|
|
||||||
{/* {buildGalleryCallout()} */}
|
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
{!isNotebookEnabled && isSampleDataEnabled && (
|
{!isNotebookEnabled && isSampleDataEnabled && (
|
||||||
@ -796,8 +637,6 @@ export const ResourceTree: React.FC<ResourceTreeProps> = ({ container }: Resourc
|
|||||||
<SampleDataTree sampleDataResourceTokenCollection={sampleDataResourceTokenCollection} />
|
<SampleDataTree sampleDataResourceTokenCollection={sampleDataResourceTokenCollection} />
|
||||||
</AccordionItemComponent>
|
</AccordionItemComponent>
|
||||||
</AccordionComponent>
|
</AccordionComponent>
|
||||||
|
|
||||||
{/* {buildGalleryCallout()} */}
|
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
{isNotebookEnabled && isSampleDataEnabled && (
|
{isNotebookEnabled && isSampleDataEnabled && (
|
||||||
@ -809,12 +648,7 @@ export const ResourceTree: React.FC<ResourceTreeProps> = ({ container }: Resourc
|
|||||||
<AccordionItemComponent title={"SAMPLE DATA"} containerStyles={{ display: "table" }}>
|
<AccordionItemComponent title={"SAMPLE DATA"} containerStyles={{ display: "table" }}>
|
||||||
<SampleDataTree sampleDataResourceTokenCollection={sampleDataResourceTokenCollection} />
|
<SampleDataTree sampleDataResourceTokenCollection={sampleDataResourceTokenCollection} />
|
||||||
</AccordionItemComponent>
|
</AccordionItemComponent>
|
||||||
<AccordionItemComponent title={"NOTEBOOKS"}>
|
|
||||||
<TreeComponent className="notebookResourceTree" rootNode={buildNotebooksTree()} />
|
|
||||||
</AccordionItemComponent>
|
|
||||||
</AccordionComponent>
|
</AccordionComponent>
|
||||||
|
|
||||||
{/* {buildGalleryCallout()} */}
|
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
|
@ -1,9 +1,7 @@
|
|||||||
import { Callout, DirectionalHint, ICalloutProps, ILinkProps, Link, Stack, Text } from "@fluentui/react";
|
|
||||||
import { getItemName } from "Utils/APITypeUtils";
|
import { getItemName } from "Utils/APITypeUtils";
|
||||||
import * as ko from "knockout";
|
import * as ko from "knockout";
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import CosmosDBIcon from "../../../images/Azure-Cosmos-DB.svg";
|
import CosmosDBIcon from "../../../images/Azure-Cosmos-DB.svg";
|
||||||
import GalleryIcon from "../../../images/GalleryIcon.svg";
|
|
||||||
import DeleteIcon from "../../../images/delete.svg";
|
import DeleteIcon from "../../../images/delete.svg";
|
||||||
import CopyIcon from "../../../images/notebook/Notebook-copy.svg";
|
import CopyIcon from "../../../images/notebook/Notebook-copy.svg";
|
||||||
import NewNotebookIcon from "../../../images/notebook/Notebook-new.svg";
|
import NewNotebookIcon from "../../../images/notebook/Notebook-new.svg";
|
||||||
@ -13,21 +11,17 @@ import PublishIcon from "../../../images/notebook/publish_content.svg";
|
|||||||
import RefreshIcon from "../../../images/refresh-cosmos.svg";
|
import RefreshIcon from "../../../images/refresh-cosmos.svg";
|
||||||
import CollectionIcon from "../../../images/tree-collection.svg";
|
import CollectionIcon from "../../../images/tree-collection.svg";
|
||||||
import { ReactAdapter } from "../../Bindings/ReactBindingHandler";
|
import { ReactAdapter } from "../../Bindings/ReactBindingHandler";
|
||||||
import { Areas } from "../../Common/Constants";
|
|
||||||
import { isPublicInternetAccessAllowed } from "../../Common/DatabaseAccountUtility";
|
import { isPublicInternetAccessAllowed } from "../../Common/DatabaseAccountUtility";
|
||||||
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 { IPinnedRepo } from "../../Juno/JunoClient";
|
import { IPinnedRepo } from "../../Juno/JunoClient";
|
||||||
import { LocalStorageUtility, StorageKey } from "../../Shared/StorageUtility";
|
|
||||||
import { Action, ActionModifiers, Source } from "../../Shared/Telemetry/TelemetryConstants";
|
import { Action, ActionModifiers, Source } 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 { isServerlessAccount } from "../../Utils/CapabilityUtils";
|
import { isServerlessAccount } from "../../Utils/CapabilityUtils";
|
||||||
import * as GitHubUtils from "../../Utils/GitHubUtils";
|
import * as GitHubUtils from "../../Utils/GitHubUtils";
|
||||||
import { useSidePanel } from "../../hooks/useSidePanel";
|
|
||||||
import { useTabs } from "../../hooks/useTabs";
|
import { useTabs } from "../../hooks/useTabs";
|
||||||
import * as ResourceTreeContextMenuButtonFactory from "../ContextMenuButtonFactory";
|
import * as ResourceTreeContextMenuButtonFactory from "../ContextMenuButtonFactory";
|
||||||
import { AccordionComponent, AccordionItemComponent } from "../Controls/Accordion/AccordionComponent";
|
|
||||||
import { useDialog } from "../Controls/Dialog";
|
import { useDialog } from "../Controls/Dialog";
|
||||||
import { TreeComponent, TreeNode, TreeNodeMenuItem } from "../Controls/TreeComponent/TreeComponent";
|
import { TreeComponent, TreeNode, TreeNodeMenuItem } from "../Controls/TreeComponent/TreeComponent";
|
||||||
import Explorer from "../Explorer";
|
import Explorer from "../Explorer";
|
||||||
@ -36,7 +30,6 @@ import { mostRecentActivity } from "../MostRecentActivity/MostRecentActivity";
|
|||||||
import { NotebookContentItem, NotebookContentItemType } from "../Notebook/NotebookContentItem";
|
import { NotebookContentItem, NotebookContentItemType } from "../Notebook/NotebookContentItem";
|
||||||
import { NotebookUtil } from "../Notebook/NotebookUtil";
|
import { NotebookUtil } from "../Notebook/NotebookUtil";
|
||||||
import { useNotebook } from "../Notebook/useNotebook";
|
import { useNotebook } from "../Notebook/useNotebook";
|
||||||
import { GitHubReposPanel } from "../Panes/GitHubReposPanel/GitHubReposPanel";
|
|
||||||
import TabsBase from "../Tabs/TabsBase";
|
import TabsBase from "../Tabs/TabsBase";
|
||||||
import { useDatabases } from "../useDatabases";
|
import { useDatabases } from "../useDatabases";
|
||||||
import { useSelectedNode } from "../useSelectedNode";
|
import { useSelectedNode } from "../useSelectedNode";
|
||||||
@ -102,27 +95,8 @@ export class ResourceTreeAdapter implements ReactAdapter {
|
|||||||
|
|
||||||
public renderComponent(): JSX.Element {
|
public renderComponent(): JSX.Element {
|
||||||
const dataRootNode = this.buildDataTree();
|
const dataRootNode = this.buildDataTree();
|
||||||
const notebooksRootNode = this.buildNotebooksTrees();
|
|
||||||
|
|
||||||
if (useNotebook.getState().isNotebookEnabled) {
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<AccordionComponent>
|
|
||||||
<AccordionItemComponent title={ResourceTreeAdapter.DataTitle} isExpanded={!this.gitHubNotebooksContentRoot}>
|
|
||||||
<TreeComponent className="dataResourceTree" rootNode={dataRootNode} />
|
|
||||||
</AccordionItemComponent>
|
|
||||||
<AccordionItemComponent title={ResourceTreeAdapter.NotebooksTitle}>
|
|
||||||
<TreeComponent className="notebookResourceTree" rootNode={notebooksRootNode} />
|
|
||||||
</AccordionItemComponent>
|
|
||||||
</AccordionComponent>
|
|
||||||
|
|
||||||
{/* {this.galleryContentRoot && this.buildGalleryCallout()} */}
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
return <TreeComponent className="dataResourceTree" rootNode={dataRootNode} />;
|
return <TreeComponent className="dataResourceTree" rootNode={dataRootNode} />;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public async initialize(): Promise<void[]> {
|
public async initialize(): Promise<void[]> {
|
||||||
const refreshTasks: Promise<void>[] = [];
|
const refreshTasks: Promise<void>[] = [];
|
||||||
@ -504,156 +478,6 @@ export class ResourceTreeAdapter implements ReactAdapter {
|
|||||||
return traverse(schema);
|
return traverse(schema);
|
||||||
}
|
}
|
||||||
|
|
||||||
private buildNotebooksTrees(): TreeNode {
|
|
||||||
let notebooksTree: TreeNode = {
|
|
||||||
label: undefined,
|
|
||||||
isExpanded: true,
|
|
||||||
children: [],
|
|
||||||
};
|
|
||||||
|
|
||||||
if (this.galleryContentRoot) {
|
|
||||||
notebooksTree.children.push(this.buildGalleryNotebooksTree());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.myNotebooksContentRoot) {
|
|
||||||
notebooksTree.children.push(this.buildMyNotebooksTree());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.gitHubNotebooksContentRoot) {
|
|
||||||
// collapse all other notebook nodes
|
|
||||||
notebooksTree.children.forEach((node) => (node.isExpanded = false));
|
|
||||||
notebooksTree.children.push(this.buildGitHubNotebooksTree());
|
|
||||||
}
|
|
||||||
|
|
||||||
return notebooksTree;
|
|
||||||
}
|
|
||||||
|
|
||||||
private buildGalleryCallout(): JSX.Element {
|
|
||||||
if (
|
|
||||||
LocalStorageUtility.hasItem(StorageKey.GalleryCalloutDismissed) &&
|
|
||||||
LocalStorageUtility.getEntryBoolean(StorageKey.GalleryCalloutDismissed)
|
|
||||||
) {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
const calloutProps: ICalloutProps = {
|
|
||||||
calloutMaxWidth: 350,
|
|
||||||
ariaLabel: "New gallery",
|
|
||||||
role: "alertdialog",
|
|
||||||
gapSpace: 0,
|
|
||||||
target: ".galleryHeader",
|
|
||||||
directionalHint: DirectionalHint.leftTopEdge,
|
|
||||||
onDismiss: () => {
|
|
||||||
LocalStorageUtility.setEntryBoolean(StorageKey.GalleryCalloutDismissed, true);
|
|
||||||
this.triggerRender();
|
|
||||||
},
|
|
||||||
setInitialFocus: true,
|
|
||||||
};
|
|
||||||
|
|
||||||
const openGalleryProps: ILinkProps = {
|
|
||||||
onClick: () => {
|
|
||||||
LocalStorageUtility.setEntryBoolean(StorageKey.GalleryCalloutDismissed, true);
|
|
||||||
this.container.openGallery();
|
|
||||||
this.triggerRender();
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Callout {...calloutProps}>
|
|
||||||
<Stack tokens={{ childrenGap: 10, padding: 20 }}>
|
|
||||||
<Text variant="xLarge" block>
|
|
||||||
New gallery
|
|
||||||
</Text>
|
|
||||||
<Text block>
|
|
||||||
Sample notebooks are now combined in gallery. View and try out samples provided by Microsoft and other
|
|
||||||
contributors.
|
|
||||||
</Text>
|
|
||||||
<Link {...openGalleryProps}>Open gallery</Link>
|
|
||||||
</Stack>
|
|
||||||
</Callout>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
private buildGalleryNotebooksTree(): TreeNode {
|
|
||||||
return {
|
|
||||||
label: "Gallery",
|
|
||||||
iconSrc: GalleryIcon,
|
|
||||||
className: "notebookHeader galleryHeader",
|
|
||||||
onClick: () => this.container.openGallery(),
|
|
||||||
isSelected: () => {
|
|
||||||
const activeTab = useTabs.getState().activeTab;
|
|
||||||
return activeTab && activeTab.tabKind === ViewModels.CollectionTabKind.Gallery;
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
private buildMyNotebooksTree(): TreeNode {
|
|
||||||
const myNotebooksTree: TreeNode = this.buildNotebookDirectoryNode(
|
|
||||||
this.myNotebooksContentRoot,
|
|
||||||
(item: NotebookContentItem) => {
|
|
||||||
this.container.openNotebook(item).then((hasOpened) => {
|
|
||||||
if (hasOpened) {
|
|
||||||
mostRecentActivity.notebookWasItemOpened(userContext.databaseAccount?.id, item);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
true,
|
|
||||||
true,
|
|
||||||
);
|
|
||||||
|
|
||||||
myNotebooksTree.isExpanded = true;
|
|
||||||
myNotebooksTree.isAlphaSorted = true;
|
|
||||||
// Remove "Delete" menu item from context menu
|
|
||||||
myNotebooksTree.contextMenu = myNotebooksTree.contextMenu.filter((menuItem) => menuItem.label !== "Delete");
|
|
||||||
return myNotebooksTree;
|
|
||||||
}
|
|
||||||
|
|
||||||
private buildGitHubNotebooksTree(): TreeNode {
|
|
||||||
const gitHubNotebooksTree: TreeNode = this.buildNotebookDirectoryNode(
|
|
||||||
this.gitHubNotebooksContentRoot,
|
|
||||||
(item: NotebookContentItem) => {
|
|
||||||
this.container.openNotebook(item).then((hasOpened) => {
|
|
||||||
if (hasOpened) {
|
|
||||||
mostRecentActivity.notebookWasItemOpened(userContext.databaseAccount?.id, item);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
true,
|
|
||||||
true,
|
|
||||||
);
|
|
||||||
|
|
||||||
gitHubNotebooksTree.contextMenu = [
|
|
||||||
{
|
|
||||||
label: "Manage GitHub settings",
|
|
||||||
onClick: () =>
|
|
||||||
useSidePanel
|
|
||||||
.getState()
|
|
||||||
.openSidePanel(
|
|
||||||
"Manage GitHub settings",
|
|
||||||
<GitHubReposPanel
|
|
||||||
explorer={this.container}
|
|
||||||
gitHubClientProp={this.container.notebookManager.gitHubClient}
|
|
||||||
junoClientProp={this.container.notebookManager.junoClient}
|
|
||||||
/>,
|
|
||||||
),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "Disconnect from GitHub",
|
|
||||||
onClick: () => {
|
|
||||||
TelemetryProcessor.trace(Action.NotebooksGitHubDisconnect, ActionModifiers.Mark, {
|
|
||||||
dataExplorerArea: Areas.Notebook,
|
|
||||||
});
|
|
||||||
this.container.notebookManager?.gitHubOAuthService.logout();
|
|
||||||
},
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
gitHubNotebooksTree.isExpanded = true;
|
|
||||||
gitHubNotebooksTree.isAlphaSorted = true;
|
|
||||||
|
|
||||||
return gitHubNotebooksTree;
|
|
||||||
}
|
|
||||||
|
|
||||||
private buildChildNodes(
|
private buildChildNodes(
|
||||||
item: NotebookContentItem,
|
item: NotebookContentItem,
|
||||||
onFileClick: (item: NotebookContentItem) => void,
|
onFileClick: (item: NotebookContentItem) => void,
|
||||||
@ -800,11 +624,6 @@ export class ResourceTreeAdapter implements ReactAdapter {
|
|||||||
iconSrc: NewNotebookIcon,
|
iconSrc: NewNotebookIcon,
|
||||||
onClick: () => this.container.onCreateDirectory(item),
|
onClick: () => this.container.onCreateDirectory(item),
|
||||||
},
|
},
|
||||||
{
|
|
||||||
label: "Upload File",
|
|
||||||
iconSrc: NewNotebookIcon,
|
|
||||||
onClick: () => this.container.openUploadFilePanel(item),
|
|
||||||
},
|
|
||||||
];
|
];
|
||||||
|
|
||||||
//disallow renaming of temporary notebook workspace
|
//disallow renaming of temporary notebook workspace
|
||||||
|
Loading…
Reference in New Issue
Block a user