Compare commits

...

9 Commits

Author SHA1 Message Date
Steve Faulkner
23599741d7 Fix strict mode 2020-09-10 18:39:52 -05:00
Steve Faulkner
d494278488 Refactor MemoryTracker to use SWR 2020-09-10 16:34:32 -05:00
DanielSPham
53bedb1641 Added descriptive aria label to autoscale throughput link (#185)
Co-authored-by: Daniel Si Pham <v-danpha@microsoft.com>
2020-09-08 11:03:48 -07:00
Steve Faulkner
e6ac5a7043 Telemetry Adjustments (#182) 2020-09-08 12:44:46 -05:00
Steve Faulkner
faf923f647 TypeScript 4.0 (#165) 2020-09-04 09:08:52 -05:00
Laurent Nguyen
d471cff77c Fix resource tree node selection bug (#170)
* Fix bug with resource tree selection for graphs

* Reformat and type fixes
2020-09-04 10:15:53 +02:00
DanielSPham
0a24a0b73e Updated aria label (#180)
Co-authored-by: Daniel Si Pham <v-danpha@microsoft.com>
2020-09-03 14:10:57 -07:00
DanielSPham
ab4753fd1d Fixed contrast ratio for links in notification area (#179)
Co-authored-by: Daniel Si Pham <v-danpha@microsoft.com>
2020-09-03 14:10:32 -07:00
victor-meng
6bc506b81f Clean up unused utility functions for creating databases and collections (#181) 2020-09-03 13:05:22 -07:00
101 changed files with 1155 additions and 1638 deletions

View File

@@ -266,10 +266,6 @@ src/ResourceProvider/ResourceProviderClientFactory.ts
src/RouteHandlers/RouteHandler.ts src/RouteHandlers/RouteHandler.ts
src/RouteHandlers/TabRouteHandler.test.ts src/RouteHandlers/TabRouteHandler.test.ts
src/RouteHandlers/TabRouteHandler.ts src/RouteHandlers/TabRouteHandler.ts
src/Shared/AddCollectionUtility.test.ts
src/Shared/AddCollectionUtility.ts
src/Shared/AddDatabaseUtility.test.ts
src/Shared/AddDatabaseUtility.ts
src/Shared/Constants.ts src/Shared/Constants.ts
src/Shared/DefaultExperienceUtility.test.ts src/Shared/DefaultExperienceUtility.test.ts
src/Shared/DefaultExperienceUtility.ts src/Shared/DefaultExperienceUtility.ts
@@ -279,8 +275,6 @@ src/Shared/StorageUtility.test.ts
src/Shared/StorageUtility.ts src/Shared/StorageUtility.ts
src/Shared/StringUtility.test.ts src/Shared/StringUtility.test.ts
src/Shared/StringUtility.ts src/Shared/StringUtility.ts
src/Shared/Telemetry/TelemetryConstants.ts
src/Shared/Telemetry/TelemetryProcessor.ts
src/Shared/appInsights.ts src/Shared/appInsights.ts
src/SparkClusterManager/ArcadiaResourceManager.ts src/SparkClusterManager/ArcadiaResourceManager.ts
src/SparkClusterManager/SparkClusterManager.ts src/SparkClusterManager/SparkClusterManager.ts
@@ -418,6 +412,5 @@ cypress/integration/dataexplorer/SQL/addCollection.spec.ts
cypress/integration/dataexplorer/TABLE/addCollection.spec.ts cypress/integration/dataexplorer/TABLE/addCollection.spec.ts
cypress/integration/notebook/newNotebook.spec.ts cypress/integration/notebook/newNotebook.spec.ts
cypress/integration/notebook/resourceTree.spec.ts cypress/integration/notebook/resourceTree.spec.ts
__mocks__/AddDatabaseUtility.ts
__mocks__/monaco-editor.ts __mocks__/monaco-editor.ts
src/Explorer/Tree/ResourceTreeAdapterForResourceToken.test.tsx src/Explorer/Tree/ResourceTreeAdapterForResourceToken.test.tsx

View File

@@ -1,5 +0,0 @@
export class AddDbUtilities {
createGremlinDatabase(params: any) {
return Promise.resolve(1)
}
}

View File

@@ -3017,4 +3017,8 @@ settings-pane {
.italic { .italic {
font-style: italic; font-style: italic;
}
.warningErrorContent a {
color: @AccentMediumHigh
} }

708
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -8,7 +8,7 @@
"@azure/cosmos-language-service": "0.0.4", "@azure/cosmos-language-service": "0.0.4",
"@jupyterlab/services": "4.2.0", "@jupyterlab/services": "4.2.0",
"@jupyterlab/terminal": "1.2.1", "@jupyterlab/terminal": "1.2.1",
"@microsoft/applicationinsights-web": "2.5.4", "@microsoft/applicationinsights-web": "2.5.8",
"@nteract/commutable": "7.1.4", "@nteract/commutable": "7.1.4",
"@nteract/connected-components": "6.7.8", "@nteract/connected-components": "6.7.8",
"@nteract/core": "13.0.0", "@nteract/core": "13.0.0",
@@ -66,13 +66,13 @@
"mkdirp": "1.0.4", "mkdirp": "1.0.4",
"monaco-editor": "0.15.6", "monaco-editor": "0.15.6",
"object.entries": "1.1.0", "object.entries": "1.1.0",
"office-ui-fabric-react": "7.121.10", "office-ui-fabric-react": "7.134.1",
"p-retry": "4.2.0", "p-retry": "4.2.0",
"plotly.js-cartesian-dist-min": "1.52.3", "plotly.js-cartesian-dist-min": "1.52.3",
"promise-polyfill": "8.1.0", "promise-polyfill": "8.1.0",
"promise.prototype.finally": "3.1.0", "promise.prototype.finally": "3.1.0",
"q": "1.5.1", "q": "1.5.1",
"react": "16.9.0", "react": "16.13.1",
"react-animate-height": "2.0.8", "react-animate-height": "2.0.8",
"react-dnd": "9.4.0", "react-dnd": "9.4.0",
"react-dnd-html5-backend": "9.4.0", "react-dnd-html5-backend": "9.4.0",
@@ -118,8 +118,8 @@
"@types/text-encoding": "0.0.33", "@types/text-encoding": "0.0.33",
"@types/underscore": "1.7.36", "@types/underscore": "1.7.36",
"@types/webfontloader": "1.6.29", "@types/webfontloader": "1.6.29",
"@typescript-eslint/eslint-plugin": "3.2.0", "@typescript-eslint/eslint-plugin": "4.0.1",
"@typescript-eslint/parser": "3.2.0", "@typescript-eslint/parser": "4.0.1",
"adal-angular": "1.0.15", "adal-angular": "1.0.15",
"axe-puppeteer": "1.1.0", "axe-puppeteer": "1.1.0",
"babel-jest": "24.9.0", "babel-jest": "24.9.0",
@@ -132,7 +132,7 @@
"enzyme": "3.10.0", "enzyme": "3.10.0",
"enzyme-adapter-react-16": "1.15.1", "enzyme-adapter-react-16": "1.15.1",
"enzyme-to-json": "3.4.3", "enzyme-to-json": "3.4.3",
"eslint": "7.3.1", "eslint": "7.8.1",
"eslint-cli": "1.1.1", "eslint-cli": "1.1.1",
"eslint-plugin-no-null": "1.0.2", "eslint-plugin-no-null": "1.0.2",
"eslint-plugin-prefer-arrow": "1.2.2", "eslint-plugin-prefer-arrow": "1.2.2",
@@ -160,11 +160,12 @@
"rimraf": "3.0.0", "rimraf": "3.0.0",
"sinon": "3.2.1", "sinon": "3.2.1",
"style-loader": "0.23.0", "style-loader": "0.23.0",
"swr": "0.3.2",
"terser-webpack-plugin": "3.0.5", "terser-webpack-plugin": "3.0.5",
"ts-loader": "6.2.2", "ts-loader": "6.2.2",
"tslint": "5.11.0", "tslint": "5.11.0",
"tslint-microsoft-contrib": "6.0.0", "tslint-microsoft-contrib": "6.0.0",
"typescript": "3.9.6", "typescript": "4.0.2",
"url-loader": "1.1.1", "url-loader": "1.1.1",
"webpack": "4.43.0", "webpack": "4.43.0",
"webpack-bundle-analyzer": "3.6.1", "webpack-bundle-analyzer": "3.6.1",

View File

@@ -5,14 +5,7 @@ import { Collection } from "../Contracts/ViewModels";
import DocumentId from "../Explorer/Tree/DocumentId"; import DocumentId from "../Explorer/Tree/DocumentId";
import { ResourceProviderClient } from "../ResourceProvider/ResourceProviderClient"; import { ResourceProviderClient } from "../ResourceProvider/ResourceProviderClient";
import { updateUserContext } from "../UserContext"; import { updateUserContext } from "../UserContext";
import { import { deleteDocument, getEndpoint, queryDocuments, readDocument, updateDocument } from "./MongoProxyClient";
deleteDocument,
getEndpoint,
queryDocuments,
readDocument,
updateDocument,
_createMongoCollectionWithARM
} from "./MongoProxyClient";
jest.mock("../ResourceProvider/ResourceProviderClient.ts"); jest.mock("../ResourceProvider/ResourceProviderClient.ts");
const databaseId = "testDB"; const databaseId = "testDB";
@@ -260,58 +253,4 @@ describe("MongoProxyClient", () => {
expect(endpoint).toEqual("https://main.documentdb.ext.azure.com/api/guest/mongo/explorer"); expect(endpoint).toEqual("https://main.documentdb.ext.azure.com/api/guest/mongo/explorer");
}); });
}); });
describe("createMongoCollectionWithARM", () => {
it("should create a collection with autopilot when autopilot is selected + shared throughput is false", () => {
const resourceProviderClientPutAsyncSpy = jest.spyOn(ResourceProviderClient.prototype, "putAsync");
const properties = {
pk: "state",
coll: "abc-collection",
cd: true,
db: "a1-db",
st: false,
sid: "a2",
rg: "c1",
dba: "main",
is: false
};
_createMongoCollectionWithARM("management.azure.com", properties, { "x-ms-cosmos-offer-autopilot-tier": "1" });
expect(resourceProviderClientPutAsyncSpy).toHaveBeenCalledWith(
"subscriptions/a2/resourceGroups/c1/providers/Microsoft.DocumentDB/databaseAccounts/foo/mongodbDatabases/a1-db/collections/abc-collection",
"2020-04-01",
{
properties: {
options: { "x-ms-cosmos-offer-autopilot-tier": "1" },
resource: { id: "abc-collection" }
}
}
);
});
it("should create a collection with provisioned throughput when provisioned throughput is selected + shared throughput is false", () => {
const resourceProviderClientPutAsyncSpy = jest.spyOn(ResourceProviderClient.prototype, "putAsync");
const properties = {
pk: "state",
coll: "abc-collection",
cd: true,
db: "a1-db",
st: false,
sid: "a2",
rg: "c1",
dba: "main",
is: false,
offerThroughput: 400
};
_createMongoCollectionWithARM("management.azure.com", properties, undefined);
expect(resourceProviderClientPutAsyncSpy).toHaveBeenCalledWith(
"subscriptions/a2/resourceGroups/c1/providers/Microsoft.DocumentDB/databaseAccounts/foo/mongodbDatabases/a1-db/collections/abc-collection",
"2020-04-01",
{
properties: {
options: { throughput: "400" },
resource: { id: "abc-collection" }
}
}
);
});
});
}); });

View File

@@ -1,15 +1,12 @@
import { Constants as CosmosSDKConstants } from "@azure/cosmos"; import { Constants as CosmosSDKConstants } from "@azure/cosmos";
import queryString from "querystring"; import queryString from "querystring";
import { AuthType } from "../AuthType"; import { AuthType } from "../AuthType";
import * as DataExplorerConstants from "../Common/Constants";
import { configContext } from "../ConfigContext"; import { configContext } from "../ConfigContext";
import * as DataModels from "../Contracts/DataModels"; import * as DataModels from "../Contracts/DataModels";
import { MessageTypes } from "../Contracts/ExplorerContracts"; import { MessageTypes } from "../Contracts/ExplorerContracts";
import { Collection } from "../Contracts/ViewModels"; import { Collection } from "../Contracts/ViewModels";
import { ConsoleDataType } from "../Explorer/Menus/NotificationConsole/NotificationConsoleComponent"; import { ConsoleDataType } from "../Explorer/Menus/NotificationConsole/NotificationConsoleComponent";
import DocumentId from "../Explorer/Tree/DocumentId"; import DocumentId from "../Explorer/Tree/DocumentId";
import { ResourceProviderClient } from "../ResourceProvider/ResourceProviderClient";
import { AddDbUtilities } from "../Shared/AddDatabaseUtility";
import * as NotificationConsoleUtils from "../Utils/NotificationConsoleUtils"; import * as NotificationConsoleUtils from "../Utils/NotificationConsoleUtils";
import { ApiType, HttpHeaders, HttpStatusCodes } from "./Constants"; import { ApiType, HttpHeaders, HttpStatusCodes } from "./Constants";
import { userContext } from "../UserContext"; import { userContext } from "../UserContext";
@@ -330,48 +327,6 @@ export function createMongoCollectionWithProxy(
}); });
} }
export function createMongoCollectionWithARM(
armEndpoint: string,
databaseId: string,
analyticalStorageTtl: number,
collectionId: string,
offerThroughput: number,
shardKey: string,
createDatabase: boolean,
sharedThroughput: boolean,
isSharded: boolean,
additionalOptions?: DataModels.RpOptions
): Promise<DataModels.CreateCollectionWithRpResponse> {
const databaseAccount = userContext.databaseAccount;
const params: DataModels.MongoParameters = {
resourceUrl: databaseAccount.properties.mongoEndpoint || databaseAccount.properties.documentEndpoint,
db: databaseId,
coll: collectionId,
pk: shardKey,
offerThroughput,
cd: createDatabase,
st: sharedThroughput,
is: isSharded,
rid: "",
rtype: "colls",
sid: userContext.subscriptionId,
rg: userContext.resourceGroup,
dba: databaseAccount.name,
analyticalStorageTtl
};
if (createDatabase) {
return AddDbUtilities.createMongoDatabaseWithARM(
armEndpoint,
params,
sharedThroughput ? additionalOptions : {}
).then(() => {
return _createMongoCollectionWithARM(armEndpoint, params, sharedThroughput ? {} : additionalOptions);
});
}
return _createMongoCollectionWithARM(armEndpoint, params, additionalOptions);
}
export function getEndpoint(databaseAccount: DataModels.DatabaseAccount): string { export function getEndpoint(databaseAccount: DataModels.DatabaseAccount): string {
const serverId = window.dataExplorer.serverId(); const serverId = window.dataExplorer.serverId();
const extensionEndpoint = window.dataExplorer.extensionEndpoint(); const extensionEndpoint = window.dataExplorer.extensionEndpoint();
@@ -404,46 +359,3 @@ async function errorHandling(response: Response, action: string, params: unknown
export function getARMCreateCollectionEndpoint(params: DataModels.MongoParameters): string { export function getARMCreateCollectionEndpoint(params: DataModels.MongoParameters): string {
return `subscriptions/${params.sid}/resourceGroups/${params.rg}/providers/Microsoft.DocumentDB/databaseAccounts/${userContext.databaseAccount.name}/mongodbDatabases/${params.db}/collections/${params.coll}`; return `subscriptions/${params.sid}/resourceGroups/${params.rg}/providers/Microsoft.DocumentDB/databaseAccounts/${userContext.databaseAccount.name}/mongodbDatabases/${params.db}/collections/${params.coll}`;
} }
export async function _createMongoCollectionWithARM(
armEndpoint: string,
params: DataModels.MongoParameters,
rpOptions: DataModels.RpOptions
): Promise<DataModels.CreateCollectionWithRpResponse> {
const rpPayloadToCreateCollection: DataModels.MongoCreationRequest = {
properties: {
resource: {
id: params.coll
},
options: {}
}
};
if (params.is) {
rpPayloadToCreateCollection.properties.resource["shardKey"] = { [params.pk]: "Hash" };
}
if (!params.st) {
if (rpOptions) {
rpPayloadToCreateCollection.properties.options = rpOptions;
} else {
rpPayloadToCreateCollection.properties.options["throughput"] =
params.offerThroughput && params.offerThroughput.toString();
}
}
if (params.analyticalStorageTtl) {
rpPayloadToCreateCollection.properties.resource.analyticalStorageTtl = params.analyticalStorageTtl;
}
try {
return new ResourceProviderClient<DataModels.CreateCollectionWithRpResponse>(armEndpoint).putAsync(
getARMCreateCollectionEndpoint(params),
DataExplorerConstants.ArmApiVersions.publicVersion,
rpPayloadToCreateCollection
);
} catch (response) {
errorHandling(response, "creating collection", undefined);
return undefined;
}
}

View File

@@ -6,23 +6,26 @@ import { ContainerRequest } from "@azure/cosmos/dist-esm/client/Container/Contai
import { DatabaseRequest } from "@azure/cosmos/dist-esm/client/Database/DatabaseRequest"; import { DatabaseRequest } from "@azure/cosmos/dist-esm/client/Database/DatabaseRequest";
import { DefaultAccountExperienceType } from "../../DefaultAccountExperienceType"; import { DefaultAccountExperienceType } from "../../DefaultAccountExperienceType";
import { RequestOptions } from "@azure/cosmos/dist-esm"; import { RequestOptions } from "@azure/cosmos/dist-esm";
import * as ARMTypes from "../../Utils/arm/generatedClients/2020-04-01/types"; import * as ARMTypes from "../../Utils/arm/generatedClients/2020-04-01-cosmos-db/types";
import { client } from "../CosmosClient"; import { client } from "../CosmosClient";
import { createMongoCollectionWithProxy } from "../MongoProxyClient"; import { createMongoCollectionWithProxy } from "../MongoProxyClient";
import { createUpdateSqlContainer, getSqlContainer } from "../../Utils/arm/generatedClients/2020-04-01/sqlResources"; import {
createUpdateSqlContainer,
getSqlContainer
} from "../../Utils/arm/generatedClients/2020-04-01-cosmos-db/sqlResources";
import { import {
createUpdateCassandraTable, createUpdateCassandraTable,
getCassandraTable getCassandraTable
} from "../../Utils/arm/generatedClients/2020-04-01/cassandraResources"; } from "../../Utils/arm/generatedClients/2020-04-01-cosmos-db/cassandraResources";
import { import {
createUpdateMongoDBCollection, createUpdateMongoDBCollection,
getMongoDBCollection getMongoDBCollection
} from "../../Utils/arm/generatedClients/2020-04-01/mongoDBResources"; } from "../../Utils/arm/generatedClients/2020-04-01-cosmos-db/mongoDBResources";
import { import {
createUpdateGremlinGraph, createUpdateGremlinGraph,
getGremlinGraph getGremlinGraph
} from "../../Utils/arm/generatedClients/2020-04-01/gremlinResources"; } from "../../Utils/arm/generatedClients/2020-04-01-cosmos-db/gremlinResources";
import { createUpdateTable, getTable } from "../../Utils/arm/generatedClients/2020-04-01/tableResources"; import { createUpdateTable, getTable } from "../../Utils/arm/generatedClients/2020-04-01-cosmos-db/tableResources";
import { logConsoleProgress, logConsoleError, logConsoleInfo } from "../../Utils/NotificationConsoleUtils"; import { logConsoleProgress, logConsoleError, logConsoleInfo } from "../../Utils/NotificationConsoleUtils";
import { logError } from "../Logger"; import { logError } from "../Logger";
import { refreshCachedResources } from "../DataAccessUtilityBase"; import { refreshCachedResources } from "../DataAccessUtilityBase";

View File

@@ -9,21 +9,24 @@ import {
MongoDBDatabaseCreateUpdateParameters, MongoDBDatabaseCreateUpdateParameters,
SqlDatabaseCreateUpdateParameters, SqlDatabaseCreateUpdateParameters,
CreateUpdateOptions CreateUpdateOptions
} from "../../Utils/arm/generatedClients/2020-04-01/types"; } from "../../Utils/arm/generatedClients/2020-04-01-cosmos-db/types";
import { client } from "../CosmosClient"; import { client } from "../CosmosClient";
import { createUpdateSqlDatabase, getSqlDatabase } from "../../Utils/arm/generatedClients/2020-04-01/sqlResources"; import {
createUpdateSqlDatabase,
getSqlDatabase
} from "../../Utils/arm/generatedClients/2020-04-01-cosmos-db/sqlResources";
import { import {
createUpdateCassandraKeyspace, createUpdateCassandraKeyspace,
getCassandraKeyspace getCassandraKeyspace
} from "../../Utils/arm/generatedClients/2020-04-01/cassandraResources"; } from "../../Utils/arm/generatedClients/2020-04-01-cosmos-db/cassandraResources";
import { import {
createUpdateMongoDBDatabase, createUpdateMongoDBDatabase,
getMongoDBDatabase getMongoDBDatabase
} from "../../Utils/arm/generatedClients/2020-04-01/mongoDBResources"; } from "../../Utils/arm/generatedClients/2020-04-01-cosmos-db/mongoDBResources";
import { import {
createUpdateGremlinDatabase, createUpdateGremlinDatabase,
getGremlinDatabase getGremlinDatabase
} from "../../Utils/arm/generatedClients/2020-04-01/gremlinResources"; } from "../../Utils/arm/generatedClients/2020-04-01-cosmos-db/gremlinResources";
import { logConsoleProgress, logConsoleError, logConsoleInfo } from "../../Utils/NotificationConsoleUtils"; import { logConsoleProgress, logConsoleError, logConsoleInfo } from "../../Utils/NotificationConsoleUtils";
import { logError } from "../Logger"; import { logError } from "../Logger";
import { refreshCachedOffers, refreshCachedResources } from "../DataAccessUtilityBase"; import { refreshCachedOffers, refreshCachedResources } from "../DataAccessUtilityBase";

View File

@@ -1,10 +1,10 @@
import { AuthType } from "../../AuthType"; import { AuthType } from "../../AuthType";
import { DefaultAccountExperienceType } from "../../DefaultAccountExperienceType"; import { DefaultAccountExperienceType } from "../../DefaultAccountExperienceType";
import { deleteSqlContainer } from "../../Utils/arm/generatedClients/2020-04-01/sqlResources"; import { deleteSqlContainer } from "../../Utils/arm/generatedClients/2020-04-01-cosmos-db/sqlResources";
import { deleteCassandraTable } from "../../Utils/arm/generatedClients/2020-04-01/cassandraResources"; import { deleteCassandraTable } from "../../Utils/arm/generatedClients/2020-04-01-cosmos-db/cassandraResources";
import { deleteMongoDBCollection } from "../../Utils/arm/generatedClients/2020-04-01/mongoDBResources"; import { deleteMongoDBCollection } from "../../Utils/arm/generatedClients/2020-04-01-cosmos-db/mongoDBResources";
import { deleteGremlinGraph } from "../../Utils/arm/generatedClients/2020-04-01/gremlinResources"; import { deleteGremlinGraph } from "../../Utils/arm/generatedClients/2020-04-01-cosmos-db/gremlinResources";
import { deleteTable } from "../../Utils/arm/generatedClients/2020-04-01/tableResources"; import { deleteTable } from "../../Utils/arm/generatedClients/2020-04-01-cosmos-db/tableResources";
import { logConsoleError, logConsoleInfo, logConsoleProgress } from "../../Utils/NotificationConsoleUtils"; import { logConsoleError, logConsoleInfo, logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
import { logError } from "../Logger"; import { logError } from "../Logger";
import { sendNotificationForError } from "./sendNotificationForError"; import { sendNotificationForError } from "./sendNotificationForError";

View File

@@ -1,9 +1,9 @@
import { AuthType } from "../../AuthType"; import { AuthType } from "../../AuthType";
import { DefaultAccountExperienceType } from "../../DefaultAccountExperienceType"; import { DefaultAccountExperienceType } from "../../DefaultAccountExperienceType";
import { deleteSqlDatabase } from "../../Utils/arm/generatedClients/2020-04-01/sqlResources"; import { deleteSqlDatabase } from "../../Utils/arm/generatedClients/2020-04-01-cosmos-db/sqlResources";
import { deleteCassandraKeyspace } from "../../Utils/arm/generatedClients/2020-04-01/cassandraResources"; import { deleteCassandraKeyspace } from "../../Utils/arm/generatedClients/2020-04-01-cosmos-db/cassandraResources";
import { deleteMongoDBDatabase } from "../../Utils/arm/generatedClients/2020-04-01/mongoDBResources"; import { deleteMongoDBDatabase } from "../../Utils/arm/generatedClients/2020-04-01-cosmos-db/mongoDBResources";
import { deleteGremlinDatabase } from "../../Utils/arm/generatedClients/2020-04-01/gremlinResources"; import { deleteGremlinDatabase } from "../../Utils/arm/generatedClients/2020-04-01-cosmos-db/gremlinResources";
import { logConsoleError, logConsoleInfo, logConsoleProgress } from "../../Utils/NotificationConsoleUtils"; import { logConsoleError, logConsoleInfo, logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
import { userContext } from "../../UserContext"; import { userContext } from "../../UserContext";
import { client } from "../CosmosClient"; import { client } from "../CosmosClient";

View File

@@ -2,11 +2,11 @@ import * as DataModels from "../../Contracts/DataModels";
import { AuthType } from "../../AuthType"; import { AuthType } from "../../AuthType";
import { DefaultAccountExperienceType } from "../../DefaultAccountExperienceType"; import { DefaultAccountExperienceType } from "../../DefaultAccountExperienceType";
import { client } from "../CosmosClient"; import { client } from "../CosmosClient";
import { listSqlContainers } from "../../Utils/arm/generatedClients/2020-04-01/sqlResources"; import { listSqlContainers } from "../../Utils/arm/generatedClients/2020-04-01-cosmos-db/sqlResources";
import { listCassandraTables } from "../../Utils/arm/generatedClients/2020-04-01/cassandraResources"; import { listCassandraTables } from "../../Utils/arm/generatedClients/2020-04-01-cosmos-db/cassandraResources";
import { listMongoDBCollections } from "../../Utils/arm/generatedClients/2020-04-01/mongoDBResources"; import { listMongoDBCollections } from "../../Utils/arm/generatedClients/2020-04-01-cosmos-db/mongoDBResources";
import { listGremlinGraphs } from "../../Utils/arm/generatedClients/2020-04-01/gremlinResources"; import { listGremlinGraphs } from "../../Utils/arm/generatedClients/2020-04-01-cosmos-db/gremlinResources";
import { listTables } from "../../Utils/arm/generatedClients/2020-04-01/tableResources"; import { listTables } from "../../Utils/arm/generatedClients/2020-04-01-cosmos-db/tableResources";
import { logConsoleProgress, logConsoleError } from "../../Utils/NotificationConsoleUtils"; import { logConsoleProgress, logConsoleError } from "../../Utils/NotificationConsoleUtils";
import { logError } from "../Logger"; import { logError } from "../Logger";
import { sendNotificationForError } from "./sendNotificationForError"; import { sendNotificationForError } from "./sendNotificationForError";

View File

@@ -2,10 +2,10 @@ import * as DataModels from "../../Contracts/DataModels";
import { AuthType } from "../../AuthType"; import { AuthType } from "../../AuthType";
import { DefaultAccountExperienceType } from "../../DefaultAccountExperienceType"; import { DefaultAccountExperienceType } from "../../DefaultAccountExperienceType";
import { client } from "../CosmosClient"; import { client } from "../CosmosClient";
import { listSqlDatabases } from "../../Utils/arm/generatedClients/2020-04-01/sqlResources"; import { listSqlDatabases } from "../../Utils/arm/generatedClients/2020-04-01-cosmos-db/sqlResources";
import { listCassandraKeyspaces } from "../../Utils/arm/generatedClients/2020-04-01/cassandraResources"; import { listCassandraKeyspaces } from "../../Utils/arm/generatedClients/2020-04-01-cosmos-db/cassandraResources";
import { listMongoDBDatabases } from "../../Utils/arm/generatedClients/2020-04-01/mongoDBResources"; import { listMongoDBDatabases } from "../../Utils/arm/generatedClients/2020-04-01-cosmos-db/mongoDBResources";
import { listGremlinDatabases } from "../../Utils/arm/generatedClients/2020-04-01/gremlinResources"; import { listGremlinDatabases } from "../../Utils/arm/generatedClients/2020-04-01-cosmos-db/gremlinResources";
import { logConsoleProgress, logConsoleError } from "../../Utils/NotificationConsoleUtils"; import { logConsoleProgress, logConsoleError } from "../../Utils/NotificationConsoleUtils";
import { logError } from "../Logger"; import { logError } from "../Logger";
import { sendNotificationForError } from "./sendNotificationForError"; import { sendNotificationForError } from "./sendNotificationForError";

View File

@@ -6,23 +6,26 @@ import {
ExtendedResourceProperties, ExtendedResourceProperties,
SqlContainerCreateUpdateParameters, SqlContainerCreateUpdateParameters,
SqlContainerResource SqlContainerResource
} from "../../Utils/arm/generatedClients/2020-04-01/types"; } from "../../Utils/arm/generatedClients/2020-04-01-cosmos-db/types";
import { RequestOptions } from "@azure/cosmos/dist-esm"; import { RequestOptions } from "@azure/cosmos/dist-esm";
import { client } from "../CosmosClient"; import { client } from "../CosmosClient";
import { createUpdateSqlContainer, getSqlContainer } from "../../Utils/arm/generatedClients/2020-04-01/sqlResources"; import {
createUpdateSqlContainer,
getSqlContainer
} from "../../Utils/arm/generatedClients/2020-04-01-cosmos-db/sqlResources";
import { import {
createUpdateCassandraTable, createUpdateCassandraTable,
getCassandraTable getCassandraTable
} from "../../Utils/arm/generatedClients/2020-04-01/cassandraResources"; } from "../../Utils/arm/generatedClients/2020-04-01-cosmos-db/cassandraResources";
import { import {
createUpdateMongoDBCollection, createUpdateMongoDBCollection,
getMongoDBCollection getMongoDBCollection
} from "../../Utils/arm/generatedClients/2020-04-01/mongoDBResources"; } from "../../Utils/arm/generatedClients/2020-04-01-cosmos-db/mongoDBResources";
import { import {
createUpdateGremlinGraph, createUpdateGremlinGraph,
getGremlinGraph getGremlinGraph
} from "../../Utils/arm/generatedClients/2020-04-01/gremlinResources"; } from "../../Utils/arm/generatedClients/2020-04-01-cosmos-db/gremlinResources";
import { createUpdateTable, getTable } from "../../Utils/arm/generatedClients/2020-04-01/tableResources"; import { createUpdateTable, getTable } from "../../Utils/arm/generatedClients/2020-04-01-cosmos-db/tableResources";
import { logConsoleError, logConsoleInfo, logConsoleProgress } from "../../Utils/NotificationConsoleUtils"; import { logConsoleError, logConsoleInfo, logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
import { logError } from "../Logger"; import { logError } from "../Logger";
import { refreshCachedResources } from "../DataAccessUtilityBase"; import { refreshCachedResources } from "../DataAccessUtilityBase";

View File

@@ -709,11 +709,6 @@ export interface SparkPool extends ArmResource {
properties: SparkPoolProperties; properties: SparkPoolProperties;
} }
export interface MemoryUsageInfo {
freeKB: number;
totalKB: number;
}
export interface resourceTokenConnectionStringProperties { export interface resourceTokenConnectionStringProperties {
accountEndpoint: string; accountEndpoint: string;
collectionId: string; collectionId: string;

View File

@@ -1,6 +1,6 @@
import { StringUtils } from "../../../Utils/StringUtils"; import { StringUtils } from "../../../Utils/StringUtils";
import { KeyCodes } from "../../../Common/Constants"; import { KeyCodes } from "../../../Common/Constants";
import TelemetryProcessor from "../../../Shared/Telemetry/TelemetryProcessor"; import * as TelemetryProcessor from "../../../Shared/Telemetry/TelemetryProcessor";
import { Action, ActionModifiers } from "../../../Shared/Telemetry/TelemetryConstants"; import { Action, ActionModifiers } from "../../../Shared/Telemetry/TelemetryConstants";
import CollapseChevronDownIcon from "../../../../images/QueryBuilder/CollapseChevronDown_16x.png"; import CollapseChevronDownIcon from "../../../../images/QueryBuilder/CollapseChevronDown_16x.png";

View File

@@ -265,6 +265,9 @@ exports[`test render renders with filters 1`] = `
"buttonTextDisabled": "#a19f9d", "buttonTextDisabled": "#a19f9d",
"buttonTextHovered": "#201f1e", "buttonTextHovered": "#201f1e",
"buttonTextPressed": "#201f1e", "buttonTextPressed": "#201f1e",
"cardShadow": "0 1.6px 3.6px 0 rgba(0, 0, 0, 0.132), 0 0.3px 0.9px 0 rgba(0, 0, 0, 0.108)",
"cardShadowHovered": "0 3.2px 7.2px 0 rgba(0, 0, 0, 0.132), 0 0.6px 1.8px 0 rgba(0, 0, 0, 0.108)",
"cardStandoutBackground": "#ffffff",
"defaultStateBackground": "#faf9f8", "defaultStateBackground": "#faf9f8",
"disabledBackground": "#f3f2f1", "disabledBackground": "#f3f2f1",
"disabledBodySubtext": "#c8c6c4", "disabledBodySubtext": "#c8c6c4",
@@ -604,6 +607,9 @@ exports[`test render renders with filters 1`] = `
"buttonTextDisabled": "#a19f9d", "buttonTextDisabled": "#a19f9d",
"buttonTextHovered": "#201f1e", "buttonTextHovered": "#201f1e",
"buttonTextPressed": "#201f1e", "buttonTextPressed": "#201f1e",
"cardShadow": "0 1.6px 3.6px 0 rgba(0, 0, 0, 0.132), 0 0.3px 0.9px 0 rgba(0, 0, 0, 0.108)",
"cardShadowHovered": "0 3.2px 7.2px 0 rgba(0, 0, 0, 0.132), 0 0.6px 1.8px 0 rgba(0, 0, 0, 0.108)",
"cardStandoutBackground": "#ffffff",
"defaultStateBackground": "#faf9f8", "defaultStateBackground": "#faf9f8",
"disabledBackground": "#f3f2f1", "disabledBackground": "#f3f2f1",
"disabledBodySubtext": "#c8c6c4", "disabledBodySubtext": "#c8c6c4",
@@ -997,6 +1003,9 @@ exports[`test render renders with filters 1`] = `
"buttonTextDisabled": "#a19f9d", "buttonTextDisabled": "#a19f9d",
"buttonTextHovered": "#201f1e", "buttonTextHovered": "#201f1e",
"buttonTextPressed": "#201f1e", "buttonTextPressed": "#201f1e",
"cardShadow": "0 1.6px 3.6px 0 rgba(0, 0, 0, 0.132), 0 0.3px 0.9px 0 rgba(0, 0, 0, 0.108)",
"cardShadowHovered": "0 3.2px 7.2px 0 rgba(0, 0, 0, 0.132), 0 0.6px 1.8px 0 rgba(0, 0, 0, 0.108)",
"cardStandoutBackground": "#ffffff",
"defaultStateBackground": "#faf9f8", "defaultStateBackground": "#faf9f8",
"disabledBackground": "#f3f2f1", "disabledBackground": "#f3f2f1",
"disabledBodySubtext": "#c8c6c4", "disabledBodySubtext": "#c8c6c4",
@@ -1113,6 +1122,11 @@ exports[`test render renders with filters 1`] = `
}, },
"iconDisabled": Object { "iconDisabled": Object {
"color": "#a19f9d", "color": "#a19f9d",
"selectors": Object {
"@media screen and (-ms-high-contrast: active)": Object {
"color": "GrayText",
},
},
}, },
"label": Array [ "label": Array [
Object { Object {
@@ -1134,6 +1148,11 @@ exports[`test render renders with filters 1`] = `
}, },
"menuIconDisabled": Object { "menuIconDisabled": Object {
"color": "#a19f9d", "color": "#a19f9d",
"selectors": Object {
"@media screen and (-ms-high-contrast: active)": Object {
"color": "GrayText",
},
},
}, },
"root": Array [ "root": Array [
Object { Object {
@@ -1150,7 +1169,6 @@ exports[`test render renders with filters 1`] = `
"right": 2, "right": 2,
"selectors": Object { "selectors": Object {
"@media screen and (-ms-high-contrast: active)": Object { "@media screen and (-ms-high-contrast: active)": Object {
"border": "none",
"bottom": -2, "bottom": -2,
"left": -2, "left": -2,
"outlineColor": "ButtonText", "outlineColor": "ButtonText",
@@ -1230,7 +1248,6 @@ exports[`test render renders with filters 1`] = `
"right": 2, "right": 2,
"selectors": Object { "selectors": Object {
"@media screen and (-ms-high-contrast: active)": Object { "@media screen and (-ms-high-contrast: active)": Object {
"border": "none",
"bottom": -2, "bottom": -2,
"left": -2, "left": -2,
"outlineColor": "ButtonText", "outlineColor": "ButtonText",
@@ -1259,10 +1276,6 @@ exports[`test render renders with filters 1`] = `
":hover": Object { ":hover": Object {
"outline": 0, "outline": 0,
}, },
"@media screen and (-ms-high-contrast: active)": Object {
"borderColor": "grayText",
"color": "grayText",
},
}, },
}, },
Object { Object {
@@ -1362,13 +1375,21 @@ exports[`test render renders with filters 1`] = `
"selectors": Object { "selectors": Object {
"@media screen and (-ms-high-contrast: active)": Object { "@media screen and (-ms-high-contrast: active)": Object {
"MsHighContrastAdjust": "none", "MsHighContrastAdjust": "none",
"backgroundColor": "WindowText", "backgroundColor": "Window",
"color": "Window", "border": "1px solid WindowText",
"borderRightWidth": "0",
"color": "WindowText",
}, },
}, },
}, },
".ms-Button--primary + .ms-Button": Object { ".ms-Button--primary + .ms-Button": Object {
"border": "none", "border": "none",
"selectors": Object {
"@media screen and (-ms-high-contrast: active)": Object {
"border": "1px solid WindowText",
"borderLeftWidth": "0",
},
},
}, },
}, },
}, },
@@ -1408,6 +1429,9 @@ exports[`test render renders with filters 1`] = `
"borderColor": "GrayText", "borderColor": "GrayText",
"color": "GrayText", "color": "GrayText",
}, },
"@media screen and (forced-colors: active)": Object {
"forcedColorAdjust": "none",
},
}, },
}, },
"splitButtonContainerFocused": Object { "splitButtonContainerFocused": Object {
@@ -1554,6 +1578,13 @@ exports[`test render renders with filters 1`] = `
}, },
}, },
}, },
".ms-Button-menuIcon": Object {
"selectors": Object {
"@media screen and (-ms-high-contrast: active)": Object {
"color": "GrayText",
},
},
},
":hover": Object { ":hover": Object {
"cursor": "default", "cursor": "default",
}, },
@@ -1775,6 +1806,9 @@ exports[`test render renders with filters 1`] = `
"buttonTextDisabled": "#a19f9d", "buttonTextDisabled": "#a19f9d",
"buttonTextHovered": "#201f1e", "buttonTextHovered": "#201f1e",
"buttonTextPressed": "#201f1e", "buttonTextPressed": "#201f1e",
"cardShadow": "0 1.6px 3.6px 0 rgba(0, 0, 0, 0.132), 0 0.3px 0.9px 0 rgba(0, 0, 0, 0.108)",
"cardShadowHovered": "0 3.2px 7.2px 0 rgba(0, 0, 0, 0.132), 0 0.6px 1.8px 0 rgba(0, 0, 0, 0.108)",
"cardStandoutBackground": "#ffffff",
"defaultStateBackground": "#faf9f8", "defaultStateBackground": "#faf9f8",
"disabledBackground": "#f3f2f1", "disabledBackground": "#f3f2f1",
"disabledBodySubtext": "#c8c6c4", "disabledBodySubtext": "#c8c6c4",

View File

@@ -6,7 +6,7 @@ import { RepoListItem } from "./GitHubReposComponent";
import { ChildrenMargin } from "./GitHubStyleConstants"; import { ChildrenMargin } from "./GitHubStyleConstants";
import * as GitHubUtils from "../../../Utils/GitHubUtils"; import * as GitHubUtils from "../../../Utils/GitHubUtils";
import { IGitHubRepo } from "../../../GitHub/GitHubClient"; import { IGitHubRepo } from "../../../GitHub/GitHubClient";
import TelemetryProcessor from "../../../Shared/Telemetry/TelemetryProcessor"; import * as TelemetryProcessor from "../../../Shared/Telemetry/TelemetryProcessor";
import UrlUtility from "../../../Common/UrlUtility"; import UrlUtility from "../../../Common/UrlUtility";
import Explorer from "../../Explorer"; import Explorer from "../../Explorer";

View File

@@ -24,7 +24,7 @@ import {
} from "office-ui-fabric-react/lib/utilities/selection/index"; } from "office-ui-fabric-react/lib/utilities/selection/index";
import { StyleConstants } from "../../../Common/Constants"; import { StyleConstants } from "../../../Common/Constants";
import { TextField, ITextFieldProps, ITextField } from "office-ui-fabric-react/lib/TextField"; import { TextField, ITextFieldProps, ITextField } from "office-ui-fabric-react/lib/TextField";
import TelemetryProcessor from "../../../Shared/Telemetry/TelemetryProcessor"; import * as TelemetryProcessor from "../../../Shared/Telemetry/TelemetryProcessor";
import SaveQueryBannerIcon from "../../../../images/save_query_banner.png"; import SaveQueryBannerIcon from "../../../../images/save_query_banner.png";
import { QueriesClient } from "../../../Common/QueriesClient"; import { QueriesClient } from "../../../Common/QueriesClient";

View File

@@ -26,7 +26,7 @@ import NewVertexPane from "./Panes/NewVertexPane";
import NotebookV2Tab, { NotebookTabOptions } from "./Tabs/NotebookV2Tab"; import NotebookV2Tab, { NotebookTabOptions } from "./Tabs/NotebookV2Tab";
import Q from "q"; import Q from "q";
import ResourceTokenCollection from "./Tree/ResourceTokenCollection"; import ResourceTokenCollection from "./Tree/ResourceTokenCollection";
import TelemetryProcessor from "../Shared/Telemetry/TelemetryProcessor"; import * as TelemetryProcessor from "../Shared/Telemetry/TelemetryProcessor";
import TerminalTab from "./Tabs/TerminalTab"; import TerminalTab from "./Tabs/TerminalTab";
import { Action, ActionModifiers } from "../Shared/Telemetry/TelemetryConstants"; import { Action, ActionModifiers } from "../Shared/Telemetry/TelemetryConstants";
import { ActionContracts, MessageTypes } from "../Contracts/ExplorerContracts"; import { ActionContracts, MessageTypes } from "../Contracts/ExplorerContracts";
@@ -243,7 +243,6 @@ export default class Explorer {
public arcadiaWorkspaces: ko.ObservableArray<ArcadiaWorkspaceItem>; public arcadiaWorkspaces: ko.ObservableArray<ArcadiaWorkspaceItem>;
public hasStorageAnalyticsAfecFeature: ko.Observable<boolean>; public hasStorageAnalyticsAfecFeature: ko.Observable<boolean>;
public isSynapseLinkUpdating: ko.Observable<boolean>; public isSynapseLinkUpdating: ko.Observable<boolean>;
public memoryUsageInfo: ko.Observable<DataModels.MemoryUsageInfo>;
public notebookManager?: any; // This is dynamically loaded public notebookManager?: any; // This is dynamically loaded
private _panes: ContextualPaneBase[] = []; private _panes: ContextualPaneBase[] = [];
@@ -374,7 +373,6 @@ export default class Explorer {
); );
} }
}); });
this.memoryUsageInfo = ko.observable<DataModels.MemoryUsageInfo>();
this.notificationsClient = options.notificationsClient; this.notificationsClient = options.notificationsClient;
this.isEmulator = options.isEmulator; this.isEmulator = options.isEmulator;
@@ -3117,12 +3115,6 @@ export default class Explorer {
} else { } else {
loadingTitle.innerHTML = title; loadingTitle.innerHTML = title;
} }
TelemetryProcessor.trace(
Action.LoadingStatus,
ActionModifiers.Mark,
title !== "Welcome to Azure Cosmos DB" ? `Title: ${title}, Text: ${text}` : text
);
} }
private _openSetupNotebooksPaneForQuickstart(): void { private _openSetupNotebooksPaneForQuickstart(): void {

View File

@@ -23,7 +23,7 @@ import { GraphConfig } from "../../Tabs/GraphTab";
import { EditorReact } from "../../Controls/Editor/EditorReact"; import { EditorReact } from "../../Controls/Editor/EditorReact";
import LoadGraphIcon from "../../../../images/LoadGraph.png"; import LoadGraphIcon from "../../../../images/LoadGraph.png";
import { Action } from "../../../Shared/Telemetry/TelemetryConstants"; import { Action } from "../../../Shared/Telemetry/TelemetryConstants";
import TelemetryProcessor from "../../../Shared/Telemetry/TelemetryProcessor"; import * as TelemetryProcessor from "../../../Shared/Telemetry/TelemetryProcessor";
import * as Constants from "../../../Common/Constants"; import * as Constants from "../../../Common/Constants";
import { InputProperty } from "../../../Contracts/ViewModels"; import { InputProperty } from "../../../Contracts/ViewModels";
import { QueryIterator, ItemDefinition, Resource } from "@azure/cosmos"; import { QueryIterator, ItemDefinition, Resource } from "@azure/cosmos";

View File

@@ -82,9 +82,7 @@ export class CommandBarComponentAdapter implements ReactAdapter {
uiFabricControlButtons.forEach((btn: ICommandBarItemProps) => (btn.iconOnly = true)); uiFabricControlButtons.forEach((btn: ICommandBarItemProps) => (btn.iconOnly = true));
if (this.isNotebookTabActive()) { if (this.isNotebookTabActive()) {
uiFabricControlButtons.unshift( uiFabricControlButtons.unshift(CommandBarUtil.createMemoryTracker("memoryTracker"));
CommandBarUtil.createMemoryTracker("memoryTracker", this.container.memoryUsageInfo)
);
} }
return ( return (

View File

@@ -2,7 +2,7 @@ import * as ViewModels from "../../../Contracts/ViewModels";
import { PlatformType } from "../../../PlatformType"; import { PlatformType } from "../../../PlatformType";
import { Action, ActionModifiers } from "../../../Shared/Telemetry/TelemetryConstants"; import { Action, ActionModifiers } from "../../../Shared/Telemetry/TelemetryConstants";
import { Areas } from "../../../Common/Constants"; import { Areas } from "../../../Common/Constants";
import TelemetryProcessor from "../../../Shared/Telemetry/TelemetryProcessor"; import * as TelemetryProcessor from "../../../Shared/Telemetry/TelemetryProcessor";
import AddDatabaseIcon from "../../../../images/AddDatabase.svg"; import AddDatabaseIcon from "../../../../images/AddDatabase.svg";
import AddCollectionIcon from "../../../../images/AddCollection.svg"; import AddCollectionIcon from "../../../../images/AddCollection.svg";

View File

@@ -1,16 +1,14 @@
import _ from "underscore"; import { ICommandBarItemProps } from "office-ui-fabric-react/lib/CommandBar";
import * as React from "react"; import { Dropdown, IDropdownOption, IDropdownStyles } from "office-ui-fabric-react/lib/Dropdown";
import { Observable } from "knockout";
import { IconType } from "office-ui-fabric-react/lib/Icon"; import { IconType } from "office-ui-fabric-react/lib/Icon";
import { IComponentAsProps } from "office-ui-fabric-react/lib/Utilities"; import { IComponentAsProps } from "office-ui-fabric-react/lib/Utilities";
import { StyleConstants } from "../../../Common/Constants"; import * as React from "react";
import { ICommandBarItemProps } from "office-ui-fabric-react/lib/CommandBar"; import _ from "underscore";
import { Dropdown, IDropdownStyles, IDropdownOption } from "office-ui-fabric-react/lib/Dropdown";
import { CommandButtonComponentProps } from "../../Controls/CommandButton/CommandButtonComponent";
import ChevronDownIcon from "../../../../images/Chevron_down.svg"; import ChevronDownIcon from "../../../../images/Chevron_down.svg";
import { StyleConstants } from "../../../Common/Constants";
import { ArcadiaMenuPicker } from "../../Controls/Arcadia/ArcadiaMenuPicker"; import { ArcadiaMenuPicker } from "../../Controls/Arcadia/ArcadiaMenuPicker";
import { CommandButtonComponentProps } from "../../Controls/CommandButton/CommandButtonComponent";
import { MemoryTrackerComponent } from "./MemoryTrackerComponent"; import { MemoryTrackerComponent } from "./MemoryTrackerComponent";
import { MemoryUsageInfo } from "../../../Contracts/DataModels";
/** /**
* Utilities for CommandBar * Utilities for CommandBar
@@ -178,10 +176,10 @@ export class CommandBarUtil {
}; };
} }
public static createMemoryTracker(key: string, memoryUsageInfo: Observable<MemoryUsageInfo>): ICommandBarItemProps { public static createMemoryTracker(key: string): ICommandBarItemProps {
return { return {
key, key,
onRender: () => <MemoryTrackerComponent memoryUsageInfo={memoryUsageInfo} /> onRender: () => <MemoryTrackerComponent />
}; };
} }
} }

View File

@@ -1,50 +1,71 @@
import * as React from "react"; import React, { FunctionComponent } from "react";
import { Observable, Subscription } from "knockout"; import useSWR from "swr";
import { MemoryUsageInfo } from "../../../Contracts/DataModels";
import { ProgressIndicator } from "office-ui-fabric-react/lib/ProgressIndicator"; import { ProgressIndicator } from "office-ui-fabric-react/lib/ProgressIndicator";
import { Spinner, SpinnerSize } from "office-ui-fabric-react/lib/Spinner"; import { Spinner, SpinnerSize } from "office-ui-fabric-react/lib/Spinner";
import { Stack } from "office-ui-fabric-react/lib/Stack"; import { Stack } from "office-ui-fabric-react/lib/Stack";
import { listConnectionInfo } from "../../../Utils/arm/generatedClients/2020-04-01-notebook/notebookWorkspaces";
import { NotebookWorkspaceConnectionInfoResult } from "../../../Utils/arm/generatedClients/2020-04-01-notebook/types";
import { userContext } from "../../../UserContext";
interface MemoryTrackerProps { export interface MemoryUsageInfo {
memoryUsageInfo: Observable<MemoryUsageInfo>; total: number;
free: number;
} }
export class MemoryTrackerComponent extends React.Component<MemoryTrackerProps> { const kbInGB = 1048576;
private memoryUsageInfoSubscription: Subscription;
public componentDidMount(): void { const fetchMemoryInfo = async (_key: unknown, connectionInfo: NotebookWorkspaceConnectionInfoResult) => {
this.memoryUsageInfoSubscription = this.props.memoryUsageInfo.subscribe(() => { const response = await fetch(`${connectionInfo.notebookServerEndpoint}/api/metrics/memory`, {
this.forceUpdate(); method: "GET",
}); headers: {
} Authorization: `Token ${connectionInfo.authToken}`,
"content-type": "application/json"
public componentWillUnmount(): void {
this.memoryUsageInfoSubscription && this.memoryUsageInfoSubscription.dispose();
}
public render(): JSX.Element {
const memoryUsageInfo: MemoryUsageInfo = this.props.memoryUsageInfo();
if (!memoryUsageInfo) {
return (
<Stack className="memoryTrackerContainer" horizontal>
<span>Memory</span>
<Spinner size={SpinnerSize.medium} />
</Stack>
);
} }
});
if (!response.ok) {
throw new Error(await response.text());
}
const memoryUsageInfo = (await response.json()) as MemoryUsageInfo;
return {
totalKB: memoryUsageInfo.total,
freeKB: memoryUsageInfo.free
};
};
const totalGB = memoryUsageInfo.totalKB / 1048576; export const MemoryTrackerComponent: FunctionComponent = () => {
const usedGB = totalGB - memoryUsageInfo.freeKB / 1048576; const { data: connectionInfo } = useSWR(
[
"notebooksConnectionInfo",
userContext.subscriptionId,
userContext.resourceGroup,
userContext.databaseAccount.name,
"default"
],
(_key, subscriptionId, resourceGroup, accountName, workspace) =>
listConnectionInfo(subscriptionId, resourceGroup, accountName, workspace)
);
const { data } = useSWR(connectionInfo ? ["memoryUsage", connectionInfo] : null, fetchMemoryInfo, {
refreshInterval: 2000
});
if (!data) {
return ( return (
<Stack className="memoryTrackerContainer" horizontal> <Stack className="memoryTrackerContainer" horizontal>
<span>Memory</span> <span>Memory</span>
<ProgressIndicator <Spinner size={SpinnerSize.medium} />
className={usedGB / totalGB > 0.8 ? "lowMemory" : ""}
description={usedGB.toFixed(1) + " of " + totalGB.toFixed(1) + " GB"}
percentComplete={usedGB / totalGB}
/>
</Stack> </Stack>
); );
} }
} const totalGB = data.totalKB / kbInGB;
const usedGB = totalGB - data.freeKB / kbInGB;
return (
<Stack className="memoryTrackerContainer" horizontal>
<span>Memory</span>
<ProgressIndicator
className={usedGB / totalGB > 0.8 ? "lowMemory" : ""}
description={usedGB.toFixed(1) + " of " + totalGB.toFixed(1) + " GB"}
percentComplete={usedGB / totalGB}
/>
</Stack>
);
};

View File

@@ -32,7 +32,7 @@ import { Store, AnyAction, MiddlewareAPI, Middleware, Dispatch } from "redux";
import configureStore from "./NotebookComponent/store"; import configureStore from "./NotebookComponent/store";
import { Notification } from "react-notification-system"; import { Notification } from "react-notification-system";
import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor"; import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
import { Action } from "../../Shared/Telemetry/TelemetryConstants"; import { Action } from "../../Shared/Telemetry/TelemetryConstants";
export type KernelSpecsDisplay = { name: string; displayName: string }; export type KernelSpecsDisplay = { name: string; displayName: string };

View File

@@ -37,7 +37,7 @@ import * as Constants from "../../../Common/Constants";
import * as NotificationConsoleUtils from "../../../Utils/NotificationConsoleUtils"; import * as NotificationConsoleUtils from "../../../Utils/NotificationConsoleUtils";
import { ConsoleDataType } from "../../Menus/NotificationConsole/NotificationConsoleComponent"; import { ConsoleDataType } from "../../Menus/NotificationConsole/NotificationConsoleComponent";
import * as CdbActions from "./actions"; import * as CdbActions from "./actions";
import TelemetryProcessor from "../../../Shared/Telemetry/TelemetryProcessor"; import * as TelemetryProcessor from "../../../Shared/Telemetry/TelemetryProcessor";
import { Action as TelemetryAction } from "../../../Shared/Telemetry/TelemetryConstants"; import { Action as TelemetryAction } from "../../../Shared/Telemetry/TelemetryConstants";
import { CdbAppState } from "./types"; import { CdbAppState } from "./types";
import { decryptJWTToken } from "../../../Utils/AuthorizationUtils"; import { decryptJWTToken } from "../../../Utils/AuthorizationUtils";

View File

@@ -1,7 +1,7 @@
import { actions, CoreRecord, reducers as nteractReducers } from "@nteract/core"; import { actions, CoreRecord, reducers as nteractReducers } from "@nteract/core";
import { Action } from "redux"; import { Action } from "redux";
import { Areas } from "../../../Common/Constants"; import { Areas } from "../../../Common/Constants";
import TelemetryProcessor from "../../../Shared/Telemetry/TelemetryProcessor"; import * as TelemetryProcessor from "../../../Shared/Telemetry/TelemetryProcessor";
import * as cdbActions from "./actions"; import * as cdbActions from "./actions";
import { CdbRecord } from "./types"; import { CdbRecord } from "./types";

View File

@@ -2,89 +2,13 @@
* Notebook container related stuff * Notebook container related stuff
*/ */
import * as DataModels from "../../Contracts/DataModels"; import * as DataModels from "../../Contracts/DataModels";
import * as Constants from "../../Common/Constants";
import { ConsoleDataType } from "../Menus/NotificationConsole/NotificationConsoleComponent";
import * as NotificationConsoleUtils from "../../Utils/NotificationConsoleUtils";
import * as Logger from "../../Common/Logger"; import * as Logger from "../../Common/Logger";
export class NotebookContainerClient { export class NotebookContainerClient {
private reconnectingNotificationId: string; private reconnectingNotificationId: string;
private isResettingWorkspace: boolean; private isResettingWorkspace: boolean;
constructor( constructor(private notebookServerInfo: ko.Observable<DataModels.NotebookWorkspaceConnectionInfo>) {}
private notebookServerInfo: ko.Observable<DataModels.NotebookWorkspaceConnectionInfo>,
private onConnectionLost: () => void,
private onMemoryUsageInfoUpdate: (update: DataModels.MemoryUsageInfo) => void
) {
if (notebookServerInfo() && notebookServerInfo().notebookServerEndpoint) {
this.scheduleHeartbeat(Constants.Notebook.heartbeatDelayMs);
} else {
const subscription = notebookServerInfo.subscribe((newServerInfo: DataModels.NotebookWorkspaceConnectionInfo) => {
if (newServerInfo && newServerInfo.notebookServerEndpoint) {
this.scheduleHeartbeat(Constants.Notebook.heartbeatDelayMs);
}
subscription.dispose();
});
}
}
/**
* Heartbeat: each ping schedules another ping
*/
private scheduleHeartbeat(delayMs: number): void {
setTimeout(() => {
this.getMemoryUsage()
.then(memoryUsageInfo => this.onMemoryUsageInfoUpdate(memoryUsageInfo))
.finally(() => this.scheduleHeartbeat(Constants.Notebook.heartbeatDelayMs));
}, delayMs);
}
private async getMemoryUsage(): Promise<DataModels.MemoryUsageInfo> {
if (!this.notebookServerInfo() || !this.notebookServerInfo().notebookServerEndpoint) {
const error = "No server endpoint detected";
Logger.logError(error, "NotebookContainerClient/getMemoryUsage");
return Promise.reject(error);
}
if (this.isResettingWorkspace) {
return undefined;
}
const { notebookServerEndpoint, authToken } = this.getNotebookServerConfig();
try {
const response = await fetch(`${notebookServerEndpoint}/api/metrics/memory`, {
method: "GET",
headers: {
Authorization: authToken,
"content-type": "application/json"
}
});
if (response.ok) {
if (this.reconnectingNotificationId) {
NotificationConsoleUtils.clearInProgressMessageWithId(this.reconnectingNotificationId);
this.reconnectingNotificationId = "";
}
const memoryUsageInfo = await response.json();
if (memoryUsageInfo) {
return {
totalKB: memoryUsageInfo.total,
freeKB: memoryUsageInfo.free
};
}
}
return undefined;
} catch (error) {
Logger.logError(error, "NotebookContainerClient/getMemoryUsage");
if (!this.reconnectingNotificationId) {
this.reconnectingNotificationId = NotificationConsoleUtils.logConsoleMessage(
ConsoleDataType.InProgress,
"Connection lost with Notebook server. Attempting to reconnect..."
);
}
this.onConnectionLost();
return undefined;
}
}
public async resetWorkspace(): Promise<void> { public async resetWorkspace(): Promise<void> {
this.isResettingWorkspace = true; this.isResettingWorkspace = true;

View File

@@ -9,14 +9,13 @@ import * as Logger from "../../Common/Logger";
import { HttpStatusCodes, Areas } from "../../Common/Constants"; import { HttpStatusCodes, Areas } from "../../Common/Constants";
import { GitHubReposPane } from "../Panes/GitHubReposPane"; import { GitHubReposPane } from "../Panes/GitHubReposPane";
import ko from "knockout"; import ko from "knockout";
import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor"; import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
import { Action, ActionModifiers } from "../../Shared/Telemetry/TelemetryConstants"; import { Action, ActionModifiers } from "../../Shared/Telemetry/TelemetryConstants";
import { IContentProvider } from "@nteract/core"; import { IContentProvider } from "@nteract/core";
import { NotebookContentProvider } from "./NotebookComponent/NotebookContentProvider"; import { NotebookContentProvider } from "./NotebookComponent/NotebookContentProvider";
import { GitHubContentProvider } from "../../GitHub/GitHubContentProvider"; import { GitHubContentProvider } from "../../GitHub/GitHubContentProvider";
import { contents } from "rx-jupyter"; import { contents } from "rx-jupyter";
import { NotebookContainerClient } from "./NotebookContainerClient"; import { NotebookContainerClient } from "./NotebookContainerClient";
import { MemoryUsageInfo } from "../../Contracts/DataModels";
import { NotebookContentClient } from "./NotebookContentClient"; import { NotebookContentClient } from "./NotebookContentClient";
import { DialogProps } from "../Controls/DialogReactComponent/DialogComponent"; import { DialogProps } from "../Controls/DialogReactComponent/DialogComponent";
import { ResourceTreeAdapter } from "../Tree/ResourceTreeAdapter"; import { ResourceTreeAdapter } from "../Tree/ResourceTreeAdapter";
@@ -76,11 +75,7 @@ export default class NotebookManager {
contents.JupyterContentProvider contents.JupyterContentProvider
); );
this.notebookClient = new NotebookContainerClient( this.notebookClient = new NotebookContainerClient(this.params.container.notebookServerInfo);
this.params.container.notebookServerInfo,
() => this.params.container.initNotebooks(this.params.container.databaseAccount()),
(update: MemoryUsageInfo) => this.params.container.memoryUsageInfo(update)
);
this.notebookContentClient = new NotebookContentClient( this.notebookContentClient = new NotebookContentClient(
this.params.container.notebookServerInfo, this.params.container.notebookServerInfo,

View File

@@ -25,7 +25,7 @@
<!-- Add collection header - Start --> <!-- Add collection header - Start -->
<div class="firstdivbg headerline"> <div class="firstdivbg headerline">
<span id="containerTitle" data-bind="text: title"></span> <span id="containerTitle" data-bind="text: title"></span>
<div class="closeImg" id="closeBtnAddCollection" role="button" aria-label="Close pane" <div class="closeImg" id="closeBtnAddCollection" role="button" aria-label="Add collection close pane"
data-bind="click: cancel, event: { keypress: onCloseKeyPress }" tabindex="0"> data-bind="click: cancel, event: { keypress: onCloseKeyPress }" tabindex="0">
<img src="../../../images/close-black.svg" title="Close" alt="Close" /> <img src="../../../images/close-black.svg" title="Close" alt="Close" />
</div> </div>

View File

@@ -9,7 +9,7 @@ import * as PricingUtils from "../../Utils/PricingUtils";
import * as SharedConstants from "../../Shared/Constants"; import * as SharedConstants from "../../Shared/Constants";
import * as ViewModels from "../../Contracts/ViewModels"; import * as ViewModels from "../../Contracts/ViewModels";
import editable from "../../Common/EditableUtility"; import editable from "../../Common/EditableUtility";
import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor"; import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
import { Action, ActionModifiers } from "../../Shared/Telemetry/TelemetryConstants"; import { Action, ActionModifiers } from "../../Shared/Telemetry/TelemetryConstants";
import { configContext, Platform } from "../../ConfigContext"; import { configContext, Platform } from "../../ConfigContext";
import { ContextualPaneBase } from "./ContextualPaneBase"; import { ContextualPaneBase } from "./ContextualPaneBase";
@@ -943,7 +943,7 @@ export default class AddCollectionPane extends ContextualPaneBase {
const defaultThroughput = this.container.collectionCreationDefaults.throughput; const defaultThroughput = this.container.collectionCreationDefaults.throughput;
this.throughputSinglePartition(defaultThroughput.fixed); this.throughputSinglePartition(defaultThroughput.fixed);
this.throughputMultiPartition( this.throughputMultiPartition(
AddCollectionUtility.Utilities.getMaxThroughput(this.container.collectionCreationDefaults, this.container) AddCollectionUtility.getMaxThroughput(this.container.collectionCreationDefaults, this.container)
); );
this.throughputDatabase(defaultThroughput.shared); this.throughputDatabase(defaultThroughput.shared);
@@ -1167,17 +1167,19 @@ export default class AddCollectionPane extends ContextualPaneBase {
private _updateThroughputLimitByCollectionStorage() { private _updateThroughputLimitByCollectionStorage() {
const storage = this.storage(); const storage = this.storage();
const minThroughputRU = AddCollectionUtility.Utilities.getMinRUForStorageOption( const minThroughputRU =
this.container.collectionCreationDefaults, storage === SharedConstants.CollectionCreation.storage10Gb
storage ? SharedConstants.CollectionCreation.DefaultCollectionRUs400
); : this.container.collectionCreationDefaults.throughput.unlimitedmin;
let maxThroughputRU = AddCollectionUtility.Utilities.getMaxRUForStorageOption( let maxThroughputRU;
this.container.collectionCreationDefaults,
storage
);
if (this.isTryCosmosDBSubscription()) { if (this.isTryCosmosDBSubscription()) {
maxThroughputRU = Constants.TryCosmosExperience.maxRU; maxThroughputRU = Constants.TryCosmosExperience.maxRU;
} else {
maxThroughputRU =
storage === SharedConstants.CollectionCreation.storage10Gb
? SharedConstants.CollectionCreation.DefaultCollectionRUs10K
: this.container.collectionCreationDefaults.throughput.unlimitedmax;
} }
this.minThroughputRU(minThroughputRU); this.minThroughputRU(minThroughputRU);

View File

@@ -1,4 +1,3 @@
import * as AddCollectionUtility from "../../Shared/AddCollectionUtility";
import * as AutoPilotUtils from "../../Utils/AutoPilotUtils"; import * as AutoPilotUtils from "../../Utils/AutoPilotUtils";
import * as Constants from "../../Common/Constants"; import * as Constants from "../../Common/Constants";
import * as DataModels from "../../Contracts/DataModels"; import * as DataModels from "../../Contracts/DataModels";
@@ -8,15 +7,11 @@ import * as PricingUtils from "../../Utils/PricingUtils";
import * as SharedConstants from "../../Shared/Constants"; import * as SharedConstants from "../../Shared/Constants";
import * as ViewModels from "../../Contracts/ViewModels"; import * as ViewModels from "../../Contracts/ViewModels";
import editable from "../../Common/EditableUtility"; import editable from "../../Common/EditableUtility";
import EnvironmentUtility from "../../Common/EnvironmentUtility"; import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
import { Action, ActionModifiers } from "../../Shared/Telemetry/TelemetryConstants"; import { Action, ActionModifiers } from "../../Shared/Telemetry/TelemetryConstants";
import { AddDbUtilities } from "../../Shared/AddDatabaseUtility";
import { CassandraAPIDataClient } from "../Tables/TableDataClient";
import { ContextualPaneBase } from "./ContextualPaneBase"; import { ContextualPaneBase } from "./ContextualPaneBase";
import { createDatabase } from "../../Common/dataAccess/createDatabase"; import { createDatabase } from "../../Common/dataAccess/createDatabase";
import { PlatformType } from "../../PlatformType"; import { PlatformType } from "../../PlatformType";
import { userContext } from "../../UserContext";
export default class AddDatabasePane extends ContextualPaneBase { export default class AddDatabasePane extends ContextualPaneBase {
public defaultExperience: ko.Computed<string>; public defaultExperience: ko.Computed<string>;

View File

@@ -5,7 +5,7 @@ import { Areas } from "../../Common/Constants";
import { ContextualPaneBase } from "./ContextualPaneBase"; import { ContextualPaneBase } from "./ContextualPaneBase";
import * as Logger from "../../Common/Logger"; import * as Logger from "../../Common/Logger";
import { QueriesGridComponentAdapter } from "../Controls/QueriesGridReactComponent/QueriesGridComponentAdapter"; import { QueriesGridComponentAdapter } from "../Controls/QueriesGridReactComponent/QueriesGridComponentAdapter";
import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor"; import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
import QueryTab from "../Tabs/QueryTab"; import QueryTab from "../Tabs/QueryTab";
export class BrowseQueriesPane extends ContextualPaneBase { export class BrowseQueriesPane extends ContextualPaneBase {

View File

@@ -7,7 +7,7 @@ import * as ko from "knockout";
import * as PricingUtils from "../../Utils/PricingUtils"; import * as PricingUtils from "../../Utils/PricingUtils";
import * as SharedConstants from "../../Shared/Constants"; import * as SharedConstants from "../../Shared/Constants";
import * as ViewModels from "../../Contracts/ViewModels"; import * as ViewModels from "../../Contracts/ViewModels";
import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor"; import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
import { Action, ActionModifiers } from "../../Shared/Telemetry/TelemetryConstants"; import { Action, ActionModifiers } from "../../Shared/Telemetry/TelemetryConstants";
import { CassandraAPIDataClient } from "../Tables/TableDataClient"; import { CassandraAPIDataClient } from "../Tables/TableDataClient";
import { ContextualPaneBase } from "./ContextualPaneBase"; import { ContextualPaneBase } from "./ContextualPaneBase";
@@ -494,9 +494,7 @@ export default class CassandraAddCollectionPane extends ContextualPaneBase {
this.selectedSharedAutoPilotTier(null); this.selectedSharedAutoPilotTier(null);
this.selectedAutoPilotThroughput(AutoPilotUtils.minAutoPilotThroughput); this.selectedAutoPilotThroughput(AutoPilotUtils.minAutoPilotThroughput);
this.sharedAutoPilotThroughput(AutoPilotUtils.minAutoPilotThroughput); this.sharedAutoPilotThroughput(AutoPilotUtils.minAutoPilotThroughput);
this.throughput( this.throughput(AddCollectionUtility.getMaxThroughput(this.container.collectionCreationDefaults, this.container));
AddCollectionUtility.Utilities.getMaxThroughput(this.container.collectionCreationDefaults, this.container)
);
this.keyspaceThroughput(throughputDefaults.shared); this.keyspaceThroughput(throughputDefaults.shared);
this.maxThroughputRU(throughputDefaults.unlimitedmax); this.maxThroughputRU(throughputDefaults.unlimitedmax);
this.minThroughputRU(throughputDefaults.unlimitedmin); this.minThroughputRU(throughputDefaults.unlimitedmin);

View File

@@ -4,7 +4,7 @@ import * as Constants from "../../Common/Constants";
import { Action, ActionModifiers } from "../../Shared/Telemetry/TelemetryConstants"; import { Action, ActionModifiers } from "../../Shared/Telemetry/TelemetryConstants";
import { KeyCodes } from "../../Common/Constants"; import { KeyCodes } from "../../Common/Constants";
import { WaitsForTemplateViewModel } from "../WaitsForTemplateViewModel"; import { WaitsForTemplateViewModel } from "../WaitsForTemplateViewModel";
import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor"; import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
import Explorer from "../Explorer"; import Explorer from "../Explorer";
// TODO: Use specific actions for logging telemetry data // TODO: Use specific actions for logging telemetry data

View File

@@ -8,7 +8,7 @@ import { Action, ActionModifiers } from "../../Shared/Telemetry/TelemetryConstan
import DeleteCollectionConfirmationPane from "./DeleteCollectionConfirmationPane"; import DeleteCollectionConfirmationPane from "./DeleteCollectionConfirmationPane";
import DeleteFeedback from "../../Common/DeleteFeedback"; import DeleteFeedback from "../../Common/DeleteFeedback";
import Explorer from "../Explorer"; import Explorer from "../Explorer";
import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor"; import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
import { TreeNode } from "../../Contracts/ViewModels"; import { TreeNode } from "../../Contracts/ViewModels";
import { deleteCollection } from "../../Common/dataAccess/deleteCollection"; import { deleteCollection } from "../../Common/dataAccess/deleteCollection";

View File

@@ -10,7 +10,7 @@ import { ContextualPaneBase } from "./ContextualPaneBase";
import { DefaultExperienceUtility } from "../../Shared/DefaultExperienceUtility"; import { DefaultExperienceUtility } from "../../Shared/DefaultExperienceUtility";
import DeleteFeedback from "../../Common/DeleteFeedback"; import DeleteFeedback from "../../Common/DeleteFeedback";
import * as NotificationConsoleUtils from "../../Utils/NotificationConsoleUtils"; import * as NotificationConsoleUtils from "../../Utils/NotificationConsoleUtils";
import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor"; import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
import { deleteCollection } from "../../Common/dataAccess/deleteCollection"; import { deleteCollection } from "../../Common/dataAccess/deleteCollection";
export default class DeleteCollectionConfirmationPane extends ContextualPaneBase { export default class DeleteCollectionConfirmationPane extends ContextualPaneBase {

View File

@@ -8,7 +8,7 @@ import * as ViewModels from "../../Contracts/ViewModels";
import DeleteDatabaseConfirmationPane from "./DeleteDatabaseConfirmationPane"; import DeleteDatabaseConfirmationPane from "./DeleteDatabaseConfirmationPane";
import DeleteFeedback from "../../Common/DeleteFeedback"; import DeleteFeedback from "../../Common/DeleteFeedback";
import Explorer from "../Explorer"; import Explorer from "../Explorer";
import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor"; import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
import { TreeNode } from "../../Contracts/ViewModels"; import { TreeNode } from "../../Contracts/ViewModels";
import { TabsManager } from "../Tabs/TabsManager"; import { TabsManager } from "../Tabs/TabsManager";
import { deleteDatabase } from "../../Common/dataAccess/deleteDatabase"; import { deleteDatabase } from "../../Common/dataAccess/deleteDatabase";

View File

@@ -11,7 +11,7 @@ import { DefaultExperienceUtility } from "../../Shared/DefaultExperienceUtility"
import DeleteFeedback from "../../Common/DeleteFeedback"; import DeleteFeedback from "../../Common/DeleteFeedback";
import * as NotificationConsoleUtils from "../../Utils/NotificationConsoleUtils"; import * as NotificationConsoleUtils from "../../Utils/NotificationConsoleUtils";
import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor"; import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
import { deleteDatabase } from "../../Common/dataAccess/deleteDatabase"; import { deleteDatabase } from "../../Common/dataAccess/deleteDatabase";
export default class DeleteDatabaseConfirmationPane extends ContextualPaneBase { export default class DeleteDatabaseConfirmationPane extends ContextualPaneBase {

View File

@@ -5,7 +5,7 @@ import * as ViewModels from "../../Contracts/ViewModels";
import { GitHubClient, IGitHubPageInfo, IGitHubRepo } from "../../GitHub/GitHubClient"; import { GitHubClient, IGitHubPageInfo, IGitHubRepo } from "../../GitHub/GitHubClient";
import { IPinnedRepo, JunoClient } from "../../Juno/JunoClient"; import { IPinnedRepo, JunoClient } from "../../Juno/JunoClient";
import { Action, ActionModifiers } from "../../Shared/Telemetry/TelemetryConstants"; import { Action, ActionModifiers } from "../../Shared/Telemetry/TelemetryConstants";
import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor"; import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
import * as GitHubUtils from "../../Utils/GitHubUtils"; import * as GitHubUtils from "../../Utils/GitHubUtils";
import { JunoUtils } from "../../Utils/JunoUtils"; import { JunoUtils } from "../../Utils/JunoUtils";
import * as NotificationConsoleUtils from "../../Utils/NotificationConsoleUtils"; import * as NotificationConsoleUtils from "../../Utils/NotificationConsoleUtils";

View File

@@ -6,7 +6,7 @@ import { Action } from "../../Shared/Telemetry/TelemetryConstants";
import { ContextualPaneBase } from "./ContextualPaneBase"; import { ContextualPaneBase } from "./ContextualPaneBase";
import { ConsoleDataType } from "../Menus/NotificationConsole/NotificationConsoleComponent"; import { ConsoleDataType } from "../Menus/NotificationConsole/NotificationConsoleComponent";
import * as NotificationConsoleUtils from "../../Utils/NotificationConsoleUtils"; import * as NotificationConsoleUtils from "../../Utils/NotificationConsoleUtils";
import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor"; import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
import QueryTab from "../Tabs/QueryTab"; import QueryTab from "../Tabs/QueryTab";
export class SaveQueryPane extends ContextualPaneBase { export class SaveQueryPane extends ContextualPaneBase {

View File

@@ -4,7 +4,7 @@ import { Areas, KeyCodes } from "../../Common/Constants";
import { ConsoleDataType } from "../Menus/NotificationConsole/NotificationConsoleComponent"; import { ConsoleDataType } from "../Menus/NotificationConsole/NotificationConsoleComponent";
import { ContextualPaneBase } from "./ContextualPaneBase"; import { ContextualPaneBase } from "./ContextualPaneBase";
import * as NotificationConsoleUtils from "../../Utils/NotificationConsoleUtils"; import * as NotificationConsoleUtils from "../../Utils/NotificationConsoleUtils";
import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor"; import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
import * as ko from "knockout"; import * as ko from "knockout";
export class SetupNotebooksPane extends ContextualPaneBase { export class SetupNotebooksPane extends ContextualPaneBase {

View File

@@ -5,7 +5,7 @@ import { DirectoryListProps } from "../Controls/Directory/DirectoryListComponent
import { DefaultDirectoryDropdownProps } from "../Controls/Directory/DefaultDirectoryDropdownComponent"; import { DefaultDirectoryDropdownProps } from "../Controls/Directory/DefaultDirectoryDropdownComponent";
import { DirectoryComponentAdapter } from "../Controls/Directory/DirectoryComponentAdapter"; import { DirectoryComponentAdapter } from "../Controls/Directory/DirectoryComponentAdapter";
import SwitchDirectoryPaneTemplate from "./SwitchDirectoryPane.html"; import SwitchDirectoryPaneTemplate from "./SwitchDirectoryPane.html";
import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor"; import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
class PaneComponent { class PaneComponent {
constructor(data: any) { constructor(data: any) {

View File

@@ -7,7 +7,7 @@ import * as CommonConstants from "../../../Common/Constants";
import * as Constants from "../Constants"; import * as Constants from "../Constants";
import * as Entities from "../Entities"; import * as Entities from "../Entities";
import QueryTablesTab from "../../Tabs/QueryTablesTab"; import QueryTablesTab from "../../Tabs/QueryTablesTab";
import TelemetryProcessor from "../../../Shared/Telemetry/TelemetryProcessor"; import * as TelemetryProcessor from "../../../Shared/Telemetry/TelemetryProcessor";
import { QueryIterator, ItemDefinition, Resource } from "@azure/cosmos"; import { QueryIterator, ItemDefinition, Resource } from "@azure/cosmos";
// This is the format of the data we will have to pass to Datatable render callback, // This is the format of the data we will have to pass to Datatable render callback,

View File

@@ -15,7 +15,7 @@ import * as Utilities from "../Utilities";
import * as Entities from "../Entities"; import * as Entities from "../Entities";
import QueryTablesTab from "../../Tabs/QueryTablesTab"; import QueryTablesTab from "../../Tabs/QueryTablesTab";
import * as TableEntityProcessor from "../TableEntityProcessor"; import * as TableEntityProcessor from "../TableEntityProcessor";
import TelemetryProcessor from "../../../Shared/Telemetry/TelemetryProcessor"; import * as TelemetryProcessor from "../../../Shared/Telemetry/TelemetryProcessor";
import * as ErrorParserUtility from "../../../Common/ErrorParserUtility"; import * as ErrorParserUtility from "../../../Common/ErrorParserUtility";
import * as DataModels from "../../../Contracts/DataModels"; import * as DataModels from "../../../Contracts/DataModels";
import * as ViewModels from "../../../Contracts/ViewModels"; import * as ViewModels from "../../../Contracts/ViewModels";

View File

@@ -13,7 +13,7 @@ import * as HeadersUtility from "../../Common/HeadersUtility";
import TabsBase from "./TabsBase"; import TabsBase from "./TabsBase";
import { DocumentsGridMetrics } from "../../Common/Constants"; import { DocumentsGridMetrics } from "../../Common/Constants";
import { Splitter, SplitterBounds, SplitterDirection } from "../../Common/Splitter"; import { Splitter, SplitterBounds, SplitterDirection } from "../../Common/Splitter";
import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor"; import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
import SaveIcon from "../../../images/save-cosmos.svg"; import SaveIcon from "../../../images/save-cosmos.svg";
import DiscardIcon from "../../../images/discard.svg"; import DiscardIcon from "../../../images/discard.svg";
import DeleteIcon from "../../../images/delete.svg"; import DeleteIcon from "../../../images/delete.svg";

View File

@@ -11,7 +11,7 @@ import editable from "../../Common/EditableUtility";
import Q from "q"; import Q from "q";
import SaveIcon from "../../../images/save-cosmos.svg"; import SaveIcon from "../../../images/save-cosmos.svg";
import TabsBase from "./TabsBase"; import TabsBase from "./TabsBase";
import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor"; import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
import { Action } from "../../Shared/Telemetry/TelemetryConstants"; import { Action } from "../../Shared/Telemetry/TelemetryConstants";
import { PlatformType } from "../../PlatformType"; import { PlatformType } from "../../PlatformType";
import { RequestOptions } from "@azure/cosmos/dist-esm"; import { RequestOptions } from "@azure/cosmos/dist-esm";

View File

@@ -14,7 +14,7 @@ import TabsBase from "./TabsBase";
import { DocumentsGridMetrics } from "../../Common/Constants"; import { DocumentsGridMetrics } from "../../Common/Constants";
import { QueryUtils } from "../../Utils/QueryUtils"; import { QueryUtils } from "../../Utils/QueryUtils";
import { Splitter, SplitterBounds, SplitterDirection } from "../../Common/Splitter"; import { Splitter, SplitterBounds, SplitterDirection } from "../../Common/Splitter";
import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor"; import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
import NewDocumentIcon from "../../../images/NewDocument.svg"; import NewDocumentIcon from "../../../images/NewDocument.svg";
import SaveIcon from "../../../images/save-cosmos.svg"; import SaveIcon from "../../../images/save-cosmos.svg";
import DiscardIcon from "../../../images/discard.svg"; import DiscardIcon from "../../../images/discard.svg";

View File

@@ -8,7 +8,7 @@ import * as ErrorParserUtility from "../../Common/ErrorParserUtility";
import MongoUtility from "../../Common/MongoUtility"; import MongoUtility from "../../Common/MongoUtility";
import ObjectId from "../Tree/ObjectId"; import ObjectId from "../Tree/ObjectId";
import Q from "q"; import Q from "q";
import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor"; import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
import { Action } from "../../Shared/Telemetry/TelemetryConstants"; import { Action } from "../../Shared/Telemetry/TelemetryConstants";
import { import {
createDocument, createDocument,

View File

@@ -6,7 +6,7 @@ import EnvironmentUtility from "../../Common/EnvironmentUtility";
import { isInvalidParentFrameOrigin } from "../../Utils/MessageValidation"; import { isInvalidParentFrameOrigin } from "../../Utils/MessageValidation";
import Q from "q"; import Q from "q";
import TabsBase from "./TabsBase"; import TabsBase from "./TabsBase";
import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor"; import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
import { Action, ActionModifiers } from "../../Shared/Telemetry/TelemetryConstants"; import { Action, ActionModifiers } from "../../Shared/Telemetry/TelemetryConstants";
import { ConsoleDataType } from "../Menus/NotificationConsole/NotificationConsoleComponent"; import { ConsoleDataType } from "../Menus/NotificationConsole/NotificationConsoleComponent";
import { HashMap } from "../../Common/HashMap"; import { HashMap } from "../../Common/HashMap";

View File

@@ -17,7 +17,7 @@ import SaveIcon from "../../../images/save-cosmos.svg";
import ClearAllOutputsIcon from "../../../images/notebook/Notebook-clear-all-outputs.svg"; import ClearAllOutputsIcon from "../../../images/notebook/Notebook-clear-all-outputs.svg";
import InterruptKernelIcon from "../../../images/notebook/Notebook-stop.svg"; import InterruptKernelIcon from "../../../images/notebook/Notebook-stop.svg";
import KillKernelIcon from "../../../images/notebook/Notebook-stop.svg"; import KillKernelIcon from "../../../images/notebook/Notebook-stop.svg";
import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor"; import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
import { Action, ActionModifiers } from "../../Shared/Telemetry/TelemetryConstants"; import { Action, ActionModifiers } from "../../Shared/Telemetry/TelemetryConstants";
import { Areas, ArmApiVersions } from "../../Common/Constants"; import { Areas, ArmApiVersions } from "../../Common/Constants";
import { CommandBarComponentButtonFactory } from "../Menus/CommandBar/CommandBarComponentButtonFactory"; import { CommandBarComponentButtonFactory } from "../Menus/CommandBar/CommandBarComponentButtonFactory";

View File

@@ -10,7 +10,7 @@ import { HashMap } from "../../Common/HashMap";
import * as HeadersUtility from "../../Common/HeadersUtility"; import * as HeadersUtility from "../../Common/HeadersUtility";
import * as Logger from "../../Common/Logger"; import * as Logger from "../../Common/Logger";
import { Splitter, SplitterBounds, SplitterDirection } from "../../Common/Splitter"; import { Splitter, SplitterBounds, SplitterDirection } from "../../Common/Splitter";
import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor"; import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
import ExecuteQueryIcon from "../../../images/ExecuteQuery.svg"; import ExecuteQueryIcon from "../../../images/ExecuteQuery.svg";
import { QueryUtils } from "../../Utils/QueryUtils"; import { QueryUtils } from "../../Utils/QueryUtils";
import SaveQueryIcon from "../../../images/save-cosmos.svg"; import SaveQueryIcon from "../../../images/save-cosmos.svg";

View File

@@ -12,7 +12,7 @@ import editable from "../../Common/EditableUtility";
import Q from "q"; import Q from "q";
import SaveIcon from "../../../images/save-cosmos.svg"; import SaveIcon from "../../../images/save-cosmos.svg";
import TabsBase from "./TabsBase"; import TabsBase from "./TabsBase";
import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor"; import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
import { Action } from "../../Shared/Telemetry/TelemetryConstants"; import { Action } from "../../Shared/Telemetry/TelemetryConstants";
import { PlatformType } from "../../PlatformType"; import { PlatformType } from "../../PlatformType";
import { RequestOptions } from "@azure/cosmos/dist-esm"; import { RequestOptions } from "@azure/cosmos/dist-esm";

View File

@@ -7,7 +7,7 @@ import * as ViewModels from "../../Contracts/ViewModels";
import { Action } from "../../Shared/Telemetry/TelemetryConstants"; import { Action } from "../../Shared/Telemetry/TelemetryConstants";
import editable from "../../Common/EditableUtility"; import editable from "../../Common/EditableUtility";
import ScriptTabBase from "./ScriptTabBase"; import ScriptTabBase from "./ScriptTabBase";
import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor"; import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
import ExecuteQueryIcon from "../../../images/ExecuteQuery.svg"; import ExecuteQueryIcon from "../../../images/ExecuteQuery.svg";
import StoredProcedure from "../Tree/StoredProcedure"; import StoredProcedure from "../Tree/StoredProcedure";
import { createStoredProcedure, updateStoredProcedure } from "../../Common/DocumentClientUtilityBase"; import { createStoredProcedure, updateStoredProcedure } from "../../Common/DocumentClientUtilityBase";

View File

@@ -5,7 +5,7 @@ import * as ViewModels from "../../Contracts/ViewModels";
import { Action, ActionModifiers } from "../../Shared/Telemetry/TelemetryConstants"; import { Action, ActionModifiers } from "../../Shared/Telemetry/TelemetryConstants";
import { RouteHandler } from "../../RouteHandlers/RouteHandler"; import { RouteHandler } from "../../RouteHandlers/RouteHandler";
import { WaitsForTemplateViewModel } from "../WaitsForTemplateViewModel"; import { WaitsForTemplateViewModel } from "../WaitsForTemplateViewModel";
import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor"; import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
import ThemeUtility from "../../Common/ThemeUtility"; import ThemeUtility from "../../Common/ThemeUtility";
import Explorer from "../Explorer"; import Explorer from "../Explorer";
import { CommandButtonComponentProps } from "../Controls/CommandButton/CommandButtonComponent"; import { CommandButtonComponentProps } from "../Controls/CommandButton/CommandButtonComponent";

View File

@@ -5,7 +5,7 @@ import * as ViewModels from "../../Contracts/ViewModels";
import { Action } from "../../Shared/Telemetry/TelemetryConstants"; import { Action } from "../../Shared/Telemetry/TelemetryConstants";
import ScriptTabBase from "./ScriptTabBase"; import ScriptTabBase from "./ScriptTabBase";
import editable from "../../Common/EditableUtility"; import editable from "../../Common/EditableUtility";
import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor"; import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
import Trigger from "../Tree/Trigger"; import Trigger from "../Tree/Trigger";
import { createTrigger, updateTrigger } from "../../Common/DocumentClientUtilityBase"; import { createTrigger, updateTrigger } from "../../Common/DocumentClientUtilityBase";

View File

@@ -4,7 +4,7 @@ import * as DataModels from "../../Contracts/DataModels";
import * as ViewModels from "../../Contracts/ViewModels"; import * as ViewModels from "../../Contracts/ViewModels";
import { Action } from "../../Shared/Telemetry/TelemetryConstants"; import { Action } from "../../Shared/Telemetry/TelemetryConstants";
import ScriptTabBase from "./ScriptTabBase"; import ScriptTabBase from "./ScriptTabBase";
import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor"; import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
import UserDefinedFunction from "../Tree/UserDefinedFunction"; import UserDefinedFunction from "../Tree/UserDefinedFunction";
import { createUserDefinedFunction, updateUserDefinedFunction } from "../../Common/DocumentClientUtilityBase"; import { createUserDefinedFunction, updateUserDefinedFunction } from "../../Common/DocumentClientUtilityBase";

View File

@@ -9,7 +9,7 @@ import * as DataModels from "../../Contracts/DataModels";
import * as ViewModels from "../../Contracts/ViewModels"; import * as ViewModels from "../../Contracts/ViewModels";
import { PlatformType } from "../../PlatformType"; import { PlatformType } from "../../PlatformType";
import { Action, ActionModifiers } from "../../Shared/Telemetry/TelemetryConstants"; import { Action, ActionModifiers } from "../../Shared/Telemetry/TelemetryConstants";
import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor"; import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
import * as NotificationConsoleUtils from "../../Utils/NotificationConsoleUtils"; import * as NotificationConsoleUtils from "../../Utils/NotificationConsoleUtils";
import { OfferUtils } from "../../Utils/OfferUtils"; import { OfferUtils } from "../../Utils/OfferUtils";
import { StartUploadMessageParams, UploadDetails, UploadDetailsRecord } from "../../workers/upload/definitions"; import { StartUploadMessageParams, UploadDetails, UploadDetailsRecord } from "../../workers/upload/definitions";

View File

@@ -7,7 +7,7 @@ import * as DataModels from "../../Contracts/DataModels";
import { Action, ActionModifiers } from "../../Shared/Telemetry/TelemetryConstants"; import { Action, ActionModifiers } from "../../Shared/Telemetry/TelemetryConstants";
import DatabaseSettingsTab from "../Tabs/DatabaseSettingsTab"; import DatabaseSettingsTab from "../Tabs/DatabaseSettingsTab";
import Collection from "./Collection"; import Collection from "./Collection";
import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor"; import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
import * as NotificationConsoleUtils from "../../Utils/NotificationConsoleUtils"; import * as NotificationConsoleUtils from "../../Utils/NotificationConsoleUtils";
import { ConsoleDataType } from "../Menus/NotificationConsole/NotificationConsoleComponent"; import { ConsoleDataType } from "../Menus/NotificationConsole/NotificationConsoleComponent";
import * as Logger from "../../Common/Logger"; import * as Logger from "../../Common/Logger";

View File

@@ -7,7 +7,7 @@ import DocumentId from "./DocumentId";
import DocumentsTab from "../Tabs/DocumentsTab"; import DocumentsTab from "../Tabs/DocumentsTab";
import Q from "q"; import Q from "q";
import QueryTab from "../Tabs/QueryTab"; import QueryTab from "../Tabs/QueryTab";
import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor"; import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
import Explorer from "../Explorer"; import Explorer from "../Explorer";
import TabsBase from "../Tabs/TabsBase"; import TabsBase from "../Tabs/TabsBase";

View File

@@ -0,0 +1,112 @@
import Explorer from "../Explorer";
import * as ko from "knockout";
import { ResourceTreeAdapter } from "./ResourceTreeAdapter";
import * as ViewModels from "../../Contracts/ViewModels";
import TabsBase from "../Tabs/TabsBase";
describe("ResourceTreeAdapter", () => {
const mockContainer = (): Explorer =>
(({
selectedNode: ko.observable<ViewModels.TreeNode>({
nodeKind: "nodeKind",
rid: "rid",
id: ko.observable<string>("id")
}),
tabsManager: {
activeTab: ko.observable<TabsBase>({
tabKind: ViewModels.CollectionTabKind.Documents
} as TabsBase)
},
isNotebookEnabled: ko.observable<boolean>(true),
nonSystemDatabases: ko.observable<ViewModels.Database[]>([])
} as unknown) as Explorer);
// TODO isDataNodeSelected needs a better design and refactor, but for now, we protect some of the code paths
describe("isDataNodeSelected", () => {
it("it should not select if no selected node", () => {
const explorer = mockContainer();
explorer.selectedNode(undefined);
const resourceTreeAdapter = new ResourceTreeAdapter(explorer);
const isDataNodeSelected = resourceTreeAdapter.isDataNodeSelected("foo", "bar", undefined);
expect(isDataNodeSelected).toBeFalsy();
});
it("it should not select incorrect subnodekinds", () => {
const resourceTreeAdapter = new ResourceTreeAdapter(mockContainer());
const isDataNodeSelected = resourceTreeAdapter.isDataNodeSelected("foo", "bar", undefined);
expect(isDataNodeSelected).toBeFalsy();
});
it("it should not select if no active tab", () => {
const explorer = mockContainer();
explorer.tabsManager.activeTab(undefined);
const resourceTreeAdapter = new ResourceTreeAdapter(explorer);
const isDataNodeSelected = resourceTreeAdapter.isDataNodeSelected("foo", "bar", undefined);
expect(isDataNodeSelected).toBeFalsy();
});
it("should select if correct database node regardless of subnodekinds", () => {
const subNodeKind = ViewModels.CollectionTabKind.Documents;
const explorer = mockContainer();
explorer.selectedNode(({
nodeKind: "Database",
rid: "dbrid",
id: ko.observable<string>("id"),
selectedSubnodeKind: ko.observable<ViewModels.CollectionTabKind>(subNodeKind)
} as unknown) as ViewModels.TreeNode);
const resourceTreeAdapter = new ResourceTreeAdapter(explorer);
const isDataNodeSelected = resourceTreeAdapter.isDataNodeSelected("dbrid", "Database", [
ViewModels.CollectionTabKind.Documents
]);
expect(isDataNodeSelected).toBeTruthy();
});
it("should select correct collection node (documents or graph node)", () => {
let subNodeKind = ViewModels.CollectionTabKind.Documents;
const explorer = mockContainer();
explorer.tabsManager.activeTab({
tabKind: subNodeKind
} as TabsBase);
explorer.selectedNode(({
nodeKind: "Collection",
rid: "collrid",
id: ko.observable<string>("id"),
selectedSubnodeKind: ko.observable<ViewModels.CollectionTabKind>(subNodeKind)
} as unknown) as ViewModels.TreeNode);
const resourceTreeAdapter = new ResourceTreeAdapter(explorer);
let isDataNodeSelected = resourceTreeAdapter.isDataNodeSelected("collrid", "Collection", [subNodeKind]);
expect(isDataNodeSelected).toBeTruthy();
subNodeKind = ViewModels.CollectionTabKind.Graph;
explorer.tabsManager.activeTab({
tabKind: subNodeKind
} as TabsBase);
explorer.selectedNode(({
nodeKind: "Collection",
rid: "collrid",
id: ko.observable<string>("id"),
selectedSubnodeKind: ko.observable<ViewModels.CollectionTabKind>(subNodeKind)
} as unknown) as ViewModels.TreeNode);
isDataNodeSelected = resourceTreeAdapter.isDataNodeSelected("collrid", "Collection", [subNodeKind]);
expect(isDataNodeSelected).toBeTruthy();
});
it("should not select incorrect collection node (e.g. Settings)", () => {
const explorer = mockContainer();
explorer.selectedNode(({
nodeKind: "Collection",
rid: "collrid",
id: ko.observable<string>("id"),
selectedSubnodeKind: ko.observable<ViewModels.CollectionTabKind>(ViewModels.CollectionTabKind.Documents)
} as unknown) as ViewModels.TreeNode);
explorer.tabsManager.activeTab({
tabKind: ViewModels.CollectionTabKind.Documents
} as TabsBase);
const resourceTreeAdapter = new ResourceTreeAdapter(explorer);
const isDataNodeSelected = resourceTreeAdapter.isDataNodeSelected("collrid", "Collection", [
ViewModels.CollectionTabKind.Settings
]);
expect(isDataNodeSelected).toBeFalsy();
});
});
});

View File

@@ -19,7 +19,7 @@ import { ArrayHashMap } from "../../Common/ArrayHashMap";
import { NotebookUtil } from "../Notebook/NotebookUtil"; import { NotebookUtil } from "../Notebook/NotebookUtil";
import _ from "underscore"; import _ from "underscore";
import { IPinnedRepo } from "../../Juno/JunoClient"; import { IPinnedRepo } from "../../Juno/JunoClient";
import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor"; import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
import { Action, ActionModifiers } from "../../Shared/Telemetry/TelemetryConstants"; import { Action, ActionModifiers } from "../../Shared/Telemetry/TelemetryConstants";
import { Areas } from "../../Common/Constants"; import { Areas } from "../../Common/Constants";
import * as GitHubUtils from "../../Utils/GitHubUtils"; import * as GitHubUtils from "../../Utils/GitHubUtils";
@@ -191,7 +191,7 @@ export class ResourceTreeAdapter implements ReactAdapter {
databaseNode.children.push({ databaseNode.children.push({
label: "Scale", label: "Scale",
isSelected: () => isSelected: () =>
this.isDataNodeSelected(database.rid, "Database", ViewModels.CollectionTabKind.DatabaseSettings), this.isDataNodeSelected(database.rid, "Database", [ViewModels.CollectionTabKind.DatabaseSettings]),
onClick: database.onSettingsClick.bind(database) onClick: database.onSettingsClick.bind(database)
}); });
} }
@@ -235,14 +235,18 @@ export class ResourceTreeAdapter implements ReactAdapter {
data: collection.rid data: collection.rid
}); });
}, },
isSelected: () => this.isDataNodeSelected(collection.rid, "Collection", ViewModels.CollectionTabKind.Documents), isSelected: () =>
this.isDataNodeSelected(collection.rid, "Collection", [
ViewModels.CollectionTabKind.Documents,
ViewModels.CollectionTabKind.Graph
]),
contextMenu: ResourceTreeContextMenuButtonFactory.createCollectionContextMenuButton(this.container, collection) contextMenu: ResourceTreeContextMenuButtonFactory.createCollectionContextMenuButton(this.container, collection)
}); });
children.push({ children.push({
label: database.isDatabaseShared() || this.container.isServerlessEnabled() ? "Settings" : "Scale & Settings", label: database.isDatabaseShared() || this.container.isServerlessEnabled() ? "Settings" : "Scale & Settings",
onClick: collection.onSettingsClick.bind(collection), onClick: collection.onSettingsClick.bind(collection),
isSelected: () => this.isDataNodeSelected(collection.rid, "Collection", ViewModels.CollectionTabKind.Settings) isSelected: () => this.isDataNodeSelected(collection.rid, "Collection", [ViewModels.CollectionTabKind.Settings])
}); });
if (ResourceTreeAdapter.showScriptNodes(this.container)) { if (ResourceTreeAdapter.showScriptNodes(this.container)) {
@@ -264,7 +268,8 @@ export class ResourceTreeAdapter implements ReactAdapter {
children.push({ children.push({
label: "Conflicts", label: "Conflicts",
onClick: collection.onConflictsClick.bind(collection), onClick: collection.onConflictsClick.bind(collection),
isSelected: () => this.isDataNodeSelected(collection.rid, "Collection", ViewModels.CollectionTabKind.Conflicts) isSelected: () =>
this.isDataNodeSelected(collection.rid, "Collection", [ViewModels.CollectionTabKind.Conflicts])
}); });
} }
@@ -302,7 +307,7 @@ export class ResourceTreeAdapter implements ReactAdapter {
label: sp.id(), label: sp.id(),
onClick: sp.open.bind(sp), onClick: sp.open.bind(sp),
isSelected: () => isSelected: () =>
this.isDataNodeSelected(collection.rid, "Collection", ViewModels.CollectionTabKind.StoredProcedures), this.isDataNodeSelected(collection.rid, "Collection", [ViewModels.CollectionTabKind.StoredProcedures]),
contextMenu: ResourceTreeContextMenuButtonFactory.createStoreProcedureContextMenuItems(this.container, sp) contextMenu: ResourceTreeContextMenuButtonFactory.createStoreProcedureContextMenuItems(this.container, sp)
})), })),
onClick: () => { onClick: () => {
@@ -321,7 +326,7 @@ export class ResourceTreeAdapter implements ReactAdapter {
label: udf.id(), label: udf.id(),
onClick: udf.open.bind(udf), onClick: udf.open.bind(udf),
isSelected: () => isSelected: () =>
this.isDataNodeSelected(collection.rid, "Collection", ViewModels.CollectionTabKind.UserDefinedFunctions), this.isDataNodeSelected(collection.rid, "Collection", [ViewModels.CollectionTabKind.UserDefinedFunctions]),
contextMenu: ResourceTreeContextMenuButtonFactory.createUserDefinedFunctionContextMenuItems(this.container, udf) contextMenu: ResourceTreeContextMenuButtonFactory.createUserDefinedFunctionContextMenuItems(this.container, udf)
})), })),
onClick: () => { onClick: () => {
@@ -339,7 +344,8 @@ export class ResourceTreeAdapter implements ReactAdapter {
children: collection.triggers().map((trigger: Trigger) => ({ children: collection.triggers().map((trigger: Trigger) => ({
label: trigger.id(), label: trigger.id(),
onClick: trigger.open.bind(trigger), onClick: trigger.open.bind(trigger),
isSelected: () => this.isDataNodeSelected(collection.rid, "Collection", ViewModels.CollectionTabKind.Triggers), isSelected: () =>
this.isDataNodeSelected(collection.rid, "Collection", [ViewModels.CollectionTabKind.Triggers]),
contextMenu: ResourceTreeContextMenuButtonFactory.createTriggerContextMenuItems(this.container, trigger) contextMenu: ResourceTreeContextMenuButtonFactory.createTriggerContextMenuItems(this.container, trigger)
})), })),
onClick: () => { onClick: () => {
@@ -697,13 +703,19 @@ export class ResourceTreeAdapter implements ReactAdapter {
window.requestAnimationFrame(() => this.parameters(Date.now())); window.requestAnimationFrame(() => this.parameters(Date.now()));
} }
private isDataNodeSelected(rid: string, nodeKind: string, subnodeKind: ViewModels.CollectionTabKind): boolean { /**
* public for testing purposes
* @param rid
* @param nodeKind
* @param subnodeKinds
*/
public isDataNodeSelected(rid: string, nodeKind: string, subnodeKinds: ViewModels.CollectionTabKind[]): boolean {
if (!this.container.selectedNode || !this.container.selectedNode()) { if (!this.container.selectedNode || !this.container.selectedNode()) {
return false; return false;
} }
const selectedNode = this.container.selectedNode(); const selectedNode = this.container.selectedNode();
if (subnodeKind === undefined) { if (subnodeKinds === undefined || !Array.isArray(subnodeKinds)) {
return selectedNode.rid === rid && selectedNode.nodeKind === nodeKind; return selectedNode.rid === rid && selectedNode.nodeKind === nodeKind;
} else { } else {
const activeTab = this.container.tabsManager.activeTab(); const activeTab = this.container.tabsManager.activeTab();
@@ -716,10 +728,10 @@ export class ResourceTreeAdapter implements ReactAdapter {
return ( return (
activeTab && activeTab &&
activeTab.tabKind === subnodeKind && subnodeKinds.includes(activeTab.tabKind) &&
selectedNode.rid === rid && selectedNode.rid === rid &&
selectedSubnodeKind !== undefined && selectedSubnodeKind !== undefined &&
selectedSubnodeKind === subnodeKind subnodeKinds.includes(selectedSubnodeKind)
); );
} }
} }

View File

@@ -5,7 +5,7 @@ import * as DataModels from "../../Contracts/DataModels";
import { Action, ActionModifiers } from "../../Shared/Telemetry/TelemetryConstants"; import { Action, ActionModifiers } from "../../Shared/Telemetry/TelemetryConstants";
import StoredProcedureTab from "../Tabs/StoredProcedureTab"; import StoredProcedureTab from "../Tabs/StoredProcedureTab";
import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor"; import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
import Explorer from "../Explorer"; import Explorer from "../Explorer";
import { deleteStoredProcedure, executeStoredProcedure } from "../../Common/DocumentClientUtilityBase"; import { deleteStoredProcedure, executeStoredProcedure } from "../../Common/DocumentClientUtilityBase";
import TabsBase from "../Tabs/TabsBase"; import TabsBase from "../Tabs/TabsBase";

View File

@@ -4,7 +4,7 @@ import * as Constants from "../../Common/Constants";
import * as DataModels from "../../Contracts/DataModels"; import * as DataModels from "../../Contracts/DataModels";
import { Action, ActionModifiers } from "../../Shared/Telemetry/TelemetryConstants"; import { Action, ActionModifiers } from "../../Shared/Telemetry/TelemetryConstants";
import TriggerTab from "../Tabs/TriggerTab"; import TriggerTab from "../Tabs/TriggerTab";
import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor"; import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
import Explorer from "../Explorer"; import Explorer from "../Explorer";
import { deleteTrigger } from "../../Common/DocumentClientUtilityBase"; import { deleteTrigger } from "../../Common/DocumentClientUtilityBase";

View File

@@ -4,7 +4,7 @@ import * as Constants from "../../Common/Constants";
import * as DataModels from "../../Contracts/DataModels"; import * as DataModels from "../../Contracts/DataModels";
import { Action, ActionModifiers } from "../../Shared/Telemetry/TelemetryConstants"; import { Action, ActionModifiers } from "../../Shared/Telemetry/TelemetryConstants";
import UserDefinedFunctionTab from "../Tabs/UserDefinedFunctionTab"; import UserDefinedFunctionTab from "../Tabs/UserDefinedFunctionTab";
import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor"; import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
import Explorer from "../Explorer"; import Explorer from "../Explorer";
import { deleteUserDefinedFunction } from "../../Common/DocumentClientUtilityBase"; import { deleteUserDefinedFunction } from "../../Common/DocumentClientUtilityBase";

View File

@@ -29,7 +29,7 @@ import { MeControlComponentAdapter } from "./Explorer/Menus/NavBar/MeControlComp
import { MessageTypes } from "./Contracts/ExplorerContracts"; import { MessageTypes } from "./Contracts/ExplorerContracts";
import * as ReactBindingHandler from "./Bindings/ReactBindingHandler"; import * as ReactBindingHandler from "./Bindings/ReactBindingHandler";
import { SwitchDirectoryPane, SwitchDirectoryPaneComponent } from "./Explorer/Panes/SwitchDirectoryPane"; import { SwitchDirectoryPane, SwitchDirectoryPaneComponent } from "./Explorer/Panes/SwitchDirectoryPane";
import TelemetryProcessor from "./Shared/Telemetry/TelemetryProcessor"; import * as TelemetryProcessor from "./Shared/Telemetry/TelemetryProcessor";
import { isInvalidParentFrameOrigin } from "./Utils/MessageValidation"; import { isInvalidParentFrameOrigin } from "./Utils/MessageValidation";
import "../less/hostedexplorer.less"; import "../less/hostedexplorer.less";
import "./Explorer/Menus/NavBar/MeControlComponent.less"; import "./Explorer/Menus/NavBar/MeControlComponent.less";

View File

@@ -60,7 +60,7 @@ import "url-polyfill/url-polyfill.min";
// import "./ReactDevTools" // import "./ReactDevTools"
import * as ko from "knockout"; import * as ko from "knockout";
import TelemetryProcessor from "./Shared/Telemetry/TelemetryProcessor"; import * as TelemetryProcessor from "./Shared/Telemetry/TelemetryProcessor";
import * as ViewModels from "./Contracts/ViewModels"; import * as ViewModels from "./Contracts/ViewModels";
import { Action, ActionModifiers } from "./Shared/Telemetry/TelemetryConstants"; import { Action, ActionModifiers } from "./Shared/Telemetry/TelemetryConstants";

View File

@@ -1,162 +1,64 @@
import * as SharedConstants from "../Shared/Constants"; import * as ko from "knockout";
import { AddDbUtilities } from "../Shared/AddDatabaseUtility"; import { Collection, Database } from "../Contracts/ViewModels";
import { CreateCollectionUtilities, CreateSqlCollectionUtilities, Utilities } from "./AddCollectionUtility"; import { getMaxThroughput } from "./AddCollectionUtility";
jest.mock("AddDatabaseUtility"); import Explorer from "../Explorer/Explorer";
const armEndpoint = "https://management.azure.com"; describe("getMaxThroughput", () => {
it("default unlimited throughput setting", () => {
const defaults = {
storage: "100",
throughput: {
fixed: 400,
unlimited: 400,
unlimitedmax: 1000000,
unlimitedmin: 400,
shared: 400
}
};
describe("Add Collection Utitlity", () => { expect(getMaxThroughput(defaults, {} as Explorer)).toEqual(defaults.throughput.unlimited);
describe("createSqlCollection", () => { });
it("should invoke createSqlCollectionWithARM if create database is false", () => {
const properties = { describe("no unlimited throughput setting", () => {
uniqueKeyPolicy: { uniqueKeys: [{ paths: [""] }] }, const defaults = {
cd: false, storage: "100",
coll: "abc-collection", throughput: {
db: "a1-db", fixed: 400,
dba: "main", unlimited: {
offerThroughput: 50000, collectionThreshold: 3,
pk: "state", lessThanOrEqualToThreshold: 400,
sid: "a1", greatThanThreshold: 500
rg: "b1", },
st: true, unlimitedmax: 1000000,
defaultTtl: -1, unlimitedmin: 400,
indexingPolicy: SharedConstants.IndexingPolicies.AllPropertiesIndexed, shared: 400
partitionKeyVersion: 2 }
}; };
const additionalOptions = {};
const createSqlCollectionWithARMSpy = jest.spyOn(CreateSqlCollectionUtilities, "createSqlCollectionWithARM"); const mockCollection1 = { id: ko.observable("collection1") } as Collection;
CreateSqlCollectionUtilities.createSqlCollection( const mockCollection2 = { id: ko.observable("collection2") } as Collection;
armEndpoint, const mockCollection3 = { id: ko.observable("collection3") } as Collection;
properties.db, const mockCollection4 = { id: ko.observable("collection4") } as Collection;
properties.defaultTtl, const mockDatabase = {} as Database;
properties.coll, const mockContainer = {
properties.indexingPolicy, databases: ko.observableArray([mockDatabase])
properties.offerThroughput, } as Explorer;
properties.pk,
properties.partitionKeyVersion, it("less than or equal to collection threshold", () => {
properties.cd, mockDatabase.collections = ko.observableArray([mockCollection1, mockCollection2]);
properties.st, expect(getMaxThroughput(defaults, mockContainer)).toEqual(
properties.sid, defaults.throughput.unlimited.lessThanOrEqualToThreshold
properties.rg,
properties.dba,
properties.uniqueKeyPolicy,
additionalOptions
); );
expect(createSqlCollectionWithARMSpy).toHaveBeenCalled();
}); });
it("should invoke createSqlDatabase + createSqlCollectionWithARM if create database is true", () => { it("exceeds collection threshold", () => {
const properties = { mockDatabase.collections = ko.observableArray([
uniqueKeyPolicy: { uniqueKeys: [{ paths: [""] }] }, mockCollection1,
cd: true, mockCollection2,
coll: "abc-collection", mockCollection3,
db: "a1-db", mockCollection4
dba: "main", ]);
offerThroughput: 50000, expect(getMaxThroughput(defaults, mockContainer)).toEqual(defaults.throughput.unlimited.greatThanThreshold);
pk: "state",
sid: "a1",
rg: "b1",
st: true,
analyticalStorageTtl: -1,
indexingPolicy: SharedConstants.IndexingPolicies.AllPropertiesIndexed,
partitionKeyVersion: 2
};
const additionalOptions = {};
const createSqlCollectionWithARMSpy = jest.spyOn(CreateSqlCollectionUtilities, "createSqlCollectionWithARM");
const createSqlDatabaseSpy = jest.spyOn(AddDbUtilities, "createSqlDatabase");
CreateSqlCollectionUtilities.createSqlCollection(
armEndpoint,
properties.db,
properties.analyticalStorageTtl,
properties.coll,
properties.indexingPolicy,
properties.offerThroughput,
properties.pk,
properties.partitionKeyVersion,
properties.cd,
properties.st,
properties.sid,
properties.rg,
properties.dba,
properties.uniqueKeyPolicy,
additionalOptions
);
expect(createSqlCollectionWithARMSpy).toHaveBeenCalled();
expect(createSqlDatabaseSpy).toHaveBeenCalled();
});
});
});
describe("Add Collection Utitlity", () => {
describe("createGremlinGraph", () => {
it("should invoke createGremlinGraphWithARM if create database is false", () => {
const properties = {
cd: false,
coll: "abc-collection",
db: "a1-db",
dba: "main",
offerThroughput: 50000,
pk: "state",
sid: "a1",
rg: "b1",
st: true,
indexingPolicy: SharedConstants.IndexingPolicies.AllPropertiesIndexed,
partitionKeyVersion: 2
};
const additionalOptions = {};
const createGremlinGraphWithARMSpy = jest.spyOn(CreateCollectionUtilities, "createGremlinGraphWithARM");
CreateCollectionUtilities.createGremlinGraph(
armEndpoint,
properties.db,
properties.coll,
properties.indexingPolicy,
properties.offerThroughput,
properties.pk,
properties.partitionKeyVersion,
properties.cd,
properties.st,
properties.sid,
properties.rg,
properties.dba,
additionalOptions
);
expect(createGremlinGraphWithARMSpy).toHaveBeenCalled();
});
it("should invoke createGremlinDatabase + createGremlinGraphWithARM if create database is true", () => {
const properties = {
cd: true,
coll: "abc-collection",
db: "a1-db",
dba: "main",
offerThroughput: 50000,
pk: "state",
sid: "a1",
rg: "b1",
st: true,
indexingPolicy: SharedConstants.IndexingPolicies.AllPropertiesIndexed,
partitionKeyVersion: 2
};
const additionalOptions = {};
const createGremlinGraphWithARMSpy = jest.spyOn(CreateCollectionUtilities, "createGremlinGraphWithARM");
const createGremlinDatabaseSpy = jest.spyOn(AddDbUtilities, "createGremlinDatabase");
CreateCollectionUtilities.createGremlinGraph(
armEndpoint,
properties.db,
properties.coll,
properties.indexingPolicy,
properties.offerThroughput,
properties.pk,
properties.partitionKeyVersion,
properties.cd,
properties.st,
properties.sid,
properties.rg,
properties.dba,
additionalOptions
);
expect(createGremlinDatabaseSpy).toHaveBeenCalled();
expect(createGremlinGraphWithARMSpy).toHaveBeenCalled();
}); });
}); });
}); });

View File

@@ -1,303 +1,23 @@
import * as _ from "underscore"; import { any } from "underscore";
import * as DataExplorerConstants from "../Common/Constants"; import { CollectionCreationDefaults } from "../Contracts/ViewModels";
import * as DataModels from "../Contracts/DataModels";
import * as SharedConstants from "./Constants";
import * as ViewModels from "../Contracts/ViewModels";
import { AddDbUtilities } from "../Shared/AddDatabaseUtility";
import { ConsoleDataType } from "../Explorer/Menus/NotificationConsole/NotificationConsoleComponent";
import { HttpStatusCodes } from "../Common/Constants";
import { sendMessage } from "../Common/MessageHandler";
import { MessageTypes } from "../Contracts/ExplorerContracts";
import * as NotificationConsoleUtils from "../Utils/NotificationConsoleUtils";
import { ResourceProviderClient } from "../ResourceProvider/ResourceProviderClient";
import Explorer from "../Explorer/Explorer"; import Explorer from "../Explorer/Explorer";
import { userContext } from "../UserContext";
export class CreateSqlCollectionUtilities { export const getMaxThroughput = (defaults: CollectionCreationDefaults, container: Explorer): number => {
public static createSqlCollection( const throughput = defaults.throughput.unlimited;
armEndpoint: string, if (typeof throughput === "number") {
databaseId: string, return throughput;
analyticalStorageTtl: number, } else {
collectionId: string, return _exceedsThreshold(throughput.collectionThreshold, container)
indexingPolicy: DataModels.IndexingPolicy, ? throughput.greatThanThreshold
offerThroughput: number, : throughput.lessThanOrEqualToThreshold;
partitionKey: string,
partitionKeyVersion: number,
createDatabase: boolean,
useDatabaseSharedOffer: boolean,
sid: string,
rg: string,
dba: string,
uniqueKeyPolicy: DataModels.UniqueKeyPolicy,
additionalOptions: DataModels.RpOptions
): Promise<DataModels.CreateCollectionWithRpResponse> {
const params: DataModels.SqlCollectionParameters = {
uniqueKeyPolicy,
db: databaseId,
coll: collectionId,
pk: partitionKey,
offerThroughput,
cd: createDatabase,
st: useDatabaseSharedOffer,
sid,
rg,
dba,
analyticalStorageTtl,
indexingPolicy,
partitionKeyVersion
};
if (params.cd) {
return AddDbUtilities.createSqlDatabase(armEndpoint, params, additionalOptions).then(() => {
return CreateSqlCollectionUtilities.createSqlCollectionWithARM(armEndpoint, params, additionalOptions);
});
}
return CreateSqlCollectionUtilities.createSqlCollectionWithARM(armEndpoint, params, additionalOptions);
} }
};
public static async createSqlCollectionWithARM( const _exceedsThreshold = (unlimitedThreshold: number, container: Explorer): boolean => {
armEndpoint: string, const databases = (container && container.databases && container.databases()) || [];
params: DataModels.SqlCollectionParameters, return any(
rpOptions: DataModels.RpOptions databases,
): Promise<DataModels.CreateCollectionWithRpResponse> { database =>
const rpPayloadToCreateCollection: DataModels.SqlCollectionCreationRequest = { database && database.collections && database.collections() && database.collections().length > unlimitedThreshold
properties: { );
resource: { };
id: params.coll,
partitionKey: {
paths: [params.pk],
kind: "Hash",
version: params.partitionKeyVersion
}
},
options: {}
}
};
if (params.analyticalStorageTtl) {
rpPayloadToCreateCollection.properties.resource.analyticalStorageTtl = params.analyticalStorageTtl;
}
if (params.indexingPolicy) {
rpPayloadToCreateCollection.properties.resource.indexingPolicy = params.indexingPolicy;
}
if (!params.st) {
if (rpOptions) {
rpPayloadToCreateCollection.properties.options = rpOptions;
} else {
rpPayloadToCreateCollection.properties.options["throughput"] =
params.offerThroughput && params.offerThroughput.toString();
}
}
if (params.uniqueKeyPolicy) {
rpPayloadToCreateCollection.properties.resource.uniqueKeyPolicy = params.uniqueKeyPolicy;
}
try {
let response = await new ResourceProviderClient<DataModels.CreateCollectionWithRpResponse>(armEndpoint).putAsync(
CreateSqlCollectionUtilities.getSqlCollectionUri(params),
DataExplorerConstants.ArmApiVersions.publicVersion,
rpPayloadToCreateCollection
);
return response;
} catch (response) {
NotificationConsoleUtils.logConsoleMessage(
ConsoleDataType.Error,
`Error creating collection: ${JSON.stringify(response)}`
);
if (response.status === HttpStatusCodes.Forbidden) {
sendMessage({ type: MessageTypes.ForbiddenError });
}
throw new Error(`Error creating collection`);
}
}
public static getSqlCollectionUri(params: DataModels.SqlCollectionParameters): string {
return `subscriptions/${params.sid}/resourceGroups/${params.rg}/providers/Microsoft.DocumentDB/databaseAccounts/${params.dba}/sqlDatabases/${params.db}/containers/${params.coll}`;
}
}
export class CreateCollectionUtilities {
public static createGremlinGraph(
armEndpoint: string,
databaseId: string,
collectionId: string,
indexingPolicy: DataModels.IndexingPolicy,
offerThroughput: number,
partitionKey: string,
partitionKeyVersion: number,
createDatabase: boolean,
useDatabaseSharedOffer: boolean,
sid: string,
rg: string,
dba: string,
additionalOptions: DataModels.RpOptions
): Promise<DataModels.CreateCollectionWithRpResponse> {
const params: DataModels.GraphParameters = {
db: databaseId,
coll: collectionId,
pk: partitionKey,
offerThroughput,
cd: createDatabase,
st: useDatabaseSharedOffer,
sid,
rg,
dba,
indexingPolicy,
partitionKeyVersion
};
if (params.cd) {
return AddDbUtilities.createGremlinDatabase(armEndpoint, params, additionalOptions).then(() => {
return CreateCollectionUtilities.createGremlinGraphWithARM(armEndpoint, params, additionalOptions);
});
}
return CreateCollectionUtilities.createGremlinGraphWithARM(armEndpoint, params, additionalOptions);
}
public static async createGremlinGraphWithARM(
armEndpoint: string,
params: DataModels.GraphParameters,
rpOptions: DataModels.RpOptions
): Promise<DataModels.CreateCollectionWithRpResponse> {
const rpPayloadToCreateCollection: DataModels.GraphCreationRequest = {
properties: {
resource: {
id: params.coll,
partitionKey: {
paths: [params.pk],
kind: "Hash",
version: params.partitionKeyVersion
}
},
options: {}
}
};
if (params.indexingPolicy) {
rpPayloadToCreateCollection.properties.resource.indexingPolicy = params.indexingPolicy;
}
if (!params.st) {
if (rpOptions) {
rpPayloadToCreateCollection.properties.options = rpOptions;
} else {
rpPayloadToCreateCollection.properties.options["throughput"] =
params.offerThroughput && params.offerThroughput.toString();
}
}
try {
let response = await new ResourceProviderClient<DataModels.CreateCollectionWithRpResponse>(armEndpoint).putAsync(
CreateCollectionUtilities.getGremlinGraphUri(params),
DataExplorerConstants.ArmApiVersions.publicVersion,
rpPayloadToCreateCollection
);
return response;
} catch (response) {
NotificationConsoleUtils.logConsoleMessage(
ConsoleDataType.Error,
`Error creating graph: ${JSON.stringify(response)}`
);
if (response.status === HttpStatusCodes.Forbidden) {
sendMessage({ type: MessageTypes.ForbiddenError });
}
throw new Error(`Error creating graph`);
}
}
public static getGremlinGraphUri(params: DataModels.GraphParameters): string {
return `subscriptions/${params.sid}/resourceGroups/${params.rg}/providers/Microsoft.DocumentDB/databaseAccounts/${params.dba}/gremlinDatabases/${params.db}/graphs/${params.coll}`;
}
}
export class Utilities {
public static async createAzureTableWithARM(
armEndpoint: string,
params: DataModels.CreateDatabaseAndCollectionRequest,
rpOptions: DataModels.RpOptions
): Promise<any> {
const rpPayloadToCreateDatabase: DataModels.CreationRequest = {
properties: {
resource: {
id: params.collectionId
},
options: {}
}
};
if (!params.databaseLevelThroughput) {
if (rpOptions) {
rpPayloadToCreateDatabase.properties.options = rpOptions;
} else {
rpPayloadToCreateDatabase.properties.options["throughput"] =
params.offerThroughput && params.offerThroughput.toString();
}
}
try {
await new ResourceProviderClient(armEndpoint).putAsync(
Utilities._getAzureTableUri(params),
DataExplorerConstants.ArmApiVersions.publicVersion,
rpPayloadToCreateDatabase
);
} catch (reason) {
NotificationConsoleUtils.logConsoleMessage(
ConsoleDataType.Error,
`Error creating table: ${JSON.stringify(reason)}, Payload: ${params}`
);
if (reason.status === HttpStatusCodes.Forbidden) {
sendMessage({ type: MessageTypes.ForbiddenError });
return;
}
throw new Error(`Error creating table`);
}
}
public static getMaxRUForStorageOption(
defaults: ViewModels.CollectionCreationDefaults,
storageOption: string
): number {
if (storageOption === SharedConstants.CollectionCreation.storage10Gb) {
return SharedConstants.CollectionCreation.DefaultCollectionRUs10K;
}
return defaults.throughput.unlimitedmax;
}
public static getMinRUForStorageOption(
defaults: ViewModels.CollectionCreationDefaults,
storageOption: string
): number {
if (storageOption === SharedConstants.CollectionCreation.storage10Gb) {
return SharedConstants.CollectionCreation.DefaultCollectionRUs400;
}
return defaults.throughput.unlimitedmin;
}
public static getMaxThroughput(defaults: ViewModels.CollectionCreationDefaults, container: Explorer): number {
const throughput = defaults.throughput.unlimited;
if (typeof throughput === "number") {
return throughput;
} else {
return this._exceedsThreshold(throughput.collectionThreshold, container)
? throughput.greatThanThreshold
: throughput.lessThanOrEqualToThreshold;
}
}
private static _exceedsThreshold(unlimitedThreshold: number, container: Explorer): boolean {
const databases = (container && container.databases && container.databases()) || [];
return _.any(
databases,
database =>
database && database.collections && database.collections() && database.collections().length > unlimitedThreshold
);
}
private static _getAzureTableUri(params: DataModels.CreateDatabaseAndCollectionRequest): string {
return `subscriptions/${userContext.subscriptionId}/resourceGroups/${userContext.resourceGroup}/providers/Microsoft.DocumentDB/databaseAccounts/${userContext.databaseAccount.name}/tables/${params.collectionId}`;
}
}

View File

@@ -1,153 +0,0 @@
import { AddDbUtilities } from "./AddDatabaseUtility";
import { ResourceProviderClient } from "../ResourceProvider/ResourceProviderClient";
jest.mock("../ResourceProvider/ResourceProviderClient.ts");
describe("Add Database Utitlity", () => {
const armEndpoint = "https://management.azure.com";
const properties = {
pk: "state",
coll: "abc-collection",
cd: true,
db: "a1-db",
offerThroughput: 50000,
st: true,
sid: "a1",
rg: "b1",
dba: "main"
};
describe("getRpClient", () => {
it("should return an instance of ResourceProviderClient", () => {
expect(AddDbUtilities.getRpClient()).not.toBeFalsy();
expect(AddDbUtilities.getRpClient()).toBeInstanceOf(ResourceProviderClient);
});
});
describe("getGremlinDatabaseUri", () => {
it("should return a uri in the correct format", () => {
expect(AddDbUtilities.getGremlinDatabaseUri(properties)).toEqual(
"subscriptions/a1/resourceGroups/b1/providers/Microsoft.DocumentDB/databaseAccounts/main/gremlinDatabases/a1-db"
);
});
});
describe("createGremlinDatabase", () => {
it("should utilize resource provider client", () => {
const resourceProviderClientSpy = spyOn<any>(AddDbUtilities, "getRpClient");
AddDbUtilities.createGremlinDatabase(armEndpoint, properties, undefined);
expect(resourceProviderClientSpy).toHaveBeenCalled();
});
it("should invoke getGremlinDatabaseUri", () => {
const getGremlinDatabaseUriSpy = spyOn<any>(AddDbUtilities, "getGremlinDatabaseUri");
AddDbUtilities.createGremlinDatabase(armEndpoint, properties, undefined);
expect(getGremlinDatabaseUriSpy).toHaveBeenCalled();
});
it("should invoke a put call via resource provider client to create a database and set throughput if shared throughtput is true", () => {
const resourceProviderClientPutAsyncSpy = jest.spyOn(ResourceProviderClient.prototype, "putAsync");
AddDbUtilities.createGremlinDatabase(armEndpoint, properties, undefined);
expect(
resourceProviderClientPutAsyncSpy
).toHaveBeenCalledWith(
"subscriptions/a1/resourceGroups/b1/providers/Microsoft.DocumentDB/databaseAccounts/main/gremlinDatabases/a1-db",
"2020-04-01",
{ properties: { options: { throughput: "50000" }, resource: { id: "a1-db" } } }
);
});
it("should invoke a put call via resource provider client to create a database and set autopilot if shared throughtput is true and autopilot settings are passed", () => {
const resourceProviderClientPutAsyncSpy = jest.spyOn(ResourceProviderClient.prototype, "putAsync");
AddDbUtilities.createGremlinDatabase(armEndpoint, properties, { "x-ms-cosmos-offer-autopilot-tier": "1" });
expect(
resourceProviderClientPutAsyncSpy
).toHaveBeenCalledWith(
"subscriptions/a1/resourceGroups/b1/providers/Microsoft.DocumentDB/databaseAccounts/main/gremlinDatabases/a1-db",
"2020-04-01",
{ properties: { options: { "x-ms-cosmos-offer-autopilot-tier": "1" }, resource: { id: "a1-db" } } }
);
});
it("should invoke a put call via resource provider client to create a database and not set throughput if shared throughtput is false", () => {
const properties = {
pk: "state",
coll: "abc-collection",
cd: true,
db: "a2-db",
st: false,
sid: "a2",
rg: "c1",
dba: "main"
};
const resourceProviderClientPutAsyncSpy = jest.spyOn(ResourceProviderClient.prototype, "putAsync");
AddDbUtilities.createGremlinDatabase(armEndpoint, properties, undefined);
expect(
resourceProviderClientPutAsyncSpy
).toHaveBeenCalledWith(
"subscriptions/a2/resourceGroups/c1/providers/Microsoft.DocumentDB/databaseAccounts/main/gremlinDatabases/a2-db",
"2020-04-01",
{ properties: { options: {}, resource: { id: "a2-db" } } }
);
});
});
describe("createSqlDatabase", () => {
it("should utilize resource provider client", () => {
const resourceProviderClientSpy = spyOn<any>(AddDbUtilities, "getRpClient");
AddDbUtilities.createSqlDatabase(armEndpoint, properties, undefined);
expect(resourceProviderClientSpy).toHaveBeenCalled();
});
it("should invoke getSqlDatabaseUri", () => {
const getSqlDatabaseUriSpy = spyOn<any>(AddDbUtilities, "getSqlDatabaseUri");
AddDbUtilities.createSqlDatabase(armEndpoint, properties, undefined);
expect(getSqlDatabaseUriSpy).toHaveBeenCalled();
});
it("should invoke a put call via resource provider client to create a database and set throughput if shared throughtput is true", () => {
const resourceProviderClientPutAsyncSpy = jest.spyOn(ResourceProviderClient.prototype, "putAsync");
AddDbUtilities.createSqlDatabase(armEndpoint, properties, undefined);
expect(
resourceProviderClientPutAsyncSpy
).toHaveBeenCalledWith(
"subscriptions/a1/resourceGroups/b1/providers/Microsoft.DocumentDB/databaseAccounts/main/sqlDatabases/a1-db",
"2020-04-01",
{ properties: { options: { throughput: "50000" }, resource: { id: "a1-db" } } }
);
});
it("should invoke a put call via resource provider client to create a database and set autopilot if shared throughtput is true and autopilot settings are passed", () => {
const resourceProviderClientPutAsyncSpy = jest.spyOn(ResourceProviderClient.prototype, "putAsync");
AddDbUtilities.createSqlDatabase(armEndpoint, properties, { "x-ms-cosmos-offer-autopilot-tier": "1" });
expect(
resourceProviderClientPutAsyncSpy
).toHaveBeenCalledWith(
"subscriptions/a1/resourceGroups/b1/providers/Microsoft.DocumentDB/databaseAccounts/main/sqlDatabases/a1-db",
"2020-04-01",
{ properties: { options: { "x-ms-cosmos-offer-autopilot-tier": "1" }, resource: { id: "a1-db" } } }
);
});
it("should invoke a put call via resource provider client to create a database and not set throughput if shared throughtput is false", () => {
const properties = {
pk: "state",
coll: "abc-collection",
cd: true,
db: "a2-db",
st: false,
sid: "a2",
rg: "c1",
dba: "main"
};
const resourceProviderClientPutAsyncSpy = jest.spyOn(ResourceProviderClient.prototype, "putAsync");
AddDbUtilities.createSqlDatabase(armEndpoint, properties, undefined);
expect(
resourceProviderClientPutAsyncSpy
).toHaveBeenCalledWith(
"subscriptions/a2/resourceGroups/c1/providers/Microsoft.DocumentDB/databaseAccounts/main/sqlDatabases/a2-db",
"2020-04-01",
{ properties: { options: {}, resource: { id: "a2-db" } } }
);
});
});
});

View File

@@ -1,187 +0,0 @@
import * as DataExplorerConstants from "../Common/Constants";
import * as DataModels from "../Contracts/DataModels";
import { configContext } from "../ConfigContext";
import { ConsoleDataType } from "../Explorer/Menus/NotificationConsole/NotificationConsoleComponent";
import { HttpStatusCodes } from "../Common/Constants";
import { sendMessage } from "../Common/MessageHandler";
import { MessageTypes } from "../Contracts/ExplorerContracts";
import * as NotificationConsoleUtils from "../Utils/NotificationConsoleUtils";
import { ResourceProviderClient } from "../ResourceProvider/ResourceProviderClient";
import { userContext } from "../UserContext";
import { createUpdateCassandraKeyspace } from "../Utils/arm/generatedClients/2020-04-01/cassandraResources";
export class AddDbUtilities {
// todo - remove any
public static async createMongoDatabaseWithARM(
armEndpoint: string,
params: DataModels.RpParameters,
rpOptions: DataModels.RpOptions
): Promise<any> {
const rpPayloadToCreateDatabase: DataModels.MongoCreationRequest = {
properties: {
resource: {
id: params.db
},
options: {}
}
};
if (params.st) {
if (rpOptions) {
rpPayloadToCreateDatabase.properties.options = rpOptions;
} else {
rpPayloadToCreateDatabase.properties.options["throughput"] =
params.offerThroughput && params.offerThroughput.toString();
}
}
try {
await AddDbUtilities.getRpClient<DataModels.CreateDatabaseWithRpResponse>(armEndpoint).putAsync(
AddDbUtilities._getMongoDatabaseUri(params),
DataExplorerConstants.ArmApiVersions.publicVersion,
rpPayloadToCreateDatabase
);
} catch (reason) {
AddDbUtilities._handleCreationError(reason, params);
}
}
// todo - remove any
public static async createCassandraKeyspace(
params: DataModels.RpParameters,
rpOptions: DataModels.RpOptions
): Promise<any> {
const rpPayloadToCreateKeyspace: DataModels.CreationRequest = {
properties: {
resource: {
id: params.db
},
options: {}
}
};
if (params.st) {
if (rpOptions) {
rpPayloadToCreateKeyspace.properties.options = rpOptions;
} else {
rpPayloadToCreateKeyspace.properties.options["throughput"] =
params.offerThroughput && params.offerThroughput.toString();
}
}
try {
await createUpdateCassandraKeyspace(
userContext.subscriptionId,
userContext.resourceGroup,
userContext.databaseAccount?.name,
params.db,
rpPayloadToCreateKeyspace
);
} catch (reason) {
AddDbUtilities._handleCreationError(reason, params, "keyspace");
}
}
public static async createSqlDatabase(
armEndpoint: string,
params: DataModels.RpParameters,
rpOptions: DataModels.RpOptions
): Promise<any> {
const rpPayloadToCreateSqlDatabase: DataModels.CreationRequest = {
properties: {
resource: {
id: params.db
},
options: {}
}
};
if (params.st) {
if (rpOptions) {
rpPayloadToCreateSqlDatabase.properties.options = rpOptions;
} else {
rpPayloadToCreateSqlDatabase.properties.options["throughput"] =
params.offerThroughput && params.offerThroughput.toString();
}
}
try {
await AddDbUtilities.getRpClient<DataModels.CreateDatabaseWithRpResponse>(armEndpoint).putAsync(
AddDbUtilities.getSqlDatabaseUri(params),
DataExplorerConstants.ArmApiVersions.publicVersion,
rpPayloadToCreateSqlDatabase
);
} catch (reason) {
AddDbUtilities._handleCreationError(reason, params, "database");
}
}
public static getRpClient<T>(armEndpoint?: string): ResourceProviderClient<T> {
return new ResourceProviderClient<T>(armEndpoint || configContext.ARM_ENDPOINT);
}
public static async createGremlinDatabase(
armEndpoint: string,
params: DataModels.RpParameters,
autoPilotSettings: DataModels.RpOptions
): Promise<DataModels.CreateDatabaseWithRpResponse> {
const rpPayloadToCreateDatabase: DataModels.CreationRequest = {
properties: {
resource: {
id: params.db
},
options: {}
}
};
const uri = AddDbUtilities.getGremlinDatabaseUri(params);
if (params.st) {
if (autoPilotSettings) {
rpPayloadToCreateDatabase.properties.options = autoPilotSettings;
} else {
rpPayloadToCreateDatabase.properties.options["throughput"] =
params.offerThroughput && params.offerThroughput.toString();
}
}
return new Promise<DataModels.CreateDatabaseWithRpResponse>((resolve, reject) => {
AddDbUtilities.getRpClient<DataModels.CreateDatabaseWithRpResponse>(armEndpoint)
.putAsync(uri, DataExplorerConstants.ArmApiVersions.publicVersion, rpPayloadToCreateDatabase)
.then(
() => {
resolve();
},
reason => {
AddDbUtilities._handleCreationError(reason, params);
reject();
}
);
});
}
private static _handleCreationError(reason: any, params: DataModels.RpParameters, dbType: string = "database") {
NotificationConsoleUtils.logConsoleError(`Error creating ${dbType}: ${JSON.stringify(reason)}, Payload: ${params}`);
if (reason.status === HttpStatusCodes.Forbidden) {
sendMessage({ type: MessageTypes.ForbiddenError });
return;
}
throw new Error(`Error creating ${dbType}`);
}
private static _getMongoDatabaseUri(params: DataModels.RpParameters): string {
return `subscriptions/${params.sid}/resourceGroups/${params.rg}/providers/Microsoft.DocumentDB/databaseAccounts/${userContext.databaseAccount.name}/mongodbDatabases/${params.db}`;
}
private static _getCassandraKeyspaceUri(params: DataModels.RpParameters): string {
return `subscriptions/${params.sid}/resourceGroups/${params.rg}/providers/Microsoft.DocumentDB/databaseAccounts/${userContext.databaseAccount.name}/cassandraKeyspaces/${params.db}`;
}
public static getGremlinDatabaseUri(params: DataModels.RpParameters): string {
return `subscriptions/${params.sid}/resourceGroups/${params.rg}/providers/Microsoft.DocumentDB/databaseAccounts/${params.dba}/gremlinDatabases/${params.db}`;
}
public static getSqlDatabaseUri(params: DataModels.RpParameters): string {
return `subscriptions/${params.sid}/resourceGroups/${params.rg}/providers/Microsoft.DocumentDB/databaseAccounts/${params.dba}/sqlDatabases/${params.db}`;
}
}

View File

@@ -1,13 +1,3 @@
/**
* Defines constants related to logging telemetry. Everything except Action should be kept in sync with the one in the Portal code as much as possible.
*
* TODO: Move this to ExplorerContracts (265329)
*/
export class General {
public static ExtensionName: string = "Microsoft_Azure_DocumentDB";
public static BladeNamePrefix: string = "Extension/Microsoft_Azure_DocumentDB/Blade/";
}
// Data Explorer specific actions. No need to keep this in sync with the one in Portal. // Data Explorer specific actions. No need to keep this in sync with the one in Portal.
export enum Action { export enum Action {
CollapseTreeNode, CollapseTreeNode,
@@ -83,24 +73,19 @@ export enum Action {
NotebooksGitHubDisconnect NotebooksGitHubDisconnect
} }
export class ActionModifiers { export const ActionModifiers = {
public static Start: string = "start"; Start: "start",
public static Success: string = "success"; Success: "success",
public static Failed: string = "failed"; Failed: "failed",
public static Mark: string = "mark"; Mark: "mark",
public static Open: string = "open"; Open: "open",
public static IFrameReady: string = "iframeready"; IFrameReady: "iframeready",
public static Close: string = "close"; Close: "close",
public static Submit: string = "submit"; Submit: "submit",
public static IndexAll: string = "index all properties"; IndexAll: "index all properties",
public static NoIndex: string = "no indexing"; NoIndex: "no indexing",
public static Cancel: string = "cancel"; Cancel: "cancel"
} } as const;
export class CosmosDBEndpointNames {
public static Gateway: string = "CosmosDBGateway";
public static ResourceProvider: string = "DocumentDBResourceProvider";
}
export enum SourceBlade { export enum SourceBlade {
AddCollection, AddCollection,
@@ -126,17 +111,3 @@ export enum SourceBlade {
ScriptExplorer, ScriptExplorer,
Keys Keys
} }
export class BladeLoadRequirements {
public static collections: string = "Collections";
public static collectionsWithOffers: string = "CollectionsWithOffers";
public static databaseAccount: string = "DatabaseAccount";
public static keys: string = "Keys";
public static metrics: string = "Metrics";
public static notifications: string = "Notifications";
public static singleCollection: string = "SingleCollection";
public static keysBlade: string[] = [BladeLoadRequirements.databaseAccount, BladeLoadRequirements.keys];
public static metricsBlade: string[] = [BladeLoadRequirements.databaseAccount];
public static overview: string[] = [BladeLoadRequirements.databaseAccount, BladeLoadRequirements.notifications];
}

View File

@@ -8,123 +8,124 @@ import { userContext } from "../../UserContext";
/** /**
* Class that persists telemetry data to the portal tables. * Class that persists telemetry data to the portal tables.
*/ */
// TODO: Move to a separate Diagnostics folder
// TODO: Log telemetry for StorageExplorer case/other clients as well
export default class TelemetryProcessor {
public static trace(action: Action, actionModifier: string = ActionModifiers.Mark, data?: any): void {
sendMessage({
type: MessageTypes.TelemetryInfo,
data: {
action: Action[action],
actionModifier: actionModifier,
data: JSON.stringify(data)
}
});
appInsights.trackEvent({ name: Action[action] }, TelemetryProcessor.getData(data)); export function trace(action: Action, actionModifier: string = ActionModifiers.Mark, data?: unknown): void {
} sendMessage({
type: MessageTypes.TelemetryInfo,
public static traceStart(action: Action, data?: any): number { data: {
const timestamp: number = Date.now(); action: Action[action],
sendMessage({ actionModifier: actionModifier,
type: MessageTypes.TelemetryInfo, data: JSON.stringify(data)
data: {
action: Action[action],
actionModifier: ActionModifiers.Start,
timestamp: timestamp,
data: JSON.stringify(data)
}
});
appInsights.startTrackEvent(Action[action]);
return timestamp;
}
public static traceSuccess(action: Action, data?: any, timestamp?: number): void {
sendMessage({
type: MessageTypes.TelemetryInfo,
data: {
action: Action[action],
actionModifier: ActionModifiers.Success,
timestamp: timestamp || Date.now(),
data: JSON.stringify(data)
}
});
appInsights.stopTrackEvent(Action[action], TelemetryProcessor.getData(data));
}
public static traceFailure(action: Action, data?: any, timestamp?: number): void {
sendMessage({
type: MessageTypes.TelemetryInfo,
data: {
action: Action[action],
actionModifier: ActionModifiers.Failed,
timestamp: timestamp || Date.now(),
data: JSON.stringify(data)
}
});
appInsights.stopTrackEvent(Action[action], TelemetryProcessor.getData(data));
}
public static traceCancel(action: Action, data?: any, timestamp?: number): void {
sendMessage({
type: MessageTypes.TelemetryInfo,
data: {
action: Action[action],
actionModifier: ActionModifiers.Cancel,
timestamp: timestamp || Date.now(),
data: JSON.stringify(data)
}
});
appInsights.stopTrackEvent(Action[action], TelemetryProcessor.getData(data));
}
public static traceOpen(action: Action, data?: any, timestamp?: number): number {
const validTimestamp = timestamp || Date.now();
sendMessage({
type: MessageTypes.TelemetryInfo,
data: {
action: Action[action],
actionModifier: ActionModifiers.Open,
timestamp: validTimestamp,
data: JSON.stringify(data)
}
});
appInsights.startTrackEvent(Action[action]);
return validTimestamp;
}
public static traceMark(action: Action, data?: any, timestamp?: number): number {
const validTimestamp = timestamp || Date.now();
sendMessage({
type: MessageTypes.TelemetryInfo,
data: {
action: Action[action],
actionModifier: ActionModifiers.Mark,
timestamp: validTimestamp,
data: JSON.stringify(data)
}
});
appInsights.startTrackEvent(Action[action]);
return validTimestamp;
}
private static getData(data: any = {}): any {
if (typeof data === "string") {
data = { message: data };
} }
});
appInsights.trackEvent({ name: Action[action] }, getData(data));
}
export function traceStart(action: Action, data?: unknown): number {
const timestamp: number = Date.now();
sendMessage({
type: MessageTypes.TelemetryInfo,
data: {
action: Action[action],
actionModifier: ActionModifiers.Start,
timestamp: timestamp,
data: JSON.stringify(data)
}
});
appInsights.startTrackEvent(Action[action]);
return timestamp;
}
export function traceSuccess(action: Action, data?: unknown, timestamp?: number): void {
sendMessage({
type: MessageTypes.TelemetryInfo,
data: {
action: Action[action],
actionModifier: ActionModifiers.Success,
timestamp: timestamp || Date.now(),
data: JSON.stringify(data)
}
});
appInsights.stopTrackEvent(Action[action], getData(data));
}
export function traceFailure(action: Action, data?: unknown, timestamp?: number): void {
sendMessage({
type: MessageTypes.TelemetryInfo,
data: {
action: Action[action],
actionModifier: ActionModifiers.Failed,
timestamp: timestamp || Date.now(),
data: JSON.stringify(data)
}
});
appInsights.stopTrackEvent(Action[action], getData(data));
}
export function traceCancel(action: Action, data?: unknown, timestamp?: number): void {
sendMessage({
type: MessageTypes.TelemetryInfo,
data: {
action: Action[action],
actionModifier: ActionModifiers.Cancel,
timestamp: timestamp || Date.now(),
data: JSON.stringify(data)
}
});
appInsights.stopTrackEvent(Action[action], getData(data));
}
export function traceOpen(action: Action, data?: unknown, timestamp?: number): number {
const validTimestamp = timestamp || Date.now();
sendMessage({
type: MessageTypes.TelemetryInfo,
data: {
action: Action[action],
actionModifier: ActionModifiers.Open,
timestamp: validTimestamp,
data: JSON.stringify(data)
}
});
appInsights.startTrackEvent(Action[action]);
return validTimestamp;
}
export function traceMark(action: Action, data?: unknown, timestamp?: number): number {
const validTimestamp = timestamp || Date.now();
sendMessage({
type: MessageTypes.TelemetryInfo,
data: {
action: Action[action],
actionModifier: ActionModifiers.Mark,
timestamp: validTimestamp,
data: JSON.stringify(data)
}
});
appInsights.startTrackEvent(Action[action]);
return validTimestamp;
}
function getData(data: unknown = {}): { [key: string]: string } | undefined {
if (typeof data === "string") {
data = { message: data };
}
if (typeof data === "object") {
return { return {
// TODO: Need to `any` here since the window imports Explorer which can't be in strict mode yet // TODO: Need to `any` here since the window imports Explorer which can't be in strict mode yet
// eslint-disable-next-line @typescript-eslint/no-explicit-any
authType: (window as any).authType, authType: (window as any).authType,
subscriptionId: userContext.subscriptionId, subscriptionId: userContext.subscriptionId as string,
platform: configContext.platform, platform: configContext.platform,
env: process.env.NODE_ENV, env: process.env.NODE_ENV as string,
...data ...data
}; };
} }
return undefined;
} }

View File

@@ -1,7 +1,9 @@
import { ApplicationInsights } from "@microsoft/applicationinsights-web"; import { ApplicationInsights } from "@microsoft/applicationinsights-web";
const appInsights = new ApplicationInsights({ const appInsights = new ApplicationInsights({
config: { config: {
instrumentationKey: "fa645d97-6237-4656-9559-0ee0cb55ee49" instrumentationKey: "fa645d97-6237-4656-9559-0ee0cb55ee49",
disableFetchTracking: false
} }
}); });
appInsights.loadAppInsights(); appInsights.loadAppInsights();

View File

@@ -3,7 +3,10 @@ import { ConsoleDataType } from "../Explorer/Menus/NotificationConsole/Notificat
const _global = typeof self === "undefined" ? window : self; const _global = typeof self === "undefined" ? window : self;
// DEPRECATED: Use logConsoleInfo, logConsoleError, logConsoleProgress instead /**
* @deprecated
* Use logConsoleInfo, logConsoleError, logConsoleProgress instead
* */
export function logConsoleMessage(type: ConsoleDataType, message: string, id?: string): string { export function logConsoleMessage(type: ConsoleDataType, message: string, id?: string): string {
const dataExplorer = _global.dataExplorer; const dataExplorer = _global.dataExplorer;
if (dataExplorer) { if (dataExplorer) {

View File

@@ -193,7 +193,7 @@ export function getAutoPilotV3SpendHtml(maxAutoPilotThroughputSet: number, isDat
maxAutoPilotThroughputSet maxAutoPilotThroughputSet
)} GB of data stored, the max RU/s will be automatically upgraded based on the new storage value. <a href='${ )} GB of data stored, the max RU/s will be automatically upgraded based on the new storage value. <a href='${
Constants.AutopilotDocumentation.Url Constants.AutopilotDocumentation.Url
}' target='_blank'>Learn more</a>.`; }' target='_blank' aria-label='Learn more about autoscale throughput'>Learn more</a>.`;
} }
export function computeAutoscaleUsagePriceHourly( export function computeAutoscaleUsagePriceHourly(

View File

@@ -0,0 +1,87 @@
/*
AUTOGENERATED FILE
Do not manually edit
Run "npm run generateARMClients" to regenerate
*/
import { armRequest } from "../../request";
import * as Types from "./types";
import { configContext } from "../../../../ConfigContext";
const apiVersion = "2020-04-01";
/* Gets the notebook workspace resources of an existing Cosmos DB account. */
export async function listByDatabaseAccount(
subscriptionId: string,
resourceGroupName: string,
accountName: string
): Promise<Types.NotebookWorkspaceListResult> {
const path = `/subscriptions/${subscriptionId}/resourceGroups/${resourceGroupName}/providers/Microsoft.DocumentDB/databaseAccounts/${accountName}/notebookWorkspaces`;
return armRequest({ host: configContext.ARM_ENDPOINT, path, method: "GET", apiVersion });
}
/* Gets the notebook workspace for a Cosmos DB account. */
export async function get(
subscriptionId: string,
resourceGroupName: string,
accountName: string,
notebookWorkspaceName: string
): Promise<Types.NotebookWorkspace> {
const path = `/subscriptions/${subscriptionId}/resourceGroups/${resourceGroupName}/providers/Microsoft.DocumentDB/databaseAccounts/${accountName}/notebookWorkspaces/${notebookWorkspaceName}`;
return armRequest({ host: configContext.ARM_ENDPOINT, path, method: "GET", apiVersion });
}
/* Creates the notebook workspace for a Cosmos DB account. */
export async function createOrUpdate(
subscriptionId: string,
resourceGroupName: string,
accountName: string,
notebookWorkspaceName: string,
body: Types.NotebookWorkspaceCreateUpdateParameters
): Promise<Types.NotebookWorkspace> {
const path = `/subscriptions/${subscriptionId}/resourceGroups/${resourceGroupName}/providers/Microsoft.DocumentDB/databaseAccounts/${accountName}/notebookWorkspaces/${notebookWorkspaceName}`;
return armRequest({ host: configContext.ARM_ENDPOINT, path, method: "PUT", apiVersion, body });
}
/* Deletes the notebook workspace for a Cosmos DB account. */
export async function destroy(
subscriptionId: string,
resourceGroupName: string,
accountName: string,
notebookWorkspaceName: string
): Promise<void> {
const path = `/subscriptions/${subscriptionId}/resourceGroups/${resourceGroupName}/providers/Microsoft.DocumentDB/databaseAccounts/${accountName}/notebookWorkspaces/${notebookWorkspaceName}`;
return armRequest({ host: configContext.ARM_ENDPOINT, path, method: "DELETE", apiVersion });
}
/* Retrieves the connection info for the notebook workspace */
export async function listConnectionInfo(
subscriptionId: string,
resourceGroupName: string,
accountName: string,
notebookWorkspaceName: string
): Promise<Types.NotebookWorkspaceConnectionInfoResult> {
const path = `/subscriptions/${subscriptionId}/resourceGroups/${resourceGroupName}/providers/Microsoft.DocumentDB/databaseAccounts/${accountName}/notebookWorkspaces/${notebookWorkspaceName}/listConnectionInfo`;
return armRequest({ host: configContext.ARM_ENDPOINT, path, method: "POST", apiVersion });
}
/* Regenerates the auth token for the notebook workspace */
export async function regenerateAuthToken(
subscriptionId: string,
resourceGroupName: string,
accountName: string,
notebookWorkspaceName: string
): Promise<void> {
const path = `/subscriptions/${subscriptionId}/resourceGroups/${resourceGroupName}/providers/Microsoft.DocumentDB/databaseAccounts/${accountName}/notebookWorkspaces/${notebookWorkspaceName}/regenerateAuthToken`;
return armRequest({ host: configContext.ARM_ENDPOINT, path, method: "POST", apiVersion });
}
/* Starts the notebook workspace */
export async function start(
subscriptionId: string,
resourceGroupName: string,
accountName: string,
notebookWorkspaceName: string
): Promise<void> {
const path = `/subscriptions/${subscriptionId}/resourceGroups/${resourceGroupName}/providers/Microsoft.DocumentDB/databaseAccounts/${accountName}/notebookWorkspaces/${notebookWorkspaceName}/start`;
return armRequest({ host: configContext.ARM_ENDPOINT, path, method: "POST", apiVersion });
}

View File

@@ -0,0 +1,36 @@
/*
AUTOGENERATED FILE
Do not manually edit
Run "npm run generateARMClients" to regenerate
*/
/* Parameters to create a notebook workspace resource */
export type NotebookWorkspaceCreateUpdateParameters = unknown;
/* A list of notebook workspace resources */
export interface NotebookWorkspaceListResult {
/* Array of notebook workspace resources */
value?: NotebookWorkspace[];
}
/* A notebook workspace resource */
export type NotebookWorkspace = unknown & {
/* Resource properties. */
properties?: NotebookWorkspaceProperties;
};
/* Properties of a notebook workspace resource. */
export interface NotebookWorkspaceProperties {
/* Specifies the endpoint of Notebook server. */
readonly notebookServerEndpoint?: string;
/* Status of the notebook workspace. Possible values are: Creating, Online, Deleting, Failed, Updating. */
readonly status?: string;
}
/* The connection info for the given notebook workspace */
export interface NotebookWorkspaceConnectionInfoResult {
/* Specifies auth token used for connecting to Notebook server (uses token-based auth). */
readonly authToken?: string;
/* Specifies the endpoint of Notebook server. */
readonly notebookServerEndpoint?: string;
}

View File

@@ -6,7 +6,7 @@ Instead, generate ARM clients that consume this function with stricter typing.
*/ */
import promiseRetry, { AbortError } from "p-retry"; import promiseRetry, { AbortError } from "p-retry";
import { ErrorResponse } from "./generatedClients/2020-04-01/types"; import { ErrorResponse } from "./generatedClients/2020-04-01-cosmos-db/types";
import { userContext } from "../../UserContext"; import { userContext } from "../../UserContext";
interface ARMError extends Error { interface ARMError extends Error {

View File

@@ -62,15 +62,13 @@
"./src/Shared/ExplorerSettings.ts", "./src/Shared/ExplorerSettings.ts",
"./src/Shared/StorageUtility.ts", "./src/Shared/StorageUtility.ts",
"./src/Shared/StringUtility.ts", "./src/Shared/StringUtility.ts",
"./src/Shared/Telemetry/TelemetryConstants.ts",
"./src/Shared/Telemetry/TelemetryProcessor.ts",
"./src/Shared/appInsights.ts", "./src/Shared/appInsights.ts",
"./src/UserContext.ts", "./src/UserContext.ts",
"./src/Utils/GitHubUtils.ts", "./src/Utils/GitHubUtils.ts",
"./src/Utils/MessageValidation.ts", "./src/Utils/MessageValidation.ts",
"./src/Utils/OfferUtils.ts", "./src/Utils/OfferUtils.ts",
"./src/Utils/StringUtils.ts", "./src/Utils/StringUtils.ts",
"./src/Utils/arm/generatedClients/2020-04-01/types.ts", "./src/Utils/arm/generatedClients/2020-04-01-cosmos-db/types.ts",
"./src/quickstart.ts", "./src/quickstart.ts",
"./src/setupTests.ts", "./src/setupTests.ts",
"./src/workers/upload/definitions.ts" "./src/workers/upload/definitions.ts"

Some files were not shown because too many files have changed in this diff Show More