From d880723be901627c81a70c6b0310f0769e478847 Mon Sep 17 00:00:00 2001 From: Steve Faulkner Date: Thu, 12 Nov 2020 20:10:59 -0600 Subject: [PATCH] React Wrapper Take 2 (#310) --- src/Main.ts | 117 --------- src/Main.tsx | 452 +++++++++++++++++++++++++++++++++++ src/applyExplorerBindings.ts | 2 +- src/explorer.html | 326 +------------------------ src/koComment.tsx | 20 ++ webpack.config.js | 2 +- 6 files changed, 475 insertions(+), 444 deletions(-) delete mode 100644 src/Main.ts create mode 100644 src/Main.tsx create mode 100644 src/koComment.tsx diff --git a/src/Main.ts b/src/Main.ts deleted file mode 100644 index 4845fc4e0..000000000 --- a/src/Main.ts +++ /dev/null @@ -1,117 +0,0 @@ -// CSS Dependencies -import "bootstrap/dist/css/bootstrap.css"; -import "../less/documentDB.less"; -import "../less/tree.less"; -import "../less/forms.less"; -import "../less/menus.less"; -import "../less/infobox.less"; -import "../less/messagebox.less"; -import "./Explorer/Controls/ErrorDisplayComponent/ErrorDisplayComponent.less"; -import "./Explorer/Menus/NotificationConsole/NotificationConsole.less"; -import "./Explorer/Menus/CommandBar/CommandBarComponent.less"; -import "./Explorer/Menus/CommandBar/MemoryTrackerComponent.less"; -import "./Explorer/Controls/CollapsiblePanel/CollapsiblePanelComponent.less"; -import "./Explorer/Controls/DynamicList/DynamicListComponent.less"; -import "./Explorer/Controls/JsonEditor/JsonEditorComponent.less"; -import "./Explorer/Graph/GraphExplorerComponent/graphExplorer.less"; -import "../less/TableStyles/queryBuilder.less"; -import "../externals/jquery.dataTables.min.css"; -import "../less/TableStyles/fulldatatables.less"; -import "../less/TableStyles/EntityEditor.less"; -import "../less/TableStyles/CustomizeColumns.less"; -import "../less/resourceTree.less"; -import "../externals/jquery.typeahead.min.css"; -import "../externals/jquery-ui.min.css"; -import "../externals/jquery-ui.structure.min.css"; -import "../externals/jquery-ui.theme.min.css"; -import "./Explorer/Graph/NewVertexComponent/newVertexComponent.less"; -import "./Explorer/Panes/GraphNewVertexPane.less"; -import "./Explorer/Tabs/QueryTab.less"; -import "./Explorer/Controls/TreeComponent/treeComponent.less"; -import "./Explorer/Controls/Accordion/AccordionComponent.less"; -import "./Explorer/SplashScreen/SplashScreenComponent.less"; -import "./Explorer/Controls/Notebook/NotebookTerminalComponent.less"; - -// Image Dependencies -import "../images/CosmosDB_rgb_ui_lighttheme.ico"; -import "../images/favicon.ico"; - -import "./Shared/appInsights"; -import "babel-polyfill"; -import "es6-symbol/implement"; -import "webcrypto-liner/build/webcrypto-liner.shim.min"; -import "./Libs/jquery"; -import "bootstrap/dist/js/npm"; -import "../externals/jquery.typeahead.min.js"; -import "../externals/jquery-ui.min.js"; -import "../externals/adal.js"; -import "promise-polyfill/src/polyfill"; -import "abort-controller/polyfill"; -import "whatwg-fetch"; -import "es6-object-assign/auto"; -import "promise.prototype.finally/auto"; -import "object.entries/auto"; -import "./Libs/is-integer-polyfill"; -import "url-polyfill/url-polyfill.min"; - -// TODO: Enable ReactDevTools after fixing the portal CORS issue -// import "./ReactDevTools" - -import * as ko from "knockout"; -import * as TelemetryProcessor from "./Shared/Telemetry/TelemetryProcessor"; -import { Action, ActionModifiers } from "./Shared/Telemetry/TelemetryConstants"; - -import { BindingHandlersRegisterer } from "./Bindings/BindingHandlersRegisterer"; -import * as Emulator from "./Platform/Emulator/Main"; -import Hosted from "./Platform/Hosted/Main"; -import * as Portal from "./Platform/Portal/Main"; -import { AuthType } from "./AuthType"; - -import { initializeIcons } from "office-ui-fabric-react/lib/Icons"; -import { applyExplorerBindings } from "./applyExplorerBindings"; -import { initializeConfiguration, Platform } from "./ConfigContext"; -import Explorer from "./Explorer/Explorer"; - -initializeIcons(/* optional base url */); - -// TODO: Encapsulate and reuse all global variables as environment variables -window.authType = AuthType.AAD; - -initializeConfiguration().then(config => { - if (config.platform === Platform.Hosted) { - try { - Hosted.initializeExplorer().then( - (explorer: Explorer) => { - applyExplorerBindings(explorer); - Hosted.configureTokenValidationDisplayPrompt(explorer); - }, - (error: any) => { - try { - const uninitializedExplorer: Explorer = Hosted.getUninitializedExplorerForGuestAccess(); - window.dataExplorer = uninitializedExplorer; - ko.applyBindings(uninitializedExplorer); - BindingHandlersRegisterer.registerBindingHandlers(); - if (window.authType !== AuthType.AAD) { - uninitializedExplorer.isRefreshingExplorer(false); - uninitializedExplorer.displayConnectExplorerForm(); - } - } catch (e) { - console.log(e); - } - console.error(error); - } - ); - } catch (e) { - console.log(e); - } - } else if (config.platform === Platform.Emulator) { - window.authType = AuthType.MasterKey; - const explorer = Emulator.initializeExplorer(); - applyExplorerBindings(explorer); - } else if (config.platform === Platform.Portal) { - TelemetryProcessor.trace(Action.InitializeDataExplorer, ActionModifiers.Open, {}); - const explorer = Portal.initializeExplorer(); - TelemetryProcessor.trace(Action.InitializeDataExplorer, ActionModifiers.IFrameReady, {}); - applyExplorerBindings(explorer); - } -}); diff --git a/src/Main.tsx b/src/Main.tsx new file mode 100644 index 000000000..92e1619c4 --- /dev/null +++ b/src/Main.tsx @@ -0,0 +1,452 @@ +// CSS Dependencies +import "bootstrap/dist/css/bootstrap.css"; +import "../less/documentDB.less"; +import "../less/tree.less"; +import "../less/forms.less"; +import "../less/menus.less"; +import "../less/infobox.less"; +import "../less/messagebox.less"; +import "./Explorer/Controls/ErrorDisplayComponent/ErrorDisplayComponent.less"; +import "./Explorer/Menus/NotificationConsole/NotificationConsole.less"; +import "./Explorer/Menus/CommandBar/CommandBarComponent.less"; +import "./Explorer/Menus/CommandBar/MemoryTrackerComponent.less"; +import "./Explorer/Controls/CollapsiblePanel/CollapsiblePanelComponent.less"; +import "./Explorer/Controls/DynamicList/DynamicListComponent.less"; +import "./Explorer/Controls/JsonEditor/JsonEditorComponent.less"; +import "./Explorer/Graph/GraphExplorerComponent/graphExplorer.less"; +import "../less/TableStyles/queryBuilder.less"; +import "../externals/jquery.dataTables.min.css"; +import "../less/TableStyles/fulldatatables.less"; +import "../less/TableStyles/EntityEditor.less"; +import "../less/TableStyles/CustomizeColumns.less"; +import "../less/resourceTree.less"; +import "../externals/jquery.typeahead.min.css"; +import "../externals/jquery-ui.min.css"; +import "../externals/jquery-ui.structure.min.css"; +import "../externals/jquery-ui.theme.min.css"; +import "./Explorer/Graph/NewVertexComponent/newVertexComponent.less"; +import "./Explorer/Panes/GraphNewVertexPane.less"; +import "./Explorer/Tabs/QueryTab.less"; +import "./Explorer/Controls/TreeComponent/treeComponent.less"; +import "./Explorer/Controls/Accordion/AccordionComponent.less"; +import "./Explorer/SplashScreen/SplashScreenComponent.less"; +import "./Explorer/Controls/Notebook/NotebookTerminalComponent.less"; + +// Image Dependencies +import "../images/CosmosDB_rgb_ui_lighttheme.ico"; +import "../images/favicon.ico"; + +import "./Shared/appInsights"; +import "babel-polyfill"; +import "es6-symbol/implement"; +import "webcrypto-liner/build/webcrypto-liner.shim.min"; +import "./Libs/jquery"; +import "bootstrap/dist/js/npm"; +import "../externals/jquery.typeahead.min.js"; +import "../externals/jquery-ui.min.js"; +import "../externals/adal.js"; +import "promise-polyfill/src/polyfill"; +import "abort-controller/polyfill"; +import "whatwg-fetch"; +import "es6-object-assign/auto"; +import "promise.prototype.finally/auto"; +import "object.entries/auto"; +import "./Libs/is-integer-polyfill"; +import "url-polyfill/url-polyfill.min"; + +initializeIcons(); + +import * as ko from "knockout"; +import * as TelemetryProcessor from "./Shared/Telemetry/TelemetryProcessor"; +import { Action, ActionModifiers } from "./Shared/Telemetry/TelemetryConstants"; + +import { BindingHandlersRegisterer } from "./Bindings/BindingHandlersRegisterer"; +import * as Emulator from "./Platform/Emulator/Main"; +import Hosted from "./Platform/Hosted/Main"; +import * as Portal from "./Platform/Portal/Main"; +import { AuthType } from "./AuthType"; + +import { initializeIcons } from "office-ui-fabric-react/lib/Icons"; +import { applyExplorerBindings } from "./applyExplorerBindings"; +import { initializeConfiguration, Platform } from "./ConfigContext"; +import Explorer from "./Explorer/Explorer"; +import React, { useEffect } from "react"; +import ReactDOM from "react-dom"; +import errorImage from "../images/error.svg"; +import copyImage from "../images/Copy.svg"; +import hdeConnectImage from "../images/HdeConnectCosmosDB.svg"; +import refreshImg from "../images/refresh-cosmos.svg"; +import arrowLeftImg from "../images/imgarrowlefticon.svg"; +import { KOCommentEnd, KOCommentIfStart } from "./koComment"; + +// TODO: Encapsulate and reuse all global variables as environment variables +window.authType = AuthType.AAD; + +const App: React.FunctionComponent = () => { + useEffect(() => { + initializeConfiguration().then(config => { + if (config.platform === Platform.Hosted) { + try { + Hosted.initializeExplorer().then( + (explorer: Explorer) => { + applyExplorerBindings(explorer); + Hosted.configureTokenValidationDisplayPrompt(explorer); + }, + (error: unknown) => { + try { + const uninitializedExplorer: Explorer = Hosted.getUninitializedExplorerForGuestAccess(); + window.dataExplorer = uninitializedExplorer; + ko.applyBindings(uninitializedExplorer); + BindingHandlersRegisterer.registerBindingHandlers(); + if (window.authType !== AuthType.AAD) { + uninitializedExplorer.isRefreshingExplorer(false); + uninitializedExplorer.displayConnectExplorerForm(); + } + } catch (e) { + console.log(e); + } + console.error(error); + } + ); + } catch (e) { + console.log(e); + } + } else if (config.platform === Platform.Emulator) { + window.authType = AuthType.MasterKey; + const explorer = Emulator.initializeExplorer(); + applyExplorerBindings(explorer); + } else if (config.platform === Platform.Portal) { + TelemetryProcessor.trace(Action.InitializeDataExplorer, ActionModifiers.Open, {}); + const explorer = Portal.initializeExplorer(); + TelemetryProcessor.trace(Action.InitializeDataExplorer, ActionModifiers.IFrameReady, {}); + applyExplorerBindings(explorer); + } + }); + }, []); + + return ( +
+
+ {/* Main Command Bar - Start */} +
+ {/* Main Command Bar - End */} + {/* Share url flyout - Start */} +
+
+
+ + Open this database account in a new browser tab with Cosmos DB Explorer. Or copy the read-write or read + only access urls below to share with others. For security purposes, the URLs grant time-bound access to + the account. When access expires, you can reconnect, using a valid connection string for the account. + +
+
+
+ + + Read-Write + +
+
+ + + Read + +
+
+
+ + + Copy link + + +
+
+
+
+ {/* Share url flyout - End */} + {/* Collections Tree and Tabs - Begin */} +
+ {/* Collections Tree - Start */} +
+
+ {/* Collections Tree Expanded - Start */} +
+ {/* Collections Window - - Start */} +
+ {/* Collections Window Title/Command Bar - Start */} +
+
+ +
+ + + + + Hide + +
+
+
+ {/* Collections Window Title/Command Bar - End */} + + {!window.dataExplorer?.isAuthWithResourceToken() && ( +
+ )} + {window.dataExplorer?.isAuthWithResourceToken() && ( +
+ )} +
+ {/* Collections Window - End */} +
+ {/* Collections Tree Expanded - End */} + {/* Collections Tree Collapsed - Start */} +
+
+
    +
  • + + Expand + + + + +
  • +
+
+
+ {/* Collections Tree Collapsed - End */} +
+ {/* Splitter - Start */} +
+ {/* Splitter - End */} +
+ {/* Collections Tree - End */} +
+
+
+ +
+
+
+ {/* Collections Tree and Tabs - End */} + + {/* Explorer Connection - Encryption Token / AAD - Start */} +
+
+
+

+ Azure Cosmos DB +

+

Welcome to Azure Cosmos DB

+
+ +

+ Connect to your account with connection string +

+
+
+

Connect to your account with connection string

+

+ + + Error notification + + +

+

+ +

+

+ Sign In with Azure Account +

+
+
+
+
+ {/* Explorer Connection - Encryption Token / AAD - End */} + {/* Global loader - Start */} +
+
+

+ Azure Cosmos DB +

+

+ Welcome to Azure Cosmos DB +

+ +
+
+ {/* Global loader - End */} +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+ + +
+ + +
+ + {/* Global access token expiration dialog - Start */} +
+
+

Please reconnect to the account using the connection string.

+
+
+ {/* Global access token expiration dialog - End */} + {/* Context switch prompt - Start */} +
+
+

+ Please save your work before you switch! When you switch to a different Azure Cosmos DB account, current + Data Explorer tabs will be closed. +

+

Proceed anyway?

+
+
+
+
+
+ ); +}; + +ReactDOM.render(, document.body); diff --git a/src/applyExplorerBindings.ts b/src/applyExplorerBindings.ts index 1bed350f7..570a65aa6 100644 --- a/src/applyExplorerBindings.ts +++ b/src/applyExplorerBindings.ts @@ -5,12 +5,12 @@ import Explorer from "./Explorer/Explorer"; export const applyExplorerBindings = (explorer: Explorer) => { if (!!explorer) { - ko.applyBindings(explorer); // This message should ideally be sent immediately after explorer has been initialized for optimal data explorer load times. // TODO: Send another message to describe that the bindings have been applied, and handle message transfers accordingly in the portal sendMessage("ready"); window.dataExplorer = explorer; BindingHandlersRegisterer.registerBindingHandlers(); + ko.applyBindings(explorer); $("#divExplorer").show(); } }; diff --git a/src/explorer.html b/src/explorer.html index 79e6bc738..5b3fb8c1b 100644 --- a/src/explorer.html +++ b/src/explorer.html @@ -8,329 +8,5 @@ - -
- - - - - - - -
-
-

Azure Cosmos DB

-

Welcome to Azure Cosmos DB

- -
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - -
- - - - - - - -
-
-
- + diff --git a/src/koComment.tsx b/src/koComment.tsx new file mode 100644 index 000000000..670ca5aea --- /dev/null +++ b/src/koComment.tsx @@ -0,0 +1,20 @@ +/* eslint-disable react/prop-types */ +import React, { useEffect, useRef } from "react"; + +export const KOCommentIfStart: React.FunctionComponent<{ if: string }> = props => { + const el = useRef(); + useEffect(() => { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + (el.current as any).outerHTML = ``; + }, []); + return
; +}; + +export const KOCommentEnd: React.FunctionComponent = () => { + const el = useRef(); + useEffect(() => { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + (el.current as any).outerHTML = ``; + }, []); + return
; +}; diff --git a/webpack.config.js b/webpack.config.js index f2c5cef4d..41eb0b920 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -174,7 +174,7 @@ module.exports = function(env = {}, argv = {}) { return { mode: mode, entry: { - main: "./src/Main.ts", + main: "./src/Main.tsx", index: "./src/Index.ts", quickstart: "./src/quickstart.ts", hostedExplorer: "./src/HostedExplorer.ts",