Switch VCore Mongo quickstart to use CloudShell terminal

- Replace NotebookTerminalComponent with CloudShellTerminalComponent in VCoreMongoQuickstartTab
- Refactor useTerminal hook to send messages via WebSocket instead of postRobot/iframe
- Register CloudShellTerminalComponent socket with useTerminal store
- Remove notebook dependencies (useNotebook, allocateContainer) from VCoreMongoQuickstartTab
- Remove useTerminal reference from NotebookTerminalComponent (dead code)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
Jade Welton
2026-05-21 10:19:13 -07:00
parent 5989c77ccf
commit c7f9d7e305
5 changed files with 28 additions and 57 deletions
@@ -3,7 +3,6 @@
*/ */
import { AuthType } from "../../../AuthType"; import { AuthType } from "../../../AuthType";
import { useTerminal } from "hooks/useTerminal";
import postRobot from "post-robot"; import postRobot from "post-robot";
import * as React from "react"; import * as React from "react";
import * as DataModels from "../../../Contracts/DataModels"; import * as DataModels from "../../../Contracts/DataModels";
@@ -55,7 +54,6 @@ export class NotebookTerminalComponent extends React.Component<NotebookTerminalC
handleFrameLoad(event: React.SyntheticEvent<HTMLIFrameElement, Event>): void { handleFrameLoad(event: React.SyntheticEvent<HTMLIFrameElement, Event>): void {
this.terminalWindow = (event.target as HTMLIFrameElement).contentWindow; this.terminalWindow = (event.target as HTMLIFrameElement).contentWindow;
useTerminal.getState().setTerminal(this.terminalWindow);
this.sendPropsToTerminalFrame(); this.sendPropsToTerminalFrame();
} }
@@ -1,3 +1,4 @@
import { useTerminal } from "hooks/useTerminal";
import React, { useEffect, useRef } from "react"; import React, { useEffect, useRef } from "react";
import { Terminal } from "xterm"; import { Terminal } from "xterm";
import { FitAddon } from "xterm-addon-fit"; import { FitAddon } from "xterm-addon-fit";
@@ -59,7 +60,14 @@ export const CloudShellTerminalComponent: React.FC<CloudShellTerminalComponentPr
}); });
resizeObserver.observe(terminalRef.current); resizeObserver.observe(terminalRef.current);
socketRef.current = startCloudShellTerminal(terminal, props.shellType); const initTerminal = async () => {
const socket = await startCloudShellTerminal(terminal, props.shellType);
socketRef.current = socket;
if (socket) {
useTerminal.getState().setSocket(socket);
}
};
initTerminal();
// Cleanup function to close WebSocket and dispose terminal // Cleanup function to close WebSocket and dispose terminal
return () => { return () => {
@@ -73,6 +81,7 @@ export const CloudShellTerminalComponent: React.FC<CloudShellTerminalComponentPr
resizeObserver.unobserve(terminalRef.current); resizeObserver.unobserve(terminalRef.current);
} }
terminal.dispose(); // Clean up XTerm instance terminal.dispose(); // Clean up XTerm instance
useTerminal.getState().setSocket(undefined);
}; };
}, []); }, []);
+1 -1
View File
@@ -315,7 +315,7 @@ const getReactTabContent = (activeReactTab: ReactTabKind, explorer: Explorer): J
} }
case ReactTabKind.Quickstart: case ReactTabKind.Quickstart:
return userContext.apiType === "VCoreMongo" ? ( return userContext.apiType === "VCoreMongo" ? (
<VcoreMongoQuickstartTab explorer={explorer} /> <VcoreMongoQuickstartTab />
) : ( ) : (
<QuickstartTab explorer={explorer} /> <QuickstartTab explorer={explorer} />
); );
+8 -38
View File
@@ -1,10 +1,8 @@
import { Spinner, SpinnerSize, Stack, Text } from "@fluentui/react"; import { Stack } from "@fluentui/react";
import { NotebookWorkspaceConnectionInfo } from "Contracts/DataModels";
import { MessageTypes } from "Contracts/ExplorerContracts"; import { MessageTypes } from "Contracts/ExplorerContracts";
import { NotebookTerminalComponent } from "Explorer/Controls/Notebook/NotebookTerminalComponent"; import { TerminalKind } from "Contracts/ViewModels";
import Explorer from "Explorer/Explorer"; import { CloudShellTerminalComponent } from "Explorer/Tabs/CloudShellTab/CloudShellTerminalComponent";
import { useNotebook } from "Explorer/Notebook/useNotebook";
import { QuickstartFirewallNotification } from "Explorer/Quickstart/QuickstartFirewallNotification"; import { QuickstartFirewallNotification } from "Explorer/Quickstart/QuickstartFirewallNotification";
import { VcoreMongoQuickstartGuide } from "Explorer/Quickstart/VCoreMongoQuickstartGuide"; import { VcoreMongoQuickstartGuide } from "Explorer/Quickstart/VCoreMongoQuickstartGuide";
import { checkFirewallRules } from "Explorer/Tabs/Shared/CheckFirewallRules"; import { checkFirewallRules } from "Explorer/Tabs/Shared/CheckFirewallRules";
@@ -12,22 +10,9 @@ import { userContext } from "UserContext";
import React, { useEffect, useState } from "react"; import React, { useEffect, useState } from "react";
import FirewallRuleScreenshot from "../../../images/vcoreMongoFirewallRule.png"; import FirewallRuleScreenshot from "../../../images/vcoreMongoFirewallRule.png";
interface VCoreMongoQuickstartTabProps { export const VcoreMongoQuickstartTab: React.FC = (): JSX.Element => {
explorer: Explorer;
}
export const VcoreMongoQuickstartTab: React.FC<VCoreMongoQuickstartTabProps> = ({
explorer,
}: VCoreMongoQuickstartTabProps): JSX.Element => {
const notebookServerInfo = useNotebook((state) => state.notebookServerInfo);
const [isAllPublicIPAddressEnabled, setIsAllPublicIPAddressEnabled] = useState<boolean>(true); const [isAllPublicIPAddressEnabled, setIsAllPublicIPAddressEnabled] = useState<boolean>(true);
const getNotebookServerInfo = (): NotebookWorkspaceConnectionInfo => ({
authToken: notebookServerInfo.authToken,
notebookServerEndpoint: `${notebookServerInfo.notebookServerEndpoint?.replace(/\/+$/, "")}/mongovcore`,
forwardingId: notebookServerInfo.forwardingId,
});
useEffect(() => { useEffect(() => {
checkFirewallRules( checkFirewallRules(
"2023-03-01-preview", "2023-03-01-preview",
@@ -38,10 +23,6 @@ export const VcoreMongoQuickstartTab: React.FC<VCoreMongoQuickstartTabProps> = (
); );
}); });
useEffect(() => {
explorer.allocateContainer();
}, []);
return ( return (
<Stack style={{ width: "100%" }} horizontal> <Stack style={{ width: "100%" }} horizontal>
<Stack style={{ width: "50%" }}> <Stack style={{ width: "50%" }}>
@@ -55,25 +36,14 @@ export const VcoreMongoQuickstartTab: React.FC<VCoreMongoQuickstartTabProps> = (
shellName="MongoDB" shellName="MongoDB"
/> />
)} )}
{isAllPublicIPAddressEnabled && notebookServerInfo?.notebookServerEndpoint && ( {isAllPublicIPAddressEnabled && (
<NotebookTerminalComponent <CloudShellTerminalComponent
notebookServerInfo={getNotebookServerInfo()}
databaseAccount={userContext.databaseAccount} databaseAccount={userContext.databaseAccount}
tabId="QuickstartVcoreMongoShell" tabId="QuickstartVcoreMongoShell"
username={userContext.vcoreMongoConnectionParams.adminLogin} username={userContext.vcoreMongoConnectionParams?.adminLogin}
shellType={TerminalKind.VCoreMongo}
/> />
)} )}
{isAllPublicIPAddressEnabled && !notebookServerInfo?.notebookServerEndpoint && (
<Stack style={{ margin: "auto 0" }}>
<Text block style={{ margin: "auto" }}>
Connecting to the Mongo shell.
</Text>
<Text block style={{ margin: "auto" }}>
If the cluster was just created, this could take up to a minute.
</Text>
<Spinner styles={{ root: { marginTop: 16 } }} size={SpinnerSize.large}></Spinner>
</Stack>
)}
</Stack> </Stack>
</Stack> </Stack>
); );
+9 -15
View File
@@ -1,26 +1,20 @@
import postRobot from "post-robot";
import create, { UseStore } from "zustand"; import create, { UseStore } from "zustand";
interface TerminalState { interface TerminalState {
terminalWindow: Window; socket: WebSocket | undefined;
setTerminal: (terminalWindow: Window) => void; setSocket: (socket: WebSocket) => void;
sendMessage: (message: string) => void; sendMessage: (message: string) => void;
} }
export const useTerminal: UseStore<TerminalState> = create((set, get) => ({ export const useTerminal: UseStore<TerminalState> = create((set, get) => ({
terminalWindow: undefined, socket: undefined,
setTerminal: (terminalWindow: Window) => { setSocket: (socket: WebSocket) => {
set({ terminalWindow }); set({ socket });
}, },
sendMessage: (message: string) => { sendMessage: (message: string) => {
const terminalWindow = get().terminalWindow; const socket = get().socket;
postRobot.send( if (socket && socket.readyState === WebSocket.OPEN) {
terminalWindow, socket.send(message + "\r");
"sendMessage", }
{ type: "stdin", content: [message] },
{
domain: window.location.origin,
},
);
}, },
})); }));