diff --git a/images/vscode.svg b/images/vscode.svg
new file mode 100644
index 000000000..137be57f0
--- /dev/null
+++ b/images/vscode.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/Explorer/Explorer.tsx b/src/Explorer/Explorer.tsx
index a07a7dad3..5c619663f 100644
--- a/src/Explorer/Explorer.tsx
+++ b/src/Explorer/Explorer.tsx
@@ -282,6 +282,69 @@ export default class Explorer {
}
}
+ public openInVsCode(): void {
+ TelemetryProcessor.traceStart(Action.OpenVSCode);
+ this.openVsCodeButtonClick();
+ }
+
+ private openVsCodeButtonClick(): void {
+ const activeTab = useTabs.getState().activeTab;
+ const resourceId = encodeURIComponent(userContext.databaseAccount.id);
+ const database = encodeURIComponent(activeTab?.collection?.databaseId);
+ const container = encodeURIComponent(activeTab?.collection?.id());
+ const baseUrl = `vscod://ms-azuretools.vscode-cosmosdb?resourceId=${resourceId}`;
+ const vscodeUrl = activeTab ? `${baseUrl}&database=${database}&container=${container}` : baseUrl;
+ const startTime = Date.now();
+ let vsCodeNotOpened = false;
+
+ setTimeout(() => {
+ const timeOutTime = Date.now() - startTime;
+ if (!vsCodeNotOpened && timeOutTime < 1050) {
+ vsCodeNotOpened = true;
+ useDialog.getState().openDialog(openVSCodeDialogProps);
+ }
+ }, 1000);
+
+ const link = document.createElement("a");
+ link.href = vscodeUrl;
+ link.rel = "noopener noreferrer";
+ document.body.appendChild(link);
+
+ try {
+ link.click();
+ document.body.removeChild(link);
+ TelemetryProcessor.traceStart(Action.OpenVSCode);
+ } catch (error) {
+ if (!vsCodeNotOpened) {
+ vsCodeNotOpened = true;
+ logConsoleError(`Failed to open VS Code: ${getErrorMessage(error)}`);
+ }
+ }
+
+ const openVSCodeDialogProps: DialogProps = {
+ linkProps: {
+ linkText: "Download Visual Studio Code",
+ linkUrl: "https://code.visualstudio.com/download",
+ },
+ isModal: true,
+ title: `Open your Azure Cosmos DB account in Visual Studio Code`,
+ subText: `Please ensure Visual Studio Code is installed on your device.
+ If you don't have it installed, please download it from the link below.`,
+ primaryButtonText: "Open in VS Code",
+ secondaryButtonText: "Cancel",
+
+ onPrimaryButtonClick: () => {
+ vsCodeNotOpened = false;
+ this.openVsCodeButtonClick();
+ useDialog.getState().closeDialog();
+ },
+ onSecondaryButtonClick: () => {
+ useDialog.getState().closeDialog();
+ TelemetryProcessor.traceCancel(Action.OpenVSCode);
+ },
+ };
+ }
+
public async openCESCVAFeedbackBlade(): Promise {
sendMessage({ type: MessageTypes.OpenCESCVAFeedbackBlade });
Logger.logInfo(
diff --git a/src/Explorer/Menus/CommandBar/CommandBarComponentButtonFactory.tsx b/src/Explorer/Menus/CommandBar/CommandBarComponentButtonFactory.tsx
index f9aa5e54f..fbf1b4434 100644
--- a/src/Explorer/Menus/CommandBar/CommandBarComponentButtonFactory.tsx
+++ b/src/Explorer/Menus/CommandBar/CommandBarComponentButtonFactory.tsx
@@ -14,6 +14,7 @@ import OpenQueryFromDiskIcon from "../../../../images/OpenQueryFromDisk.svg";
import OpenInTabIcon from "../../../../images/open-in-tab.svg";
import SettingsIcon from "../../../../images/settings_15x15.svg";
import SynapseIcon from "../../../../images/synapse-link.svg";
+import VSCodeIcon from "../../../../images/vscode.svg";
import { AuthType } from "../../../AuthType";
import * as Constants from "../../../Common/Constants";
import { Platform, configContext } from "../../../ConfigContext";
@@ -60,6 +61,10 @@ export function createStaticCommandBarButtons(
addDivider();
buttons.push(addSynapseLink);
}
+ if (userContext.apiType !== "Gremlin") {
+ const addVsCode = createOpenVsCodeDialogButton(container);
+ buttons.push(addVsCode);
+ }
}
if (isDataplaneRbacSupported(userContext.apiType)) {
@@ -268,6 +273,18 @@ function createOpenSynapseLinkDialogButton(container: Explorer): CommandButtonCo
};
}
+function createOpenVsCodeDialogButton(container: Explorer): CommandButtonComponentProps {
+ const label = "Visual Studio Code";
+ return {
+ iconSrc: VSCodeIcon,
+ iconAlt: label,
+ onCommandClick: () => container.openInVsCode(),
+ commandButtonLabel: label,
+ hasPopup: false,
+ ariaLabel: label,
+ };
+}
+
function createLoginForEntraIDButton(container: Explorer): CommandButtonComponentProps {
if (configContext.platform !== Platform.Portal) {
return undefined;
@@ -500,6 +517,6 @@ export function createPostgreButtons(container: Explorer): CommandButtonComponen
export function createVCoreMongoButtons(container: Explorer): CommandButtonComponentProps[] {
const openVCoreMongoTerminalButton = createOpenTerminalButtonByKind(container, ViewModels.TerminalKind.VCoreMongo);
-
- return [openVCoreMongoTerminalButton];
+ const addVsCode = createOpenVsCodeDialogButton(container);
+ return [openVCoreMongoTerminalButton, addVsCode];
}
diff --git a/src/Shared/Telemetry/TelemetryConstants.ts b/src/Shared/Telemetry/TelemetryConstants.ts
index c20a49f93..031d061cc 100644
--- a/src/Shared/Telemetry/TelemetryConstants.ts
+++ b/src/Shared/Telemetry/TelemetryConstants.ts
@@ -149,6 +149,7 @@ export enum Action {
UploadDocuments, // Used in Fabric. Please do not rename.
CloudShellUserConsent,
CloudShellTerminalSession,
+ OpenVSCode,
}
export const ActionModifiers = {
diff --git a/web.config b/web.config
index 8efe7ce6d..f29c8b878 100644
--- a/web.config
+++ b/web.config
@@ -30,7 +30,7 @@
-
+