Remove Phoenix & Notebooks - Phase 2: Remove in-app notebook authoring & rendering (#2515)

Delete the nteract rendering engine, notebook tabs, panes, the read-only viewer, Schema Analyzer (pulled forward from Phase 3), and all UI entry points that open notebooks. Decouple surviving files (Explorer, NotebookManager, useNotebook, ResourceTreeAdapter) with minimal edits, keeping GitHub/Juno/Phoenix wiring for later phases.

Removed 22 zero-importer notebook-only npm deps; re-added phantom transitively-hoisted deps still used by surviving code: xterm, xterm-addon-fit (CloudShell), d3-collection (Graph), @nteract/myths (@nteract/core).

Verified: compile, compile:strict, lint (0 errors), format:check, test (1945 passing), build:ci all green.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
jawelton74
2026-06-22 09:36:47 -07:00
committed by GitHub
parent 0e175c8a9c
commit 8e90672ff5
109 changed files with 142 additions and 14512 deletions
-46
View File
@@ -548,52 +548,6 @@ export default class Collection implements ViewModels.Collection {
}
};
public onSchemaAnalyzerClick = async () => {
if (useNotebook.getState().isPhoenixFeatures) {
await this.container.allocateContainer();
}
useSelectedNode.getState().setSelectedNode(this);
this.selectedSubnodeKind(ViewModels.CollectionTabKind.SchemaAnalyzer);
const SchemaAnalyzerTab = await (await import("../Tabs/SchemaAnalyzerTab")).default;
TelemetryProcessor.trace(Action.SelectItem, ActionModifiers.Mark, {
description: "Schema node",
databaseName: this.databaseId,
collectionName: this.id(),
dataExplorerArea: Constants.Areas.ResourceTree,
});
for (const tab of useTabs.getState().openedTabs) {
if (
tab instanceof SchemaAnalyzerTab &&
tab.collection?.databaseId === this.databaseId &&
tab.collection?.id() === this.id()
) {
return useTabs.getState().activateTab(tab);
}
}
const startKey = TelemetryProcessor.traceStart(Action.Tab, {
databaseName: this.databaseId,
collectionName: this.id(),
dataExplorerArea: Constants.Areas.Tab,
tabTitle: "Schema",
});
this.documentIds([]);
useTabs.getState().activateNewTab(
new SchemaAnalyzerTab({
account: userContext.databaseAccount,
masterKey: userContext.masterKey || "",
container: this.container,
tabKind: ViewModels.CollectionTabKind.SchemaAnalyzer,
title: "Schema",
tabPath: "",
collection: this,
node: this,
onLoadStartKey: startKey,
}),
);
};
public onSettingsClick = async (): Promise<void> => {
useSelectedNode.getState().setSelectedNode(this);
const throughputCap = userContext.databaseAccount?.properties.capacity?.totalThroughputLimit;
+7 -120
View File
@@ -106,15 +106,6 @@ export class ResourceTreeAdapter implements ReactAdapter {
type: NotebookContentItemType.Directory,
};
// Only if notebook server is available we can refresh
if (useNotebook.getState().notebookServerInfo?.notebookServerEndpoint) {
refreshTasks.push(
this.container.refreshContentItem(this.myNotebooksContentRoot).then(() => {
this.triggerRender();
this.traceMyNotebookTreeInfo();
}),
);
}
this.gitHubNotebooksContentRoot = {
name: ResourceTreeAdapter.GitHubReposTitle,
path: ResourceTreeAdapter.PseudoDirPath,
@@ -490,117 +481,17 @@ export class ResourceTreeAdapter implements ReactAdapter {
(activeTab as any).notebookPath() === item.path
);
},
contextMenu: createFileContextMenu && this.createFileContextMenu(item),
contextMenu: createFileContextMenu && this.createFileContextMenu(),
data: item,
};
}
private createFileContextMenu(item: NotebookContentItem): TreeNodeMenuItem[] {
let items: TreeNodeMenuItem[] = [
{
label: "Rename",
iconSrc: NotebookIcon,
onClick: () => this.container.renameNotebook(item),
},
{
label: "Delete",
iconSrc: DeleteIcon,
onClick: () => {
useDialog
.getState()
.showOkCancelModalDialog(
"Confirm delete",
`Are you sure you want to delete "${item.name}"`,
"Delete",
() => this.container.deleteNotebookFile(item).then(() => this.triggerRender()),
"Cancel",
undefined,
);
},
},
{
label: "Copy to ...",
iconSrc: CopyIcon,
onClick: () => this.copyNotebook(item),
},
{
label: "Download",
iconSrc: NotebookIcon,
onClick: () => this.container.downloadFile(item),
},
];
if (item.type === NotebookContentItemType.Notebook) {
// Additional notebook-specific context menu items can be added here
}
// "Copy to ..." isn't needed if github locations are not available
if (!this.container.notebookManager?.gitHubOAuthService.isLoggedIn()) {
items = items.filter((item) => item.label !== "Copy to ...");
}
return items;
private createFileContextMenu(): TreeNodeMenuItem[] {
return [];
}
private copyNotebook = async (item: NotebookContentItem) => {
const content = await this.container.readFile(item);
if (content) {
this.container.copyNotebook(item.name, content);
}
};
private createDirectoryContextMenu(item: NotebookContentItem): TreeNodeMenuItem[] {
let items: TreeNodeMenuItem[] = [
{
label: "Refresh",
iconSrc: RefreshIcon,
onClick: () => this.container.refreshContentItem(item).then(() => this.triggerRender()),
},
{
label: "Delete",
iconSrc: DeleteIcon,
onClick: () => {
useDialog
.getState()
.showOkCancelModalDialog(
"Confirm delete",
`Are you sure you want to delete "${item.name}?"`,
"Delete",
() => this.container.deleteNotebookFile(item).then(() => this.triggerRender()),
"Cancel",
undefined,
);
},
},
{
label: "Rename",
iconSrc: NotebookIcon,
onClick: () => this.container.renameNotebook(item),
},
{
label: "New Directory",
iconSrc: NewNotebookIcon,
onClick: () => this.container.onCreateDirectory(item),
},
];
//disallow renaming of temporary notebook workspace
if (item?.path === useNotebook.getState().notebookBasePath) {
items = items.filter((item) => item.label !== "Rename");
}
// For GitHub paths remove "Delete", "Rename", "New Directory", "Upload File"
if (GitHubUtils.fromContentUri(item.path)) {
items = items.filter(
(item) =>
item.label !== "Delete" &&
item.label !== "Rename" &&
item.label !== "New Directory" &&
item.label !== "Upload File",
);
}
return items;
private createDirectoryContextMenu(): TreeNodeMenuItem[] {
return [];
}
private buildNotebookDirectoryNode(
@@ -615,11 +506,7 @@ export class ResourceTreeAdapter implements ReactAdapter {
className: "notebookHeader",
isAlphaSorted: true,
isLeavesParentsSeparate: true,
onClick: () => {
if (!item.children) {
this.container.refreshContentItem(item).then(() => this.triggerRender());
}
},
onClick: undefined,
isSelected: () => {
const activeTab = useTabs.getState().activeTab;
return (
@@ -633,7 +520,7 @@ export class ResourceTreeAdapter implements ReactAdapter {
},
contextMenu:
createDirectoryContextMenu && item.path !== ResourceTreeAdapter.PseudoDirPath
? this.createDirectoryContextMenu(item)
? this.createDirectoryContextMenu()
: undefined,
data: item,
children: this.buildChildNodes(item, onFileClick, createDirectoryContextMenu, createFileContextMenu),