mirror of
https://github.com/Azure/cosmos-explorer.git
synced 2025-12-20 17:30:46 +00:00
Resolve conflict
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
**/node_modules/
|
**/node_modules/
|
||||||
|
src/**/__mocks__/**/*
|
||||||
dist/
|
dist/
|
||||||
Contracts/
|
Contracts/
|
||||||
src/Api/Apis.ts
|
src/Api/Apis.ts
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ module.exports = {
|
|||||||
},
|
},
|
||||||
parser: "@typescript-eslint/parser",
|
parser: "@typescript-eslint/parser",
|
||||||
parserOptions: {
|
parserOptions: {
|
||||||
|
project: ["./tsconfig.json", "./tsconfig.test.json"],
|
||||||
ecmaFeatures: {
|
ecmaFeatures: {
|
||||||
jsx: true,
|
jsx: true,
|
||||||
},
|
},
|
||||||
@@ -35,6 +36,7 @@ module.exports = {
|
|||||||
rules: {
|
rules: {
|
||||||
"no-console": ["error", { allow: ["error", "warn", "dir"] }],
|
"no-console": ["error", { allow: ["error", "warn", "dir"] }],
|
||||||
curly: "error",
|
curly: "error",
|
||||||
|
"@typescript-eslint/switch-exhaustiveness-check": "error",
|
||||||
"@typescript-eslint/no-unused-vars": "error",
|
"@typescript-eslint/no-unused-vars": "error",
|
||||||
"@typescript-eslint/no-extraneous-class": "error",
|
"@typescript-eslint/no-extraneous-class": "error",
|
||||||
"no-null/no-null": "error",
|
"no-null/no-null": "error",
|
||||||
|
|||||||
1
.github/workflows/ci.yml
vendored
1
.github/workflows/ci.yml
vendored
@@ -138,6 +138,7 @@ jobs:
|
|||||||
matrix:
|
matrix:
|
||||||
test-file:
|
test-file:
|
||||||
- ./test/cassandra/container.spec.ts
|
- ./test/cassandra/container.spec.ts
|
||||||
|
- ./test/graph/container.spec.ts
|
||||||
- ./test/sql/container.spec.ts
|
- ./test/sql/container.spec.ts
|
||||||
- ./test/mongo/container.spec.ts
|
- ./test/mongo/container.spec.ts
|
||||||
- ./test/selfServe/selfServeExample.spec.ts
|
- ./test/selfServe/selfServeExample.spec.ts
|
||||||
|
|||||||
30730
package-lock.json
generated
30730
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -130,8 +130,8 @@
|
|||||||
"@types/sinon": "2.3.3",
|
"@types/sinon": "2.3.3",
|
||||||
"@types/styled-components": "5.1.1",
|
"@types/styled-components": "5.1.1",
|
||||||
"@types/underscore": "1.7.36",
|
"@types/underscore": "1.7.36",
|
||||||
"@typescript-eslint/eslint-plugin": "4.0.1",
|
"@typescript-eslint/eslint-plugin": "4.22.0",
|
||||||
"@typescript-eslint/parser": "4.0.1",
|
"@typescript-eslint/parser": "4.22.0",
|
||||||
"babel-jest": "24.9.0",
|
"babel-jest": "24.9.0",
|
||||||
"babel-loader": "8.1.0",
|
"babel-loader": "8.1.0",
|
||||||
"buffer": "5.1.0",
|
"buffer": "5.1.0",
|
||||||
@@ -193,7 +193,7 @@
|
|||||||
"pack:fast": "node --max_old_space_size=10196 ./node_modules/webpack/bin/webpack.js --mode development --progress",
|
"pack:fast": "node --max_old_space_size=10196 ./node_modules/webpack/bin/webpack.js --mode development --progress",
|
||||||
"copyToConsumers": "node copyToConsumers",
|
"copyToConsumers": "node copyToConsumers",
|
||||||
"test": "rimraf coverage && jest",
|
"test": "rimraf coverage && jest",
|
||||||
"test:e2e": "jest -c ./jest.config.e2e.js --detectOpenHandles",
|
"test:e2e": "jest -c ./jest.config.playwright.js --detectOpenHandles",
|
||||||
"watch": "npm run start",
|
"watch": "npm run start",
|
||||||
"wait-for-server": "wait-on -t 240000 -i 5000 -v https-get://0.0.0.0:1234/",
|
"wait-for-server": "wait-on -t 240000 -i 5000 -v https-get://0.0.0.0:1234/",
|
||||||
"build:ase": "gulp build:ase",
|
"build:ase": "gulp build:ase",
|
||||||
|
|||||||
10
src/CellOutputViewer/CellOutputViewer.less
Normal file
10
src/CellOutputViewer/CellOutputViewer.less
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
.schema-analyzer-cell-outputs {
|
||||||
|
padding: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.schema-analyzer-cell-output {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
padding: 10px;
|
||||||
|
border-radius: 2px;
|
||||||
|
box-shadow: rgba(0, 0, 0, 13%) 0px 1.6px 3.6px 0px, rgba(0, 0, 0, 11%) 0px 0.3px 0.9px 0px;
|
||||||
|
}
|
||||||
@@ -11,13 +11,14 @@ import * as ReactDOM from "react-dom";
|
|||||||
import "../../externals/iframeResizer.contentWindow.min.js"; // Required for iFrameResizer to work
|
import "../../externals/iframeResizer.contentWindow.min.js"; // Required for iFrameResizer to work
|
||||||
import "../Explorer/Notebook/NotebookRenderer/base.css";
|
import "../Explorer/Notebook/NotebookRenderer/base.css";
|
||||||
import "../Explorer/Notebook/NotebookRenderer/default.css";
|
import "../Explorer/Notebook/NotebookRenderer/default.css";
|
||||||
|
import "./CellOutputViewer.less";
|
||||||
import { TransformMedia } from "./TransformMedia";
|
import { TransformMedia } from "./TransformMedia";
|
||||||
|
|
||||||
export interface CellOutputViewerProps {
|
export interface CellOutputViewerProps {
|
||||||
id: string;
|
id: string;
|
||||||
contentRef: ContentRef;
|
contentRef: ContentRef;
|
||||||
hidden: boolean;
|
outputsContainerClassName: string;
|
||||||
expanded: boolean;
|
outputClassName: string;
|
||||||
outputs: OnDiskOutput[];
|
outputs: OnDiskOutput[];
|
||||||
onMetadataChange: (metadata: JSONObject, mediaType: string, index?: number) => void;
|
onMetadataChange: (metadata: JSONObject, mediaType: string, index?: number) => void;
|
||||||
}
|
}
|
||||||
@@ -34,27 +35,26 @@ const onInit = async () => {
|
|||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
const props = (event as any).data as CellOutputViewerProps;
|
const props = (event as any).data as CellOutputViewerProps;
|
||||||
const outputs = (
|
const outputs = (
|
||||||
<div
|
<div data-iframe-height className={props.outputsContainerClassName}>
|
||||||
data-iframe-height
|
|
||||||
className={`nteract-cell-outputs ${props.hidden ? "hidden" : ""} ${props.expanded ? "expanded" : ""}`}
|
|
||||||
>
|
|
||||||
{props.outputs?.map((output, index) => (
|
{props.outputs?.map((output, index) => (
|
||||||
<Output output={createImmutableOutput(output)} key={index}>
|
<div className={props.outputClassName} key={index}>
|
||||||
<TransformMedia
|
<Output output={createImmutableOutput(output)} key={index}>
|
||||||
output_type={"display_data"}
|
<TransformMedia
|
||||||
id={props.id}
|
output_type={"display_data"}
|
||||||
contentRef={props.contentRef}
|
id={props.id}
|
||||||
onMetadataChange={(metadata, mediaType) => props.onMetadataChange(metadata, mediaType, index)}
|
contentRef={props.contentRef}
|
||||||
/>
|
onMetadataChange={(metadata, mediaType) => props.onMetadataChange(metadata, mediaType, index)}
|
||||||
<TransformMedia
|
/>
|
||||||
output_type={"execute_result"}
|
<TransformMedia
|
||||||
id={props.id}
|
output_type={"execute_result"}
|
||||||
contentRef={props.contentRef}
|
id={props.id}
|
||||||
onMetadataChange={(metadata, mediaType) => props.onMetadataChange(metadata, mediaType, index)}
|
contentRef={props.contentRef}
|
||||||
/>
|
onMetadataChange={(metadata, mediaType) => props.onMetadataChange(metadata, mediaType, index)}
|
||||||
<KernelOutputError />
|
/>
|
||||||
<StreamText />
|
<KernelOutputError />
|
||||||
</Output>
|
<StreamText />
|
||||||
|
</Output>
|
||||||
|
</div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -65,28 +65,18 @@ export class ClientDefaults {
|
|||||||
public static readonly arcadiaTokenRefreshIntervalPaddingMs: number = 2000;
|
public static readonly arcadiaTokenRefreshIntervalPaddingMs: number = 2000;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class AccountKind {
|
export enum AccountKind {
|
||||||
public static DocumentDB: string = "DocumentDB";
|
DocumentDB = "DocumentDB",
|
||||||
public static MongoDB: string = "MongoDB";
|
MongoDB = "MongoDB",
|
||||||
public static Parse: string = "Parse";
|
Parse = "Parse",
|
||||||
public static GlobalDocumentDB: string = "GlobalDocumentDB";
|
GlobalDocumentDB = "GlobalDocumentDB",
|
||||||
public static Default: string = AccountKind.DocumentDB;
|
Default = "DocumentDB",
|
||||||
}
|
}
|
||||||
|
|
||||||
export class CorrelationBackend {
|
export class CorrelationBackend {
|
||||||
public static Url: string = "https://aka.ms/cosmosdbanalytics";
|
public static Url: string = "https://aka.ms/cosmosdbanalytics";
|
||||||
}
|
}
|
||||||
|
|
||||||
export class DefaultAccountExperience {
|
|
||||||
public static DocumentDB: string = "DocumentDB";
|
|
||||||
public static Graph: string = "Graph";
|
|
||||||
public static MongoDB: string = "MongoDB";
|
|
||||||
public static ApiForMongoDB: string = "Azure Cosmos DB for MongoDB API";
|
|
||||||
public static Table: string = "Table";
|
|
||||||
public static Cassandra: string = "Cassandra";
|
|
||||||
public static Default: string = DefaultAccountExperience.DocumentDB;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class CapabilityNames {
|
export class CapabilityNames {
|
||||||
public static EnableTable: string = "EnableTable";
|
public static EnableTable: string = "EnableTable";
|
||||||
public static EnableGremlin: string = "EnableGremlin";
|
public static EnableGremlin: string = "EnableGremlin";
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { ResourceType } from "@azure/cosmos/dist-esm/common/constants";
|
import { ResourceType } from "@azure/cosmos/dist-esm/common/constants";
|
||||||
import { configContext, Platform, updateConfigContext, resetConfigContext } from "../ConfigContext";
|
import { Platform, resetConfigContext, updateConfigContext } from "../ConfigContext";
|
||||||
import { updateUserContext } from "../UserContext";
|
import { updateUserContext } from "../UserContext";
|
||||||
import { endpoint, getTokenFromAuthService, requestPlugin, tokenProvider } from "./CosmosClient";
|
import { endpoint, getTokenFromAuthService, requestPlugin, tokenProvider } from "./CosmosClient";
|
||||||
|
|
||||||
@@ -91,7 +91,6 @@ describe("endpoint", () => {
|
|||||||
location: "foo",
|
location: "foo",
|
||||||
type: "foo",
|
type: "foo",
|
||||||
kind: "foo",
|
kind: "foo",
|
||||||
tags: [],
|
|
||||||
properties: {
|
properties: {
|
||||||
documentEndpoint: "bar",
|
documentEndpoint: "bar",
|
||||||
gremlinEndpoint: "foo",
|
gremlinEndpoint: "foo",
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ export interface DatabaseAccount {
|
|||||||
location: string;
|
location: string;
|
||||||
type: string;
|
type: string;
|
||||||
kind: string;
|
kind: string;
|
||||||
tags: any;
|
|
||||||
properties: DatabaseAccountExtendedProperties;
|
properties: DatabaseAccountExtendedProperties;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ const createTestDatabaseAccount = (): DataModels.DatabaseAccount => {
|
|||||||
gremlinEndpoint: null,
|
gremlinEndpoint: null,
|
||||||
tableEndpoint: null,
|
tableEndpoint: null,
|
||||||
},
|
},
|
||||||
tags: "testTags",
|
|
||||||
type: "testType",
|
type: "testType",
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@@ -30,7 +29,6 @@ const createTestMongo32DatabaseAccount = (): DataModels.DatabaseAccount => {
|
|||||||
gremlinEndpoint: null,
|
gremlinEndpoint: null,
|
||||||
tableEndpoint: null,
|
tableEndpoint: null,
|
||||||
},
|
},
|
||||||
tags: "testTags",
|
|
||||||
type: "testType",
|
type: "testType",
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@@ -48,7 +46,6 @@ const createTestMongo36DatabaseAccount = (): DataModels.DatabaseAccount => {
|
|||||||
tableEndpoint: null,
|
tableEndpoint: null,
|
||||||
mongoEndpoint: "https://testMongoEndpoint.azure.com/",
|
mongoEndpoint: "https://testMongoEndpoint.azure.com/",
|
||||||
},
|
},
|
||||||
tags: "testTags",
|
|
||||||
type: "testType",
|
type: "testType",
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@@ -65,7 +62,6 @@ const createTestCassandraDatabaseAccount = (): DataModels.DatabaseAccount => {
|
|||||||
gremlinEndpoint: null,
|
gremlinEndpoint: null,
|
||||||
tableEndpoint: null,
|
tableEndpoint: null,
|
||||||
},
|
},
|
||||||
tags: "testTags",
|
|
||||||
type: "testType",
|
type: "testType",
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
import { shallow } from "enzyme";
|
import { shallow } from "enzyme";
|
||||||
|
import ko from "knockout";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { ScaleComponent, ScaleComponentProps } from "./ScaleComponent";
|
|
||||||
import { container, collection } from "../TestUtils";
|
|
||||||
import { ThroughputInputAutoPilotV3Component } from "./ThroughputInputComponents/ThroughputInputAutoPilotV3Component";
|
|
||||||
import Explorer from "../../../Explorer";
|
|
||||||
import * as Constants from "../../../../Common/Constants";
|
import * as Constants from "../../../../Common/Constants";
|
||||||
import * as DataModels from "../../../../Contracts/DataModels";
|
import * as DataModels from "../../../../Contracts/DataModels";
|
||||||
import { throughputUnit } from "../SettingsRenderUtils";
|
|
||||||
import * as SharedConstants from "../../../../Shared/Constants";
|
import * as SharedConstants from "../../../../Shared/Constants";
|
||||||
import ko from "knockout";
|
import Explorer from "../../../Explorer";
|
||||||
|
import { throughputUnit } from "../SettingsRenderUtils";
|
||||||
|
import { collection, container } from "../TestUtils";
|
||||||
|
import { ScaleComponent, ScaleComponentProps } from "./ScaleComponent";
|
||||||
|
import { ThroughputInputAutoPilotV3Component } from "./ThroughputInputComponents/ThroughputInputAutoPilotV3Component";
|
||||||
|
|
||||||
describe("ScaleComponent", () => {
|
describe("ScaleComponent", () => {
|
||||||
const nonNationalCloudContainer = new Explorer();
|
const nonNationalCloudContainer = new Explorer();
|
||||||
@@ -87,7 +87,6 @@ describe("ScaleComponent", () => {
|
|||||||
location: undefined,
|
location: undefined,
|
||||||
type: undefined,
|
type: undefined,
|
||||||
kind: "documentdb",
|
kind: "documentdb",
|
||||||
tags: undefined,
|
|
||||||
properties: {
|
properties: {
|
||||||
documentEndpoint: undefined,
|
documentEndpoint: undefined,
|
||||||
tableEndpoint: undefined,
|
tableEndpoint: undefined,
|
||||||
|
|||||||
@@ -424,7 +424,6 @@ exports[`SettingsComponent renders 1`] = `
|
|||||||
},
|
},
|
||||||
"databaseAccount": [Function],
|
"databaseAccount": [Function],
|
||||||
"databases": [Function],
|
"databases": [Function],
|
||||||
"defaultExperience": [Function],
|
|
||||||
"deleteCollectionText": [Function],
|
"deleteCollectionText": [Function],
|
||||||
"deleteDatabaseText": [Function],
|
"deleteDatabaseText": [Function],
|
||||||
"gitHubClient": GitHubClient {
|
"gitHubClient": GitHubClient {
|
||||||
@@ -1710,7 +1709,6 @@ exports[`SettingsComponent renders 1`] = `
|
|||||||
},
|
},
|
||||||
"databaseAccount": [Function],
|
"databaseAccount": [Function],
|
||||||
"databases": [Function],
|
"databases": [Function],
|
||||||
"defaultExperience": [Function],
|
|
||||||
"deleteCollectionText": [Function],
|
"deleteCollectionText": [Function],
|
||||||
"deleteDatabaseText": [Function],
|
"deleteDatabaseText": [Function],
|
||||||
"gitHubClient": GitHubClient {
|
"gitHubClient": GitHubClient {
|
||||||
@@ -3009,7 +3007,6 @@ exports[`SettingsComponent renders 1`] = `
|
|||||||
},
|
},
|
||||||
"databaseAccount": [Function],
|
"databaseAccount": [Function],
|
||||||
"databases": [Function],
|
"databases": [Function],
|
||||||
"defaultExperience": [Function],
|
|
||||||
"deleteCollectionText": [Function],
|
"deleteCollectionText": [Function],
|
||||||
"deleteDatabaseText": [Function],
|
"deleteDatabaseText": [Function],
|
||||||
"gitHubClient": GitHubClient {
|
"gitHubClient": GitHubClient {
|
||||||
@@ -4295,7 +4292,6 @@ exports[`SettingsComponent renders 1`] = `
|
|||||||
},
|
},
|
||||||
"databaseAccount": [Function],
|
"databaseAccount": [Function],
|
||||||
"databases": [Function],
|
"databases": [Function],
|
||||||
"defaultExperience": [Function],
|
|
||||||
"deleteCollectionText": [Function],
|
"deleteCollectionText": [Function],
|
||||||
"deleteDatabaseText": [Function],
|
"deleteDatabaseText": [Function],
|
||||||
"gitHubClient": GitHubClient {
|
"gitHubClient": GitHubClient {
|
||||||
|
|||||||
@@ -79,7 +79,6 @@ describe("ContainerSampleGenerator", () => {
|
|||||||
location: "foo",
|
location: "foo",
|
||||||
type: "foo",
|
type: "foo",
|
||||||
kind: "foo",
|
kind: "foo",
|
||||||
tags: [],
|
|
||||||
properties: {
|
properties: {
|
||||||
documentEndpoint: "bar",
|
documentEndpoint: "bar",
|
||||||
gremlinEndpoint: "foo",
|
gremlinEndpoint: "foo",
|
||||||
|
|||||||
@@ -116,11 +116,6 @@ export default class Explorer {
|
|||||||
* */
|
* */
|
||||||
public databaseAccount: ko.Observable<DataModels.DatabaseAccount>;
|
public databaseAccount: ko.Observable<DataModels.DatabaseAccount>;
|
||||||
public collectionCreationDefaults: ViewModels.CollectionCreationDefaults = SharedConstants.CollectionCreationDefaults;
|
public collectionCreationDefaults: ViewModels.CollectionCreationDefaults = SharedConstants.CollectionCreationDefaults;
|
||||||
/**
|
|
||||||
* @deprecated
|
|
||||||
* Use userContext.apiType instead
|
|
||||||
* */
|
|
||||||
public defaultExperience: ko.Observable<string>;
|
|
||||||
public isFixedCollectionWithSharedThroughputSupported: ko.Computed<boolean>;
|
public isFixedCollectionWithSharedThroughputSupported: ko.Computed<boolean>;
|
||||||
/**
|
/**
|
||||||
* @deprecated
|
* @deprecated
|
||||||
@@ -377,17 +372,6 @@ export default class Explorer {
|
|||||||
bounds: splitterBounds,
|
bounds: splitterBounds,
|
||||||
direction: SplitterDirection.Vertical,
|
direction: SplitterDirection.Vertical,
|
||||||
});
|
});
|
||||||
this.defaultExperience = ko.observable<string>();
|
|
||||||
// this.databaseAccount.subscribe((databaseAccount) => {
|
|
||||||
// const defaultExperience: string = DefaultExperienceUtility.getDefaultExperienceFromDatabaseAccount(
|
|
||||||
// databaseAccount
|
|
||||||
// );
|
|
||||||
// this.defaultExperience(defaultExperience);
|
|
||||||
// // TODO. Remove this entirely
|
|
||||||
// updateUserContext({
|
|
||||||
// apiType: DefaultExperienceUtility.mapDefaultExperienceStringToEnum(defaultExperience),
|
|
||||||
// });
|
|
||||||
// });
|
|
||||||
|
|
||||||
this.isFixedCollectionWithSharedThroughputSupported = ko.computed(() => {
|
this.isFixedCollectionWithSharedThroughputSupported = ko.computed(() => {
|
||||||
if (userContext.features.enableFixedCollectionWithSharedThroughput) {
|
if (userContext.features.enableFixedCollectionWithSharedThroughput) {
|
||||||
@@ -1644,7 +1628,9 @@ export default class Explorer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const databaseAccount = this.databaseAccount();
|
const databaseAccount = this.databaseAccount();
|
||||||
const databaseAccountLocation = databaseAccount && databaseAccount.location.toLowerCase();
|
const firstWriteLocation =
|
||||||
|
databaseAccount?.properties?.writeLocations &&
|
||||||
|
databaseAccount?.properties?.writeLocations[0]?.locationName.toLowerCase();
|
||||||
const disallowedLocationsUri = `${configContext.BACKEND_ENDPOINT}/api/disallowedLocations`;
|
const disallowedLocationsUri = `${configContext.BACKEND_ENDPOINT}/api/disallowedLocations`;
|
||||||
const authorizationHeader = getAuthorizationHeader();
|
const authorizationHeader = getAuthorizationHeader();
|
||||||
try {
|
try {
|
||||||
@@ -1669,9 +1655,9 @@ export default class Explorer {
|
|||||||
this.isNotebooksEnabledForAccount(true);
|
this.isNotebooksEnabledForAccount(true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const isAccountInAllowedLocation = !disallowedLocations.some(
|
|
||||||
(disallowedLocation) => disallowedLocation === databaseAccountLocation
|
// firstWriteLocation should not be disallowed
|
||||||
);
|
const isAccountInAllowedLocation = firstWriteLocation && disallowedLocations.indexOf(firstWriteLocation) === -1;
|
||||||
this.isNotebooksEnabledForAccount(isAccountInAllowedLocation);
|
this.isNotebooksEnabledForAccount(isAccountInAllowedLocation);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
Logger.logError(getErrorMessage(error), "Explorer/isNotebooksEnabledForAccount");
|
Logger.logError(getErrorMessage(error), "Explorer/isNotebooksEnabledForAccount");
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { actions, ContentRef } from "@nteract/core";
|
import { actions, ContentRef } from "@nteract/core";
|
||||||
import { Cells, CodeCell, MarkdownCell, RawCell } from "@nteract/stateful-components";
|
import { Cells, CodeCell, RawCell } from "@nteract/stateful-components";
|
||||||
import MonacoEditor from "@nteract/stateful-components/lib/inputs/connected-editors/monacoEditor";
|
import MonacoEditor from "@nteract/stateful-components/lib/inputs/connected-editors/monacoEditor";
|
||||||
import { PassedEditorProps } from "@nteract/stateful-components/lib/inputs/editor";
|
import { PassedEditorProps } from "@nteract/stateful-components/lib/inputs/editor";
|
||||||
import Prompt, { PassedPromptProps } from "@nteract/stateful-components/lib/inputs/prompt";
|
import Prompt, { PassedPromptProps } from "@nteract/stateful-components/lib/inputs/prompt";
|
||||||
@@ -11,6 +11,7 @@ import loadTransform from "../NotebookComponent/loadTransform";
|
|||||||
import { AzureTheme } from "./AzureTheme";
|
import { AzureTheme } from "./AzureTheme";
|
||||||
import "./base.css";
|
import "./base.css";
|
||||||
import "./default.css";
|
import "./default.css";
|
||||||
|
import MarkdownCell from "./markdown-cell";
|
||||||
import "./NotebookReadOnlyRenderer.less";
|
import "./NotebookReadOnlyRenderer.less";
|
||||||
import SandboxOutputs from "./outputs/SandboxOutputs";
|
import SandboxOutputs from "./outputs/SandboxOutputs";
|
||||||
|
|
||||||
|
|||||||
@@ -15,6 +15,8 @@ import { CellOutputViewerProps } from "../../../../CellOutputViewer/CellOutputVi
|
|||||||
interface ComponentProps {
|
interface ComponentProps {
|
||||||
id: string;
|
id: string;
|
||||||
contentRef: ContentRef;
|
contentRef: ContentRef;
|
||||||
|
outputsContainerClassName?: string;
|
||||||
|
outputClassName?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface StateProps {
|
interface StateProps {
|
||||||
@@ -59,8 +61,10 @@ export class SandboxOutputs extends React.PureComponent<ComponentProps & StatePr
|
|||||||
const props: CellOutputViewerProps = {
|
const props: CellOutputViewerProps = {
|
||||||
id: this.props.id,
|
id: this.props.id,
|
||||||
contentRef: this.props.contentRef,
|
contentRef: this.props.contentRef,
|
||||||
hidden: this.props.hidden,
|
outputsContainerClassName: `nteract-cell-outputs ${this.props.hidden ? "hidden" : ""} ${
|
||||||
expanded: this.props.expanded,
|
this.props.expanded ? "expanded" : ""
|
||||||
|
} ${this.props.outputsContainerClassName}`,
|
||||||
|
outputClassName: this.props.outputClassName,
|
||||||
outputs: this.props.outputs.toArray().map((output) => outputToJS(output)),
|
outputs: this.props.outputs.toArray().map((output) => outputToJS(output)),
|
||||||
onMetadataChange: this.props.onMetadataChange,
|
onMetadataChange: this.props.onMetadataChange,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,10 +1,5 @@
|
|||||||
.shemaAnalyzerComponent {
|
.schemaAnalyzerComponent {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.schemaAnalyzerCard {
|
|
||||||
max-width: 4096px;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
@@ -1,14 +1,12 @@
|
|||||||
import { ImmutableOutput } from "@nteract/commutable";
|
import { ImmutableOutput } from "@nteract/commutable";
|
||||||
import { actions, AppState, ContentRef, KernelRef, selectors } from "@nteract/core";
|
import { actions, AppState, ContentRef, KernelRef, selectors } from "@nteract/core";
|
||||||
import { KernelOutputError, Output, StreamText } from "@nteract/outputs";
|
|
||||||
import TransformMedia from "@nteract/stateful-components/lib/outputs/transform-media";
|
|
||||||
import { Card } from "@uifabric/react-cards";
|
|
||||||
import Immutable from "immutable";
|
import Immutable from "immutable";
|
||||||
import { FontIcon, PrimaryButton, Spinner, SpinnerSize, Stack, Text, TextField } from "office-ui-fabric-react";
|
import { FontIcon, PrimaryButton, Spinner, SpinnerSize, Stack, Text, TextField } from "office-ui-fabric-react";
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import { connect } from "react-redux";
|
import { connect } from "react-redux";
|
||||||
import { Dispatch } from "redux";
|
import { Dispatch } from "redux";
|
||||||
import loadTransform from "../NotebookComponent/loadTransform";
|
import loadTransform from "../NotebookComponent/loadTransform";
|
||||||
|
import SandboxOutputs from "../NotebookRenderer/outputs/SandboxOutputs";
|
||||||
import "./SchemaAnalyzerComponent.less";
|
import "./SchemaAnalyzerComponent.less";
|
||||||
|
|
||||||
interface SchemaAnalyzerComponentPureProps {
|
interface SchemaAnalyzerComponentPureProps {
|
||||||
@@ -91,70 +89,66 @@ export class SchemaAnalyzerComponent extends React.Component<
|
|||||||
const showSchemaOutput = isKernelIdle && outputs.size > 0;
|
const showSchemaOutput = isKernelIdle && outputs.size > 0;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Stack className="schemaAnalyzerComponent" horizontalAlign="center" tokens={{ childrenGap: 20, padding: 20 }}>
|
<div className="schemaAnalyzerComponent">
|
||||||
<Stack.Item grow styles={{ root: { display: "contents" } }}>
|
<Stack horizontalAlign="center" tokens={{ childrenGap: 20, padding: 20 }}>
|
||||||
<Stack horizontal tokens={{ childrenGap: 20 }} styles={{ root: { width: "100%" } }}>
|
<Stack.Item grow styles={{ root: { display: "contents" } }}>
|
||||||
<Stack.Item grow align="end">
|
<Stack horizontal tokens={{ childrenGap: 20 }} styles={{ root: { width: "100%" } }}>
|
||||||
<TextField
|
<Stack.Item grow align="end">
|
||||||
value={this.state.filter}
|
<TextField
|
||||||
onChange={this.onFilterTextFieldChange}
|
value={this.state.filter}
|
||||||
label="Filter"
|
onChange={this.onFilterTextFieldChange}
|
||||||
placeholder="{ field: 'value' }"
|
label="Filter"
|
||||||
disabled={!isKernelIdle}
|
placeholder="{ field: 'value' }"
|
||||||
/>
|
disabled={!isKernelIdle}
|
||||||
</Stack.Item>
|
/>
|
||||||
<Stack.Item align="end">
|
</Stack.Item>
|
||||||
<PrimaryButton
|
<Stack.Item align="end">
|
||||||
text={isKernelBusy ? "Analyzing..." : "Analyze"}
|
<PrimaryButton
|
||||||
onClick={this.onAnalyzeButtonClick}
|
text={isKernelBusy ? "Analyzing..." : "Analyze"}
|
||||||
disabled={!isKernelIdle}
|
onClick={this.onAnalyzeButtonClick}
|
||||||
/>
|
disabled={!isKernelIdle}
|
||||||
</Stack.Item>
|
/>
|
||||||
</Stack>
|
</Stack.Item>
|
||||||
</Stack.Item>
|
</Stack>
|
||||||
|
|
||||||
{showSchemaOutput ? (
|
|
||||||
outputs.map((output, index) => (
|
|
||||||
<Card className="schemaAnalyzerCard" key={index}>
|
|
||||||
<Card.Item tokens={{ padding: 10 }}>
|
|
||||||
<Output output={output}>
|
|
||||||
<TransformMedia output_type={"display_data"} id={id} contentRef={contentRef} />
|
|
||||||
<TransformMedia output_type={"execute_result"} id={id} contentRef={contentRef} />
|
|
||||||
<KernelOutputError />
|
|
||||||
<StreamText />
|
|
||||||
</Output>
|
|
||||||
</Card.Item>
|
|
||||||
</Card>
|
|
||||||
))
|
|
||||||
) : this.state.isFiltering ? (
|
|
||||||
<Stack.Item>
|
|
||||||
{isKernelBusy && <Spinner styles={{ root: { marginTop: 40 } }} size={SpinnerSize.large} />}
|
|
||||||
</Stack.Item>
|
</Stack.Item>
|
||||||
) : (
|
|
||||||
<>
|
{showSchemaOutput ? (
|
||||||
|
<SandboxOutputs
|
||||||
|
id={id}
|
||||||
|
contentRef={contentRef}
|
||||||
|
outputsContainerClassName="schema-analyzer-cell-outputs"
|
||||||
|
outputClassName="schema-analyzer-cell-output"
|
||||||
|
/>
|
||||||
|
) : this.state.isFiltering ? (
|
||||||
<Stack.Item>
|
<Stack.Item>
|
||||||
<FontIcon iconName="Chart" style={{ fontSize: 100, color: "#43B1E5", marginTop: 40 }} />
|
{isKernelBusy && <Spinner styles={{ root: { marginTop: 40 } }} size={SpinnerSize.large} />}
|
||||||
</Stack.Item>
|
</Stack.Item>
|
||||||
<Stack.Item>
|
) : (
|
||||||
<Text variant="xxLarge">Explore your schema</Text>
|
<>
|
||||||
</Stack.Item>
|
<Stack.Item>
|
||||||
<Stack.Item>
|
<FontIcon iconName="Chart" style={{ fontSize: 100, color: "#43B1E5", marginTop: 40 }} />
|
||||||
<Text variant="large">
|
</Stack.Item>
|
||||||
Quickly visualize your schema to infer the frequency, types and ranges of fields in your data set.
|
<Stack.Item>
|
||||||
</Text>
|
<Text variant="xxLarge">Explore your schema</Text>
|
||||||
</Stack.Item>
|
</Stack.Item>
|
||||||
<Stack.Item>
|
<Stack.Item>
|
||||||
<PrimaryButton
|
<Text variant="large">
|
||||||
styles={{ root: { fontSize: 18, padding: 30 } }}
|
Quickly visualize your schema to infer the frequency, types and ranges of fields in your data set.
|
||||||
text={isKernelBusy ? "Analyzing..." : "Analyze Schema"}
|
</Text>
|
||||||
onClick={this.onAnalyzeButtonClick}
|
</Stack.Item>
|
||||||
disabled={kernelStatus !== "idle"}
|
<Stack.Item>
|
||||||
/>
|
<PrimaryButton
|
||||||
</Stack.Item>
|
styles={{ root: { fontSize: 18, padding: 30 } }}
|
||||||
<Stack.Item>{isKernelBusy && <Spinner size={SpinnerSize.large} />}</Stack.Item>
|
text={isKernelBusy ? "Analyzing..." : "Analyze Schema"}
|
||||||
</>
|
onClick={this.onAnalyzeButtonClick}
|
||||||
)}
|
disabled={kernelStatus !== "idle"}
|
||||||
</Stack>
|
/>
|
||||||
|
</Stack.Item>
|
||||||
|
<Stack.Item>{isKernelBusy && <Spinner size={SpinnerSize.large} />}</Stack.Item>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</Stack>
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,6 @@ describe("Add Collection Pane", () => {
|
|||||||
enableFreeTier: false,
|
enableFreeTier: false,
|
||||||
},
|
},
|
||||||
type: undefined,
|
type: undefined,
|
||||||
tags: [],
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const mockFreeTierDatabaseAccount: DatabaseAccount = {
|
const mockFreeTierDatabaseAccount: DatabaseAccount = {
|
||||||
@@ -36,7 +35,6 @@ describe("Add Collection Pane", () => {
|
|||||||
enableFreeTier: true,
|
enableFreeTier: true,
|
||||||
},
|
},
|
||||||
type: undefined,
|
type: undefined,
|
||||||
tags: [],
|
|
||||||
};
|
};
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
@@ -44,7 +42,13 @@ describe("Add Collection Pane", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("should be true if graph API and partition key is not /id nor /label", () => {
|
it("should be true if graph API and partition key is not /id nor /label", () => {
|
||||||
explorer.defaultExperience(Constants.DefaultAccountExperience.Graph.toLowerCase());
|
updateUserContext({
|
||||||
|
databaseAccount: {
|
||||||
|
properties: {
|
||||||
|
capabilities: [{ name: "EnableGremlin" }],
|
||||||
|
},
|
||||||
|
} as DatabaseAccount,
|
||||||
|
});
|
||||||
const addCollectionPane = explorer.addCollectionPane as AddCollectionPane;
|
const addCollectionPane = explorer.addCollectionPane as AddCollectionPane;
|
||||||
addCollectionPane.partitionKey("/blah");
|
addCollectionPane.partitionKey("/blah");
|
||||||
expect(addCollectionPane.isValid()).toBe(true);
|
expect(addCollectionPane.isValid()).toBe(true);
|
||||||
@@ -58,7 +62,6 @@ describe("Add Collection Pane", () => {
|
|||||||
},
|
},
|
||||||
} as DatabaseAccount,
|
} as DatabaseAccount,
|
||||||
});
|
});
|
||||||
|
|
||||||
const addCollectionPane = explorer.addCollectionPane as AddCollectionPane;
|
const addCollectionPane = explorer.addCollectionPane as AddCollectionPane;
|
||||||
addCollectionPane.partitionKey("/id");
|
addCollectionPane.partitionKey("/id");
|
||||||
expect(addCollectionPane.isValid()).toBe(false);
|
expect(addCollectionPane.isValid()).toBe(false);
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ describe("Add Database Pane", () => {
|
|||||||
enableFreeTier: false,
|
enableFreeTier: false,
|
||||||
},
|
},
|
||||||
type: undefined,
|
type: undefined,
|
||||||
tags: [],
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const mockFreeTierDatabaseAccount: DatabaseAccount = {
|
const mockFreeTierDatabaseAccount: DatabaseAccount = {
|
||||||
@@ -37,7 +36,6 @@ describe("Add Database Pane", () => {
|
|||||||
enableFreeTier: true,
|
enableFreeTier: true,
|
||||||
},
|
},
|
||||||
type: undefined,
|
type: undefined,
|
||||||
tags: [],
|
|
||||||
};
|
};
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
|
|||||||
@@ -413,7 +413,6 @@ exports[`GitHub Repos Panel should render Default properly 1`] = `
|
|||||||
},
|
},
|
||||||
"databaseAccount": [Function],
|
"databaseAccount": [Function],
|
||||||
"databases": [Function],
|
"databases": [Function],
|
||||||
"defaultExperience": [Function],
|
|
||||||
"deleteCollectionText": [Function],
|
"deleteCollectionText": [Function],
|
||||||
"deleteDatabaseText": [Function],
|
"deleteDatabaseText": [Function],
|
||||||
"gitHubClient": GitHubClient {
|
"gitHubClient": GitHubClient {
|
||||||
|
|||||||
@@ -403,7 +403,6 @@ exports[`StringInput Pane should render Create new directory properly 1`] = `
|
|||||||
},
|
},
|
||||||
"databaseAccount": [Function],
|
"databaseAccount": [Function],
|
||||||
"databases": [Function],
|
"databases": [Function],
|
||||||
"defaultExperience": [Function],
|
|
||||||
"deleteCollectionText": [Function],
|
"deleteCollectionText": [Function],
|
||||||
"deleteDatabaseText": [Function],
|
"deleteDatabaseText": [Function],
|
||||||
"gitHubClient": GitHubClient {
|
"gitHubClient": GitHubClient {
|
||||||
|
|||||||
@@ -401,7 +401,6 @@ exports[`Delete Database Confirmation Pane submit() Should call delete database
|
|||||||
},
|
},
|
||||||
"databaseAccount": [Function],
|
"databaseAccount": [Function],
|
||||||
"databases": [Function],
|
"databases": [Function],
|
||||||
"defaultExperience": [Function],
|
|
||||||
"deleteCollectionText": [Function],
|
"deleteCollectionText": [Function],
|
||||||
"deleteDatabaseText": [Function],
|
"deleteDatabaseText": [Function],
|
||||||
"gitHubClient": GitHubClient {
|
"gitHubClient": GitHubClient {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import * as ko from "knockout";
|
import * as ko from "knockout";
|
||||||
import * as Constants from "../../Common/Constants";
|
import { DatabaseAccount } from "../../Contracts/DataModels";
|
||||||
import * as ViewModels from "../../Contracts/ViewModels";
|
import * as ViewModels from "../../Contracts/ViewModels";
|
||||||
import { updateUserContext } from "../../UserContext";
|
import { updateUserContext } from "../../UserContext";
|
||||||
import { CommandButtonComponentProps } from "../Controls/CommandButton/CommandButtonComponent";
|
import { CommandButtonComponentProps } from "../Controls/CommandButton/CommandButtonComponent";
|
||||||
@@ -27,7 +27,13 @@ describe("Documents tab", () => {
|
|||||||
describe("showPartitionKey", () => {
|
describe("showPartitionKey", () => {
|
||||||
const explorer = new Explorer();
|
const explorer = new Explorer();
|
||||||
const mongoExplorer = new Explorer();
|
const mongoExplorer = new Explorer();
|
||||||
mongoExplorer.defaultExperience(Constants.DefaultAccountExperience.MongoDB);
|
updateUserContext({
|
||||||
|
databaseAccount: {
|
||||||
|
properties: {
|
||||||
|
capabilities: [{ name: "EnableGremlin" }],
|
||||||
|
},
|
||||||
|
} as DatabaseAccount,
|
||||||
|
});
|
||||||
|
|
||||||
const collectionWithoutPartitionKey = <ViewModels.Collection>(<unknown>{
|
const collectionWithoutPartitionKey = <ViewModels.Collection>(<unknown>{
|
||||||
id: ko.observable<string>("foo"),
|
id: ko.observable<string>("foo"),
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import * as DataModels from "../../Contracts/DataModels";
|
|||||||
import * as ViewModels from "../../Contracts/ViewModels";
|
import * as ViewModels from "../../Contracts/ViewModels";
|
||||||
import { ActionModifiers } from "../../Shared/Telemetry/TelemetryConstants";
|
import { ActionModifiers } from "../../Shared/Telemetry/TelemetryConstants";
|
||||||
import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
||||||
|
import { userContext } from "../../UserContext";
|
||||||
import Explorer from "../Explorer";
|
import Explorer from "../Explorer";
|
||||||
import { NotebookClientV2 } from "../Notebook/NotebookClientV2";
|
import { NotebookClientV2 } from "../Notebook/NotebookClientV2";
|
||||||
import TabsBase from "./TabsBase";
|
import TabsBase from "./TabsBase";
|
||||||
@@ -29,7 +30,7 @@ export default class NotebookTabBase extends TabsBase {
|
|||||||
NotebookTabBase.clientManager = new NotebookClientV2({
|
NotebookTabBase.clientManager = new NotebookClientV2({
|
||||||
connectionInfo: this.container.notebookServerInfo(),
|
connectionInfo: this.container.notebookServerInfo(),
|
||||||
databaseAccountName: this.container.databaseAccount().name,
|
databaseAccountName: this.container.databaseAccount().name,
|
||||||
defaultExperience: this.container.defaultExperience(),
|
defaultExperience: userContext.apiType,
|
||||||
contentProvider: this.container.notebookManager?.notebookContentProvider,
|
contentProvider: this.container.notebookManager?.notebookContentProvider,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,7 +23,6 @@ describe("Tabs manager tests", () => {
|
|||||||
location: "",
|
location: "",
|
||||||
type: "",
|
type: "",
|
||||||
kind: "",
|
kind: "",
|
||||||
tags: "",
|
|
||||||
properties: undefined,
|
properties: undefined,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
import * as DataModels from "../../Contracts/DataModels";
|
|
||||||
import * as ko from "knockout";
|
import * as ko from "knockout";
|
||||||
import Database from "./Database";
|
|
||||||
import Explorer from "../Explorer";
|
|
||||||
import { HttpStatusCodes } from "../../Common/Constants";
|
import { HttpStatusCodes } from "../../Common/Constants";
|
||||||
|
import * as DataModels from "../../Contracts/DataModels";
|
||||||
import { JunoClient } from "../../Juno/JunoClient";
|
import { JunoClient } from "../../Juno/JunoClient";
|
||||||
import { userContext, updateUserContext } from "../../UserContext";
|
import { updateUserContext, userContext } from "../../UserContext";
|
||||||
|
import Explorer from "../Explorer";
|
||||||
|
import Database from "./Database";
|
||||||
|
|
||||||
const createMockContainer = (): Explorer => {
|
const createMockContainer = (): Explorer => {
|
||||||
const mockContainer = new Explorer();
|
const mockContainer = new Explorer();
|
||||||
@@ -19,7 +19,6 @@ updateUserContext({
|
|||||||
name: "fakeName",
|
name: "fakeName",
|
||||||
location: "fakeLocation",
|
location: "fakeLocation",
|
||||||
type: "fakeType",
|
type: "fakeType",
|
||||||
tags: undefined,
|
|
||||||
kind: "fakeKind",
|
kind: "fakeKind",
|
||||||
properties: {
|
properties: {
|
||||||
documentEndpoint: "fakeEndpoint",
|
documentEndpoint: "fakeEndpoint",
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ const sampleDatabaseAccount: DataModels.DatabaseAccount = {
|
|||||||
location: "location",
|
location: "location",
|
||||||
type: "type",
|
type: "type",
|
||||||
kind: "kind",
|
kind: "kind",
|
||||||
tags: [],
|
|
||||||
properties: {
|
properties: {
|
||||||
documentEndpoint: "documentEndpoint",
|
documentEndpoint: "documentEndpoint",
|
||||||
gremlinEndpoint: "gremlinEndpoint",
|
gremlinEndpoint: "gremlinEndpoint",
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ const sampleDatabaseAccount: DatabaseAccount = {
|
|||||||
location: "location",
|
location: "location",
|
||||||
type: "type",
|
type: "type",
|
||||||
kind: "kind",
|
kind: "kind",
|
||||||
tags: [],
|
|
||||||
properties: {
|
properties: {
|
||||||
documentEndpoint: "documentEndpoint",
|
documentEndpoint: "documentEndpoint",
|
||||||
gremlinEndpoint: "gremlinEndpoint",
|
gremlinEndpoint: "gremlinEndpoint",
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { AccountKind, DefaultAccountExperience, TagNames } from "../../Common/Constants";
|
import { AccountKind } from "../../Common/Constants";
|
||||||
|
|
||||||
export const emulatorAccount = {
|
export const emulatorAccount = {
|
||||||
name: "",
|
name: "",
|
||||||
@@ -6,9 +6,6 @@ export const emulatorAccount = {
|
|||||||
location: "",
|
location: "",
|
||||||
type: "",
|
type: "",
|
||||||
kind: AccountKind.DocumentDB,
|
kind: AccountKind.DocumentDB,
|
||||||
tags: {
|
|
||||||
[TagNames.defaultExperience]: DefaultAccountExperience.DocumentDB,
|
|
||||||
},
|
|
||||||
properties: {
|
properties: {
|
||||||
documentEndpoint: "",
|
documentEndpoint: "",
|
||||||
tableEndpoint: "",
|
tableEndpoint: "",
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import Q from "q";
|
|
||||||
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";
|
||||||
@@ -21,8 +20,7 @@ export default class AuthHeadersUtil {
|
|||||||
const databaseAccount = userContext.databaseAccount;
|
const databaseAccount = userContext.databaseAccount;
|
||||||
const subscriptionId: string = userContext.subscriptionId;
|
const subscriptionId: string = userContext.subscriptionId;
|
||||||
const resourceGroup = userContext.resourceGroup;
|
const resourceGroup = userContext.resourceGroup;
|
||||||
const defaultExperience: string = DefaultExperienceUtility.getDefaultExperienceFromDatabaseAccount(databaseAccount);
|
const apiKind: DataModels.ApiKind = DefaultExperienceUtility.getApiKindFromDefaultExperience(userContext.apiType);
|
||||||
const apiKind: DataModels.ApiKind = DefaultExperienceUtility.getApiKindFromDefaultExperience(defaultExperience);
|
|
||||||
const accountEndpoint = (databaseAccount && databaseAccount.properties.documentEndpoint) || "";
|
const accountEndpoint = (databaseAccount && databaseAccount.properties.documentEndpoint) || "";
|
||||||
const sid = subscriptionId || "";
|
const sid = subscriptionId || "";
|
||||||
const rg = resourceGroup || "";
|
const rg = resourceGroup || "";
|
||||||
|
|||||||
@@ -1,27 +1,28 @@
|
|||||||
import { DefaultAccountExperience, CapabilityNames, AccountKind } from "../../Common/Constants";
|
import { AccountKind, CapabilityNames } from "../../Common/Constants";
|
||||||
import { AccessInputMetadata, ApiKind } from "../../Contracts/DataModels";
|
import { AccessInputMetadata, ApiKind } from "../../Contracts/DataModels";
|
||||||
import { DefaultExperienceUtility } from "../../Shared/DefaultExperienceUtility";
|
import { DefaultExperienceUtility } from "../../Shared/DefaultExperienceUtility";
|
||||||
|
import { userContext } from "../../UserContext";
|
||||||
|
|
||||||
export function getDatabaseAccountPropertiesFromMetadata(metadata: AccessInputMetadata): unknown {
|
export function getDatabaseAccountPropertiesFromMetadata(metadata: AccessInputMetadata): unknown {
|
||||||
let properties = { documentEndpoint: metadata.documentEndpoint };
|
let properties = { documentEndpoint: metadata.documentEndpoint };
|
||||||
const apiExperience: string = DefaultExperienceUtility.getDefaultExperienceFromApiKind(metadata.apiKind);
|
const apiExperience = DefaultExperienceUtility.getDefaultExperienceFromApiKind(metadata.apiKind);
|
||||||
|
|
||||||
if (apiExperience === DefaultAccountExperience.Cassandra) {
|
if (apiExperience === "Cassandra") {
|
||||||
properties = Object.assign(properties, {
|
properties = Object.assign(properties, {
|
||||||
cassandraEndpoint: metadata.apiEndpoint,
|
cassandraEndpoint: metadata.apiEndpoint,
|
||||||
capabilities: [{ name: CapabilityNames.EnableCassandra }],
|
capabilities: [{ name: CapabilityNames.EnableCassandra }],
|
||||||
});
|
});
|
||||||
} else if (apiExperience === DefaultAccountExperience.Table) {
|
} else if (apiExperience === "Tables") {
|
||||||
properties = Object.assign(properties, {
|
properties = Object.assign(properties, {
|
||||||
tableEndpoint: metadata.apiEndpoint,
|
tableEndpoint: metadata.apiEndpoint,
|
||||||
capabilities: [{ name: CapabilityNames.EnableTable }],
|
capabilities: [{ name: CapabilityNames.EnableTable }],
|
||||||
});
|
});
|
||||||
} else if (apiExperience === DefaultAccountExperience.Graph) {
|
} else if (apiExperience === "Gremlin") {
|
||||||
properties = Object.assign(properties, {
|
properties = Object.assign(properties, {
|
||||||
gremlinEndpoint: metadata.apiEndpoint,
|
gremlinEndpoint: metadata.apiEndpoint,
|
||||||
capabilities: [{ name: CapabilityNames.EnableGremlin }],
|
capabilities: [{ name: CapabilityNames.EnableGremlin }],
|
||||||
});
|
});
|
||||||
} else if (apiExperience === DefaultAccountExperience.MongoDB) {
|
} else if (apiExperience === "Mongo") {
|
||||||
if (metadata.apiKind === ApiKind.MongoDBCompute) {
|
if (metadata.apiKind === ApiKind.MongoDBCompute) {
|
||||||
properties = Object.assign(properties, {
|
properties = Object.assign(properties, {
|
||||||
mongoEndpoint: metadata.mongoEndpoint,
|
mongoEndpoint: metadata.mongoEndpoint,
|
||||||
@@ -31,12 +32,8 @@ export function getDatabaseAccountPropertiesFromMetadata(metadata: AccessInputMe
|
|||||||
return properties;
|
return properties;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getDatabaseAccountKindFromExperience(apiExperience: string): string {
|
export function getDatabaseAccountKindFromExperience(apiExperience: typeof userContext.apiType): AccountKind {
|
||||||
if (apiExperience === DefaultAccountExperience.MongoDB) {
|
if (apiExperience === "Mongo") {
|
||||||
return AccountKind.MongoDB;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (apiExperience === DefaultAccountExperience.ApiForMongoDB) {
|
|
||||||
return AccountKind.MongoDB;
|
return AccountKind.MongoDB;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,133 +1,67 @@
|
|||||||
import * as Constants from "../Common/Constants";
|
|
||||||
import * as DataModels from "../Contracts/DataModels";
|
import * as DataModels from "../Contracts/DataModels";
|
||||||
import * as ViewModels from "../Contracts/ViewModels";
|
import { userContext } from "../UserContext";
|
||||||
import { DefaultExperienceUtility } from "./DefaultExperienceUtility";
|
import { DefaultExperienceUtility } from "./DefaultExperienceUtility";
|
||||||
|
|
||||||
describe("Default Experience Utility", () => {
|
describe("Default Experience Utility", () => {
|
||||||
describe("getDefaultExperienceFromApiKind()", () => {
|
describe("getDefaultExperienceFromApiKind()", () => {
|
||||||
function runScenario(apiKind: number, expectedExperience: string): 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, Constants.DefaultAccountExperience.DocumentDB));
|
it("should return SQL", () => runScenario(DataModels.ApiKind.SQL, "SQL"));
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("On MongoDB", () => {
|
describe("On MongoDB", () => {
|
||||||
it("should return MongoDB", () =>
|
it("should return MongoDB", () => runScenario(DataModels.ApiKind.MongoDB, "Mongo"));
|
||||||
runScenario(DataModels.ApiKind.MongoDB, Constants.DefaultAccountExperience.MongoDB));
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("On Table", () => {
|
describe("On Table", () => {
|
||||||
it("should return Table", () => runScenario(DataModels.ApiKind.Table, Constants.DefaultAccountExperience.Table));
|
it("should return Table", () => runScenario(DataModels.ApiKind.Table, "Tables"));
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("On Cassandra", () => {
|
describe("On Cassandra", () => {
|
||||||
it("should return Cassandra", () =>
|
it("should return Cassandra", () => runScenario(DataModels.ApiKind.Cassandra, "Cassandra"));
|
||||||
runScenario(DataModels.ApiKind.Cassandra, Constants.DefaultAccountExperience.Cassandra));
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("On Graph", () => {
|
describe("On Graph", () => {
|
||||||
it("should return Graph", () => runScenario(DataModels.ApiKind.Graph, Constants.DefaultAccountExperience.Graph));
|
it("should return Graph", () => runScenario(DataModels.ApiKind.Graph, "Gremlin"));
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("On unknown", () => {
|
describe("On unknown", () => {
|
||||||
it("should return Default", () => runScenario(-1, Constants.DefaultAccountExperience.Default));
|
it("should return Default", () => runScenario(-1, "SQL"));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("getApiKindFromDefaultExperience()", () => {
|
describe("getApiKindFromDefaultExperience()", () => {
|
||||||
function runScenario(defaultExperience: string, expectedApiKind: number): void {
|
function runScenario(defaultExperience: typeof userContext.apiType, 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(Constants.DefaultAccountExperience.DocumentDB, DataModels.ApiKind.SQL));
|
it("should return SQL", () => runScenario("SQL", DataModels.ApiKind.SQL));
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("On MongoDB", () => {
|
describe("On MongoDB", () => {
|
||||||
it("should return MongoDB", () =>
|
it("should return MongoDB", () => runScenario("Mongo", DataModels.ApiKind.MongoDB));
|
||||||
runScenario(Constants.DefaultAccountExperience.MongoDB, DataModels.ApiKind.MongoDB));
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("On Table", () => {
|
describe("On Table", () => {
|
||||||
it("should return Table", () => runScenario(Constants.DefaultAccountExperience.Table, DataModels.ApiKind.Table));
|
it("should return Table", () => runScenario("Tables", DataModels.ApiKind.Table));
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("On Cassandra", () => {
|
describe("On Cassandra", () => {
|
||||||
it("should return Cassandra", () =>
|
it("should return Cassandra", () => runScenario("Cassandra", DataModels.ApiKind.Cassandra));
|
||||||
runScenario(Constants.DefaultAccountExperience.Cassandra, DataModels.ApiKind.Cassandra));
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("On Graph", () => {
|
describe("On Graph", () => {
|
||||||
it("should return Graph", () => runScenario(Constants.DefaultAccountExperience.Graph, DataModels.ApiKind.Graph));
|
it("should return Graph", () => runScenario("Gremlin", DataModels.ApiKind.Graph));
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("On null", () => {
|
describe("On null", () => {
|
||||||
it("should return SQL", () => runScenario(null, DataModels.ApiKind.SQL));
|
it("should return SQL", () => runScenario(null, DataModels.ApiKind.SQL));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("getDefaultExperienceFromDatabaseAccount()", () => {
|
|
||||||
function runScenario(databaseAccount: DataModels.DatabaseAccount, expectedDefaultExperience: string): void {
|
|
||||||
const resolvedExperience = DefaultExperienceUtility.getDefaultExperienceFromDatabaseAccount(databaseAccount);
|
|
||||||
expect(resolvedExperience).toEqual(expectedDefaultExperience);
|
|
||||||
}
|
|
||||||
|
|
||||||
const databaseAccountWithWrongTagsAndCapabilities: DataModels.DatabaseAccount = {
|
|
||||||
id: "test",
|
|
||||||
kind: "GlobalDocumentDB",
|
|
||||||
name: "test",
|
|
||||||
location: "somewhere",
|
|
||||||
type: "DocumentDB",
|
|
||||||
tags: {
|
|
||||||
defaultExperience: "Gremlin (graph)",
|
|
||||||
},
|
|
||||||
properties: {
|
|
||||||
documentEndpoint: "",
|
|
||||||
cassandraEndpoint: "",
|
|
||||||
gremlinEndpoint: "",
|
|
||||||
tableEndpoint: "",
|
|
||||||
capabilities: [
|
|
||||||
{
|
|
||||||
name: Constants.CapabilityNames.EnableGremlin,
|
|
||||||
description: "something",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
const databaseAccountWithApiKind: DataModels.DatabaseAccount = {
|
|
||||||
id: "test",
|
|
||||||
kind: Constants.AccountKind.MongoDB,
|
|
||||||
name: "test",
|
|
||||||
location: "somewhere",
|
|
||||||
type: "DocumentDB",
|
|
||||||
tags: {},
|
|
||||||
properties: {
|
|
||||||
documentEndpoint: "",
|
|
||||||
cassandraEndpoint: "",
|
|
||||||
gremlinEndpoint: "",
|
|
||||||
tableEndpoint: "",
|
|
||||||
capabilities: [
|
|
||||||
{
|
|
||||||
name: Constants.CapabilityNames.EnableGremlin,
|
|
||||||
description: "something",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
describe("Disregard tags", () => {
|
|
||||||
it("should return Graph", () =>
|
|
||||||
runScenario(databaseAccountWithWrongTagsAndCapabilities, Constants.DefaultAccountExperience.Graph));
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("Respect Kind over capabilities", () => {
|
|
||||||
it("should return MongoDB", () =>
|
|
||||||
runScenario(databaseAccountWithApiKind, Constants.DefaultAccountExperience.MongoDB));
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,132 +1,47 @@
|
|||||||
import * as _ from "underscore";
|
|
||||||
import * as Constants from "../Common/Constants";
|
|
||||||
import * as DataModels from "../Contracts/DataModels";
|
import * as DataModels from "../Contracts/DataModels";
|
||||||
|
import { userContext } from "../UserContext";
|
||||||
|
|
||||||
export class DefaultExperienceUtility {
|
export class DefaultExperienceUtility {
|
||||||
public static getDefaultExperienceFromDatabaseAccount(databaseAccount: DataModels.DatabaseAccount): string | null {
|
public static getApiKindFromDefaultExperience(defaultExperience: typeof userContext.apiType): DataModels.ApiKind {
|
||||||
if (!databaseAccount) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
const kind: string =
|
|
||||||
databaseAccount && databaseAccount.kind && databaseAccount.kind && databaseAccount.kind.toLowerCase();
|
|
||||||
const capabilities = (databaseAccount.properties && databaseAccount.properties.capabilities) || [];
|
|
||||||
|
|
||||||
return DefaultExperienceUtility._getDefaultExperience(kind, capabilities);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static getApiKindFromDefaultExperience(defaultExperience: string): DataModels.ApiKind {
|
|
||||||
if (!defaultExperience) {
|
if (!defaultExperience) {
|
||||||
return DataModels.ApiKind.SQL;
|
return DataModels.ApiKind.SQL;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (defaultExperience) {
|
switch (defaultExperience) {
|
||||||
case Constants.DefaultAccountExperience.DocumentDB:
|
case "SQL":
|
||||||
return DataModels.ApiKind.SQL;
|
return DataModels.ApiKind.SQL;
|
||||||
case Constants.DefaultAccountExperience.MongoDB:
|
case "Mongo":
|
||||||
case Constants.DefaultAccountExperience.ApiForMongoDB:
|
|
||||||
return DataModels.ApiKind.MongoDB;
|
return DataModels.ApiKind.MongoDB;
|
||||||
case Constants.DefaultAccountExperience.Table:
|
case "Tables":
|
||||||
return DataModels.ApiKind.Table;
|
return DataModels.ApiKind.Table;
|
||||||
case Constants.DefaultAccountExperience.Cassandra:
|
case "Cassandra":
|
||||||
return DataModels.ApiKind.Cassandra;
|
return DataModels.ApiKind.Cassandra;
|
||||||
case Constants.DefaultAccountExperience.Graph:
|
case "Gremlin":
|
||||||
return DataModels.ApiKind.Graph;
|
return DataModels.ApiKind.Graph;
|
||||||
default:
|
default:
|
||||||
return DataModels.ApiKind.SQL;
|
return DataModels.ApiKind.SQL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static getDefaultExperienceFromApiKind(apiKind: DataModels.ApiKind): string {
|
public static getDefaultExperienceFromApiKind(apiKind: DataModels.ApiKind): typeof userContext.apiType {
|
||||||
if (apiKind == null) {
|
if (apiKind == null) {
|
||||||
return Constants.DefaultAccountExperience.Default;
|
return "SQL";
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (apiKind) {
|
switch (apiKind) {
|
||||||
case DataModels.ApiKind.SQL:
|
case DataModels.ApiKind.SQL:
|
||||||
return Constants.DefaultAccountExperience.DocumentDB;
|
return "SQL";
|
||||||
case DataModels.ApiKind.MongoDB:
|
case DataModels.ApiKind.MongoDB:
|
||||||
case DataModels.ApiKind.MongoDBCompute:
|
case DataModels.ApiKind.MongoDBCompute:
|
||||||
return Constants.DefaultAccountExperience.MongoDB;
|
return "Mongo";
|
||||||
case DataModels.ApiKind.Table:
|
case DataModels.ApiKind.Table:
|
||||||
return Constants.DefaultAccountExperience.Table;
|
return "Tables";
|
||||||
case DataModels.ApiKind.Cassandra:
|
case DataModels.ApiKind.Cassandra:
|
||||||
return Constants.DefaultAccountExperience.Cassandra;
|
return "Cassandra";
|
||||||
case DataModels.ApiKind.Graph:
|
case DataModels.ApiKind.Graph:
|
||||||
return Constants.DefaultAccountExperience.Graph;
|
return "Gremlin";
|
||||||
default:
|
default:
|
||||||
return Constants.DefaultAccountExperience.Default;
|
return "SQL";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static _getDefaultExperience(kind: string, capabilities: DataModels.Capability[]): string {
|
|
||||||
const defaultDefaultExperience: string = Constants.DefaultAccountExperience.DocumentDB;
|
|
||||||
const defaultExperienceFromKind: string = DefaultExperienceUtility._getDefaultExperienceFromAccountKind(kind) || "";
|
|
||||||
const defaultExperienceFromCapabilities: string =
|
|
||||||
DefaultExperienceUtility._getDefaultExperienceFromAccountCapabilities(capabilities) || "";
|
|
||||||
if (!!defaultExperienceFromKind) {
|
|
||||||
return defaultExperienceFromKind;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!!defaultExperienceFromCapabilities) {
|
|
||||||
return defaultExperienceFromCapabilities;
|
|
||||||
}
|
|
||||||
|
|
||||||
return defaultDefaultExperience;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static _getDefaultExperienceFromAccountKind(kind: string): string | null {
|
|
||||||
if (!kind) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (kind.toLowerCase() === Constants.AccountKind.MongoDB.toLowerCase()) {
|
|
||||||
return Constants.DefaultAccountExperience.MongoDB;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (kind.toLowerCase() === Constants.AccountKind.Parse.toLowerCase()) {
|
|
||||||
return Constants.DefaultAccountExperience.MongoDB;
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static _getDefaultExperienceFromAccountCapabilities(capabilities: DataModels.Capability[]): string | null {
|
|
||||||
if (!capabilities) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!Array.isArray(capabilities)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
const enableTable = DefaultExperienceUtility._findCapability(capabilities, Constants.CapabilityNames.EnableTable);
|
|
||||||
if (enableTable) {
|
|
||||||
return Constants.DefaultAccountExperience.Table;
|
|
||||||
}
|
|
||||||
|
|
||||||
const enableGremlin = DefaultExperienceUtility._findCapability(
|
|
||||||
capabilities,
|
|
||||||
Constants.CapabilityNames.EnableGremlin
|
|
||||||
);
|
|
||||||
if (enableGremlin) {
|
|
||||||
return Constants.DefaultAccountExperience.Graph;
|
|
||||||
}
|
|
||||||
|
|
||||||
const enableCassandra = DefaultExperienceUtility._findCapability(
|
|
||||||
capabilities,
|
|
||||||
Constants.CapabilityNames.EnableCassandra
|
|
||||||
);
|
|
||||||
if (enableCassandra) {
|
|
||||||
return Constants.DefaultAccountExperience.Cassandra;
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static _findCapability(capabilities: DataModels.Capability[], capabilityName: string): DataModels.Capability {
|
|
||||||
return _.find(capabilities, (capability) => {
|
|
||||||
return capability && capability.name && capability.name.toLowerCase() === capabilityName.toLowerCase();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ interface UserContext {
|
|||||||
readonly hasWriteAccess: boolean;
|
readonly hasWriteAccess: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
type ApiType = "SQL" | "Mongo" | "Gremlin" | "Tables" | "Cassandra";
|
export type ApiType = "SQL" | "Mongo" | "Gremlin" | "Tables" | "Cassandra";
|
||||||
export type PortalEnv = "localhost" | "blackforest" | "fairfax" | "mooncake" | "prod" | "dev";
|
export type PortalEnv = "localhost" | "blackforest" | "fairfax" | "mooncake" | "prod" | "dev";
|
||||||
|
|
||||||
const features = extractFeatures();
|
const features = extractFeatures();
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { applyExplorerBindings } from "../applyExplorerBindings";
|
import { applyExplorerBindings } from "../applyExplorerBindings";
|
||||||
import { AuthType } from "../AuthType";
|
import { AuthType } from "../AuthType";
|
||||||
import { AccountKind, DefaultAccountExperience } from "../Common/Constants";
|
import { AccountKind } from "../Common/Constants";
|
||||||
import { normalizeArmEndpoint } from "../Common/EnvironmentUtility";
|
import { normalizeArmEndpoint } from "../Common/EnvironmentUtility";
|
||||||
import { sendMessage, sendReadyMessage } from "../Common/MessageHandler";
|
import { sendMessage, sendReadyMessage } from "../Common/MessageHandler";
|
||||||
import { configContext, Platform, updateConfigContext } from "../ConfigContext";
|
import { configContext, Platform, updateConfigContext } from "../ConfigContext";
|
||||||
@@ -141,8 +141,6 @@ function configureHostedWithResourceToken(config: ResourceToken, explorerParams:
|
|||||||
name: parsedResourceToken.accountEndpoint,
|
name: parsedResourceToken.accountEndpoint,
|
||||||
kind: AccountKind.GlobalDocumentDB,
|
kind: AccountKind.GlobalDocumentDB,
|
||||||
properties: { documentEndpoint: parsedResourceToken.accountEndpoint },
|
properties: { documentEndpoint: parsedResourceToken.accountEndpoint },
|
||||||
// Resource tokens can only be used with SQL API
|
|
||||||
tags: { defaultExperience: DefaultAccountExperience.DocumentDB },
|
|
||||||
};
|
};
|
||||||
updateUserContext({
|
updateUserContext({
|
||||||
databaseAccount,
|
databaseAccount,
|
||||||
@@ -165,9 +163,7 @@ function configureHostedWithEncryptedToken(config: EncryptedToken, explorerParam
|
|||||||
authType: AuthType.EncryptedToken,
|
authType: AuthType.EncryptedToken,
|
||||||
accessToken: encodeURIComponent(config.encryptedToken),
|
accessToken: encodeURIComponent(config.encryptedToken),
|
||||||
});
|
});
|
||||||
const apiExperience: string = DefaultExperienceUtility.getDefaultExperienceFromApiKind(
|
const apiExperience = DefaultExperienceUtility.getDefaultExperienceFromApiKind(config.encryptedTokenMetadata.apiKind);
|
||||||
config.encryptedTokenMetadata.apiKind
|
|
||||||
);
|
|
||||||
const explorer = new Explorer(explorerParams);
|
const explorer = new Explorer(explorerParams);
|
||||||
explorer.configure({
|
explorer.configure({
|
||||||
databaseAccount: {
|
databaseAccount: {
|
||||||
|
|||||||
37
test/graph/container.spec.ts
Normal file
37
test/graph/container.spec.ts
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
import { jest } from "@jest/globals";
|
||||||
|
import "expect-playwright";
|
||||||
|
import { safeClick } from "../utils/safeClick";
|
||||||
|
import { generateDatabaseNameWithTimestamp, generateUniqueName } from "../utils/shared";
|
||||||
|
jest.setTimeout(240000);
|
||||||
|
|
||||||
|
test("Graph CRUD", async () => {
|
||||||
|
const databaseId = generateDatabaseNameWithTimestamp();
|
||||||
|
const containerId = generateUniqueName("container");
|
||||||
|
|
||||||
|
await page.goto("https://localhost:1234/testExplorer.html?accountName=portal-gremlin-runner");
|
||||||
|
await page.waitForSelector("iframe");
|
||||||
|
const explorer = page.frame({
|
||||||
|
name: "explorer",
|
||||||
|
});
|
||||||
|
|
||||||
|
// Create new database and graph
|
||||||
|
await explorer.click('[data-test="New Graph"]');
|
||||||
|
await explorer.fill('[aria-label="New database id"]', databaseId);
|
||||||
|
await explorer.fill('[aria-label="Graph id"]', containerId);
|
||||||
|
await explorer.fill('[aria-label="Partition key"]', "/pk");
|
||||||
|
await explorer.click("#sidePanelOkButton");
|
||||||
|
await safeClick(explorer, `.nodeItem >> text=${databaseId}`);
|
||||||
|
await safeClick(explorer, `.nodeItem >> text=${containerId}`);
|
||||||
|
// Delete database and graph
|
||||||
|
await safeClick(explorer, `[data-test="${containerId}"] [aria-label="More"]`);
|
||||||
|
await safeClick(explorer, 'button[role="menuitem"]:has-text("Delete Graph")');
|
||||||
|
await explorer.fill('text=* Confirm by typing the graph id >> input[type="text"]', containerId);
|
||||||
|
await explorer.click('[aria-label="Submit"]');
|
||||||
|
await explorer.click(`[data-test="${databaseId}"] [aria-label="More"]`);
|
||||||
|
await explorer.click('button[role="menuitem"]:has-text("Delete Database")');
|
||||||
|
await explorer.click('text=* Confirm by typing the database id >> input[type="text"]');
|
||||||
|
await explorer.fill('text=* Confirm by typing the database id >> input[type="text"]', databaseId);
|
||||||
|
await explorer.click("#sidePanelOkButton");
|
||||||
|
await expect(explorer).not.toHaveText(".dataResourceTree", databaseId);
|
||||||
|
await expect(explorer).not.toHaveText(".dataResourceTree", containerId);
|
||||||
|
});
|
||||||
@@ -21,6 +21,6 @@
|
|||||||
"noEmit": true,
|
"noEmit": true,
|
||||||
"types": ["jest"]
|
"types": ["jest"]
|
||||||
},
|
},
|
||||||
"include": ["./src/**/*", "./test/testExplorer/TestExplorer.ts"],
|
"include": ["./src/**/*", "./utils/**/*"],
|
||||||
"exclude": ["./src/**/__mocks__/**/*"]
|
"exclude": ["./src/**/__mocks__/**/*"]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
{
|
{
|
||||||
"extends": "./tsconfig.json",
|
"extends": "./tsconfig.json",
|
||||||
|
"include": ["./test/**/*"],
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"module": "commonjs"
|
"module": "commonjs"
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user