diff --git a/src/Common/Constants.ts b/src/Common/Constants.ts index 36dfa83a1..6a1316681 100644 --- a/src/Common/Constants.ts +++ b/src/Common/Constants.ts @@ -365,7 +365,7 @@ export class Notebook { public static readonly containerStatusHeartbeatDelayMs = 30000; public static readonly kernelRestartInitialDelayMs = 1000; public static readonly kernelRestartMaxDelayMs = 20000; - public static readonly autoSaveIntervalMs = 120000; + public static readonly autoSaveIntervalMs = 300000; public static readonly memoryGuageToGB = 1048576; public static readonly lowMemoryThreshold = 0.8; public static readonly remainingTimeForAlert = 10; @@ -378,7 +378,7 @@ export class Notebook { "We have identified an issue with the Cassandra Shell and it is unavailable right now. We are actively working on the mitigation."; public static saveNotebookModalTitle = "Save notebook in temporary workspace"; public static saveNotebookModalContent = - "This notebook will be saved in the temporary workspace and will be removed when the session expires. To save your work permanently, save your notebooks to a GitHub repository or download the notebooks to your local machine before the session ends."; + "This notebook will be saved in the temporary workspace and will be removed when the session expires."; public static newNotebookModalTitle = "Create notebook in temporary workspace"; public static newNotebookUploadModalTitle = "Upload notebook to temporary workspace"; public static newNotebookModalContent1 = diff --git a/src/Explorer/Notebook/NotebookComponent/NotebookComponentBootstrapper.tsx b/src/Explorer/Notebook/NotebookComponent/NotebookComponentBootstrapper.tsx index 068c63a2f..7f1237bf6 100644 --- a/src/Explorer/Notebook/NotebookComponent/NotebookComponentBootstrapper.tsx +++ b/src/Explorer/Notebook/NotebookComponent/NotebookComponentBootstrapper.tsx @@ -1,4 +1,5 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ +import { Link } from "@fluentui/react"; import { CellId, CellType, ImmutableNotebook } from "@nteract/commutable"; // Vendor modules import { @@ -14,13 +15,15 @@ import "@nteract/styles/editor-overrides.css"; import "@nteract/styles/global-variables.css"; import "codemirror/addon/hint/show-hint.css"; import "codemirror/lib/codemirror.css"; +import { Notebook } from "Common/Constants"; +import { useDialog } from "Explorer/Controls/Dialog"; import * as Immutable from "immutable"; import * as React from "react"; import { Provider } from "react-redux"; import "react-table/react-table.css"; import { AnyAction, Store } from "redux"; import { NotebookClientV2 } from "../NotebookClientV2"; -import { NotebookUtil } from "../NotebookUtil"; +import { NotebookContentProviderType, NotebookUtil } from "../NotebookUtil"; import * as NteractUtil from "../NTeractUtil"; import * as CdbActions from "./actions"; import { NotebookComponent } from "./NotebookComponent"; @@ -99,6 +102,10 @@ export class NotebookComponentBootstrapper { }; } + public getNotebookPath(): string { + return this.getStore().getState().core.entities.contents.byRef.get(this.contentRef)?.filepath; + } + public setContent(name: string, content: unknown): void { this.getStore().dispatch( actions.fetchContentFulfilled({ @@ -130,11 +137,32 @@ export class NotebookComponentBootstrapper { /* Notebook operations. See nteract/packages/connected-components/src/notebook-menu/index.tsx */ public notebookSave(): void { - this.getStore().dispatch( - actions.save({ - contentRef: this.contentRef, - }) - ); + if ( + NotebookUtil.getContentProviderType(this.getNotebookPath()) === + NotebookContentProviderType.JupyterContentProviderType + ) { + useDialog.getState().showOkCancelModalDialog( + Notebook.saveNotebookModalTitle, + undefined, + "Save", + async () => { + this.getStore().dispatch( + actions.save({ + contentRef: this.contentRef, + }) + ); + }, + "Cancel", + undefined, + this.getSaveNotebookSubText() + ); + } else { + this.getStore().dispatch( + actions.save({ + contentRef: this.contentRef, + }) + ); + } } public notebookChangeKernel(kernelSpecName: string): void { @@ -341,4 +369,19 @@ export class NotebookComponentBootstrapper { protected getStore(): Store { return this.notebookClient.getStore(); } + + private getSaveNotebookSubText(): JSX.Element { + return ( + <> +

{Notebook.saveNotebookModalContent}

+
+

+ {Notebook.newNotebookModalContent2} + + {Notebook.learnMore} + +

+ + ); + } } diff --git a/src/Explorer/Notebook/NotebookUtil.ts b/src/Explorer/Notebook/NotebookUtil.ts index b060533d7..b44719beb 100644 --- a/src/Explorer/Notebook/NotebookUtil.ts +++ b/src/Explorer/Notebook/NotebookUtil.ts @@ -5,11 +5,17 @@ import Html2Canvas from "html2canvas"; import path from "path"; import * as GitHubUtils from "../../Utils/GitHubUtils"; import * as StringUtils from "../../Utils/StringUtils"; +import * as InMemoryContentProviderUtils from "../Notebook/NotebookComponent/ContentProviders/InMemoryContentProviderUtils"; import { SnapshotFragment } from "./NotebookComponent/types"; import { NotebookContentItem, NotebookContentItemType } from "./NotebookContentItem"; // Must match rx-jupyter' FileType export type FileType = "directory" | "file" | "notebook"; +export enum NotebookContentProviderType { + GitHubContentProviderType, + InMemoryContentProviderType, + JupyterContentProviderType, +} // Utilities for notebooks export class NotebookUtil { public static UntrustedNotebookRunHint = "Please trust notebook first before running any code cells"; @@ -126,6 +132,18 @@ export class NotebookUtil { return relativePath.split("/").pop(); } + public static getContentProviderType(path: string): NotebookContentProviderType { + if (InMemoryContentProviderUtils.fromContentUri(path)) { + return NotebookContentProviderType.InMemoryContentProviderType; + } + + if (GitHubUtils.fromContentUri(path)) { + return NotebookContentProviderType.GitHubContentProviderType; + } + + return NotebookContentProviderType.JupyterContentProviderType; + } + public static replaceName(path: string, newName: string): string { const contentInfo = GitHubUtils.fromContentUri(path); if (contentInfo) {