mirror of
https://github.com/Azure/cosmos-explorer.git
synced 2024-11-25 15:06:55 +00:00
Migrate Mongo Shell tab to React (#900)
This commit is contained in:
parent
f9bd12eaa6
commit
f255387ccd
@ -143,7 +143,7 @@ src/Explorer/Tabs/DocumentsTab.ts
|
|||||||
src/Explorer/Tabs/GraphTab.ts
|
src/Explorer/Tabs/GraphTab.ts
|
||||||
src/Explorer/Tabs/MongoDocumentsTab.ts
|
src/Explorer/Tabs/MongoDocumentsTab.ts
|
||||||
# src/Explorer/Tabs/MongoQueryTab.ts
|
# src/Explorer/Tabs/MongoQueryTab.ts
|
||||||
src/Explorer/Tabs/MongoShellTab.ts
|
# src/Explorer/Tabs/MongoShellTab.ts
|
||||||
src/Explorer/Tabs/NotebookV2Tab.ts
|
src/Explorer/Tabs/NotebookV2Tab.ts
|
||||||
src/Explorer/Tabs/ScriptTabBase.ts
|
src/Explorer/Tabs/ScriptTabBase.ts
|
||||||
src/Explorer/Tabs/StoredProcedureTab.ts
|
src/Explorer/Tabs/StoredProcedureTab.ts
|
||||||
|
@ -1,15 +0,0 @@
|
|||||||
<iframe
|
|
||||||
name="explorer"
|
|
||||||
class="iframe"
|
|
||||||
style="width: 100%; height: 100%; border: 0px; padding: 0px; margin: 0px; overflow: hidden"
|
|
||||||
data-bind="
|
|
||||||
attr: {
|
|
||||||
src: url,
|
|
||||||
id: tabId
|
|
||||||
},
|
|
||||||
event:{
|
|
||||||
load: setContentFocus(event)
|
|
||||||
}"
|
|
||||||
title="Mongo Shell"
|
|
||||||
role="tabpanel"
|
|
||||||
></iframe>
|
|
39
src/Explorer/Tabs/MongoShellTab/MongoShellTab.tsx
Normal file
39
src/Explorer/Tabs/MongoShellTab/MongoShellTab.tsx
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
import React from "react";
|
||||||
|
import * as DataModels from "../../../Contracts/DataModels";
|
||||||
|
import type { TabOptions } from "../../../Contracts/ViewModels";
|
||||||
|
import Explorer from "../../Explorer";
|
||||||
|
import TabsBase from "../TabsBase";
|
||||||
|
import MongoShellTabComponent, { IMongoShellTabAccessor, IMongoShellTabComponentProps } from "./MongoShellTabComponent";
|
||||||
|
|
||||||
|
export interface IMongoShellTabProps {
|
||||||
|
container: Explorer;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class NewMongoShellTab extends TabsBase {
|
||||||
|
public queryText: string;
|
||||||
|
public currentQuery: string;
|
||||||
|
public partitionKey: DataModels.PartitionKey;
|
||||||
|
public iMongoShellTabComponentProps: IMongoShellTabComponentProps;
|
||||||
|
public iMongoShellTabAccessor: IMongoShellTabAccessor;
|
||||||
|
|
||||||
|
constructor(options: TabOptions, private props: IMongoShellTabProps) {
|
||||||
|
super(options);
|
||||||
|
this.iMongoShellTabComponentProps = {
|
||||||
|
collection: this.collection,
|
||||||
|
tabsBaseInstance: this,
|
||||||
|
container: this.props.container,
|
||||||
|
onMongoShellTabAccessor: (instance: IMongoShellTabAccessor) => {
|
||||||
|
this.iMongoShellTabAccessor = instance;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public render(): JSX.Element {
|
||||||
|
return <MongoShellTabComponent {...this.iMongoShellTabComponentProps} />;
|
||||||
|
}
|
||||||
|
|
||||||
|
public onTabClick(): void {
|
||||||
|
this.manager?.activateTab(this);
|
||||||
|
this.iMongoShellTabAccessor.onTabClickEvent();
|
||||||
|
}
|
||||||
|
}
|
@ -1,28 +1,71 @@
|
|||||||
import * as ko from "knockout";
|
import React, { Component } from "react";
|
||||||
import * as Constants from "../../Common/Constants";
|
import * as Constants from "../../../Common/Constants";
|
||||||
import { configContext, Platform } from "../../ConfigContext";
|
import { configContext, Platform } from "../../../ConfigContext";
|
||||||
import * as ViewModels from "../../Contracts/ViewModels";
|
import * as ViewModels from "../../../Contracts/ViewModels";
|
||||||
import { Action, ActionModifiers } from "../../Shared/Telemetry/TelemetryConstants";
|
import { Action, ActionModifiers } 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 { isInvalidParentFrameOrigin, isReadyMessage } from "../../Utils/MessageValidation";
|
import { isInvalidParentFrameOrigin, isReadyMessage } from "../../../Utils/MessageValidation";
|
||||||
import { logConsoleError, logConsoleInfo, logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
|
import { logConsoleError, logConsoleInfo, logConsoleProgress } from "../../../Utils/NotificationConsoleUtils";
|
||||||
import Explorer from "../Explorer";
|
import Explorer from "../../Explorer";
|
||||||
import template from "./MongoShellTab.html";
|
import TabsBase from "../TabsBase";
|
||||||
import TabsBase from "./TabsBase";
|
|
||||||
|
|
||||||
export default class MongoShellTab extends TabsBase {
|
//eslint-disable-next-line
|
||||||
public readonly html = template;
|
class MessageType {
|
||||||
public url: ko.Computed<string>;
|
static IframeReady = "iframeready";
|
||||||
private _container: Explorer;
|
static Notification = "notification";
|
||||||
|
static Log = "log";
|
||||||
|
}
|
||||||
|
|
||||||
|
//eslint-disable-next-line
|
||||||
|
class LogType {
|
||||||
|
static Information = "information";
|
||||||
|
static Warning = "warning";
|
||||||
|
static Verbose = "verbose";
|
||||||
|
static InProgress = "inprogress";
|
||||||
|
static StartTrace = "start";
|
||||||
|
static SuccessTrace = "success";
|
||||||
|
static FailureTrace = "failure";
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IMongoShellTabAccessor {
|
||||||
|
onTabClickEvent: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IMongoShellTabComponentStates {
|
||||||
|
url: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IMongoShellTabComponentProps {
|
||||||
|
collection: ViewModels.CollectionBase;
|
||||||
|
tabsBaseInstance: TabsBase;
|
||||||
|
container: Explorer;
|
||||||
|
onMongoShellTabAccessor: (instance: IMongoShellTabAccessor) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class MongoShellTabComponent extends Component<
|
||||||
|
IMongoShellTabComponentProps,
|
||||||
|
IMongoShellTabComponentStates
|
||||||
|
> {
|
||||||
private _runtimeEndpoint: string;
|
private _runtimeEndpoint: string;
|
||||||
private _logTraces: Map<string, number>;
|
private _logTraces: Map<string, number>;
|
||||||
|
|
||||||
constructor(options: ViewModels.TabOptions) {
|
constructor(props: IMongoShellTabComponentProps) {
|
||||||
super(options);
|
super(props);
|
||||||
this._logTraces = new Map();
|
this._logTraces = new Map();
|
||||||
this._container = options.collection.container;
|
|
||||||
this.url = ko.computed<string>(() => {
|
this.state = {
|
||||||
|
url: this.getURL(),
|
||||||
|
};
|
||||||
|
|
||||||
|
props.onMongoShellTabAccessor({
|
||||||
|
onTabClickEvent: this.onTabClick.bind(this),
|
||||||
|
});
|
||||||
|
|
||||||
|
window.addEventListener("message", this.handleMessage.bind(this), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public getURL(): string {
|
||||||
const { databaseAccount: account } = userContext;
|
const { databaseAccount: account } = userContext;
|
||||||
const resourceId = account?.id;
|
const resourceId = account?.id;
|
||||||
const accountName = account?.name;
|
const accountName = account?.name;
|
||||||
@ -36,32 +79,23 @@ export default class MongoShellTab extends TabsBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return `${extensionEndpoint}${baseUrl}index.html?resourceId=${resourceId}&accountName=${accountName}&mongoEndpoint=${mongoEndpoint}`;
|
return `${extensionEndpoint}${baseUrl}index.html?resourceId=${resourceId}&accountName=${accountName}&mongoEndpoint=${mongoEndpoint}`;
|
||||||
});
|
|
||||||
|
|
||||||
window.addEventListener("message", this.handleMessage.bind(this), false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public setContentFocus(event: any): any {
|
//eslint-disable-next-line
|
||||||
// TODO: Work around cross origin security issue in Hosted Data Explorer by using Shell <-> Data Explorer messaging (253527)
|
public setContentFocus(event: React.SyntheticEvent<HTMLIFrameElement, Event>): void {}
|
||||||
// if(event.type === "load" && window.dataExplorerPlatform != PlatformType.Hosted) {
|
|
||||||
// let activeShell = event.target.contentWindow && event.target.contentWindow.mongo && event.target.contentWindow.mongo.shells && event.target.contentWindow.mongo.shells[0];
|
|
||||||
// activeShell && setTimeout(function(){
|
|
||||||
// activeShell.focus();
|
|
||||||
// },2000);
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
public onTabClick(): void {
|
public onTabClick(): void {
|
||||||
super.onTabClick();
|
this.props.collection.selectedSubnodeKind(ViewModels.CollectionTabKind.Documents);
|
||||||
this.collection.selectedSubnodeKind(ViewModels.CollectionTabKind.Documents);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public handleMessage(event: MessageEvent) {
|
public handleMessage(event: MessageEvent): void {
|
||||||
if (isInvalidParentFrameOrigin(event)) {
|
if (isInvalidParentFrameOrigin(event)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const shellIframe: HTMLIFrameElement = <HTMLIFrameElement>document.getElementById(this.tabId);
|
const shellIframe: HTMLIFrameElement = document.getElementById(
|
||||||
|
this.props.tabsBaseInstance.tabId
|
||||||
|
) as HTMLIFrameElement;
|
||||||
|
|
||||||
if (!shellIframe) {
|
if (!shellIframe) {
|
||||||
return;
|
return;
|
||||||
@ -73,9 +107,9 @@ export default class MongoShellTab extends TabsBase {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (event.data.eventType == MessageType.IframeReady) {
|
if (event.data.eventType === MessageType.IframeReady) {
|
||||||
this.handleReadyMessage(event, shellIframe);
|
this.handleReadyMessage(event, shellIframe);
|
||||||
} else if (event.data.eventType == MessageType.Notification) {
|
} else if (event.data.eventType === MessageType.Notification) {
|
||||||
this.handleNotificationMessage(event, shellIframe);
|
this.handleNotificationMessage(event, shellIframe);
|
||||||
} else {
|
} else {
|
||||||
this.handleLogMessage(event, shellIframe);
|
this.handleLogMessage(event, shellIframe);
|
||||||
@ -98,8 +132,8 @@ export default class MongoShellTab extends TabsBase {
|
|||||||
documentEndpoint.length -
|
documentEndpoint.length -
|
||||||
(Constants.MongoDBAccounts.protocol.length + 2 + Constants.MongoDBAccounts.defaultPort.length)
|
(Constants.MongoDBAccounts.protocol.length + 2 + Constants.MongoDBAccounts.defaultPort.length)
|
||||||
) + Constants.MongoDBAccounts.defaultPort.toString();
|
) + Constants.MongoDBAccounts.defaultPort.toString();
|
||||||
const databaseId = this.collection.databaseId;
|
const databaseId = this.props.collection.databaseId;
|
||||||
const collectionId = this.collection.id();
|
const collectionId = this.props.collection.id();
|
||||||
const apiEndpoint = configContext.BACKEND_ENDPOINT;
|
const apiEndpoint = configContext.BACKEND_ENDPOINT;
|
||||||
const encryptedAuthToken: string = userContext.accessToken;
|
const encryptedAuthToken: string = userContext.accessToken;
|
||||||
|
|
||||||
@ -121,6 +155,7 @@ export default class MongoShellTab extends TabsBase {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//eslint-disable-next-line
|
||||||
private handleLogMessage(event: MessageEvent, shellIframe: HTMLIFrameElement) {
|
private handleLogMessage(event: MessageEvent, shellIframe: HTMLIFrameElement) {
|
||||||
if (!("logType" in event.data.data) || typeof event.data.data["logType"] !== "string") {
|
if (!("logType" in event.data.data) || typeof event.data.data["logType"] !== "string") {
|
||||||
return;
|
return;
|
||||||
@ -144,6 +179,7 @@ export default class MongoShellTab extends TabsBase {
|
|||||||
TelemetryProcessor.trace(Action.MongoShell, ActionModifiers.Mark, dataToLog);
|
TelemetryProcessor.trace(Action.MongoShell, ActionModifiers.Mark, dataToLog);
|
||||||
break;
|
break;
|
||||||
case LogType.StartTrace:
|
case LogType.StartTrace:
|
||||||
|
//eslint-disable-next-line
|
||||||
const telemetryTraceId: number = TelemetryProcessor.traceStart(Action.MongoShell, dataToLog);
|
const telemetryTraceId: number = TelemetryProcessor.traceStart(Action.MongoShell, dataToLog);
|
||||||
this._logTraces.set(shellTraceId, telemetryTraceId);
|
this._logTraces.set(shellTraceId, telemetryTraceId);
|
||||||
break;
|
break;
|
||||||
@ -168,6 +204,7 @@ export default class MongoShellTab extends TabsBase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//eslint-disable-next-line
|
||||||
private handleNotificationMessage(event: MessageEvent, shellIframe: HTMLIFrameElement) {
|
private handleNotificationMessage(event: MessageEvent, shellIframe: HTMLIFrameElement) {
|
||||||
if (!("logType" in event.data.data) || typeof event.data.data["logType"] !== "string") {
|
if (!("logType" in event.data.data) || typeof event.data.data["logType"] !== "string") {
|
||||||
return;
|
return;
|
||||||
@ -188,20 +225,19 @@ export default class MongoShellTab extends TabsBase {
|
|||||||
return logConsoleProgress(dataToLog);
|
return logConsoleProgress(dataToLog);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
class MessageType {
|
render(): JSX.Element {
|
||||||
static IframeReady: string = "iframeready";
|
return (
|
||||||
static Notification: string = "notification";
|
<iframe
|
||||||
static Log: string = "log";
|
name="explorer"
|
||||||
|
className="iframe"
|
||||||
|
style={{ width: "100%", height: "100%", border: 0, padding: 0, margin: 0, overflow: "hidden" }}
|
||||||
|
src={this.state.url}
|
||||||
|
id={this.props.tabsBaseInstance.tabId}
|
||||||
|
onLoad={(event) => this.setContentFocus(event)}
|
||||||
|
title="Mongo Shell"
|
||||||
|
role="tabpanel"
|
||||||
|
></iframe>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
class LogType {
|
|
||||||
static Information: string = "information";
|
|
||||||
static Warning: string = "warning";
|
|
||||||
static Verbose: string = "verbose";
|
|
||||||
static InProgress: string = "inprogress";
|
|
||||||
static StartTrace: string = "start";
|
|
||||||
static SuccessTrace: string = "success";
|
|
||||||
static FailureTrace: string = "failure";
|
|
||||||
}
|
}
|
@ -29,7 +29,7 @@ import DocumentsTab from "../Tabs/DocumentsTab";
|
|||||||
import GraphTab from "../Tabs/GraphTab";
|
import GraphTab from "../Tabs/GraphTab";
|
||||||
import MongoDocumentsTab from "../Tabs/MongoDocumentsTab";
|
import MongoDocumentsTab from "../Tabs/MongoDocumentsTab";
|
||||||
import { NewMongoQueryTab } from "../Tabs/MongoQueryTab/MongoQueryTab";
|
import { NewMongoQueryTab } from "../Tabs/MongoQueryTab/MongoQueryTab";
|
||||||
import MongoShellTab from "../Tabs/MongoShellTab";
|
import { NewMongoShellTab } from "../Tabs/MongoShellTab/MongoShellTab";
|
||||||
import { NewQueryTab } from "../Tabs/QueryTab/QueryTab";
|
import { NewQueryTab } from "../Tabs/QueryTab/QueryTab";
|
||||||
import QueryTablesTab from "../Tabs/QueryTablesTab";
|
import QueryTablesTab from "../Tabs/QueryTablesTab";
|
||||||
import { CollectionSettingsTabV2 } from "../Tabs/SettingsTabV2";
|
import { CollectionSettingsTabV2 } from "../Tabs/SettingsTabV2";
|
||||||
@ -703,14 +703,15 @@ export default class Collection implements ViewModels.Collection {
|
|||||||
public onNewMongoShellClick() {
|
public onNewMongoShellClick() {
|
||||||
const mongoShellTabs = this.container.tabsManager.getTabs(
|
const mongoShellTabs = this.container.tabsManager.getTabs(
|
||||||
ViewModels.CollectionTabKind.MongoShell
|
ViewModels.CollectionTabKind.MongoShell
|
||||||
) as MongoShellTab[];
|
) as NewMongoShellTab[];
|
||||||
|
|
||||||
let index = 1;
|
let index = 1;
|
||||||
if (mongoShellTabs.length > 0) {
|
if (mongoShellTabs.length > 0) {
|
||||||
index = mongoShellTabs[mongoShellTabs.length - 1].index + 1;
|
index = mongoShellTabs[mongoShellTabs.length - 1].index + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
const mongoShellTab: MongoShellTab = new MongoShellTab({
|
const mongoShellTab: NewMongoShellTab = new NewMongoShellTab(
|
||||||
|
{
|
||||||
tabKind: ViewModels.CollectionTabKind.MongoShell,
|
tabKind: ViewModels.CollectionTabKind.MongoShell,
|
||||||
title: "Shell " + index,
|
title: "Shell " + index,
|
||||||
tabPath: "",
|
tabPath: "",
|
||||||
@ -718,7 +719,11 @@ export default class Collection implements ViewModels.Collection {
|
|||||||
node: this,
|
node: this,
|
||||||
hashLocation: `${Constants.HashRoutePrefixes.collectionsWithIds(this.databaseId, this.id())}/mongoShell`,
|
hashLocation: `${Constants.HashRoutePrefixes.collectionsWithIds(this.databaseId, this.id())}/mongoShell`,
|
||||||
index: index,
|
index: index,
|
||||||
});
|
},
|
||||||
|
{
|
||||||
|
container: this.container,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
this.container.tabsManager.activateNewTab(mongoShellTab);
|
this.container.tabsManager.activateNewTab(mongoShellTab);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user