mirror of
https://github.com/Azure/cosmos-explorer.git
synced 2025-12-26 20:31:33 +00:00
Compare commits
4 Commits
resolve_De
...
resolve_es
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0897c75114 | ||
|
|
271256bffb | ||
|
|
b9e06858c5 | ||
|
|
043541b0dc |
@@ -2,8 +2,6 @@
|
|||||||
src/**/__mocks__/**/*
|
src/**/__mocks__/**/*
|
||||||
dist/
|
dist/
|
||||||
Contracts/
|
Contracts/
|
||||||
src/Api/Apis.ts
|
|
||||||
src/AuthType.ts
|
|
||||||
src/Bindings/BindingHandlersRegisterer.ts
|
src/Bindings/BindingHandlersRegisterer.ts
|
||||||
src/Bindings/ReactBindingHandler.ts
|
src/Bindings/ReactBindingHandler.ts
|
||||||
src/Common/Constants.ts
|
src/Common/Constants.ts
|
||||||
@@ -37,7 +35,6 @@ src/Definitions/svg.d.ts
|
|||||||
src/Explorer/ComponentRegisterer.test.ts
|
src/Explorer/ComponentRegisterer.test.ts
|
||||||
src/Explorer/ComponentRegisterer.ts
|
src/Explorer/ComponentRegisterer.ts
|
||||||
src/Explorer/Controls/DiffEditor/DiffEditorComponent.ts
|
src/Explorer/Controls/DiffEditor/DiffEditorComponent.ts
|
||||||
|
|
||||||
src/Explorer/Controls/Editor/EditorComponent.ts
|
src/Explorer/Controls/Editor/EditorComponent.ts
|
||||||
src/Explorer/Controls/JsonEditor/JsonEditorComponent.ts
|
src/Explorer/Controls/JsonEditor/JsonEditorComponent.ts
|
||||||
src/Explorer/DataSamples/ContainerSampleGenerator.test.ts
|
src/Explorer/DataSamples/ContainerSampleGenerator.test.ts
|
||||||
@@ -81,18 +78,15 @@ src/Explorer/Tables/DataTable/DataTableBindingManager.ts
|
|||||||
src/Explorer/Tables/DataTable/DataTableBuilder.ts
|
src/Explorer/Tables/DataTable/DataTableBuilder.ts
|
||||||
src/Explorer/Tables/DataTable/DataTableContextMenu.ts
|
src/Explorer/Tables/DataTable/DataTableContextMenu.ts
|
||||||
src/Explorer/Tables/DataTable/DataTableOperationManager.ts
|
src/Explorer/Tables/DataTable/DataTableOperationManager.ts
|
||||||
# src/Explorer/Tables/DataTable/DataTableOperations.ts
|
|
||||||
src/Explorer/Tables/DataTable/DataTableViewModel.ts
|
src/Explorer/Tables/DataTable/DataTableViewModel.ts
|
||||||
# src/Explorer/Tables/DataTable/TableCommands.ts
|
|
||||||
# src/Explorer/Tables/DataTable/TableEntityCache.ts
|
|
||||||
src/Explorer/Tables/DataTable/TableEntityListViewModel.ts
|
src/Explorer/Tables/DataTable/TableEntityListViewModel.ts
|
||||||
# src/Explorer/Tables/Entities.ts
|
|
||||||
src/Explorer/Tables/QueryBuilder/CustomTimestampHelper.ts
|
src/Explorer/Tables/QueryBuilder/CustomTimestampHelper.ts
|
||||||
src/Explorer/Tables/TableDataClient.ts
|
src/Explorer/Tables/TableDataClient.ts
|
||||||
src/Explorer/Tables/TableEntityProcessor.ts
|
src/Explorer/Tables/TableEntityProcessor.ts
|
||||||
src/Explorer/Tables/Utilities.ts
|
src/Explorer/Tables/Utilities.ts
|
||||||
src/Explorer/Tabs/ConflictsTab.ts
|
src/Explorer/Tabs/ConflictsTab.ts
|
||||||
src/Explorer/Tabs/DatabaseSettingsTab.ts
|
src/Explorer/Tabs/DatabaseSettingsTab.ts
|
||||||
|
src/Explorer/Tabs/DocumentsTab.test.ts
|
||||||
src/Explorer/Tabs/DocumentsTab.ts
|
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
|
||||||
@@ -117,12 +111,10 @@ src/Index.ts
|
|||||||
src/Platform/Hosted/Authorization.ts
|
src/Platform/Hosted/Authorization.ts
|
||||||
src/ReactDevTools.ts
|
src/ReactDevTools.ts
|
||||||
src/Shared/Constants.ts
|
src/Shared/Constants.ts
|
||||||
src/Shared/appInsights.ts
|
src/Shared/DefaultExperienceUtility.test.ts
|
||||||
src/SparkClusterManager/ArcadiaResourceManager.ts
|
src/Shared/DefaultExperienceUtility.ts
|
||||||
src/SparkClusterManager/SparkClusterManager.ts
|
|
||||||
src/Terminal/JupyterLabAppFactory.ts
|
src/Terminal/JupyterLabAppFactory.ts
|
||||||
src/Terminal/NotebookAppContracts.d.ts
|
src/Terminal/NotebookAppContracts.d.ts
|
||||||
src/applyExplorerBindings.ts
|
|
||||||
src/global.d.ts
|
src/global.d.ts
|
||||||
src/setupTests.ts
|
src/setupTests.ts
|
||||||
src/Explorer/Controls/InputTypeahead/InputTypeaheadComponent.tsx
|
src/Explorer/Controls/InputTypeahead/InputTypeaheadComponent.tsx
|
||||||
@@ -131,25 +123,15 @@ src/Explorer/Controls/Notebook/NotebookTerminalComponent.tsx
|
|||||||
src/Explorer/Controls/NotebookViewer/NotebookViewerComponent.tsx
|
src/Explorer/Controls/NotebookViewer/NotebookViewerComponent.tsx
|
||||||
src/Explorer/Controls/TreeComponent/TreeComponent.tsx
|
src/Explorer/Controls/TreeComponent/TreeComponent.tsx
|
||||||
src/Explorer/Graph/GraphExplorerComponent/GraphExplorer.test.tsx
|
src/Explorer/Graph/GraphExplorerComponent/GraphExplorer.test.tsx
|
||||||
; src/Explorer/Graph/GraphExplorerComponent/GraphExplorer.tsx
|
|
||||||
src/Explorer/Graph/GraphExplorerComponent/GraphVizComponent.tsx
|
|
||||||
src/Explorer/Graph/GraphExplorerComponent/LeftPaneComponent.tsx
|
|
||||||
src/Explorer/Graph/GraphExplorerComponent/MiddlePaneComponent.tsx
|
|
||||||
src/Explorer/Graph/GraphExplorerComponent/NodePropertiesComponent.test.tsx
|
|
||||||
src/Explorer/Graph/GraphExplorerComponent/NodePropertiesComponent.tsx
|
src/Explorer/Graph/GraphExplorerComponent/NodePropertiesComponent.tsx
|
||||||
src/Explorer/Graph/GraphExplorerComponent/ReadOnlyNodePropertiesComponent.test.tsx
|
|
||||||
src/Explorer/Graph/GraphExplorerComponent/ReadOnlyNodePropertiesComponent.tsx
|
|
||||||
src/Explorer/Menus/CommandBar/CommandBarUtil.tsx
|
src/Explorer/Menus/CommandBar/CommandBarUtil.tsx
|
||||||
src/Explorer/Notebook/NotebookComponent/NotebookComponentAdapter.tsx
|
src/Explorer/Notebook/NotebookComponent/NotebookComponentAdapter.tsx
|
||||||
; src/Explorer/Notebook/NotebookComponent/NotebookComponentBootstrapper.tsx
|
|
||||||
src/Explorer/Notebook/NotebookComponent/VirtualCommandBarComponent.tsx
|
src/Explorer/Notebook/NotebookComponent/VirtualCommandBarComponent.tsx
|
||||||
src/Explorer/Notebook/NotebookComponent/contents/index.tsx
|
src/Explorer/Notebook/NotebookComponent/contents/index.tsx
|
||||||
; src/Explorer/Notebook/NotebookRenderer/NotebookReadOnlyRenderer.tsx
|
|
||||||
src/Explorer/Notebook/NotebookRenderer/NotebookRenderer.tsx
|
src/Explorer/Notebook/NotebookRenderer/NotebookRenderer.tsx
|
||||||
src/Explorer/Notebook/NotebookRenderer/decorators/draggable/index.tsx
|
src/Explorer/Notebook/NotebookRenderer/decorators/draggable/index.tsx
|
||||||
src/Explorer/Notebook/NotebookRenderer/decorators/hijack-scroll/index.tsx
|
src/Explorer/Notebook/NotebookRenderer/decorators/hijack-scroll/index.tsx
|
||||||
src/Explorer/Notebook/NotebookRenderer/decorators/kbd-shortcuts/index.tsx
|
src/Explorer/Notebook/NotebookRenderer/decorators/kbd-shortcuts/index.tsx
|
||||||
src/Explorer/Notebook/temp/inputs/connected-editors/codemirror.tsx
|
|
||||||
src/Explorer/Tree/ResourceTreeAdapter.tsx
|
src/Explorer/Tree/ResourceTreeAdapter.tsx
|
||||||
__mocks__/monaco-editor.ts
|
__mocks__/monaco-editor.ts
|
||||||
src/Explorer/Tree/ResourceTree.tsx
|
src/Explorer/Tree/ResourceTree.tsx
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
/**
|
/**
|
||||||
* Data Explorer version {major.minor.patch}
|
* Data Explorer version {major.minor.patch}
|
||||||
*/
|
*/
|
||||||
export const DataExplorer: string = "1.0.1";
|
export const DataExplorer = "1.0.1";
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ export class LeftPaneComponent extends React.Component<LeftPaneComponentProps> {
|
|||||||
className={className}
|
className={className}
|
||||||
as="tr"
|
as="tr"
|
||||||
aria-label={node.caption}
|
aria-label={node.caption}
|
||||||
onActivated={(e) => this.props.onRootNodeSelected(node.id)}
|
onActivated={() => this.props.onRootNodeSelected(node.id)}
|
||||||
key={node.id}
|
key={node.id}
|
||||||
>
|
>
|
||||||
<td className="resultItem">
|
<td className="resultItem">
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import React from "react";
|
|
||||||
import { mount, ReactWrapper } from "enzyme";
|
import { mount, ReactWrapper } from "enzyme";
|
||||||
import * as Q from "q";
|
import * as Q from "q";
|
||||||
import { NodePropertiesComponent, NodePropertiesComponentProps, Mode } from "./NodePropertiesComponent";
|
import React from "react";
|
||||||
import { GraphHighlightedNodeData, EditedProperties, EditedEdges, PossibleVertex } from "./GraphExplorer";
|
import { GraphHighlightedNodeData, PossibleVertex } from "./GraphExplorer";
|
||||||
|
import { Mode, NodePropertiesComponent, NodePropertiesComponentProps } from "./NodePropertiesComponent";
|
||||||
|
|
||||||
describe("Property pane", () => {
|
describe("Property pane", () => {
|
||||||
const title = "My Title";
|
const title = "My Title";
|
||||||
@@ -37,17 +37,18 @@ describe("Property pane", () => {
|
|||||||
return {
|
return {
|
||||||
expandedTitle: title,
|
expandedTitle: title,
|
||||||
isCollapsed: false,
|
isCollapsed: false,
|
||||||
onCollapsedChanged: (newValue: boolean): void => {},
|
onCollapsedChanged: jest.fn(),
|
||||||
node: highlightedNode,
|
node: highlightedNode,
|
||||||
getPkIdFromNodeData: (v: GraphHighlightedNodeData): string => null,
|
getPkIdFromNodeData: (): string => undefined,
|
||||||
collectionPartitionKeyProperty: null,
|
collectionPartitionKeyProperty: undefined,
|
||||||
updateVertexProperties: (editedProperties: EditedProperties): Q.Promise<void> => Q.resolve(),
|
updateVertexProperties: (): Q.Promise<void> => Q.resolve(),
|
||||||
selectNode: (id: string): void => {},
|
selectNode: jest.fn(),
|
||||||
updatePossibleVertices: (): Q.Promise<PossibleVertex[]> => Q.resolve(null),
|
updatePossibleVertices: (): Q.Promise<PossibleVertex[]> => Q.resolve(undefined),
|
||||||
possibleEdgeLabels: null,
|
possibleEdgeLabels: undefined,
|
||||||
editGraphEdges: (editedEdges: EditedEdges): Q.Promise<any> => Q.resolve(),
|
//eslint-disable-next-line
|
||||||
deleteHighlightedNode: (): void => {},
|
editGraphEdges: (): Q.Promise<any> => Q.resolve(),
|
||||||
onModeChanged: (newMode: Mode): void => {},
|
deleteHighlightedNode: jest.fn(),
|
||||||
|
onModeChanged: jest.fn(),
|
||||||
viewMode: Mode.READONLY_PROP,
|
viewMode: Mode.READONLY_PROP,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ export class NodePropertiesComponent extends React.Component<
|
|||||||
super(props);
|
super(props);
|
||||||
this.state = {
|
this.state = {
|
||||||
editedProperties: {
|
editedProperties: {
|
||||||
pkId: null,
|
pkId: undefined,
|
||||||
readOnlyProperties: [],
|
readOnlyProperties: [],
|
||||||
existingProperties: [],
|
existingProperties: [],
|
||||||
addedProperties: [],
|
addedProperties: [],
|
||||||
@@ -98,15 +98,12 @@ export class NodePropertiesComponent extends React.Component<
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public static getDerivedStateFromProps(
|
public static getDerivedStateFromProps(props: NodePropertiesComponentProps): Partial<NodePropertiesComponentState> {
|
||||||
props: NodePropertiesComponentProps,
|
|
||||||
state: NodePropertiesComponentState
|
|
||||||
): Partial<NodePropertiesComponentState> {
|
|
||||||
if (props.viewMode !== Mode.READONLY_PROP) {
|
if (props.viewMode !== Mode.READONLY_PROP) {
|
||||||
return { isDeleteConfirm: false };
|
return { isDeleteConfirm: false };
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
public render(): JSX.Element {
|
public render(): JSX.Element {
|
||||||
@@ -138,10 +135,10 @@ export class NodePropertiesComponent extends React.Component<
|
|||||||
* @param value
|
* @param value
|
||||||
*/
|
*/
|
||||||
private static getTypeOption(value: any): ViewModels.InputPropertyValueTypeString {
|
private static getTypeOption(value: any): ViewModels.InputPropertyValueTypeString {
|
||||||
if (value == null) {
|
if (value === undefined) {
|
||||||
return "null";
|
return "null";
|
||||||
}
|
}
|
||||||
let type = typeof value;
|
const type = typeof value;
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case "number":
|
case "number":
|
||||||
case "boolean":
|
case "boolean":
|
||||||
@@ -172,10 +169,9 @@ export class NodePropertiesComponent extends React.Component<
|
|||||||
];
|
];
|
||||||
|
|
||||||
const existingProps: ViewModels.InputProperty[] = [];
|
const existingProps: ViewModels.InputProperty[] = [];
|
||||||
|
|
||||||
if (this.props.node.hasOwnProperty("properties")) {
|
if (this.props.node.hasOwnProperty("properties")) {
|
||||||
const hProps = this.props.node["properties"];
|
const hProps = this.props.node["properties"];
|
||||||
for (let p in hProps) {
|
for (const p in hProps) {
|
||||||
const propValues = hProps[p];
|
const propValues = hProps[p];
|
||||||
(p === partitionKeyProperty ? readOnlyProps : existingProps).push({
|
(p === partitionKeyProperty ? readOnlyProps : existingProps).push({
|
||||||
key: p,
|
key: p,
|
||||||
@@ -437,7 +433,7 @@ export class NodePropertiesComponent extends React.Component<
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return undefined;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import React from "react";
|
|
||||||
import { shallow } from "enzyme";
|
import { shallow } from "enzyme";
|
||||||
|
import React from "react";
|
||||||
import { GraphHighlightedNodeData } from "./GraphExplorer";
|
import { GraphHighlightedNodeData } from "./GraphExplorer";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
ReadOnlyNodePropertiesComponent,
|
ReadOnlyNodePropertiesComponent,
|
||||||
ReadOnlyNodePropertiesComponentProps,
|
ReadOnlyNodePropertiesComponentProps,
|
||||||
@@ -44,7 +43,7 @@ describe("<ReadOnlyNodePropertiesComponent />", () => {
|
|||||||
const mockNode2 = {
|
const mockNode2 = {
|
||||||
...mockNode,
|
...mockNode,
|
||||||
properties: {
|
properties: {
|
||||||
key3: ["abcd", 1234, true, false, undefined, null],
|
key3: ["abcd", 1234, true, false, undefined],
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
const props: ReadOnlyNodePropertiesComponentProps = { node: mockNode2 };
|
const props: ReadOnlyNodePropertiesComponentProps = { node: mockNode2 };
|
||||||
|
|||||||
@@ -60,9 +60,7 @@ export class ReadOnlyNodePropertiesComponent extends React.Component<ReadOnlyNod
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static singlePropertyValueToString(value: ViewModels.GremlinPropertyValueType): string {
|
public static singlePropertyValueToString(value: ViewModels.GremlinPropertyValueType): string {
|
||||||
if (value === null) {
|
if (typeof value === "undefined") {
|
||||||
return "null";
|
|
||||||
} else if (typeof value === "undefined") {
|
|
||||||
return "undefined";
|
return "undefined";
|
||||||
} else {
|
} else {
|
||||||
return value.toString();
|
return value.toString();
|
||||||
@@ -71,11 +69,8 @@ export class ReadOnlyNodePropertiesComponent extends React.Component<ReadOnlyNod
|
|||||||
|
|
||||||
public static renderSinglePropertyValue(value: ViewModels.GremlinPropertyValueType): JSX.Element {
|
public static renderSinglePropertyValue(value: ViewModels.GremlinPropertyValueType): JSX.Element {
|
||||||
let singlePropValue = value;
|
let singlePropValue = value;
|
||||||
let className = "propertyValue";
|
const className = "propertyValue";
|
||||||
if (singlePropValue === null) {
|
if (typeof singlePropValue === "undefined") {
|
||||||
singlePropValue = "null";
|
|
||||||
className += " isNull";
|
|
||||||
} else if (typeof singlePropValue === "undefined") {
|
|
||||||
singlePropValue = "undefined";
|
singlePropValue = "undefined";
|
||||||
} else {
|
} else {
|
||||||
singlePropValue = value.toString();
|
singlePropValue = value.toString();
|
||||||
|
|||||||
@@ -123,7 +123,7 @@ exports[`<ReadOnlyNodePropertiesComponent /> renders properties (with multiple v
|
|||||||
</td>
|
</td>
|
||||||
<td
|
<td
|
||||||
className="valueCol"
|
className="valueCol"
|
||||||
title="abcd, 1234, true, false, undefined, null"
|
title="abcd, 1234, true, false, undefined"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
className="propertyValue"
|
className="propertyValue"
|
||||||
@@ -155,12 +155,6 @@ exports[`<ReadOnlyNodePropertiesComponent /> renders properties (with multiple v
|
|||||||
>
|
>
|
||||||
undefined
|
undefined
|
||||||
</div>
|
</div>
|
||||||
<div
|
|
||||||
className="propertyValue isNull"
|
|
||||||
key="null"
|
|
||||||
>
|
|
||||||
null
|
|
||||||
</div>
|
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ import * as React from "react";
|
|||||||
import { useFullScreenURLs } from "../hooks/useFullScreenURLs";
|
import { useFullScreenURLs } from "../hooks/useFullScreenURLs";
|
||||||
|
|
||||||
export const OpenFullScreen: React.FunctionComponent = () => {
|
export const OpenFullScreen: React.FunctionComponent = () => {
|
||||||
|
const [isReadUrlCopy, setIsReadUrlCopy] = React.useState<boolean>(false);
|
||||||
|
const [isReadWriteUrlCopy, setIsReadWriteUrlCopy] = React.useState<boolean>(false);
|
||||||
const result = useFullScreenURLs();
|
const result = useFullScreenURLs();
|
||||||
if (!result) {
|
if (!result) {
|
||||||
return <Spinner label="Generating URLs..." ariaLive="assertive" labelPosition="right" />;
|
return <Spinner label="Generating URLs..." ariaLive="assertive" labelPosition="right" />;
|
||||||
@@ -25,8 +27,9 @@ export const OpenFullScreen: React.FunctionComponent = () => {
|
|||||||
<DefaultButton
|
<DefaultButton
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
copyToClipboard(readWriteUrl);
|
copyToClipboard(readWriteUrl);
|
||||||
|
setIsReadWriteUrlCopy(true);
|
||||||
}}
|
}}
|
||||||
text="Copy"
|
text={isReadWriteUrlCopy ? "Copied" : "Copy"}
|
||||||
iconProps={{ iconName: "Copy" }}
|
iconProps={{ iconName: "Copy" }}
|
||||||
/>
|
/>
|
||||||
<PrimaryButton
|
<PrimaryButton
|
||||||
@@ -41,9 +44,10 @@ export const OpenFullScreen: React.FunctionComponent = () => {
|
|||||||
<Stack horizontal tokens={{ childrenGap: 10 }}>
|
<Stack horizontal tokens={{ childrenGap: 10 }}>
|
||||||
<DefaultButton
|
<DefaultButton
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
|
setIsReadUrlCopy(true);
|
||||||
copyToClipboard(readUrl);
|
copyToClipboard(readUrl);
|
||||||
}}
|
}}
|
||||||
text="Copy"
|
text={isReadUrlCopy ? "Copied" : "Copy"}
|
||||||
iconProps={{ iconName: "Copy" }}
|
iconProps={{ iconName: "Copy" }}
|
||||||
/>
|
/>
|
||||||
<PrimaryButton
|
<PrimaryButton
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import { Collection } from "Contracts/ViewModels";
|
|||||||
import { useSidePanel } from "hooks/useSidePanel";
|
import { useSidePanel } from "hooks/useSidePanel";
|
||||||
import { useTabs } from "hooks/useTabs";
|
import { useTabs } from "hooks/useTabs";
|
||||||
import React, { FunctionComponent, useState } from "react";
|
import React, { FunctionComponent, useState } from "react";
|
||||||
import * as DefaultExperienceUtility from "Shared/DefaultExperienceUtility";
|
import { DefaultExperienceUtility } from "Shared/DefaultExperienceUtility";
|
||||||
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";
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import { Collection, Database } from "Contracts/ViewModels";
|
|||||||
import { useSidePanel } from "hooks/useSidePanel";
|
import { useSidePanel } from "hooks/useSidePanel";
|
||||||
import { useTabs } from "hooks/useTabs";
|
import { useTabs } from "hooks/useTabs";
|
||||||
import React, { FunctionComponent, useState } from "react";
|
import React, { FunctionComponent, useState } from "react";
|
||||||
import * as DefaultExperienceUtility from "Shared/DefaultExperienceUtility";
|
import { DefaultExperienceUtility } from "Shared/DefaultExperienceUtility";
|
||||||
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";
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ describe("Documents tab", () => {
|
|||||||
describe("buildQuery", () => {
|
describe("buildQuery", () => {
|
||||||
it("should generate the right select query for SQL API", () => {
|
it("should generate the right select query for SQL API", () => {
|
||||||
const documentsTab = new DocumentsTab({
|
const documentsTab = new DocumentsTab({
|
||||||
partitionKey: undefined,
|
partitionKey: null,
|
||||||
documentIds: ko.observableArray<DocumentId>(),
|
documentIds: ko.observableArray<DocumentId>(),
|
||||||
tabKind: ViewModels.CollectionTabKind.Documents,
|
tabKind: ViewModels.CollectionTabKind.Documents,
|
||||||
title: "",
|
title: "",
|
||||||
@@ -82,9 +82,9 @@ describe("Documents tab", () => {
|
|||||||
container: mongoExplorer,
|
container: mongoExplorer,
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should be false for undefined or undefined collection", () => {
|
it("should be false for null or undefined collection", () => {
|
||||||
const documentsTab = new DocumentsTab({
|
const documentsTab = new DocumentsTab({
|
||||||
partitionKey: undefined,
|
partitionKey: null,
|
||||||
documentIds: ko.observableArray<DocumentId>(),
|
documentIds: ko.observableArray<DocumentId>(),
|
||||||
tabKind: ViewModels.CollectionTabKind.Documents,
|
tabKind: ViewModels.CollectionTabKind.Documents,
|
||||||
title: "",
|
title: "",
|
||||||
@@ -94,10 +94,10 @@ describe("Documents tab", () => {
|
|||||||
expect(documentsTab.showPartitionKey).toBe(false);
|
expect(documentsTab.showPartitionKey).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should be false for undefined or undefined partitionKey", () => {
|
it("should be false for null or undefined partitionKey", () => {
|
||||||
const documentsTab = new DocumentsTab({
|
const documentsTab = new DocumentsTab({
|
||||||
collection: collectionWithoutPartitionKey,
|
collection: collectionWithoutPartitionKey,
|
||||||
partitionKey: undefined,
|
partitionKey: null,
|
||||||
documentIds: ko.observableArray<DocumentId>(),
|
documentIds: ko.observableArray<DocumentId>(),
|
||||||
tabKind: ViewModels.CollectionTabKind.Documents,
|
tabKind: ViewModels.CollectionTabKind.Documents,
|
||||||
title: "",
|
title: "",
|
||||||
@@ -110,7 +110,7 @@ describe("Documents tab", () => {
|
|||||||
it("should be true for non-Mongo accounts with system partitionKey", () => {
|
it("should be true for non-Mongo accounts with system partitionKey", () => {
|
||||||
const documentsTab = new DocumentsTab({
|
const documentsTab = new DocumentsTab({
|
||||||
collection: collectionWithSystemPartitionKey,
|
collection: collectionWithSystemPartitionKey,
|
||||||
partitionKey: undefined,
|
partitionKey: null,
|
||||||
documentIds: ko.observableArray<DocumentId>(),
|
documentIds: ko.observableArray<DocumentId>(),
|
||||||
tabKind: ViewModels.CollectionTabKind.Documents,
|
tabKind: ViewModels.CollectionTabKind.Documents,
|
||||||
title: "",
|
title: "",
|
||||||
@@ -126,7 +126,7 @@ describe("Documents tab", () => {
|
|||||||
});
|
});
|
||||||
const documentsTab = new DocumentsTab({
|
const documentsTab = new DocumentsTab({
|
||||||
collection: mongoCollectionWithSystemPartitionKey,
|
collection: mongoCollectionWithSystemPartitionKey,
|
||||||
partitionKey: undefined,
|
partitionKey: null,
|
||||||
documentIds: ko.observableArray<DocumentId>(),
|
documentIds: ko.observableArray<DocumentId>(),
|
||||||
tabKind: ViewModels.CollectionTabKind.Documents,
|
tabKind: ViewModels.CollectionTabKind.Documents,
|
||||||
title: "",
|
title: "",
|
||||||
@@ -139,7 +139,7 @@ describe("Documents tab", () => {
|
|||||||
it("should be true for non-system partitionKey", () => {
|
it("should be true for non-system partitionKey", () => {
|
||||||
const documentsTab = new DocumentsTab({
|
const documentsTab = new DocumentsTab({
|
||||||
collection: collectionWithNonSystemPartitionKey,
|
collection: collectionWithNonSystemPartitionKey,
|
||||||
partitionKey: undefined,
|
partitionKey: null,
|
||||||
documentIds: ko.observableArray<DocumentId>(),
|
documentIds: ko.observableArray<DocumentId>(),
|
||||||
tabKind: ViewModels.CollectionTabKind.Documents,
|
tabKind: ViewModels.CollectionTabKind.Documents,
|
||||||
title: "",
|
title: "",
|
||||||
|
|||||||
@@ -118,7 +118,7 @@ export default class NotebookTabV2 extends NotebookTabBase {
|
|||||||
const saveButtonChildren = [];
|
const saveButtonChildren = [];
|
||||||
if (this.container.notebookManager?.gitHubOAuthService.isLoggedIn()) {
|
if (this.container.notebookManager?.gitHubOAuthService.isLoggedIn()) {
|
||||||
saveButtonChildren.push({
|
saveButtonChildren.push({
|
||||||
iconName: "Copy",
|
iconName: copyToLabel,
|
||||||
onCommandClick: () => this.copyNotebook(),
|
onCommandClick: () => this.copyNotebook(),
|
||||||
commandButtonLabel: copyToLabel,
|
commandButtonLabel: copyToLabel,
|
||||||
hasPopup: false,
|
hasPopup: false,
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import * as ko from "knockout";
|
import * as ko from "knockout";
|
||||||
import * as Constants from "../Common/Constants";
|
|
||||||
import * as ViewModels from "../Contracts/ViewModels";
|
import * as ViewModels from "../Contracts/ViewModels";
|
||||||
|
import * as Constants from "../Common/Constants";
|
||||||
|
|
||||||
export abstract class WaitsForTemplateViewModel implements ViewModels.WaitsForTemplate {
|
export abstract class WaitsForTemplateViewModel implements ViewModels.WaitsForTemplate {
|
||||||
public isTemplateReady: ko.Observable<boolean>;
|
public isTemplateReady: ko.Observable<boolean>;
|
||||||
@@ -14,11 +14,11 @@ export abstract class WaitsForTemplateViewModel implements ViewModels.WaitsForTe
|
|||||||
callback(value);
|
callback(value);
|
||||||
});
|
});
|
||||||
|
|
||||||
document.addEventListener("keydown", (e: KeyboardEvent) => {
|
document.addEventListener("keydown", function (e: KeyboardEvent) {
|
||||||
// To trap keyboard focus in AddCollection pane
|
// To trap keyboard focus in AddCollection pane
|
||||||
const firstFocusableElement = document.getElementById("closeBtnAddCollection");
|
let firstFocusableElement = document.getElementById("closeBtnAddCollection");
|
||||||
const lastFocusableElement = document.getElementById("submitBtnAddCollection");
|
let lastFocusableElement = document.getElementById("submitBtnAddCollection");
|
||||||
const isTabPressed = e.keyCode === Constants.KeyCodes.Tab;
|
var isTabPressed = e.keyCode === Constants.KeyCodes.Tab;
|
||||||
if (isTabPressed) {
|
if (isTabPressed) {
|
||||||
if (e.shiftKey) {
|
if (e.shiftKey) {
|
||||||
/* shift + tab */ if (document.activeElement === firstFocusableElement) {
|
/* shift + tab */ if (document.activeElement === firstFocusableElement) {
|
||||||
|
|||||||
@@ -1,10 +1,22 @@
|
|||||||
import * as Constants from "../../Common/Constants";
|
import * as Constants from "../../Common/Constants";
|
||||||
import { configContext } from "../../ConfigContext";
|
import { configContext } from "../../ConfigContext";
|
||||||
import * as DataModels from "../../Contracts/DataModels";
|
import * as DataModels from "../../Contracts/DataModels";
|
||||||
import * as DefaultExperienceUtility from "../../Shared/DefaultExperienceUtility";
|
import { DefaultExperienceUtility } from "../../Shared/DefaultExperienceUtility";
|
||||||
import { userContext } from "../../UserContext";
|
import { userContext } from "../../UserContext";
|
||||||
|
|
||||||
export const _generateResourceUrl = (): string => {
|
export default class AuthHeadersUtil {
|
||||||
|
public static async generateEncryptedToken(readOnly: boolean = false): Promise<DataModels.GenerateTokenResponse> {
|
||||||
|
const url = configContext.BACKEND_ENDPOINT + "/api/tokens/generateToken" + AuthHeadersUtil._generateResourceUrl();
|
||||||
|
const headers: any = { authorization: userContext.authorizationToken };
|
||||||
|
headers[Constants.HttpHeaders.getReadOnlyKey] = readOnly;
|
||||||
|
|
||||||
|
const response = await fetch(url, { method: "POST", headers });
|
||||||
|
const result = await response.json();
|
||||||
|
// This API has a quirk where the response must be parsed to JSON twice
|
||||||
|
return JSON.parse(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static _generateResourceUrl(): string {
|
||||||
const { databaseAccount, resourceGroup, subscriptionId } = userContext;
|
const { databaseAccount, resourceGroup, subscriptionId } = userContext;
|
||||||
const apiKind: DataModels.ApiKind = DefaultExperienceUtility.getApiKindFromDefaultExperience(userContext.apiType);
|
const apiKind: DataModels.ApiKind = DefaultExperienceUtility.getApiKindFromDefaultExperience(userContext.apiType);
|
||||||
const accountEndpoint = databaseAccount?.properties?.documentEndpoint || "";
|
const accountEndpoint = databaseAccount?.properties?.documentEndpoint || "";
|
||||||
@@ -15,15 +27,5 @@ export const _generateResourceUrl = (): string => {
|
|||||||
const rid = "";
|
const rid = "";
|
||||||
const rtype = "";
|
const rtype = "";
|
||||||
return `?resourceUrl=${resourceUrl}&rid=${rid}&rtype=${rtype}&sid=${sid}&rg=${rg}&dba=${dba}&api=${apiKind}`;
|
return `?resourceUrl=${resourceUrl}&rid=${rid}&rtype=${rtype}&sid=${sid}&rg=${rg}&dba=${dba}&api=${apiKind}`;
|
||||||
};
|
}
|
||||||
|
}
|
||||||
export const generateEncryptedToken = async (readOnly = false): Promise<DataModels.GenerateTokenResponse> => {
|
|
||||||
const url = configContext.BACKEND_ENDPOINT + "/api/tokens/generateToken" + _generateResourceUrl();
|
|
||||||
const headers: any = { authorization: userContext.authorizationToken };
|
|
||||||
headers[Constants.HttpHeaders.getReadOnlyKey] = readOnly;
|
|
||||||
|
|
||||||
const response = await fetch(url, { method: "POST", headers });
|
|
||||||
const result = await response.json();
|
|
||||||
// This API has a quirk where the response must be parsed to JSON twice
|
|
||||||
return JSON.parse(result);
|
|
||||||
};
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { AccountKind, CapabilityNames } from "../../Common/Constants";
|
import { AccountKind, CapabilityNames } from "../../Common/Constants";
|
||||||
import { AccessInputMetadata, ApiKind } from "../../Contracts/DataModels";
|
import { AccessInputMetadata, ApiKind } from "../../Contracts/DataModels";
|
||||||
import * as DefaultExperienceUtility from "../../Shared/DefaultExperienceUtility";
|
import { DefaultExperienceUtility } from "../../Shared/DefaultExperienceUtility";
|
||||||
import { userContext } from "../../UserContext";
|
import { userContext } from "../../UserContext";
|
||||||
|
|
||||||
export function getDatabaseAccountPropertiesFromMetadata(metadata: AccessInputMetadata): unknown {
|
export function getDatabaseAccountPropertiesFromMetadata(metadata: AccessInputMetadata): unknown {
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
import * as DataModels from "../Contracts/DataModels";
|
import * as DataModels from "../Contracts/DataModels";
|
||||||
import { userContext } from "../UserContext";
|
import { userContext } from "../UserContext";
|
||||||
import * as DefaultExperienceUtility from "./DefaultExperienceUtility";
|
import { DefaultExperienceUtility } from "./DefaultExperienceUtility";
|
||||||
|
|
||||||
describe("Default Experience Utility", () => {
|
describe("Default Experience Utility", () => {
|
||||||
describe("getDefaultExperienceFromApiKind()", () => {
|
describe("getDefaultExperienceFromApiKind()", () => {
|
||||||
const runScenario = (apiKind: number, expectedExperience: typeof userContext.apiType): void => {
|
function runScenario(apiKind: number, expectedExperience: typeof userContext.apiType): void {
|
||||||
const resolvedExperience = DefaultExperienceUtility.getDefaultExperienceFromApiKind(apiKind);
|
const resolvedExperience = DefaultExperienceUtility.getDefaultExperienceFromApiKind(apiKind);
|
||||||
expect(resolvedExperience).toEqual(expectedExperience);
|
expect(resolvedExperience).toEqual(expectedExperience);
|
||||||
};
|
}
|
||||||
|
|
||||||
describe("On SQL", () => {
|
describe("On SQL", () => {
|
||||||
it("should return SQL", () => runScenario(DataModels.ApiKind.SQL, "SQL"));
|
it("should return SQL", () => runScenario(DataModels.ApiKind.SQL, "SQL"));
|
||||||
@@ -35,10 +35,10 @@ describe("Default Experience Utility", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe("getApiKindFromDefaultExperience()", () => {
|
describe("getApiKindFromDefaultExperience()", () => {
|
||||||
const runScenario = (defaultExperience: typeof userContext.apiType | null, expectedApiKind: number): void => {
|
function runScenario(defaultExperience: typeof userContext.apiType | null, expectedApiKind: number): void {
|
||||||
const resolvedApiKind = DefaultExperienceUtility.getApiKindFromDefaultExperience(defaultExperience);
|
const resolvedApiKind = DefaultExperienceUtility.getApiKindFromDefaultExperience(defaultExperience);
|
||||||
expect(resolvedApiKind).toEqual(expectedApiKind);
|
expect(resolvedApiKind).toEqual(expectedApiKind);
|
||||||
};
|
}
|
||||||
|
|
||||||
describe("On SQL", () => {
|
describe("On SQL", () => {
|
||||||
it("should return SQL", () => runScenario("SQL", DataModels.ApiKind.SQL));
|
it("should return SQL", () => runScenario("SQL", DataModels.ApiKind.SQL));
|
||||||
@@ -60,8 +60,8 @@ describe("Default Experience Utility", () => {
|
|||||||
it("should return Graph", () => runScenario("Gremlin", DataModels.ApiKind.Graph));
|
it("should return Graph", () => runScenario("Gremlin", DataModels.ApiKind.Graph));
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("On undefined", () => {
|
describe("On null", () => {
|
||||||
it("should return SQL", () => runScenario(undefined, DataModels.ApiKind.SQL));
|
it("should return SQL", () => runScenario(null, DataModels.ApiKind.SQL));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
import * as DataModels from "../Contracts/DataModels";
|
import * as DataModels from "../Contracts/DataModels";
|
||||||
import { userContext } from "../UserContext";
|
import { userContext } from "../UserContext";
|
||||||
|
|
||||||
export const getApiKindFromDefaultExperience = (defaultExperience: typeof userContext.apiType): DataModels.ApiKind => {
|
export class DefaultExperienceUtility {
|
||||||
|
public static getApiKindFromDefaultExperience(defaultExperience: typeof userContext.apiType): DataModels.ApiKind {
|
||||||
if (!defaultExperience) {
|
if (!defaultExperience) {
|
||||||
return DataModels.ApiKind.SQL;
|
return DataModels.ApiKind.SQL;
|
||||||
}
|
}
|
||||||
@@ -20,10 +21,10 @@ export const getApiKindFromDefaultExperience = (defaultExperience: typeof userCo
|
|||||||
default:
|
default:
|
||||||
return DataModels.ApiKind.SQL;
|
return DataModels.ApiKind.SQL;
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
export const getDefaultExperienceFromApiKind = (apiKind: DataModels.ApiKind): typeof userContext.apiType => {
|
public static getDefaultExperienceFromApiKind(apiKind: DataModels.ApiKind): typeof userContext.apiType {
|
||||||
if (apiKind === undefined) {
|
if (apiKind == null) {
|
||||||
return "SQL";
|
return "SQL";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -42,4 +43,5 @@ export const getDefaultExperienceFromApiKind = (apiKind: DataModels.ApiKind): ty
|
|||||||
default:
|
default:
|
||||||
return "SQL";
|
return "SQL";
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -5,7 +5,8 @@ import { ServerConnection, TerminalManager } from "@jupyterlab/services";
|
|||||||
import { Terminal } from "@jupyterlab/terminal";
|
import { Terminal } from "@jupyterlab/terminal";
|
||||||
import { Panel, Widget } from "@phosphor/widgets";
|
import { Panel, Widget } from "@phosphor/widgets";
|
||||||
|
|
||||||
export const createTerminalApp = async (serverSettings: ServerConnection.ISettings) => {
|
export class JupyterLabAppFactory {
|
||||||
|
public static async createTerminalApp(serverSettings: ServerConnection.ISettings) {
|
||||||
const manager = new TerminalManager({
|
const manager = new TerminalManager({
|
||||||
serverSettings: serverSettings,
|
serverSettings: serverSettings,
|
||||||
});
|
});
|
||||||
@@ -20,7 +21,7 @@ export const createTerminalApp = async (serverSettings: ServerConnection.ISettin
|
|||||||
term.title.closable = false;
|
term.title.closable = false;
|
||||||
term.addClass("terminalWidget");
|
term.addClass("terminalWidget");
|
||||||
|
|
||||||
const panel = new Panel();
|
let panel = new Panel();
|
||||||
panel.addWidget(term as any);
|
panel.addWidget(term as any);
|
||||||
panel.id = "main";
|
panel.id = "main";
|
||||||
|
|
||||||
@@ -36,4 +37,5 @@ export const createTerminalApp = async (serverSettings: ServerConnection.ISettin
|
|||||||
window.addEventListener("unload", () => {
|
window.addEventListener("unload", () => {
|
||||||
panel.dispose();
|
panel.dispose();
|
||||||
});
|
});
|
||||||
};
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import { Action } from "../Shared/Telemetry/TelemetryConstants";
|
|||||||
import * as TelemetryProcessor from "../Shared/Telemetry/TelemetryProcessor";
|
import * as TelemetryProcessor from "../Shared/Telemetry/TelemetryProcessor";
|
||||||
import { updateUserContext } from "../UserContext";
|
import { updateUserContext } from "../UserContext";
|
||||||
import "./index.css";
|
import "./index.css";
|
||||||
import { createTerminalApp } from "./JupyterLabAppFactory";
|
import { JupyterLabAppFactory } from "./JupyterLabAppFactory";
|
||||||
import { TerminalProps } from "./TerminalProps";
|
import { TerminalProps } from "./TerminalProps";
|
||||||
|
|
||||||
const createServerSettings = (props: TerminalProps): ServerConnection.ISettings => {
|
const createServerSettings = (props: TerminalProps): ServerConnection.ISettings => {
|
||||||
@@ -54,7 +54,7 @@ const initTerminal = async (props: TerminalProps) => {
|
|||||||
const startTime = TelemetryProcessor.traceStart(Action.OpenTerminal, data);
|
const startTime = TelemetryProcessor.traceStart(Action.OpenTerminal, data);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await createTerminalApp(serverSettings);
|
await JupyterLabAppFactory.createTerminalApp(serverSettings);
|
||||||
TelemetryProcessor.traceSuccess(Action.OpenTerminal, data, startTime);
|
TelemetryProcessor.traceSuccess(Action.OpenTerminal, data, startTime);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
TelemetryProcessor.traceFailure(Action.OpenTerminal, data, startTime);
|
TelemetryProcessor.traceFailure(Action.OpenTerminal, data, startTime);
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { BindingHandlersRegisterer } from "./Bindings/BindingHandlersRegisterer"
|
|||||||
import Explorer from "./Explorer/Explorer";
|
import Explorer from "./Explorer/Explorer";
|
||||||
|
|
||||||
export const applyExplorerBindings = (explorer: Explorer) => {
|
export const applyExplorerBindings = (explorer: Explorer) => {
|
||||||
if (!!explorer) {
|
if (explorer) {
|
||||||
window.dataExplorer = explorer;
|
window.dataExplorer = explorer;
|
||||||
BindingHandlersRegisterer.registerBindingHandlers();
|
BindingHandlersRegisterer.registerBindingHandlers();
|
||||||
ko.applyBindings(explorer);
|
ko.applyBindings(explorer);
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { GenerateTokenResponse } from "../Contracts/DataModels";
|
import { GenerateTokenResponse } from "../Contracts/DataModels";
|
||||||
import * as AuthHeadersUtil from "../Platform/Hosted/Authorization";
|
import AuthHeadersUtil from "../Platform/Hosted/Authorization";
|
||||||
|
|
||||||
export function useFullScreenURLs(): GenerateTokenResponse | undefined {
|
export function useFullScreenURLs(): GenerateTokenResponse | undefined {
|
||||||
const [state, setState] = useState<GenerateTokenResponse>();
|
const [state, setState] = useState<GenerateTokenResponse>();
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ import {
|
|||||||
getDatabaseAccountPropertiesFromMetadata,
|
getDatabaseAccountPropertiesFromMetadata,
|
||||||
} from "../Platform/Hosted/HostedUtils";
|
} from "../Platform/Hosted/HostedUtils";
|
||||||
import { CollectionCreation } from "../Shared/Constants";
|
import { CollectionCreation } from "../Shared/Constants";
|
||||||
import * as DefaultExperienceUtility from "../Shared/DefaultExperienceUtility";
|
import { DefaultExperienceUtility } from "../Shared/DefaultExperienceUtility";
|
||||||
import { PortalEnv, updateUserContext, userContext } from "../UserContext";
|
import { PortalEnv, updateUserContext, userContext } from "../UserContext";
|
||||||
import { listKeys } from "../Utils/arm/generatedClients/cosmos/databaseAccounts";
|
import { listKeys } from "../Utils/arm/generatedClients/cosmos/databaseAccounts";
|
||||||
import { DatabaseAccountListKeysResult } from "../Utils/arm/generatedClients/cosmos/types";
|
import { DatabaseAccountListKeysResult } from "../Utils/arm/generatedClients/cosmos/types";
|
||||||
|
|||||||
Reference in New Issue
Block a user