Refactor DocumentClientUtilityBase to not be a class (#115)
This commit is contained in:
parent
6d142f16f9
commit
2e49ed45c3
|
@ -52,6 +52,7 @@ jobs:
|
||||||
- run: npm run test
|
- run: npm run test
|
||||||
build:
|
build:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
needs: [lint, format, compile, unittest]
|
||||||
name: "Build"
|
name: "Build"
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
|
@ -75,6 +76,7 @@ jobs:
|
||||||
path: dist/
|
path: dist/
|
||||||
endtoendemulator:
|
endtoendemulator:
|
||||||
name: "End To End Tests | Emulator | SQL"
|
name: "End To End Tests | Emulator | SQL"
|
||||||
|
needs: [lint, format, compile, unittest]
|
||||||
runs-on: windows-latest
|
runs-on: windows-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
|
@ -101,6 +103,7 @@ jobs:
|
||||||
CYPRESS_CACHE_FOLDER: ~/.cache/Cypress
|
CYPRESS_CACHE_FOLDER: ~/.cache/Cypress
|
||||||
endtoendsql:
|
endtoendsql:
|
||||||
name: "End To End Tests | SQL"
|
name: "End To End Tests | SQL"
|
||||||
|
needs: [lint, format, compile, unittest]
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
|
@ -129,6 +132,7 @@ jobs:
|
||||||
CYPRESS_CONNECTION_STRING: ${{ secrets.CONNECTION_STRING_SQL }}
|
CYPRESS_CONNECTION_STRING: ${{ secrets.CONNECTION_STRING_SQL }}
|
||||||
endtoendmongo:
|
endtoendmongo:
|
||||||
name: "End To End Tests | Mongo"
|
name: "End To End Tests | Mongo"
|
||||||
|
needs: [lint, format, compile, unittest]
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
|
@ -157,6 +161,7 @@ jobs:
|
||||||
CYPRESS_CONNECTION_STRING: ${{ secrets.CONNECTION_STRING_MONGO }}
|
CYPRESS_CONNECTION_STRING: ${{ secrets.CONNECTION_STRING_MONGO }}
|
||||||
accessibility:
|
accessibility:
|
||||||
name: "Accessibility | Hosted"
|
name: "Accessibility | Hosted"
|
||||||
|
needs: [lint, format, compile, unittest]
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
|
|
|
@ -39,10 +39,10 @@ module.exports = {
|
||||||
// An object that configures minimum threshold enforcement for coverage results
|
// An object that configures minimum threshold enforcement for coverage results
|
||||||
coverageThreshold: {
|
coverageThreshold: {
|
||||||
global: {
|
global: {
|
||||||
branches: 18,
|
branches: 19.5,
|
||||||
functions: 22,
|
functions: 24,
|
||||||
lines: 28,
|
lines: 29.5,
|
||||||
statements: 27
|
statements: 28.5
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -11,6 +11,13 @@ import * as Logger from "./Logger";
|
||||||
import { NotificationConsoleUtils } from "../Utils/NotificationConsoleUtils";
|
import { NotificationConsoleUtils } from "../Utils/NotificationConsoleUtils";
|
||||||
import { QueryUtils } from "../Utils/QueryUtils";
|
import { QueryUtils } from "../Utils/QueryUtils";
|
||||||
import Explorer from "../Explorer/Explorer";
|
import Explorer from "../Explorer/Explorer";
|
||||||
|
import {
|
||||||
|
getOrCreateDatabaseAndCollection,
|
||||||
|
createDocument,
|
||||||
|
queryDocuments,
|
||||||
|
queryDocumentsPage,
|
||||||
|
deleteDocument
|
||||||
|
} from "./DocumentClientUtilityBase";
|
||||||
|
|
||||||
export class QueriesClient implements ViewModels.QueriesClient {
|
export class QueriesClient implements ViewModels.QueriesClient {
|
||||||
private static readonly PartitionKey: DataModels.PartitionKey = {
|
private static readonly PartitionKey: DataModels.PartitionKey = {
|
||||||
|
@ -33,14 +40,13 @@ export class QueriesClient implements ViewModels.QueriesClient {
|
||||||
ConsoleDataType.InProgress,
|
ConsoleDataType.InProgress,
|
||||||
"Setting up account for saving queries"
|
"Setting up account for saving queries"
|
||||||
);
|
);
|
||||||
return this.container.documentClientUtility
|
return getOrCreateDatabaseAndCollection({
|
||||||
.getOrCreateDatabaseAndCollection({
|
collectionId: SavedQueries.CollectionName,
|
||||||
collectionId: SavedQueries.CollectionName,
|
databaseId: SavedQueries.DatabaseName,
|
||||||
databaseId: SavedQueries.DatabaseName,
|
partitionKey: QueriesClient.PartitionKey,
|
||||||
partitionKey: QueriesClient.PartitionKey,
|
offerThroughput: SavedQueries.OfferThroughput,
|
||||||
offerThroughput: SavedQueries.OfferThroughput,
|
databaseLevelThroughput: undefined
|
||||||
databaseLevelThroughput: undefined
|
})
|
||||||
})
|
|
||||||
.then(
|
.then(
|
||||||
(collection: DataModels.Collection) => {
|
(collection: DataModels.Collection) => {
|
||||||
NotificationConsoleUtils.logConsoleMessage(
|
NotificationConsoleUtils.logConsoleMessage(
|
||||||
|
@ -89,8 +95,7 @@ export class QueriesClient implements ViewModels.QueriesClient {
|
||||||
`Saving query ${query.queryName}`
|
`Saving query ${query.queryName}`
|
||||||
);
|
);
|
||||||
query.id = query.queryName;
|
query.id = query.queryName;
|
||||||
return this.container.documentClientUtility
|
return createDocument(queriesCollection, query)
|
||||||
.createDocument(queriesCollection, query)
|
|
||||||
.then(
|
.then(
|
||||||
(savedQuery: DataModels.Query) => {
|
(savedQuery: DataModels.Query) => {
|
||||||
NotificationConsoleUtils.logConsoleMessage(
|
NotificationConsoleUtils.logConsoleMessage(
|
||||||
|
@ -131,17 +136,11 @@ export class QueriesClient implements ViewModels.QueriesClient {
|
||||||
|
|
||||||
const options: any = { enableCrossPartitionQuery: true };
|
const options: any = { enableCrossPartitionQuery: true };
|
||||||
const id = NotificationConsoleUtils.logConsoleMessage(ConsoleDataType.InProgress, "Fetching saved queries");
|
const id = NotificationConsoleUtils.logConsoleMessage(ConsoleDataType.InProgress, "Fetching saved queries");
|
||||||
return this.container.documentClientUtility
|
return queryDocuments(SavedQueries.DatabaseName, SavedQueries.CollectionName, this.fetchQueriesQuery(), options)
|
||||||
.queryDocuments(SavedQueries.DatabaseName, SavedQueries.CollectionName, this.fetchQueriesQuery(), options)
|
|
||||||
.then(
|
.then(
|
||||||
(queryIterator: QueryIterator<ItemDefinition & Resource>) => {
|
(queryIterator: QueryIterator<ItemDefinition & Resource>) => {
|
||||||
const fetchQueries = (firstItemIndex: number): Q.Promise<ViewModels.QueryResults> =>
|
const fetchQueries = (firstItemIndex: number): Q.Promise<ViewModels.QueryResults> =>
|
||||||
this.container.documentClientUtility.queryDocumentsPage(
|
queryDocumentsPage(queriesCollection.id(), queryIterator, firstItemIndex, options);
|
||||||
queriesCollection.id(),
|
|
||||||
queryIterator,
|
|
||||||
firstItemIndex,
|
|
||||||
options
|
|
||||||
);
|
|
||||||
return QueryUtils.queryAllPages(fetchQueries).then(
|
return QueryUtils.queryAllPages(fetchQueries).then(
|
||||||
(results: ViewModels.QueryResults) => {
|
(results: ViewModels.QueryResults) => {
|
||||||
let queries: DataModels.Query[] = _.map(results.documents, (document: DataModels.Query) => {
|
let queries: DataModels.Query[] = _.map(results.documents, (document: DataModels.Query) => {
|
||||||
|
@ -226,8 +225,7 @@ export class QueriesClient implements ViewModels.QueriesClient {
|
||||||
query.queryName
|
query.queryName
|
||||||
); // TODO: Remove DocumentId's dependency on DocumentsTab
|
); // TODO: Remove DocumentId's dependency on DocumentsTab
|
||||||
const options: any = { partitionKey: query.resourceId };
|
const options: any = { partitionKey: query.resourceId };
|
||||||
return this.container.documentClientUtility
|
return deleteDocument(queriesCollection, documentId)
|
||||||
.deleteDocument(queriesCollection, documentId)
|
|
||||||
.then(
|
.then(
|
||||||
() => {
|
() => {
|
||||||
NotificationConsoleUtils.logConsoleMessage(
|
NotificationConsoleUtils.logConsoleMessage(
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import * as DataModels from "./DataModels";
|
import * as DataModels from "./DataModels";
|
||||||
import * as monaco from "monaco-editor";
|
import * as monaco from "monaco-editor";
|
||||||
import DocumentClientUtilityBase from "../Common/DocumentClientUtilityBase";
|
|
||||||
import Q from "q";
|
import Q from "q";
|
||||||
import { AccessibleVerticalList } from "../Explorer/Tree/AccessibleVerticalList";
|
import { AccessibleVerticalList } from "../Explorer/Tree/AccessibleVerticalList";
|
||||||
import { CassandraTableKey, CassandraTableKeys } from "../Explorer/Tables/TableDataClient";
|
import { CassandraTableKey, CassandraTableKeys } from "../Explorer/Tables/TableDataClient";
|
||||||
|
@ -18,7 +17,6 @@ import ConflictsTab from "../Explorer/Tabs/ConflictsTab";
|
||||||
import Trigger from "../Explorer/Tree/Trigger";
|
import Trigger from "../Explorer/Tree/Trigger";
|
||||||
|
|
||||||
export interface ExplorerOptions {
|
export interface ExplorerOptions {
|
||||||
documentClientUtility: DocumentClientUtilityBase;
|
|
||||||
notificationsClient: NotificationsClient;
|
notificationsClient: NotificationsClient;
|
||||||
isEmulator: boolean;
|
isEmulator: boolean;
|
||||||
}
|
}
|
||||||
|
@ -245,13 +243,11 @@ export interface ConflictId {
|
||||||
*/
|
*/
|
||||||
export interface PaneOptions {
|
export interface PaneOptions {
|
||||||
id: string;
|
id: string;
|
||||||
documentClientUtility: DocumentClientUtilityBase;
|
|
||||||
visible: ko.Observable<boolean>;
|
visible: ko.Observable<boolean>;
|
||||||
container?: Explorer;
|
container?: Explorer;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ContextualPane {
|
export interface ContextualPane {
|
||||||
documentClientUtility: DocumentClientUtilityBase;
|
|
||||||
formErrors: ko.Observable<string>;
|
formErrors: ko.Observable<string>;
|
||||||
formErrorsDetails: ko.Observable<string>;
|
formErrorsDetails: ko.Observable<string>;
|
||||||
id: string;
|
id: string;
|
||||||
|
@ -406,7 +402,6 @@ export interface TabOptions {
|
||||||
tabKind: CollectionTabKind;
|
tabKind: CollectionTabKind;
|
||||||
title: string;
|
title: string;
|
||||||
tabPath: string;
|
tabPath: string;
|
||||||
documentClientUtility: DocumentClientUtilityBase;
|
|
||||||
selfLink: string;
|
selfLink: string;
|
||||||
isActive: ko.Observable<boolean>;
|
isActive: ko.Observable<boolean>;
|
||||||
hashLocation: string;
|
hashLocation: string;
|
||||||
|
@ -493,11 +488,9 @@ export interface ScriptTabOption extends TabOptions {
|
||||||
|
|
||||||
// Tabs
|
// Tabs
|
||||||
export interface Tab {
|
export interface Tab {
|
||||||
documentClientUtility: DocumentClientUtilityBase;
|
|
||||||
node: TreeNode; // Can be null
|
node: TreeNode; // Can be null
|
||||||
collection: CollectionBase;
|
collection: CollectionBase;
|
||||||
rid: string;
|
rid: string;
|
||||||
|
|
||||||
tabKind: CollectionTabKind;
|
tabKind: CollectionTabKind;
|
||||||
tabId: string;
|
tabId: string;
|
||||||
isActive: ko.Observable<boolean>;
|
isActive: ko.Observable<boolean>;
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
|
jest.mock("../../Common/DocumentClientUtilityBase");
|
||||||
import * as ko from "knockout";
|
import * as ko from "knockout";
|
||||||
import * as sinon from "sinon";
|
import * as sinon from "sinon";
|
||||||
import * as ViewModels from "../../Contracts/ViewModels";
|
import * as ViewModels from "../../Contracts/ViewModels";
|
||||||
import DocumentClientUtilityBase from "../../Common/DocumentClientUtilityBase";
|
|
||||||
import Q from "q";
|
import Q from "q";
|
||||||
import { ContainerSampleGenerator } from "./ContainerSampleGenerator";
|
import { ContainerSampleGenerator } from "./ContainerSampleGenerator";
|
||||||
import { CosmosClient } from "../../Common/CosmosClient";
|
import { CosmosClient } from "../../Common/CosmosClient";
|
||||||
|
import * as DocumentClientUtility from "../../Common/DocumentClientUtilityBase";
|
||||||
import { GremlinClient } from "../Graph/GraphExplorerComponent/GremlinClient";
|
import { GremlinClient } from "../Graph/GraphExplorerComponent/GremlinClient";
|
||||||
import Explorer from "../Explorer";
|
import Explorer from "../Explorer";
|
||||||
|
|
||||||
|
@ -62,19 +63,12 @@ describe("ContainerSampleGenerator", () => {
|
||||||
|
|
||||||
const explorerStub = createExplorerStub(database);
|
const explorerStub = createExplorerStub(database);
|
||||||
explorerStub.isPreferredApiDocumentDB = ko.computed<boolean>(() => true);
|
explorerStub.isPreferredApiDocumentDB = ko.computed<boolean>(() => true);
|
||||||
|
|
||||||
const fakeDocumentClientUtility = sinon.createStubInstance(DocumentClientUtilityBase);
|
|
||||||
fakeDocumentClientUtility.getOrCreateDatabaseAndCollection.returns(Q.resolve(collection));
|
|
||||||
fakeDocumentClientUtility.createDocument.returns(Q.resolve());
|
|
||||||
|
|
||||||
explorerStub.documentClientUtility = fakeDocumentClientUtility;
|
|
||||||
|
|
||||||
const generator = await ContainerSampleGenerator.createSampleGeneratorAsync(explorerStub);
|
const generator = await ContainerSampleGenerator.createSampleGeneratorAsync(explorerStub);
|
||||||
generator.setData(sampleData);
|
generator.setData(sampleData);
|
||||||
|
|
||||||
await generator.createSampleContainerAsync();
|
await generator.createSampleContainerAsync();
|
||||||
|
|
||||||
expect(fakeDocumentClientUtility.createDocument.called).toBe(true);
|
expect(DocumentClientUtility.createDocument).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should send gremlin queries for Graph API account", async () => {
|
it("should send gremlin queries for Graph API account", async () => {
|
||||||
|
@ -109,18 +103,12 @@ describe("ContainerSampleGenerator", () => {
|
||||||
const explorerStub = createExplorerStub(database);
|
const explorerStub = createExplorerStub(database);
|
||||||
explorerStub.isPreferredApiGraph = ko.computed<boolean>(() => true);
|
explorerStub.isPreferredApiGraph = ko.computed<boolean>(() => true);
|
||||||
|
|
||||||
const fakeDocumentClientUtility = sinon.createStubInstance(DocumentClientUtilityBase);
|
|
||||||
fakeDocumentClientUtility.getOrCreateDatabaseAndCollection.returns(Q.resolve(collection));
|
|
||||||
fakeDocumentClientUtility.createDocument.returns(Q.resolve());
|
|
||||||
|
|
||||||
explorerStub.documentClientUtility = fakeDocumentClientUtility;
|
|
||||||
|
|
||||||
const generator = await ContainerSampleGenerator.createSampleGeneratorAsync(explorerStub);
|
const generator = await ContainerSampleGenerator.createSampleGeneratorAsync(explorerStub);
|
||||||
generator.setData(sampleData);
|
generator.setData(sampleData);
|
||||||
|
|
||||||
await generator.createSampleContainerAsync();
|
await generator.createSampleContainerAsync();
|
||||||
|
|
||||||
expect(fakeDocumentClientUtility.createDocument.called).toBe(false);
|
expect(DocumentClientUtility.createDocument).toHaveBeenCalled();
|
||||||
expect(executeStub.called).toBe(true);
|
expect(executeStub.called).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@ import { CosmosClient } from "../../Common/CosmosClient";
|
||||||
import { GremlinClient } from "../Graph/GraphExplorerComponent/GremlinClient";
|
import { GremlinClient } from "../Graph/GraphExplorerComponent/GremlinClient";
|
||||||
import { NotificationConsoleUtils } from "../../Utils/NotificationConsoleUtils";
|
import { NotificationConsoleUtils } from "../../Utils/NotificationConsoleUtils";
|
||||||
import Explorer from "../Explorer";
|
import Explorer from "../Explorer";
|
||||||
|
import { createDocument, getOrCreateDatabaseAndCollection } from "../../Common/DocumentClientUtilityBase";
|
||||||
|
|
||||||
interface SampleDataFile extends DataModels.CreateDatabaseAndCollectionRequest {
|
interface SampleDataFile extends DataModels.CreateDatabaseAndCollectionRequest {
|
||||||
data: any[];
|
data: any[];
|
||||||
|
@ -64,7 +65,7 @@ export class ContainerSampleGenerator {
|
||||||
options.initialHeaders[Constants.HttpHeaders.usePolygonsSmallerThanAHemisphere] = true;
|
options.initialHeaders[Constants.HttpHeaders.usePolygonsSmallerThanAHemisphere] = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
await this.container.documentClientUtility.getOrCreateDatabaseAndCollection(createRequest, options);
|
await getOrCreateDatabaseAndCollection(createRequest, options);
|
||||||
await this.container.refreshAllDatabases();
|
await this.container.refreshAllDatabases();
|
||||||
const database = this.container.findDatabaseWithId(this.sampleDataFile.databaseId);
|
const database = this.container.findDatabaseWithId(this.sampleDataFile.databaseId);
|
||||||
if (!database) {
|
if (!database) {
|
||||||
|
@ -103,7 +104,7 @@ export class ContainerSampleGenerator {
|
||||||
} else {
|
} else {
|
||||||
// For SQL all queries are executed at the same time
|
// For SQL all queries are executed at the same time
|
||||||
this.sampleDataFile.data.forEach(doc => {
|
this.sampleDataFile.data.forEach(doc => {
|
||||||
const subPromise = this.container.documentClientUtility.createDocument(collection, doc);
|
const subPromise = createDocument(collection, doc);
|
||||||
subPromise.catch(reason => NotificationConsoleUtils.logConsoleMessage(ConsoleDataType.Error, reason));
|
subPromise.catch(reason => NotificationConsoleUtils.logConsoleMessage(ConsoleDataType.Error, reason));
|
||||||
promises.push(subPromise);
|
promises.push(subPromise);
|
||||||
});
|
});
|
||||||
|
|
|
@ -15,7 +15,7 @@ import CassandraAddCollectionPane from "./Panes/CassandraAddCollectionPane";
|
||||||
import Database from "./Tree/Database";
|
import Database from "./Tree/Database";
|
||||||
import DeleteCollectionConfirmationPane from "./Panes/DeleteCollectionConfirmationPane";
|
import DeleteCollectionConfirmationPane from "./Panes/DeleteCollectionConfirmationPane";
|
||||||
import DeleteDatabaseConfirmationPane from "./Panes/DeleteDatabaseConfirmationPane";
|
import DeleteDatabaseConfirmationPane from "./Panes/DeleteDatabaseConfirmationPane";
|
||||||
import DocumentClientUtilityBase from "../Common/DocumentClientUtilityBase";
|
import { readDatabases, readCollection, readOffers, refreshCachedResources } from "../Common/DocumentClientUtilityBase";
|
||||||
import EditTableEntityPane from "./Panes/Tables/EditTableEntityPane";
|
import EditTableEntityPane from "./Panes/Tables/EditTableEntityPane";
|
||||||
import EnvironmentUtility from "../Common/EnvironmentUtility";
|
import EnvironmentUtility from "../Common/EnvironmentUtility";
|
||||||
import GraphStylingPane from "./Panes/GraphStylingPane";
|
import GraphStylingPane from "./Panes/GraphStylingPane";
|
||||||
|
@ -127,7 +127,6 @@ export default class Explorer {
|
||||||
public extensionEndpoint: ko.Observable<string>;
|
public extensionEndpoint: ko.Observable<string>;
|
||||||
public armEndpoint: ko.Observable<string>;
|
public armEndpoint: ko.Observable<string>;
|
||||||
public isTryCosmosDBSubscription: ko.Observable<boolean>;
|
public isTryCosmosDBSubscription: ko.Observable<boolean>;
|
||||||
public documentClientUtility: DocumentClientUtilityBase;
|
|
||||||
public notificationsClient: ViewModels.NotificationsClient;
|
public notificationsClient: ViewModels.NotificationsClient;
|
||||||
public queriesClient: ViewModels.QueriesClient;
|
public queriesClient: ViewModels.QueriesClient;
|
||||||
public tableDataClient: TableDataClient;
|
public tableDataClient: TableDataClient;
|
||||||
|
@ -358,7 +357,6 @@ export default class Explorer {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
this.memoryUsageInfo = ko.observable<DataModels.MemoryUsageInfo>();
|
this.memoryUsageInfo = ko.observable<DataModels.MemoryUsageInfo>();
|
||||||
this.documentClientUtility = options.documentClientUtility;
|
|
||||||
this.notificationsClient = options.notificationsClient;
|
this.notificationsClient = options.notificationsClient;
|
||||||
this.isEmulator = options.isEmulator;
|
this.isEmulator = options.isEmulator;
|
||||||
|
|
||||||
|
@ -584,7 +582,6 @@ export default class Explorer {
|
||||||
});
|
});
|
||||||
|
|
||||||
this.addDatabasePane = new AddDatabasePane({
|
this.addDatabasePane = new AddDatabasePane({
|
||||||
documentClientUtility: this.documentClientUtility,
|
|
||||||
id: "adddatabasepane",
|
id: "adddatabasepane",
|
||||||
visible: ko.observable<boolean>(false),
|
visible: ko.observable<boolean>(false),
|
||||||
|
|
||||||
|
@ -593,7 +590,6 @@ export default class Explorer {
|
||||||
|
|
||||||
this.addCollectionPane = new AddCollectionPane({
|
this.addCollectionPane = new AddCollectionPane({
|
||||||
isPreferredApiTable: ko.computed(() => this.isPreferredApiTable()),
|
isPreferredApiTable: ko.computed(() => this.isPreferredApiTable()),
|
||||||
documentClientUtility: this.documentClientUtility,
|
|
||||||
id: "addcollectionpane",
|
id: "addcollectionpane",
|
||||||
visible: ko.observable<boolean>(false),
|
visible: ko.observable<boolean>(false),
|
||||||
|
|
||||||
|
@ -601,7 +597,6 @@ export default class Explorer {
|
||||||
});
|
});
|
||||||
|
|
||||||
this.deleteCollectionConfirmationPane = new DeleteCollectionConfirmationPane({
|
this.deleteCollectionConfirmationPane = new DeleteCollectionConfirmationPane({
|
||||||
documentClientUtility: this.documentClientUtility,
|
|
||||||
id: "deletecollectionconfirmationpane",
|
id: "deletecollectionconfirmationpane",
|
||||||
visible: ko.observable<boolean>(false),
|
visible: ko.observable<boolean>(false),
|
||||||
|
|
||||||
|
@ -609,7 +604,6 @@ export default class Explorer {
|
||||||
});
|
});
|
||||||
|
|
||||||
this.deleteDatabaseConfirmationPane = new DeleteDatabaseConfirmationPane({
|
this.deleteDatabaseConfirmationPane = new DeleteDatabaseConfirmationPane({
|
||||||
documentClientUtility: this.documentClientUtility,
|
|
||||||
id: "deletedatabaseconfirmationpane",
|
id: "deletedatabaseconfirmationpane",
|
||||||
visible: ko.observable<boolean>(false),
|
visible: ko.observable<boolean>(false),
|
||||||
|
|
||||||
|
@ -617,7 +611,6 @@ export default class Explorer {
|
||||||
});
|
});
|
||||||
|
|
||||||
this.graphStylingPane = new GraphStylingPane({
|
this.graphStylingPane = new GraphStylingPane({
|
||||||
documentClientUtility: this.documentClientUtility,
|
|
||||||
id: "graphstylingpane",
|
id: "graphstylingpane",
|
||||||
visible: ko.observable<boolean>(false),
|
visible: ko.observable<boolean>(false),
|
||||||
|
|
||||||
|
@ -625,7 +618,6 @@ export default class Explorer {
|
||||||
});
|
});
|
||||||
|
|
||||||
this.addTableEntityPane = new AddTableEntityPane({
|
this.addTableEntityPane = new AddTableEntityPane({
|
||||||
documentClientUtility: this.documentClientUtility,
|
|
||||||
id: "addtableentitypane",
|
id: "addtableentitypane",
|
||||||
visible: ko.observable<boolean>(false),
|
visible: ko.observable<boolean>(false),
|
||||||
|
|
||||||
|
@ -633,7 +625,6 @@ export default class Explorer {
|
||||||
});
|
});
|
||||||
|
|
||||||
this.editTableEntityPane = new EditTableEntityPane({
|
this.editTableEntityPane = new EditTableEntityPane({
|
||||||
documentClientUtility: this.documentClientUtility,
|
|
||||||
id: "edittableentitypane",
|
id: "edittableentitypane",
|
||||||
visible: ko.observable<boolean>(false),
|
visible: ko.observable<boolean>(false),
|
||||||
|
|
||||||
|
@ -641,7 +632,6 @@ export default class Explorer {
|
||||||
});
|
});
|
||||||
|
|
||||||
this.tableColumnOptionsPane = new TableColumnOptionsPane({
|
this.tableColumnOptionsPane = new TableColumnOptionsPane({
|
||||||
documentClientUtility: this.documentClientUtility,
|
|
||||||
id: "tablecolumnoptionspane",
|
id: "tablecolumnoptionspane",
|
||||||
visible: ko.observable<boolean>(false),
|
visible: ko.observable<boolean>(false),
|
||||||
|
|
||||||
|
@ -649,7 +639,6 @@ export default class Explorer {
|
||||||
});
|
});
|
||||||
|
|
||||||
this.querySelectPane = new QuerySelectPane({
|
this.querySelectPane = new QuerySelectPane({
|
||||||
documentClientUtility: this.documentClientUtility,
|
|
||||||
id: "queryselectpane",
|
id: "queryselectpane",
|
||||||
visible: ko.observable<boolean>(false),
|
visible: ko.observable<boolean>(false),
|
||||||
|
|
||||||
|
@ -657,7 +646,6 @@ export default class Explorer {
|
||||||
});
|
});
|
||||||
|
|
||||||
this.newVertexPane = new NewVertexPane({
|
this.newVertexPane = new NewVertexPane({
|
||||||
documentClientUtility: this.documentClientUtility,
|
|
||||||
id: "newvertexpane",
|
id: "newvertexpane",
|
||||||
visible: ko.observable<boolean>(false),
|
visible: ko.observable<boolean>(false),
|
||||||
|
|
||||||
|
@ -665,7 +653,6 @@ export default class Explorer {
|
||||||
});
|
});
|
||||||
|
|
||||||
this.cassandraAddCollectionPane = new CassandraAddCollectionPane({
|
this.cassandraAddCollectionPane = new CassandraAddCollectionPane({
|
||||||
documentClientUtility: this.documentClientUtility,
|
|
||||||
id: "cassandraaddcollectionpane",
|
id: "cassandraaddcollectionpane",
|
||||||
visible: ko.observable<boolean>(false),
|
visible: ko.observable<boolean>(false),
|
||||||
|
|
||||||
|
@ -673,7 +660,6 @@ export default class Explorer {
|
||||||
});
|
});
|
||||||
|
|
||||||
this.settingsPane = new SettingsPane({
|
this.settingsPane = new SettingsPane({
|
||||||
documentClientUtility: this.documentClientUtility,
|
|
||||||
id: "settingspane",
|
id: "settingspane",
|
||||||
visible: ko.observable<boolean>(false),
|
visible: ko.observable<boolean>(false),
|
||||||
|
|
||||||
|
@ -681,7 +667,6 @@ export default class Explorer {
|
||||||
});
|
});
|
||||||
|
|
||||||
this.executeSprocParamsPane = new ExecuteSprocParamsPane({
|
this.executeSprocParamsPane = new ExecuteSprocParamsPane({
|
||||||
documentClientUtility: this.documentClientUtility,
|
|
||||||
id: "executesprocparamspane",
|
id: "executesprocparamspane",
|
||||||
visible: ko.observable<boolean>(false),
|
visible: ko.observable<boolean>(false),
|
||||||
|
|
||||||
|
@ -689,7 +674,6 @@ export default class Explorer {
|
||||||
});
|
});
|
||||||
|
|
||||||
this.renewAdHocAccessPane = new RenewAdHocAccessPane({
|
this.renewAdHocAccessPane = new RenewAdHocAccessPane({
|
||||||
documentClientUtility: this.documentClientUtility,
|
|
||||||
id: "renewadhocaccesspane",
|
id: "renewadhocaccesspane",
|
||||||
visible: ko.observable<boolean>(false),
|
visible: ko.observable<boolean>(false),
|
||||||
|
|
||||||
|
@ -697,7 +681,6 @@ export default class Explorer {
|
||||||
});
|
});
|
||||||
|
|
||||||
this.uploadItemsPane = new UploadItemsPane({
|
this.uploadItemsPane = new UploadItemsPane({
|
||||||
documentClientUtility: this.documentClientUtility,
|
|
||||||
id: "uploaditemspane",
|
id: "uploaditemspane",
|
||||||
visible: ko.observable<boolean>(false),
|
visible: ko.observable<boolean>(false),
|
||||||
|
|
||||||
|
@ -707,7 +690,6 @@ export default class Explorer {
|
||||||
this.uploadItemsPaneAdapter = new UploadItemsPaneAdapter(this);
|
this.uploadItemsPaneAdapter = new UploadItemsPaneAdapter(this);
|
||||||
|
|
||||||
this.loadQueryPane = new LoadQueryPane({
|
this.loadQueryPane = new LoadQueryPane({
|
||||||
documentClientUtility: this.documentClientUtility,
|
|
||||||
id: "loadquerypane",
|
id: "loadquerypane",
|
||||||
visible: ko.observable<boolean>(false),
|
visible: ko.observable<boolean>(false),
|
||||||
|
|
||||||
|
@ -715,7 +697,6 @@ export default class Explorer {
|
||||||
});
|
});
|
||||||
|
|
||||||
this.saveQueryPane = new SaveQueryPane({
|
this.saveQueryPane = new SaveQueryPane({
|
||||||
documentClientUtility: this.documentClientUtility,
|
|
||||||
id: "savequerypane",
|
id: "savequerypane",
|
||||||
visible: ko.observable<boolean>(false),
|
visible: ko.observable<boolean>(false),
|
||||||
|
|
||||||
|
@ -723,7 +704,6 @@ export default class Explorer {
|
||||||
});
|
});
|
||||||
|
|
||||||
this.browseQueriesPane = new BrowseQueriesPane({
|
this.browseQueriesPane = new BrowseQueriesPane({
|
||||||
documentClientUtility: this.documentClientUtility,
|
|
||||||
id: "browsequeriespane",
|
id: "browsequeriespane",
|
||||||
visible: ko.observable<boolean>(false),
|
visible: ko.observable<boolean>(false),
|
||||||
|
|
||||||
|
@ -731,7 +711,6 @@ export default class Explorer {
|
||||||
});
|
});
|
||||||
|
|
||||||
this.uploadFilePane = new UploadFilePane({
|
this.uploadFilePane = new UploadFilePane({
|
||||||
documentClientUtility: this.documentClientUtility,
|
|
||||||
id: "uploadfilepane",
|
id: "uploadfilepane",
|
||||||
visible: ko.observable<boolean>(false),
|
visible: ko.observable<boolean>(false),
|
||||||
|
|
||||||
|
@ -739,7 +718,6 @@ export default class Explorer {
|
||||||
});
|
});
|
||||||
|
|
||||||
this.stringInputPane = new StringInputPane({
|
this.stringInputPane = new StringInputPane({
|
||||||
documentClientUtility: this.documentClientUtility,
|
|
||||||
id: "stringinputpane",
|
id: "stringinputpane",
|
||||||
visible: ko.observable<boolean>(false),
|
visible: ko.observable<boolean>(false),
|
||||||
|
|
||||||
|
@ -747,7 +725,6 @@ export default class Explorer {
|
||||||
});
|
});
|
||||||
|
|
||||||
this.setupNotebooksPane = new SetupNotebooksPane({
|
this.setupNotebooksPane = new SetupNotebooksPane({
|
||||||
documentClientUtility: this.documentClientUtility,
|
|
||||||
id: "setupnotebookspane",
|
id: "setupnotebookspane",
|
||||||
visible: ko.observable<boolean>(false),
|
visible: ko.observable<boolean>(false),
|
||||||
|
|
||||||
|
@ -780,7 +757,6 @@ export default class Explorer {
|
||||||
this.setupNotebooksPane
|
this.setupNotebooksPane
|
||||||
];
|
];
|
||||||
this.addDatabaseText.subscribe((addDatabaseText: string) => this.addDatabasePane.title(addDatabaseText));
|
this.addDatabaseText.subscribe((addDatabaseText: string) => this.addDatabasePane.title(addDatabaseText));
|
||||||
this.rebindDocumentClientUtility.bind(this);
|
|
||||||
this.isTabsContentExpanded = ko.observable(false);
|
this.isTabsContentExpanded = ko.observable(false);
|
||||||
|
|
||||||
document.addEventListener(
|
document.addEventListener(
|
||||||
|
@ -862,7 +838,7 @@ export default class Explorer {
|
||||||
this.editTableEntityPane.title("Edit Table Entity");
|
this.editTableEntityPane.title("Edit Table Entity");
|
||||||
this.deleteCollectionConfirmationPane.title("Delete Table");
|
this.deleteCollectionConfirmationPane.title("Delete Table");
|
||||||
this.deleteCollectionConfirmationPane.collectionIdConfirmationText("Confirm by typing the table id");
|
this.deleteCollectionConfirmationPane.collectionIdConfirmationText("Confirm by typing the table id");
|
||||||
this.tableDataClient = new TablesAPIDataClient(this.documentClientUtility);
|
this.tableDataClient = new TablesAPIDataClient();
|
||||||
break;
|
break;
|
||||||
case Constants.DefaultAccountExperience.Cassandra.toLowerCase():
|
case Constants.DefaultAccountExperience.Cassandra.toLowerCase():
|
||||||
this.addCollectionText("New Table");
|
this.addCollectionText("New Table");
|
||||||
|
@ -881,7 +857,7 @@ export default class Explorer {
|
||||||
this.deleteCollectionConfirmationPane.collectionIdConfirmationText("Confirm by typing the table id");
|
this.deleteCollectionConfirmationPane.collectionIdConfirmationText("Confirm by typing the table id");
|
||||||
this.deleteDatabaseConfirmationPane.title("Delete Keyspace");
|
this.deleteDatabaseConfirmationPane.title("Delete Keyspace");
|
||||||
this.deleteDatabaseConfirmationPane.databaseIdConfirmationText("Confirm by typing the keyspace id");
|
this.deleteDatabaseConfirmationPane.databaseIdConfirmationText("Confirm by typing the keyspace id");
|
||||||
this.tableDataClient = new CassandraAPIDataClient(this.documentClientUtility);
|
this.tableDataClient = new CassandraAPIDataClient();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -1066,13 +1042,6 @@ export default class Explorer {
|
||||||
// TODO: return result
|
// TODO: return result
|
||||||
}
|
}
|
||||||
|
|
||||||
public rebindDocumentClientUtility(documentClientUtility: DocumentClientUtilityBase): void {
|
|
||||||
this.documentClientUtility = documentClientUtility;
|
|
||||||
this._panes.forEach((pane: ViewModels.ContextualPane) => {
|
|
||||||
pane.documentClientUtility = documentClientUtility;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public copyUrlLink(src: any, event: MouseEvent): void {
|
public copyUrlLink(src: any, event: MouseEvent): void {
|
||||||
const urlLinkInput: HTMLInputElement = document.getElementById("shareUrlLink") as HTMLInputElement;
|
const urlLinkInput: HTMLInputElement = document.getElementById("shareUrlLink") as HTMLInputElement;
|
||||||
urlLinkInput && urlLinkInput.select();
|
urlLinkInput && urlLinkInput.select();
|
||||||
|
@ -1391,7 +1360,7 @@ export default class Explorer {
|
||||||
}
|
}
|
||||||
|
|
||||||
const deferred: Q.Deferred<void> = Q.defer();
|
const deferred: Q.Deferred<void> = Q.defer();
|
||||||
this.documentClientUtility.readCollection(databaseId, collectionId).then((collection: DataModels.Collection) => {
|
readCollection(databaseId, collectionId).then((collection: DataModels.Collection) => {
|
||||||
this.resourceTokenCollection(new ResourceTokenCollection(this, databaseId, collection));
|
this.resourceTokenCollection(new ResourceTokenCollection(this, databaseId, collection));
|
||||||
this.selectedNode(this.resourceTokenCollection());
|
this.selectedNode(this.resourceTokenCollection());
|
||||||
deferred.resolve();
|
deferred.resolve();
|
||||||
|
@ -1421,7 +1390,7 @@ export default class Explorer {
|
||||||
|
|
||||||
const refreshDatabases = (offers?: DataModels.Offer[]) => {
|
const refreshDatabases = (offers?: DataModels.Offer[]) => {
|
||||||
this._setLoadingStatusText("Fetching databases...");
|
this._setLoadingStatusText("Fetching databases...");
|
||||||
this.documentClientUtility.readDatabases(null /*options*/).then(
|
readDatabases(null /*options*/).then(
|
||||||
(databases: DataModels.Database[]) => {
|
(databases: DataModels.Database[]) => {
|
||||||
this._setLoadingStatusText("Successfully fetched databases.");
|
this._setLoadingStatusText("Successfully fetched databases.");
|
||||||
TelemetryProcessor.traceSuccess(
|
TelemetryProcessor.traceSuccess(
|
||||||
|
@ -1478,7 +1447,7 @@ export default class Explorer {
|
||||||
// Serverless accounts don't support offers call
|
// Serverless accounts don't support offers call
|
||||||
refreshDatabases();
|
refreshDatabases();
|
||||||
} else {
|
} else {
|
||||||
const offerPromise: Q.Promise<DataModels.Offer[]> = this.documentClientUtility.readOffers();
|
const offerPromise: Q.Promise<DataModels.Offer[]> = readOffers();
|
||||||
this._setLoadingStatusText("Fetching offers...");
|
this._setLoadingStatusText("Fetching offers...");
|
||||||
offerPromise.then(
|
offerPromise.then(
|
||||||
(offers: DataModels.Offer[]) => {
|
(offers: DataModels.Offer[]) => {
|
||||||
|
@ -1554,7 +1523,7 @@ export default class Explorer {
|
||||||
dataExplorerArea: Constants.Areas.ResourceTree
|
dataExplorerArea: Constants.Areas.ResourceTree
|
||||||
});
|
});
|
||||||
this.isRefreshingExplorer(true);
|
this.isRefreshingExplorer(true);
|
||||||
this.documentClientUtility.refreshCachedResources().then(
|
refreshCachedResources().then(
|
||||||
() => {
|
() => {
|
||||||
TelemetryProcessor.traceSuccess(
|
TelemetryProcessor.traceSuccess(
|
||||||
Action.LoadDatabases,
|
Action.LoadDatabases,
|
||||||
|
@ -2480,8 +2449,6 @@ export default class Explorer {
|
||||||
node: null,
|
node: null,
|
||||||
title: notebookContentItem.name,
|
title: notebookContentItem.name,
|
||||||
tabPath: notebookContentItem.path,
|
tabPath: notebookContentItem.path,
|
||||||
documentClientUtility: null,
|
|
||||||
|
|
||||||
collection: null,
|
collection: null,
|
||||||
selfLink: null,
|
selfLink: null,
|
||||||
masterKey: CosmosClient.masterKey() || "",
|
masterKey: CosmosClient.masterKey() || "",
|
||||||
|
@ -2923,8 +2890,6 @@ export default class Explorer {
|
||||||
node: null,
|
node: null,
|
||||||
title: title,
|
title: title,
|
||||||
tabPath: title,
|
tabPath: title,
|
||||||
documentClientUtility: null,
|
|
||||||
|
|
||||||
collection: null,
|
collection: null,
|
||||||
selfLink: null,
|
selfLink: null,
|
||||||
hashLocation: hashLocation,
|
hashLocation: hashLocation,
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
jest.mock("../../../Common/DocumentClientUtilityBase");
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import * as sinon from "sinon";
|
import * as sinon from "sinon";
|
||||||
import { mount, ReactWrapper } from "enzyme";
|
import { mount, ReactWrapper } from "enzyme";
|
||||||
|
@ -7,11 +8,11 @@ import { GraphExplorer, GraphExplorerProps, GraphAccessor, GraphHighlightedNodeD
|
||||||
import * as D3ForceGraph from "./D3ForceGraph";
|
import * as D3ForceGraph from "./D3ForceGraph";
|
||||||
import { GraphData } from "./GraphData";
|
import { GraphData } from "./GraphData";
|
||||||
import { TabComponent } from "../../Controls/Tabs/TabComponent";
|
import { TabComponent } from "../../Controls/Tabs/TabComponent";
|
||||||
import * as ViewModels from "../../../Contracts/ViewModels";
|
|
||||||
import * as DataModels from "../../../Contracts/DataModels";
|
import * as DataModels from "../../../Contracts/DataModels";
|
||||||
import * as StorageUtility from "../../../Shared/StorageUtility";
|
import * as StorageUtility from "../../../Shared/StorageUtility";
|
||||||
import GraphTab from "../../Tabs/GraphTab";
|
import GraphTab from "../../Tabs/GraphTab";
|
||||||
import { ConsoleDataType } from "../../Menus/NotificationConsole/NotificationConsoleComponent";
|
import { ConsoleDataType } from "../../Menus/NotificationConsole/NotificationConsoleComponent";
|
||||||
|
import { queryDocuments, queryDocumentsPage } from "../../../Common/DocumentClientUtilityBase";
|
||||||
|
|
||||||
describe("Check whether query result is vertex array", () => {
|
describe("Check whether query result is vertex array", () => {
|
||||||
it("should reject null as vertex array", () => {
|
it("should reject null as vertex array", () => {
|
||||||
|
@ -134,7 +135,7 @@ describe("GraphExplorer", () => {
|
||||||
const COLLECTION_SELF_LINK = "collectionSelfLink";
|
const COLLECTION_SELF_LINK = "collectionSelfLink";
|
||||||
const gremlinRU = 789.12;
|
const gremlinRU = 789.12;
|
||||||
|
|
||||||
const createMockProps = (documentClientUtility?: any): GraphExplorerProps => {
|
const createMockProps = (): GraphExplorerProps => {
|
||||||
const graphConfig = GraphTab.createGraphConfig();
|
const graphConfig = GraphTab.createGraphConfig();
|
||||||
const graphConfigUi = GraphTab.createGraphConfigUiData(graphConfig);
|
const graphConfigUi = GraphTab.createGraphConfigUiData(graphConfig);
|
||||||
|
|
||||||
|
@ -149,7 +150,6 @@ describe("GraphExplorer", () => {
|
||||||
onIsValidQueryChange: (isValidQuery: boolean): void => {},
|
onIsValidQueryChange: (isValidQuery: boolean): void => {},
|
||||||
|
|
||||||
collectionPartitionKeyProperty: "collectionPartitionKeyProperty",
|
collectionPartitionKeyProperty: "collectionPartitionKeyProperty",
|
||||||
documentClientUtility: documentClientUtility,
|
|
||||||
collectionRid: COLLECTION_RID,
|
collectionRid: COLLECTION_RID,
|
||||||
collectionSelfLink: COLLECTION_SELF_LINK,
|
collectionSelfLink: COLLECTION_SELF_LINK,
|
||||||
graphBackendEndpoint: "graphBackendEndpoint",
|
graphBackendEndpoint: "graphBackendEndpoint",
|
||||||
|
@ -188,7 +188,6 @@ describe("GraphExplorer", () => {
|
||||||
let wrapper: ReactWrapper;
|
let wrapper: ReactWrapper;
|
||||||
|
|
||||||
let connectStub: sinon.SinonSpy;
|
let connectStub: sinon.SinonSpy;
|
||||||
let queryDocStub: sinon.SinonSpy;
|
|
||||||
let submitToBackendSpy: sinon.SinonSpy;
|
let submitToBackendSpy: sinon.SinonSpy;
|
||||||
let renderResultAsJsonStub: sinon.SinonSpy;
|
let renderResultAsJsonStub: sinon.SinonSpy;
|
||||||
let onMiddlePaneInitializedStub: sinon.SinonSpy;
|
let onMiddlePaneInitializedStub: sinon.SinonSpy;
|
||||||
|
@ -215,46 +214,6 @@ describe("GraphExplorer", () => {
|
||||||
[query: string]: AjaxResponse;
|
[query: string]: AjaxResponse;
|
||||||
}
|
}
|
||||||
|
|
||||||
const createDocumentClientUtilityMock = (docDBResponse: AjaxResponse) => {
|
|
||||||
const mock = {
|
|
||||||
queryDocuments: () => {},
|
|
||||||
queryDocumentsPage: (
|
|
||||||
rid: string,
|
|
||||||
iterator: any,
|
|
||||||
firstItemIndex: number,
|
|
||||||
options: any
|
|
||||||
): Q.Promise<ViewModels.QueryResults> => {
|
|
||||||
const qresult = {
|
|
||||||
hasMoreResults: false,
|
|
||||||
firstItemIndex: firstItemIndex,
|
|
||||||
lastItemIndex: 0,
|
|
||||||
itemCount: 0,
|
|
||||||
documents: docDBResponse.response,
|
|
||||||
activityId: "",
|
|
||||||
headers: [] as any[],
|
|
||||||
requestCharge: gVRU
|
|
||||||
};
|
|
||||||
|
|
||||||
return Q.resolve(qresult);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const fakeIterator: any = {
|
|
||||||
nextItem: (callback: (error: any, document: DataModels.DocumentId) => void): void => {},
|
|
||||||
hasMoreResults: () => false,
|
|
||||||
executeNext: (callback: (error: any, documents: DataModels.DocumentId[], headers: any) => void): void => {}
|
|
||||||
};
|
|
||||||
|
|
||||||
queryDocStub = sinon.stub(mock, "queryDocuments").callsFake(
|
|
||||||
(container: ViewModels.DocumentRequestContainer, query: string, options: any): Q.Promise<any> => {
|
|
||||||
(fakeIterator as any)._query = query;
|
|
||||||
return Q.resolve(fakeIterator);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
return mock;
|
|
||||||
};
|
|
||||||
|
|
||||||
const setupMocks = (
|
const setupMocks = (
|
||||||
graphExplorer: GraphExplorer,
|
graphExplorer: GraphExplorer,
|
||||||
backendResponses: BackendResponses,
|
backendResponses: BackendResponses,
|
||||||
|
@ -333,7 +292,29 @@ describe("GraphExplorer", () => {
|
||||||
done: any,
|
done: any,
|
||||||
ignoreD3Update: boolean
|
ignoreD3Update: boolean
|
||||||
): GraphExplorer => {
|
): GraphExplorer => {
|
||||||
const props: GraphExplorerProps = createMockProps(createDocumentClientUtilityMock(docDBResponse));
|
(queryDocuments as jest.Mock).mockImplementation((container: any, query: string, options: any) => {
|
||||||
|
return Q.resolve({
|
||||||
|
_query: query,
|
||||||
|
nextItem: (callback: (error: any, document: DataModels.DocumentId) => void): void => {},
|
||||||
|
hasMoreResults: () => false,
|
||||||
|
executeNext: (callback: (error: any, documents: DataModels.DocumentId[], headers: any) => void): void => {}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
(queryDocumentsPage as jest.Mock).mockImplementation(
|
||||||
|
(rid: string, iterator: any, firstItemIndex: number, options: any) => {
|
||||||
|
return Q.resolve({
|
||||||
|
hasMoreResults: false,
|
||||||
|
firstItemIndex: firstItemIndex,
|
||||||
|
lastItemIndex: 0,
|
||||||
|
itemCount: 0,
|
||||||
|
documents: docDBResponse.response,
|
||||||
|
activityId: "",
|
||||||
|
headers: [] as any[],
|
||||||
|
requestCharge: gVRU
|
||||||
|
});
|
||||||
|
}
|
||||||
|
);
|
||||||
|
const props: GraphExplorerProps = createMockProps();
|
||||||
wrapper = mount(<GraphExplorer {...props} />);
|
wrapper = mount(<GraphExplorer {...props} />);
|
||||||
graphExplorerInstance = wrapper.instance() as GraphExplorer;
|
graphExplorerInstance = wrapper.instance() as GraphExplorer;
|
||||||
setupMocks(graphExplorerInstance, backendResponses, done, ignoreD3Update);
|
setupMocks(graphExplorerInstance, backendResponses, done, ignoreD3Update);
|
||||||
|
@ -341,7 +322,7 @@ describe("GraphExplorer", () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const cleanUpStubsWrapper = () => {
|
const cleanUpStubsWrapper = () => {
|
||||||
queryDocStub.restore();
|
jest.resetAllMocks();
|
||||||
connectStub.restore();
|
connectStub.restore();
|
||||||
submitToBackendSpy.restore();
|
submitToBackendSpy.restore();
|
||||||
renderResultAsJsonStub.restore();
|
renderResultAsJsonStub.restore();
|
||||||
|
@ -378,22 +359,11 @@ describe("GraphExplorer", () => {
|
||||||
expect((graphExplorerInstance.submitToBackend as sinon.SinonSpy).calledWith("g.V()")).toBe(false);
|
expect((graphExplorerInstance.submitToBackend as sinon.SinonSpy).calledWith("g.V()")).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should submit g.V() as docdb query with proper query", () => {
|
|
||||||
expect(
|
|
||||||
(graphExplorerInstance.props.documentClientUtility.queryDocuments as sinon.SinonSpy).getCall(0).args[2]
|
|
||||||
).toBe(DOCDB_G_DOT_V_QUERY);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should submit g.V() as docdb query with proper parameters", () => {
|
it("should submit g.V() as docdb query with proper parameters", () => {
|
||||||
expect(
|
expect(queryDocuments).toBeCalledWith("databaseId", "collectionId", DOCDB_G_DOT_V_QUERY, {
|
||||||
(graphExplorerInstance.props.documentClientUtility.queryDocuments as sinon.SinonSpy).getCall(0).args[0]
|
maxItemCount: GraphExplorer.ROOT_LIST_PAGE_SIZE,
|
||||||
).toEqual("databaseId");
|
enableCrossPartitionQuery: true
|
||||||
expect(
|
});
|
||||||
(graphExplorerInstance.props.documentClientUtility.queryDocuments as sinon.SinonSpy).getCall(0).args[1]
|
|
||||||
).toEqual("collectionId");
|
|
||||||
expect(
|
|
||||||
(graphExplorerInstance.props.documentClientUtility.queryDocuments as sinon.SinonSpy).getCall(0).args[3]
|
|
||||||
).toEqual({ maxItemCount: GraphExplorer.ROOT_LIST_PAGE_SIZE, enableCrossPartitionQuery: true });
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should call backend thrice (user query, fetch outE, then fetch inE)", () => {
|
it("should call backend thrice (user query, fetch outE, then fetch inE)", () => {
|
||||||
|
@ -426,22 +396,11 @@ describe("GraphExplorer", () => {
|
||||||
expect((graphExplorerInstance.submitToBackend as sinon.SinonSpy).calledWith("g.V()")).toBe(false);
|
expect((graphExplorerInstance.submitToBackend as sinon.SinonSpy).calledWith("g.V()")).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should submit g.V() as docdb query with proper query", () => {
|
|
||||||
expect(
|
|
||||||
(graphExplorerInstance.props.documentClientUtility.queryDocuments as sinon.SinonSpy).getCall(0).args[2]
|
|
||||||
).toBe(DOCDB_G_DOT_V_QUERY);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should submit g.V() as docdb query with proper parameters", () => {
|
it("should submit g.V() as docdb query with proper parameters", () => {
|
||||||
expect(
|
expect(queryDocuments).toBeCalledWith("databaseId", "collectionId", DOCDB_G_DOT_V_QUERY, {
|
||||||
(graphExplorerInstance.props.documentClientUtility.queryDocuments as sinon.SinonSpy).getCall(0).args[0]
|
maxItemCount: GraphExplorer.ROOT_LIST_PAGE_SIZE,
|
||||||
).toEqual("databaseId");
|
enableCrossPartitionQuery: true
|
||||||
expect(
|
});
|
||||||
(graphExplorerInstance.props.documentClientUtility.queryDocuments as sinon.SinonSpy).getCall(0).args[1]
|
|
||||||
).toEqual("collectionId");
|
|
||||||
expect(
|
|
||||||
(graphExplorerInstance.props.documentClientUtility.queryDocuments as sinon.SinonSpy).getCall(0).args[3]
|
|
||||||
).toEqual({ maxItemCount: GraphExplorer.ROOT_LIST_PAGE_SIZE, enableCrossPartitionQuery: true });
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should call backend thrice (user query, fetch outE, then fetch inE)", () => {
|
it("should call backend thrice (user query, fetch outE, then fetch inE)", () => {
|
||||||
|
|
|
@ -28,7 +28,7 @@ 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";
|
||||||
import LoadingIndicatorIcon from "../../../../images/LoadingIndicator_3Squares.gif";
|
import LoadingIndicatorIcon from "../../../../images/LoadingIndicator_3Squares.gif";
|
||||||
import DocumentClientUtilityBase from "../../../Common/DocumentClientUtilityBase";
|
import { queryDocuments, queryDocumentsPage } from "../../../Common/DocumentClientUtilityBase";
|
||||||
|
|
||||||
export interface GraphAccessor {
|
export interface GraphAccessor {
|
||||||
applyFilter: () => void;
|
applyFilter: () => void;
|
||||||
|
@ -47,7 +47,6 @@ export interface GraphExplorerProps {
|
||||||
onIsValidQueryChange: (isValidQuery: boolean) => void;
|
onIsValidQueryChange: (isValidQuery: boolean) => void;
|
||||||
|
|
||||||
collectionPartitionKeyProperty: string;
|
collectionPartitionKeyProperty: string;
|
||||||
documentClientUtility: DocumentClientUtilityBase;
|
|
||||||
collectionRid: string;
|
collectionRid: string;
|
||||||
collectionSelfLink: string;
|
collectionSelfLink: string;
|
||||||
graphBackendEndpoint: string;
|
graphBackendEndpoint: string;
|
||||||
|
@ -697,7 +696,6 @@ export class GraphExplorer extends React.Component<GraphExplorerProps, GraphExpl
|
||||||
* @param cmd
|
* @param cmd
|
||||||
*/
|
*/
|
||||||
public submitToBackend(cmd: string): Q.Promise<GremlinClient.GremlinRequestResult> {
|
public submitToBackend(cmd: string): Q.Promise<GremlinClient.GremlinRequestResult> {
|
||||||
console.log("submit:", cmd);
|
|
||||||
const id = GraphExplorer.reportToConsole(ConsoleDataType.InProgress, `Executing: ${cmd}`);
|
const id = GraphExplorer.reportToConsole(ConsoleDataType.InProgress, `Executing: ${cmd}`);
|
||||||
this.setExecuteCounter(this.executeCounter + 1);
|
this.setExecuteCounter(this.executeCounter + 1);
|
||||||
|
|
||||||
|
@ -730,26 +728,24 @@ export class GraphExplorer extends React.Component<GraphExplorerProps, GraphExpl
|
||||||
*/
|
*/
|
||||||
public executeNonPagedDocDbQuery(query: string): Q.Promise<DataModels.DocumentId[]> {
|
public executeNonPagedDocDbQuery(query: string): Q.Promise<DataModels.DocumentId[]> {
|
||||||
// TODO maxItemCount: this reduces throttling, but won't cap the # of results
|
// TODO maxItemCount: this reduces throttling, but won't cap the # of results
|
||||||
return this.props.documentClientUtility
|
return queryDocuments(this.props.databaseId, this.props.collectionId, query, {
|
||||||
.queryDocuments(this.props.databaseId, this.props.collectionId, query, {
|
maxItemCount: GraphExplorer.PAGE_ALL,
|
||||||
maxItemCount: GraphExplorer.PAGE_ALL,
|
enableCrossPartitionQuery:
|
||||||
enableCrossPartitionQuery:
|
StorageUtility.LocalStorageUtility.getEntryString(StorageUtility.StorageKey.IsCrossPartitionQueryEnabled) ===
|
||||||
StorageUtility.LocalStorageUtility.getEntryString(StorageUtility.StorageKey.IsCrossPartitionQueryEnabled) ===
|
"true"
|
||||||
"true"
|
}).then(
|
||||||
})
|
(iterator: QueryIterator<ItemDefinition & Resource>) => {
|
||||||
.then(
|
return iterator.fetchNext().then(response => response.resources);
|
||||||
(iterator: QueryIterator<ItemDefinition & Resource>) => {
|
},
|
||||||
return iterator.fetchNext().then(response => response.resources);
|
(reason: any) => {
|
||||||
},
|
GraphExplorer.reportToConsole(
|
||||||
(reason: any) => {
|
ConsoleDataType.Error,
|
||||||
GraphExplorer.reportToConsole(
|
`Failed to execute non-paged query ${query}. Reason:${reason}`,
|
||||||
ConsoleDataType.Error,
|
reason
|
||||||
`Failed to execute non-paged query ${query}. Reason:${reason}`,
|
);
|
||||||
reason
|
return null;
|
||||||
);
|
}
|
||||||
return null;
|
);
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1732,12 +1728,10 @@ export class GraphExplorer extends React.Component<GraphExplorerProps, GraphExpl
|
||||||
query = `select root.id, root.${this.props.collectionPartitionKeyProperty} from root where IS_DEFINED(root._isEdge) = false order by root._ts asc`;
|
query = `select root.id, root.${this.props.collectionPartitionKeyProperty} from root where IS_DEFINED(root._isEdge) = false order by root._ts asc`;
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.props.documentClientUtility
|
return queryDocuments(this.props.databaseId, this.props.collectionId, query, {
|
||||||
.queryDocuments(this.props.databaseId, this.props.collectionId, query, {
|
maxItemCount: GraphExplorer.ROOT_LIST_PAGE_SIZE,
|
||||||
maxItemCount: GraphExplorer.ROOT_LIST_PAGE_SIZE,
|
enableCrossPartitionQuery: LocalStorageUtility.getEntryString(StorageKey.IsCrossPartitionQueryEnabled) === "true"
|
||||||
enableCrossPartitionQuery:
|
})
|
||||||
LocalStorageUtility.getEntryString(StorageKey.IsCrossPartitionQueryEnabled) === "true"
|
|
||||||
})
|
|
||||||
.then(
|
.then(
|
||||||
(iterator: QueryIterator<ItemDefinition & Resource>) => {
|
(iterator: QueryIterator<ItemDefinition & Resource>) => {
|
||||||
this.currentDocDBQueryInfo = {
|
this.currentDocDBQueryInfo = {
|
||||||
|
@ -1766,16 +1760,15 @@ export class GraphExplorer extends React.Component<GraphExplorerProps, GraphExpl
|
||||||
.currentDocDBQueryInfo.index + GraphExplorer.ROOT_LIST_PAGE_SIZE})`;
|
.currentDocDBQueryInfo.index + GraphExplorer.ROOT_LIST_PAGE_SIZE})`;
|
||||||
const id = GraphExplorer.reportToConsole(ConsoleDataType.InProgress, `Executing: ${queryInfoStr}`);
|
const id = GraphExplorer.reportToConsole(ConsoleDataType.InProgress, `Executing: ${queryInfoStr}`);
|
||||||
|
|
||||||
return this.props.documentClientUtility
|
return queryDocumentsPage(
|
||||||
.queryDocumentsPage(
|
this.props.collectionRid,
|
||||||
this.props.collectionRid,
|
this.currentDocDBQueryInfo.iterator,
|
||||||
this.currentDocDBQueryInfo.iterator,
|
this.currentDocDBQueryInfo.index,
|
||||||
this.currentDocDBQueryInfo.index,
|
{
|
||||||
{
|
enableCrossPartitionQuery:
|
||||||
enableCrossPartitionQuery:
|
LocalStorageUtility.getEntryString(StorageKey.IsCrossPartitionQueryEnabled) === "true"
|
||||||
LocalStorageUtility.getEntryString(StorageKey.IsCrossPartitionQueryEnabled) === "true"
|
}
|
||||||
}
|
)
|
||||||
)
|
|
||||||
.then((results: ViewModels.QueryResults) => {
|
.then((results: ViewModels.QueryResults) => {
|
||||||
GraphExplorer.clearConsoleProgress(id);
|
GraphExplorer.clearConsoleProgress(id);
|
||||||
this.currentDocDBQueryInfo.index = results.lastItemIndex + 1;
|
this.currentDocDBQueryInfo.index = results.lastItemIndex + 1;
|
||||||
|
|
|
@ -3,7 +3,6 @@ import { ReactAdapter } from "../../../Bindings/ReactBindingHandler";
|
||||||
import { GraphConfig } from "../../Tabs/GraphTab";
|
import { GraphConfig } from "../../Tabs/GraphTab";
|
||||||
import * as ViewModels from "../../../Contracts/ViewModels";
|
import * as ViewModels from "../../../Contracts/ViewModels";
|
||||||
import { GraphExplorer, GraphAccessor } from "./GraphExplorer";
|
import { GraphExplorer, GraphAccessor } from "./GraphExplorer";
|
||||||
import DocumentClientUtilityBase from "../../../Common/DocumentClientUtilityBase";
|
|
||||||
|
|
||||||
interface Parameter {
|
interface Parameter {
|
||||||
onIsNewVertexDisabledChange: (isEnabled: boolean) => void;
|
onIsNewVertexDisabledChange: (isEnabled: boolean) => void;
|
||||||
|
@ -18,7 +17,6 @@ interface Parameter {
|
||||||
graphConfig?: GraphConfig;
|
graphConfig?: GraphConfig;
|
||||||
|
|
||||||
collectionPartitionKeyProperty: string;
|
collectionPartitionKeyProperty: string;
|
||||||
documentClientUtility: DocumentClientUtilityBase;
|
|
||||||
collectionRid: string;
|
collectionRid: string;
|
||||||
collectionSelfLink: string;
|
collectionSelfLink: string;
|
||||||
graphBackendEndpoint: string;
|
graphBackendEndpoint: string;
|
||||||
|
@ -51,7 +49,6 @@ export class GraphExplorerAdapter implements ReactAdapter {
|
||||||
onIsGraphDisplayed={this.params.onIsGraphDisplayed}
|
onIsGraphDisplayed={this.params.onIsGraphDisplayed}
|
||||||
onResetDefaultGraphConfigValues={this.params.onResetDefaultGraphConfigValues}
|
onResetDefaultGraphConfigValues={this.params.onResetDefaultGraphConfigValues}
|
||||||
collectionPartitionKeyProperty={this.params.collectionPartitionKeyProperty}
|
collectionPartitionKeyProperty={this.params.collectionPartitionKeyProperty}
|
||||||
documentClientUtility={this.params.documentClientUtility}
|
|
||||||
collectionRid={this.params.collectionRid}
|
collectionRid={this.params.collectionRid}
|
||||||
collectionSelfLink={this.params.collectionSelfLink}
|
collectionSelfLink={this.params.collectionSelfLink}
|
||||||
graphBackendEndpoint={this.params.graphBackendEndpoint}
|
graphBackendEndpoint={this.params.graphBackendEndpoint}
|
||||||
|
|
|
@ -57,7 +57,6 @@ export default class NotebookManager {
|
||||||
this.gitHubOAuthService = new GitHubOAuthService(this.junoClient);
|
this.gitHubOAuthService = new GitHubOAuthService(this.junoClient);
|
||||||
this.gitHubClient = new GitHubClient(this.onGitHubClientError);
|
this.gitHubClient = new GitHubClient(this.onGitHubClientError);
|
||||||
this.gitHubReposPane = new GitHubReposPane({
|
this.gitHubReposPane = new GitHubReposPane({
|
||||||
documentClientUtility: this.params.container.documentClientUtility,
|
|
||||||
id: "gitHubReposPane",
|
id: "gitHubReposPane",
|
||||||
visible: ko.observable<boolean>(false),
|
visible: ko.observable<boolean>(false),
|
||||||
container: this.params.container,
|
container: this.params.container,
|
||||||
|
|
|
@ -41,7 +41,7 @@ describe("Add Collection Pane", () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
explorer = new Explorer({ documentClientUtility: null, notificationsClient: null, isEmulator: false });
|
explorer = new Explorer({ notificationsClient: null, isEmulator: false });
|
||||||
explorer.hasAutoPilotV2FeatureFlag = ko.computed<boolean>(() => true);
|
explorer.hasAutoPilotV2FeatureFlag = ko.computed<boolean>(() => true);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,7 @@ import { createMongoCollectionWithARM, createMongoCollectionWithProxy } from "..
|
||||||
import { DynamicListItem } from "../Controls/DynamicList/DynamicListComponent";
|
import { DynamicListItem } from "../Controls/DynamicList/DynamicListComponent";
|
||||||
import { HashMap } from "../../Common/HashMap";
|
import { HashMap } from "../../Common/HashMap";
|
||||||
import { PlatformType } from "../../PlatformType";
|
import { PlatformType } from "../../PlatformType";
|
||||||
|
import { refreshCachedResources, getOrCreateDatabaseAndCollection } from "../../Common/DocumentClientUtilityBase";
|
||||||
|
|
||||||
export default class AddCollectionPane extends ContextualPaneBase {
|
export default class AddCollectionPane extends ContextualPaneBase {
|
||||||
public defaultExperience: ko.Computed<string>;
|
public defaultExperience: ko.Computed<string>;
|
||||||
|
@ -941,8 +942,7 @@ export default class AddCollectionPane extends ContextualPaneBase {
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
createCollectionFunc = () =>
|
createCollectionFunc = () => getOrCreateDatabaseAndCollection(createRequest, options);
|
||||||
this.container.documentClientUtility.getOrCreateDatabaseAndCollection(createRequest, options);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
createCollectionFunc().then(
|
createCollectionFunc().then(
|
||||||
|
@ -978,7 +978,7 @@ export default class AddCollectionPane extends ContextualPaneBase {
|
||||||
};
|
};
|
||||||
TelemetryProcessor.traceSuccess(Action.CreateCollection, addCollectionPaneSuccessMessage, startKey);
|
TelemetryProcessor.traceSuccess(Action.CreateCollection, addCollectionPaneSuccessMessage, startKey);
|
||||||
this.resetData();
|
this.resetData();
|
||||||
return this.container.documentClientUtility.refreshCachedResources().then(() => {
|
return refreshCachedResources().then(() => {
|
||||||
this.container.refreshAllDatabases();
|
this.container.refreshAllDatabases();
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
|
@ -40,7 +40,6 @@ describe("Add Database Pane", () => {
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
explorer = new Explorer({
|
explorer = new Explorer({
|
||||||
documentClientUtility: null,
|
|
||||||
notificationsClient: null,
|
notificationsClient: null,
|
||||||
isEmulator: false
|
isEmulator: false
|
||||||
});
|
});
|
||||||
|
|
|
@ -16,6 +16,7 @@ import { CassandraAPIDataClient } from "../Tables/TableDataClient";
|
||||||
import { ContextualPaneBase } from "./ContextualPaneBase";
|
import { ContextualPaneBase } from "./ContextualPaneBase";
|
||||||
import { CosmosClient } from "../../Common/CosmosClient";
|
import { CosmosClient } from "../../Common/CosmosClient";
|
||||||
import { PlatformType } from "../../PlatformType";
|
import { PlatformType } from "../../PlatformType";
|
||||||
|
import { refreshCachedOffers, refreshCachedResources, createDatabase } from "../../Common/DocumentClientUtilityBase";
|
||||||
|
|
||||||
export default class AddDatabasePane extends ContextualPaneBase {
|
export default class AddDatabasePane extends ContextualPaneBase {
|
||||||
public defaultExperience: ko.Computed<string>;
|
public defaultExperience: ko.Computed<string>;
|
||||||
|
@ -334,10 +335,7 @@ export default class AddDatabasePane extends ContextualPaneBase {
|
||||||
) {
|
) {
|
||||||
AddDbUtilities.createSqlDatabase(this.container.armEndpoint(), createDatabaseParameters, autoPilotSettings).then(
|
AddDbUtilities.createSqlDatabase(this.container.armEndpoint(), createDatabaseParameters, autoPilotSettings).then(
|
||||||
() => {
|
() => {
|
||||||
Promise.all([
|
Promise.all([refreshCachedOffers(), refreshCachedResources()]).then(() => {
|
||||||
this.container.documentClientUtility.refreshCachedOffers(),
|
|
||||||
this.container.documentClientUtility.refreshCachedResources()
|
|
||||||
]).then(() => {
|
|
||||||
this._onCreateDatabaseSuccess(createDatabaseParameters.offerThroughput, startKey);
|
this._onCreateDatabaseSuccess(createDatabaseParameters.offerThroughput, startKey);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -354,10 +352,7 @@ export default class AddDatabasePane extends ContextualPaneBase {
|
||||||
createDatabaseParameters,
|
createDatabaseParameters,
|
||||||
autoPilotSettings
|
autoPilotSettings
|
||||||
).then(() => {
|
).then(() => {
|
||||||
Promise.all([
|
Promise.all([refreshCachedOffers(), refreshCachedResources()]).then(() => {
|
||||||
this.container.documentClientUtility.refreshCachedOffers(),
|
|
||||||
this.container.documentClientUtility.refreshCachedResources()
|
|
||||||
]).then(() => {
|
|
||||||
this._onCreateDatabaseSuccess(createDatabaseParameters.offerThroughput, startKey);
|
this._onCreateDatabaseSuccess(createDatabaseParameters.offerThroughput, startKey);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -373,10 +368,7 @@ export default class AddDatabasePane extends ContextualPaneBase {
|
||||||
createDatabaseParameters,
|
createDatabaseParameters,
|
||||||
autoPilotSettings
|
autoPilotSettings
|
||||||
).then(() => {
|
).then(() => {
|
||||||
Promise.all([
|
Promise.all([refreshCachedOffers(), refreshCachedResources()]).then(() => {
|
||||||
this.container.documentClientUtility.refreshCachedOffers(),
|
|
||||||
this.container.documentClientUtility.refreshCachedResources()
|
|
||||||
]).then(() => {
|
|
||||||
this._onCreateDatabaseSuccess(createDatabaseParameters.offerThroughput, startKey);
|
this._onCreateDatabaseSuccess(createDatabaseParameters.offerThroughput, startKey);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -413,7 +405,7 @@ export default class AddDatabasePane extends ContextualPaneBase {
|
||||||
autoPilot,
|
autoPilot,
|
||||||
hasAutoPilotV2FeatureFlag: this.hasAutoPilotV2FeatureFlag()
|
hasAutoPilotV2FeatureFlag: this.hasAutoPilotV2FeatureFlag()
|
||||||
};
|
};
|
||||||
this.container.documentClientUtility.createDatabase(createRequest).then(
|
createDatabase(createRequest).then(
|
||||||
(database: DataModels.Database) => {
|
(database: DataModels.Database) => {
|
||||||
this._onCreateDatabaseSuccess(offerThroughput, telemetryStartKey);
|
this._onCreateDatabaseSuccess(offerThroughput, telemetryStartKey);
|
||||||
},
|
},
|
||||||
|
@ -464,10 +456,7 @@ export default class AddDatabasePane extends ContextualPaneBase {
|
||||||
startKey: number
|
startKey: number
|
||||||
): void {
|
): void {
|
||||||
AddDbUtilities.createCassandraKeyspace(armEndpoint, createKeyspaceParameters, autoPilotSettings).then(() => {
|
AddDbUtilities.createCassandraKeyspace(armEndpoint, createKeyspaceParameters, autoPilotSettings).then(() => {
|
||||||
Promise.all([
|
Promise.all([refreshCachedOffers(), refreshCachedResources()]).then(() => {
|
||||||
this.container.documentClientUtility.refreshCachedOffers(),
|
|
||||||
this.container.documentClientUtility.refreshCachedResources()
|
|
||||||
]).then(() => {
|
|
||||||
this._onCreateDatabaseSuccess(createKeyspaceParameters.offerThroughput, startKey);
|
this._onCreateDatabaseSuccess(createKeyspaceParameters.offerThroughput, startKey);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -5,7 +5,6 @@ import { Action, ActionModifiers } from "../../Shared/Telemetry/TelemetryConstan
|
||||||
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 TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
||||||
import DocumentClientUtilityBase from "../../Common/DocumentClientUtilityBase";
|
|
||||||
import Explorer from "../Explorer";
|
import Explorer from "../Explorer";
|
||||||
|
|
||||||
// TODO: Use specific actions for logging telemetry data
|
// TODO: Use specific actions for logging telemetry data
|
||||||
|
@ -17,14 +16,12 @@ export abstract class ContextualPaneBase extends WaitsForTemplateViewModel imple
|
||||||
public formErrors: ko.Observable<string>;
|
public formErrors: ko.Observable<string>;
|
||||||
public title: ko.Observable<string>;
|
public title: ko.Observable<string>;
|
||||||
public visible: ko.Observable<boolean>;
|
public visible: ko.Observable<boolean>;
|
||||||
public documentClientUtility: DocumentClientUtilityBase;
|
|
||||||
public isExecuting: ko.Observable<boolean>;
|
public isExecuting: ko.Observable<boolean>;
|
||||||
|
|
||||||
constructor(options: ViewModels.PaneOptions) {
|
constructor(options: ViewModels.PaneOptions) {
|
||||||
super();
|
super();
|
||||||
this.id = options.id;
|
this.id = options.id;
|
||||||
this.container = options.container;
|
this.container = options.container;
|
||||||
this.documentClientUtility = options.documentClientUtility;
|
|
||||||
this.visible = options.visible || ko.observable(false);
|
this.visible = options.visible || ko.observable(false);
|
||||||
this.firstFieldHasFocus = ko.observable<boolean>(false);
|
this.firstFieldHasFocus = ko.observable<boolean>(false);
|
||||||
this.formErrors = ko.observable<string>();
|
this.formErrors = ko.observable<string>();
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
jest.mock("../../Common/DocumentClientUtilityBase");
|
||||||
import * as ko from "knockout";
|
import * as ko from "knockout";
|
||||||
import * as sinon from "sinon";
|
import * as sinon from "sinon";
|
||||||
import Q from "q";
|
import Q from "q";
|
||||||
|
@ -6,7 +7,7 @@ import * as ViewModels from "../../Contracts/ViewModels";
|
||||||
import { Action, ActionModifiers } from "../../Shared/Telemetry/TelemetryConstants";
|
import { Action, ActionModifiers } from "../../Shared/Telemetry/TelemetryConstants";
|
||||||
import DeleteCollectionConfirmationPane from "./DeleteCollectionConfirmationPane";
|
import DeleteCollectionConfirmationPane from "./DeleteCollectionConfirmationPane";
|
||||||
import DeleteFeedback from "../../Common/DeleteFeedback";
|
import DeleteFeedback from "../../Common/DeleteFeedback";
|
||||||
import DocumentClientUtilityBase from "../../Common/DocumentClientUtilityBase";
|
import { deleteCollection } from "../../Common/DocumentClientUtilityBase";
|
||||||
import Explorer from "../Explorer";
|
import Explorer from "../Explorer";
|
||||||
import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
||||||
import { TreeNode } from "../../Contracts/ViewModels";
|
import { TreeNode } from "../../Contracts/ViewModels";
|
||||||
|
@ -16,7 +17,7 @@ describe("Delete Collection Confirmation Pane", () => {
|
||||||
let explorer: Explorer;
|
let explorer: Explorer;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
explorer = new Explorer({ documentClientUtility: null, notificationsClient: null, isEmulator: false });
|
explorer = new Explorer({ notificationsClient: null, isEmulator: false });
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should be true if 1 database and 1 collection", () => {
|
it("should be true if 1 database and 1 collection", () => {
|
||||||
|
@ -55,15 +56,11 @@ describe("Delete Collection Confirmation Pane", () => {
|
||||||
|
|
||||||
describe("shouldRecordFeedback()", () => {
|
describe("shouldRecordFeedback()", () => {
|
||||||
it("should return true if last collection and database does not have shared throughput else false", () => {
|
it("should return true if last collection and database does not have shared throughput else false", () => {
|
||||||
let fakeDocumentClientUtility = sinon.createStubInstance<DocumentClientUtilityBase>(
|
let fakeExplorer = new Explorer({ notificationsClient: null, isEmulator: false });
|
||||||
DocumentClientUtilityBase as any
|
|
||||||
);
|
|
||||||
let fakeExplorer = new Explorer({ documentClientUtility: null, notificationsClient: null, isEmulator: false });
|
|
||||||
fakeExplorer.isNotificationConsoleExpanded = ko.observable<boolean>(false);
|
fakeExplorer.isNotificationConsoleExpanded = ko.observable<boolean>(false);
|
||||||
fakeExplorer.refreshAllDatabases = () => Q.resolve();
|
fakeExplorer.refreshAllDatabases = () => Q.resolve();
|
||||||
|
|
||||||
let pane = new DeleteCollectionConfirmationPane({
|
let pane = new DeleteCollectionConfirmationPane({
|
||||||
documentClientUtility: fakeDocumentClientUtility as any,
|
|
||||||
id: "deletecollectionconfirmationpane",
|
id: "deletecollectionconfirmationpane",
|
||||||
visible: ko.observable<boolean>(false),
|
visible: ko.observable<boolean>(false),
|
||||||
container: fakeExplorer
|
container: fakeExplorer
|
||||||
|
@ -96,8 +93,7 @@ describe("Delete Collection Confirmation Pane", () => {
|
||||||
|
|
||||||
it("it should log feedback if last collection and database is not shared", () => {
|
it("it should log feedback if last collection and database is not shared", () => {
|
||||||
let selectedCollectionId = "testCol";
|
let selectedCollectionId = "testCol";
|
||||||
let fakeDocumentClientUtility = {} as DocumentClientUtilityBase;
|
(deleteCollection as jest.Mock).mockResolvedValue(null);
|
||||||
fakeDocumentClientUtility.deleteCollection = () => Q(null);
|
|
||||||
let fakeExplorer = {} as Explorer;
|
let fakeExplorer = {} as Explorer;
|
||||||
fakeExplorer.findSelectedCollection = () => {
|
fakeExplorer.findSelectedCollection = () => {
|
||||||
return {
|
return {
|
||||||
|
@ -120,14 +116,12 @@ describe("Delete Collection Confirmation Pane", () => {
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
|
|
||||||
fakeExplorer.documentClientUtility = fakeDocumentClientUtility;
|
|
||||||
fakeExplorer.selectedNode = ko.observable<TreeNode>();
|
fakeExplorer.selectedNode = ko.observable<TreeNode>();
|
||||||
fakeExplorer.isLastCollection = () => true;
|
fakeExplorer.isLastCollection = () => true;
|
||||||
fakeExplorer.isSelectedDatabaseShared = () => false;
|
fakeExplorer.isSelectedDatabaseShared = () => false;
|
||||||
fakeExplorer.refreshAllDatabases = () => Q.resolve();
|
fakeExplorer.refreshAllDatabases = () => Q.resolve();
|
||||||
|
|
||||||
let pane = new DeleteCollectionConfirmationPane({
|
let pane = new DeleteCollectionConfirmationPane({
|
||||||
documentClientUtility: fakeDocumentClientUtility as any,
|
|
||||||
id: "deletecollectionconfirmationpane",
|
id: "deletecollectionconfirmationpane",
|
||||||
visible: ko.observable<boolean>(false),
|
visible: ko.observable<boolean>(false),
|
||||||
container: fakeExplorer as any
|
container: fakeExplorer as any
|
||||||
|
|
|
@ -11,6 +11,7 @@ import { DefaultExperienceUtility } from "../../Shared/DefaultExperienceUtility"
|
||||||
import DeleteFeedback from "../../Common/DeleteFeedback";
|
import DeleteFeedback from "../../Common/DeleteFeedback";
|
||||||
import { NotificationConsoleUtils } from "../../Utils/NotificationConsoleUtils";
|
import { NotificationConsoleUtils } from "../../Utils/NotificationConsoleUtils";
|
||||||
import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
||||||
|
import { deleteCollection } from "../../Common/DocumentClientUtilityBase";
|
||||||
|
|
||||||
export default class DeleteCollectionConfirmationPane extends ContextualPaneBase {
|
export default class DeleteCollectionConfirmationPane extends ContextualPaneBase {
|
||||||
public collectionIdConfirmationText: ko.Observable<string>;
|
public collectionIdConfirmationText: ko.Observable<string>;
|
||||||
|
@ -58,7 +59,7 @@ export default class DeleteCollectionConfirmationPane extends ContextualPaneBase
|
||||||
this.container
|
this.container
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
promise = this.container.documentClientUtility.deleteCollection(selectedCollection);
|
promise = deleteCollection(selectedCollection);
|
||||||
}
|
}
|
||||||
return promise.then(
|
return promise.then(
|
||||||
() => {
|
() => {
|
||||||
|
|
|
@ -1,23 +1,28 @@
|
||||||
|
jest.mock("../../Common/DocumentClientUtilityBase");
|
||||||
|
jest.mock("../../Shared/Telemetry/TelemetryProcessor");
|
||||||
import * as ko from "knockout";
|
import * as ko from "knockout";
|
||||||
import * as sinon from "sinon";
|
|
||||||
import Q from "q";
|
import Q from "q";
|
||||||
import { Action, ActionModifiers } from "../../Shared/Telemetry/TelemetryConstants";
|
import { Action, ActionModifiers } from "../../Shared/Telemetry/TelemetryConstants";
|
||||||
import * as DataModels from "../../Contracts/DataModels";
|
import * as DataModels from "../../Contracts/DataModels";
|
||||||
import * as ViewModels from "../../Contracts/ViewModels";
|
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 DocumentClientUtilityBase from "../../Common/DocumentClientUtilityBase";
|
|
||||||
import Explorer from "../Explorer";
|
import Explorer from "../Explorer";
|
||||||
import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
import 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/DocumentClientUtilityBase";
|
||||||
|
|
||||||
describe("Delete Database Confirmation Pane", () => {
|
describe("Delete Database Confirmation Pane", () => {
|
||||||
describe("Explorer.isLastDatabase() and Explorer.isLastNonEmptyDatabase()", () => {
|
describe("Explorer.isLastDatabase() and Explorer.isLastNonEmptyDatabase()", () => {
|
||||||
let explorer: Explorer;
|
let explorer: Explorer;
|
||||||
|
|
||||||
|
beforeAll(() => {
|
||||||
|
(deleteDatabase as jest.Mock).mockResolvedValue(undefined);
|
||||||
|
});
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
explorer = new Explorer({ documentClientUtility: null, notificationsClient: null, isEmulator: false });
|
explorer = new Explorer({ notificationsClient: null, isEmulator: false });
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should be true if only 1 database", () => {
|
it("should be true if only 1 database", () => {
|
||||||
|
@ -49,12 +54,10 @@ describe("Delete Database Confirmation Pane", () => {
|
||||||
|
|
||||||
describe("shouldRecordFeedback()", () => {
|
describe("shouldRecordFeedback()", () => {
|
||||||
it("should return true if last non empty database or is last database that has shared throughput, else false", () => {
|
it("should return true if last non empty database or is last database that has shared throughput, else false", () => {
|
||||||
let fakeDocumentClientUtility = {} as DocumentClientUtilityBase;
|
|
||||||
let fakeExplorer = {} as Explorer;
|
let fakeExplorer = {} as Explorer;
|
||||||
fakeExplorer.isNotificationConsoleExpanded = ko.observable<boolean>(false);
|
fakeExplorer.isNotificationConsoleExpanded = ko.observable<boolean>(false);
|
||||||
|
|
||||||
let pane = new DeleteDatabaseConfirmationPane({
|
let pane = new DeleteDatabaseConfirmationPane({
|
||||||
documentClientUtility: fakeDocumentClientUtility as any,
|
|
||||||
id: "deletedatabaseconfirmationpane",
|
id: "deletedatabaseconfirmationpane",
|
||||||
visible: ko.observable<boolean>(false),
|
visible: ko.observable<boolean>(false),
|
||||||
container: fakeExplorer as any
|
container: fakeExplorer as any
|
||||||
|
@ -78,20 +81,8 @@ describe("Delete Database Confirmation Pane", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("submit()", () => {
|
describe("submit()", () => {
|
||||||
let telemetryProcessorSpy: sinon.SinonSpy;
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
telemetryProcessorSpy = sinon.spy(TelemetryProcessor, "trace");
|
|
||||||
});
|
|
||||||
|
|
||||||
afterEach(() => {
|
|
||||||
telemetryProcessorSpy.restore();
|
|
||||||
});
|
|
||||||
|
|
||||||
it("on submit() it should log feedback if last non empty database or is last database that has shared throughput", () => {
|
it("on submit() it should log feedback if last non empty database or is last database that has shared throughput", () => {
|
||||||
let selectedDatabaseId = "testDB";
|
let selectedDatabaseId = "testDB";
|
||||||
let fakeDocumentClientUtility = {} as DocumentClientUtilityBase;
|
|
||||||
fakeDocumentClientUtility.deleteDatabase = () => Q.resolve(null);
|
|
||||||
let fakeExplorer = {} as Explorer;
|
let fakeExplorer = {} as Explorer;
|
||||||
fakeExplorer.findSelectedDatabase = () => {
|
fakeExplorer.findSelectedDatabase = () => {
|
||||||
return {
|
return {
|
||||||
|
@ -114,13 +105,11 @@ describe("Delete Database Confirmation Pane", () => {
|
||||||
fakeExplorer.isPreferredApiCassandra = ko.computed(() => {
|
fakeExplorer.isPreferredApiCassandra = ko.computed(() => {
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
fakeExplorer.documentClientUtility = fakeDocumentClientUtility;
|
|
||||||
fakeExplorer.selectedNode = ko.observable<TreeNode>();
|
fakeExplorer.selectedNode = ko.observable<TreeNode>();
|
||||||
fakeExplorer.tabsManager = new TabsManager();
|
fakeExplorer.tabsManager = new TabsManager();
|
||||||
fakeExplorer.isLastNonEmptyDatabase = () => true;
|
fakeExplorer.isLastNonEmptyDatabase = () => true;
|
||||||
|
|
||||||
let pane = new DeleteDatabaseConfirmationPane({
|
let pane = new DeleteDatabaseConfirmationPane({
|
||||||
documentClientUtility: fakeDocumentClientUtility as any,
|
|
||||||
id: "deletedatabaseconfirmationpane",
|
id: "deletedatabaseconfirmationpane",
|
||||||
visible: ko.observable<boolean>(false),
|
visible: ko.observable<boolean>(false),
|
||||||
container: fakeExplorer as any
|
container: fakeExplorer as any
|
||||||
|
@ -130,15 +119,12 @@ describe("Delete Database Confirmation Pane", () => {
|
||||||
pane.databaseDeleteFeedback(Feedback);
|
pane.databaseDeleteFeedback(Feedback);
|
||||||
|
|
||||||
return pane.submit().then(() => {
|
return pane.submit().then(() => {
|
||||||
expect(telemetryProcessorSpy.called).toBe(true);
|
|
||||||
let deleteFeedback = new DeleteFeedback(SubscriptionId, AccountName, DataModels.ApiKind.SQL, Feedback);
|
let deleteFeedback = new DeleteFeedback(SubscriptionId, AccountName, DataModels.ApiKind.SQL, Feedback);
|
||||||
expect(
|
expect(TelemetryProcessor.trace).toHaveBeenCalledWith(
|
||||||
telemetryProcessorSpy.calledWith(
|
Action.DeleteDatabase,
|
||||||
Action.DeleteDatabase,
|
ActionModifiers.Mark,
|
||||||
ActionModifiers.Mark,
|
JSON.stringify(deleteFeedback, Object.getOwnPropertyNames(deleteFeedback))
|
||||||
JSON.stringify(deleteFeedback, Object.getOwnPropertyNames(deleteFeedback))
|
);
|
||||||
)
|
|
||||||
).toBe(true);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -12,6 +12,7 @@ import DeleteFeedback from "../../Common/DeleteFeedback";
|
||||||
|
|
||||||
import { NotificationConsoleUtils } from "../../Utils/NotificationConsoleUtils";
|
import { NotificationConsoleUtils } from "../../Utils/NotificationConsoleUtils";
|
||||||
import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
||||||
|
import { deleteDatabase } from "../../Common/DocumentClientUtilityBase";
|
||||||
|
|
||||||
export default class DeleteDatabaseConfirmationPane extends ContextualPaneBase {
|
export default class DeleteDatabaseConfirmationPane extends ContextualPaneBase {
|
||||||
public databaseIdConfirmationText: ko.Observable<string>;
|
public databaseIdConfirmationText: ko.Observable<string>;
|
||||||
|
@ -59,7 +60,7 @@ export default class DeleteDatabaseConfirmationPane extends ContextualPaneBase {
|
||||||
this.container
|
this.container
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
promise = this.container.documentClientUtility.deleteDatabase(selectedDatabase);
|
promise = deleteDatabase(selectedDatabase);
|
||||||
}
|
}
|
||||||
return promise.then(
|
return promise.then(
|
||||||
() => {
|
() => {
|
||||||
|
|
|
@ -7,7 +7,7 @@ describe("Settings Pane", () => {
|
||||||
let explorer: Explorer;
|
let explorer: Explorer;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
explorer = new Explorer({ documentClientUtility: null, notificationsClient: null, isEmulator: false });
|
explorer = new Explorer({ notificationsClient: null, isEmulator: false });
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should be true for SQL API", () => {
|
it("should be true for SQL API", () => {
|
||||||
|
|
|
@ -15,8 +15,14 @@ import * as TableEntityProcessor from "./TableEntityProcessor";
|
||||||
import * as ViewModels from "../../Contracts/ViewModels";
|
import * as ViewModels from "../../Contracts/ViewModels";
|
||||||
import { MessageTypes } from "../../Contracts/ExplorerContracts";
|
import { MessageTypes } from "../../Contracts/ExplorerContracts";
|
||||||
import { sendMessage } from "../../Common/MessageHandler";
|
import { sendMessage } from "../../Common/MessageHandler";
|
||||||
import DocumentClientUtilityBase from "../../Common/DocumentClientUtilityBase";
|
|
||||||
import Explorer from "../Explorer";
|
import Explorer from "../Explorer";
|
||||||
|
import {
|
||||||
|
queryDocuments,
|
||||||
|
refreshCachedResources,
|
||||||
|
deleteDocument,
|
||||||
|
updateDocument,
|
||||||
|
createDocument
|
||||||
|
} from "../../Common/DocumentClientUtilityBase";
|
||||||
|
|
||||||
export interface CassandraTableKeys {
|
export interface CassandraTableKeys {
|
||||||
partitionKeys: CassandraTableKey[];
|
partitionKeys: CassandraTableKey[];
|
||||||
|
@ -29,11 +35,7 @@ export interface CassandraTableKey {
|
||||||
}
|
}
|
||||||
|
|
||||||
export abstract class TableDataClient {
|
export abstract class TableDataClient {
|
||||||
public documentClientUtility: DocumentClientUtilityBase;
|
constructor() {}
|
||||||
|
|
||||||
constructor(documentClientUtility: DocumentClientUtilityBase) {
|
|
||||||
this.documentClientUtility = documentClientUtility;
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract createDocument(
|
public abstract createDocument(
|
||||||
collection: ViewModels.Collection,
|
collection: ViewModels.Collection,
|
||||||
|
@ -65,20 +67,18 @@ export class TablesAPIDataClient extends TableDataClient {
|
||||||
entity: Entities.ITableEntity
|
entity: Entities.ITableEntity
|
||||||
): Q.Promise<Entities.ITableEntity> {
|
): Q.Promise<Entities.ITableEntity> {
|
||||||
const deferred = Q.defer<Entities.ITableEntity>();
|
const deferred = Q.defer<Entities.ITableEntity>();
|
||||||
this.documentClientUtility
|
createDocument(
|
||||||
.createDocument(
|
collection,
|
||||||
collection,
|
TableEntityProcessor.convertEntityToNewDocument(<Entities.ITableEntityForTablesAPI>entity)
|
||||||
TableEntityProcessor.convertEntityToNewDocument(<Entities.ITableEntityForTablesAPI>entity)
|
).then(
|
||||||
)
|
(newDocument: any) => {
|
||||||
.then(
|
const newEntity = TableEntityProcessor.convertDocumentsToEntities([newDocument])[0];
|
||||||
(newDocument: any) => {
|
deferred.resolve(newEntity);
|
||||||
const newEntity = TableEntityProcessor.convertDocumentsToEntities([newDocument])[0];
|
},
|
||||||
deferred.resolve(newEntity);
|
reason => {
|
||||||
},
|
deferred.reject(reason);
|
||||||
reason => {
|
}
|
||||||
deferred.reject(reason);
|
);
|
||||||
}
|
|
||||||
);
|
|
||||||
return deferred.promise;
|
return deferred.promise;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,21 +88,20 @@ export class TablesAPIDataClient extends TableDataClient {
|
||||||
entity: Entities.ITableEntity
|
entity: Entities.ITableEntity
|
||||||
): Q.Promise<Entities.ITableEntity> {
|
): Q.Promise<Entities.ITableEntity> {
|
||||||
const deferred = Q.defer<Entities.ITableEntity>();
|
const deferred = Q.defer<Entities.ITableEntity>();
|
||||||
this.documentClientUtility
|
|
||||||
.updateDocument(
|
updateDocument(
|
||||||
collection,
|
collection,
|
||||||
originalDocument,
|
originalDocument,
|
||||||
TableEntityProcessor.convertEntityToNewDocument(<Entities.ITableEntityForTablesAPI>entity)
|
TableEntityProcessor.convertEntityToNewDocument(<Entities.ITableEntityForTablesAPI>entity)
|
||||||
)
|
).then(
|
||||||
.then(
|
(newDocument: any) => {
|
||||||
(newDocument: any) => {
|
const newEntity = TableEntityProcessor.convertDocumentsToEntities([newDocument])[0];
|
||||||
const newEntity = TableEntityProcessor.convertDocumentsToEntities([newDocument])[0];
|
deferred.resolve(newEntity);
|
||||||
deferred.resolve(newEntity);
|
},
|
||||||
},
|
reason => {
|
||||||
reason => {
|
deferred.reject(reason);
|
||||||
deferred.reject(reason);
|
}
|
||||||
}
|
);
|
||||||
);
|
|
||||||
return deferred.promise;
|
return deferred.promise;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -114,7 +113,7 @@ export class TablesAPIDataClient extends TableDataClient {
|
||||||
|
|
||||||
let options: any = {};
|
let options: any = {};
|
||||||
options.enableCrossPartitionQuery = HeadersUtility.shouldEnableCrossPartitionKey();
|
options.enableCrossPartitionQuery = HeadersUtility.shouldEnableCrossPartitionKey();
|
||||||
this.documentClientUtility.queryDocuments(collection.databaseId, collection.id(), query, options).then(
|
queryDocuments(collection.databaseId, collection.id(), query, options).then(
|
||||||
iterator => {
|
iterator => {
|
||||||
iterator
|
iterator
|
||||||
.fetchNext()
|
.fetchNext()
|
||||||
|
@ -150,7 +149,7 @@ export class TablesAPIDataClient extends TableDataClient {
|
||||||
documentsToDelete &&
|
documentsToDelete &&
|
||||||
documentsToDelete.forEach(document => {
|
documentsToDelete.forEach(document => {
|
||||||
document.id = ko.observable<string>(document.id);
|
document.id = ko.observable<string>(document.id);
|
||||||
let promise: Q.Promise<any> = this.documentClientUtility.deleteDocument(collection, document);
|
let promise: Q.Promise<any> = deleteDocument(collection, document);
|
||||||
promiseArray.push(promise);
|
promiseArray.push(promise);
|
||||||
});
|
});
|
||||||
return Q.all(promiseArray);
|
return Q.all(promiseArray);
|
||||||
|
@ -425,7 +424,7 @@ export class CassandraAPIDataClient extends TableDataClient {
|
||||||
ConsoleDataType.Info,
|
ConsoleDataType.Info,
|
||||||
`Successfully created a keyspace with query ${createKeyspaceQuery}`
|
`Successfully created a keyspace with query ${createKeyspaceQuery}`
|
||||||
);
|
);
|
||||||
explorer.documentClientUtility.refreshCachedResources().finally(() => deferred.resolve());
|
refreshCachedResources().finally(() => deferred.resolve());
|
||||||
},
|
},
|
||||||
reason => {
|
reason => {
|
||||||
NotificationConsoleUtils.logConsoleMessage(
|
NotificationConsoleUtils.logConsoleMessage(
|
||||||
|
@ -472,7 +471,7 @@ export class CassandraAPIDataClient extends TableDataClient {
|
||||||
ConsoleDataType.Info,
|
ConsoleDataType.Info,
|
||||||
`Successfully created a table with query ${createTableQuery}`
|
`Successfully created a table with query ${createTableQuery}`
|
||||||
);
|
);
|
||||||
this.documentClientUtility.refreshCachedResources(null).then(
|
refreshCachedResources(null).then(
|
||||||
() => {
|
() => {
|
||||||
deferred.resolve();
|
deferred.resolve();
|
||||||
},
|
},
|
||||||
|
@ -521,7 +520,7 @@ export class CassandraAPIDataClient extends TableDataClient {
|
||||||
ConsoleDataType.Info,
|
ConsoleDataType.Info,
|
||||||
`Successfully deleted resource with query ${deleteQuery}`
|
`Successfully deleted resource with query ${deleteQuery}`
|
||||||
);
|
);
|
||||||
this.documentClientUtility.refreshCachedResources(null).then(
|
refreshCachedResources(null).then(
|
||||||
() => {
|
() => {
|
||||||
deferred.resolve();
|
deferred.resolve();
|
||||||
},
|
},
|
||||||
|
|
|
@ -21,6 +21,13 @@ import DeleteIcon from "../../../images/delete.svg";
|
||||||
import { QueryIterator, ItemDefinition, Resource, ConflictDefinition } from "@azure/cosmos";
|
import { QueryIterator, ItemDefinition, Resource, ConflictDefinition } from "@azure/cosmos";
|
||||||
import { MinimalQueryIterator } from "../../Common/IteratorUtilities";
|
import { MinimalQueryIterator } from "../../Common/IteratorUtilities";
|
||||||
import Explorer from "../Explorer";
|
import Explorer from "../Explorer";
|
||||||
|
import {
|
||||||
|
queryConflicts,
|
||||||
|
deleteConflict,
|
||||||
|
deleteDocument,
|
||||||
|
createDocument,
|
||||||
|
updateDocument
|
||||||
|
} from "../../Common/DocumentClientUtilityBase";
|
||||||
|
|
||||||
export default class ConflictsTab extends TabsBase {
|
export default class ConflictsTab extends TabsBase {
|
||||||
public selectedConflictId: ko.Observable<ViewModels.ConflictId>;
|
public selectedConflictId: ko.Observable<ViewModels.ConflictId>;
|
||||||
|
@ -286,7 +293,7 @@ export default class ConflictsTab extends TabsBase {
|
||||||
if (selectedConflict.operationType === Constants.ConflictOperationType.Replace) {
|
if (selectedConflict.operationType === Constants.ConflictOperationType.Replace) {
|
||||||
const documentContent = JSON.parse(this.selectedConflictContent());
|
const documentContent = JSON.parse(this.selectedConflictContent());
|
||||||
|
|
||||||
operationPromise = this._container.documentClientUtility.updateDocument(
|
operationPromise = updateDocument(
|
||||||
this.collection,
|
this.collection,
|
||||||
selectedConflict.buildDocumentIdFromConflict(documentContent[selectedConflict.partitionKeyProperty]),
|
selectedConflict.buildDocumentIdFromConflict(documentContent[selectedConflict.partitionKeyProperty]),
|
||||||
documentContent
|
documentContent
|
||||||
|
@ -296,13 +303,13 @@ export default class ConflictsTab extends TabsBase {
|
||||||
if (selectedConflict.operationType === Constants.ConflictOperationType.Create) {
|
if (selectedConflict.operationType === Constants.ConflictOperationType.Create) {
|
||||||
const documentContent = JSON.parse(this.selectedConflictContent());
|
const documentContent = JSON.parse(this.selectedConflictContent());
|
||||||
|
|
||||||
operationPromise = this._container.documentClientUtility.createDocument(this.collection, documentContent);
|
operationPromise = createDocument(this.collection, documentContent);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (selectedConflict.operationType === Constants.ConflictOperationType.Delete && !!this.selectedConflictContent()) {
|
if (selectedConflict.operationType === Constants.ConflictOperationType.Delete && !!this.selectedConflictContent()) {
|
||||||
const documentContent = JSON.parse(this.selectedConflictContent());
|
const documentContent = JSON.parse(this.selectedConflictContent());
|
||||||
|
|
||||||
operationPromise = this._container.documentClientUtility.deleteDocument(
|
operationPromise = deleteDocument(
|
||||||
this.collection,
|
this.collection,
|
||||||
selectedConflict.buildDocumentIdFromConflict(documentContent[selectedConflict.partitionKeyProperty])
|
selectedConflict.buildDocumentIdFromConflict(documentContent[selectedConflict.partitionKeyProperty])
|
||||||
);
|
);
|
||||||
|
@ -311,7 +318,7 @@ export default class ConflictsTab extends TabsBase {
|
||||||
return operationPromise
|
return operationPromise
|
||||||
.then(
|
.then(
|
||||||
() => {
|
() => {
|
||||||
return this._container.documentClientUtility.deleteConflict(this.collection, selectedConflict).then(() => {
|
return deleteConflict(this.collection, selectedConflict).then(() => {
|
||||||
this.conflictIds.remove((conflictId: ViewModels.ConflictId) => conflictId.rid === selectedConflict.rid);
|
this.conflictIds.remove((conflictId: ViewModels.ConflictId) => conflictId.rid === selectedConflict.rid);
|
||||||
this.selectedConflictContent("");
|
this.selectedConflictContent("");
|
||||||
this.selectedConflictCurrent("");
|
this.selectedConflictCurrent("");
|
||||||
|
@ -370,8 +377,7 @@ export default class ConflictsTab extends TabsBase {
|
||||||
conflictResourceId: selectedConflict.resourceId
|
conflictResourceId: selectedConflict.resourceId
|
||||||
});
|
});
|
||||||
|
|
||||||
return this._container.documentClientUtility
|
return deleteConflict(this.collection, selectedConflict)
|
||||||
.deleteConflict(this.collection, selectedConflict)
|
|
||||||
.then(
|
.then(
|
||||||
() => {
|
() => {
|
||||||
this.conflictIds.remove((conflictId: ViewModels.ConflictId) => conflictId.rid === selectedConflict.rid);
|
this.conflictIds.remove((conflictId: ViewModels.ConflictId) => conflictId.rid === selectedConflict.rid);
|
||||||
|
@ -491,7 +497,7 @@ export default class ConflictsTab extends TabsBase {
|
||||||
const query: string = undefined;
|
const query: string = undefined;
|
||||||
let options: any = {};
|
let options: any = {};
|
||||||
options.enableCrossPartitionQuery = HeadersUtility.shouldEnableCrossPartitionKey();
|
options.enableCrossPartitionQuery = HeadersUtility.shouldEnableCrossPartitionKey();
|
||||||
return this.documentClientUtility.queryConflicts(this.collection.databaseId, this.collection.id(), query, options);
|
return queryConflicts(this.collection.databaseId, this.collection.id(), query, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
public loadNextPage(): Q.Promise<any> {
|
public loadNextPage(): Q.Promise<any> {
|
||||||
|
|
|
@ -18,6 +18,7 @@ import { CosmosClient } from "../../Common/CosmosClient";
|
||||||
import { PlatformType } from "../../PlatformType";
|
import { PlatformType } from "../../PlatformType";
|
||||||
import { RequestOptions } from "@azure/cosmos/dist-esm";
|
import { RequestOptions } from "@azure/cosmos/dist-esm";
|
||||||
import Explorer from "../Explorer";
|
import Explorer from "../Explorer";
|
||||||
|
import { updateOfferThroughputBeyondLimit, updateOffer } from "../../Common/DocumentClientUtilityBase";
|
||||||
|
|
||||||
const updateThroughputBeyondLimitWarningMessage: string = `
|
const updateThroughputBeyondLimitWarningMessage: string = `
|
||||||
You are about to request an increase in throughput beyond the pre-allocated capacity.
|
You are about to request an increase in throughput beyond the pre-allocated capacity.
|
||||||
|
@ -499,13 +500,13 @@ export default class DatabaseSettingsTab extends TabsBase implements ViewModels.
|
||||||
delete newOffer.content.offerAutopilotSettings;
|
delete newOffer.content.offerAutopilotSettings;
|
||||||
}
|
}
|
||||||
|
|
||||||
const updateOfferPromise = this.container.documentClientUtility
|
const updateOfferPromise = updateOffer(this.database.offer(), newOffer, headerOptions).then(
|
||||||
.updateOffer(this.database.offer(), newOffer, headerOptions)
|
(updatedOffer: DataModels.Offer) => {
|
||||||
.then((updatedOffer: DataModels.Offer) => {
|
|
||||||
this.database.offer(updatedOffer);
|
this.database.offer(updatedOffer);
|
||||||
this.database.offer.valueHasMutated();
|
this.database.offer.valueHasMutated();
|
||||||
this._wasAutopilotOriginallySet(this.isAutoPilotSelected());
|
this._wasAutopilotOriginallySet(this.isAutoPilotSelected());
|
||||||
});
|
}
|
||||||
|
);
|
||||||
promises.push(updateOfferPromise);
|
promises.push(updateOfferPromise);
|
||||||
} else {
|
} else {
|
||||||
if (this.throughput.editableIsDirty() || this.isAutoPilotSelected.editableIsDirty()) {
|
if (this.throughput.editableIsDirty() || this.isAutoPilotSelected.editableIsDirty()) {
|
||||||
|
@ -527,32 +528,30 @@ export default class DatabaseSettingsTab extends TabsBase implements ViewModels.
|
||||||
throughput: newThroughput,
|
throughput: newThroughput,
|
||||||
offerIsRUPerMinuteThroughputEnabled: false
|
offerIsRUPerMinuteThroughputEnabled: false
|
||||||
};
|
};
|
||||||
const updateOfferBeyondLimitPromise: Q.Promise<void> = this.documentClientUtility
|
const updateOfferBeyondLimitPromise: Q.Promise<void> = updateOfferThroughputBeyondLimit(requestPayload).then(
|
||||||
.updateOfferThroughputBeyondLimit(requestPayload)
|
() => {
|
||||||
.then(
|
this.database.offer().content.offerThroughput = originalThroughputValue;
|
||||||
() => {
|
this.throughput(originalThroughputValue);
|
||||||
this.database.offer().content.offerThroughput = originalThroughputValue;
|
this.notificationStatusInfo(
|
||||||
this.throughput(originalThroughputValue);
|
throughputApplyDelayedMessage(this.isAutoPilotSelected(), newThroughput, this.database.id())
|
||||||
this.notificationStatusInfo(
|
);
|
||||||
throughputApplyDelayedMessage(this.isAutoPilotSelected(), newThroughput, this.database.id())
|
this.throughput.valueHasMutated(); // force component re-render
|
||||||
);
|
},
|
||||||
this.throughput.valueHasMutated(); // force component re-render
|
(error: any) => {
|
||||||
},
|
TelemetryProcessor.traceFailure(
|
||||||
(error: any) => {
|
Action.UpdateSettings,
|
||||||
TelemetryProcessor.traceFailure(
|
{
|
||||||
Action.UpdateSettings,
|
databaseAccountName: this.container.databaseAccount().name,
|
||||||
{
|
databaseName: this.database && this.database.id(),
|
||||||
databaseAccountName: this.container.databaseAccount().name,
|
defaultExperience: this.container.defaultExperience(),
|
||||||
databaseName: this.database && this.database.id(),
|
dataExplorerArea: Constants.Areas.Tab,
|
||||||
defaultExperience: this.container.defaultExperience(),
|
tabTitle: this.tabTitle(),
|
||||||
dataExplorerArea: Constants.Areas.Tab,
|
error: error
|
||||||
tabTitle: this.tabTitle(),
|
},
|
||||||
error: error
|
startKey
|
||||||
},
|
);
|
||||||
startKey
|
}
|
||||||
);
|
);
|
||||||
}
|
|
||||||
);
|
|
||||||
promises.push(updateOfferBeyondLimitPromise);
|
promises.push(updateOfferBeyondLimitPromise);
|
||||||
} else {
|
} else {
|
||||||
const newOffer: DataModels.Offer = {
|
const newOffer: DataModels.Offer = {
|
||||||
|
@ -577,13 +576,13 @@ export default class DatabaseSettingsTab extends TabsBase implements ViewModels.
|
||||||
newOffer.content.offerAutopilotSettings = { maxThroughput: 0 };
|
newOffer.content.offerAutopilotSettings = { maxThroughput: 0 };
|
||||||
}
|
}
|
||||||
|
|
||||||
const updateOfferPromise = this.container.documentClientUtility
|
const updateOfferPromise = updateOffer(this.database.offer(), newOffer, headerOptions).then(
|
||||||
.updateOffer(this.database.offer(), newOffer, headerOptions)
|
(updatedOffer: DataModels.Offer) => {
|
||||||
.then((updatedOffer: DataModels.Offer) => {
|
|
||||||
this._wasAutopilotOriginallySet(this.isAutoPilotSelected());
|
this._wasAutopilotOriginallySet(this.isAutoPilotSelected());
|
||||||
this.database.offer(updatedOffer);
|
this.database.offer(updatedOffer);
|
||||||
this.database.offer.valueHasMutated();
|
this.database.offer.valueHasMutated();
|
||||||
});
|
}
|
||||||
|
);
|
||||||
|
|
||||||
promises.push(updateOfferPromise);
|
promises.push(updateOfferPromise);
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,6 @@ import * as ViewModels from "../../Contracts/ViewModels";
|
||||||
import * as Constants from "../../Common/Constants";
|
import * as Constants from "../../Common/Constants";
|
||||||
import DocumentsTab from "./DocumentsTab";
|
import DocumentsTab from "./DocumentsTab";
|
||||||
import Explorer from "../Explorer";
|
import Explorer from "../Explorer";
|
||||||
import DocumentClientUtilityBase from "../../Common/DocumentClientUtilityBase";
|
|
||||||
|
|
||||||
describe("Documents tab", () => {
|
describe("Documents tab", () => {
|
||||||
describe("buildQuery", () => {
|
describe("buildQuery", () => {
|
||||||
|
@ -14,7 +13,6 @@ describe("Documents tab", () => {
|
||||||
tabKind: ViewModels.CollectionTabKind.Documents,
|
tabKind: ViewModels.CollectionTabKind.Documents,
|
||||||
title: "",
|
title: "",
|
||||||
tabPath: "",
|
tabPath: "",
|
||||||
documentClientUtility: new DocumentClientUtilityBase(),
|
|
||||||
selfLink: "",
|
selfLink: "",
|
||||||
hashLocation: "",
|
hashLocation: "",
|
||||||
isActive: ko.observable<boolean>(false),
|
isActive: ko.observable<boolean>(false),
|
||||||
|
@ -28,13 +26,11 @@ describe("Documents tab", () => {
|
||||||
|
|
||||||
describe("showPartitionKey", () => {
|
describe("showPartitionKey", () => {
|
||||||
const explorer = new Explorer({
|
const explorer = new Explorer({
|
||||||
documentClientUtility: null,
|
|
||||||
notificationsClient: null,
|
notificationsClient: null,
|
||||||
isEmulator: false
|
isEmulator: false
|
||||||
});
|
});
|
||||||
|
|
||||||
const mongoExplorer = new Explorer({
|
const mongoExplorer = new Explorer({
|
||||||
documentClientUtility: null,
|
|
||||||
notificationsClient: null,
|
notificationsClient: null,
|
||||||
isEmulator: false
|
isEmulator: false
|
||||||
});
|
});
|
||||||
|
@ -97,7 +93,6 @@ describe("Documents tab", () => {
|
||||||
tabKind: ViewModels.CollectionTabKind.Documents,
|
tabKind: ViewModels.CollectionTabKind.Documents,
|
||||||
title: "",
|
title: "",
|
||||||
tabPath: "",
|
tabPath: "",
|
||||||
documentClientUtility: new DocumentClientUtilityBase(),
|
|
||||||
selfLink: "",
|
selfLink: "",
|
||||||
hashLocation: "",
|
hashLocation: "",
|
||||||
isActive: ko.observable<boolean>(false),
|
isActive: ko.observable<boolean>(false),
|
||||||
|
@ -116,7 +111,6 @@ describe("Documents tab", () => {
|
||||||
tabKind: ViewModels.CollectionTabKind.Documents,
|
tabKind: ViewModels.CollectionTabKind.Documents,
|
||||||
title: "",
|
title: "",
|
||||||
tabPath: "",
|
tabPath: "",
|
||||||
documentClientUtility: new DocumentClientUtilityBase(),
|
|
||||||
selfLink: "",
|
selfLink: "",
|
||||||
hashLocation: "",
|
hashLocation: "",
|
||||||
isActive: ko.observable<boolean>(false),
|
isActive: ko.observable<boolean>(false),
|
||||||
|
@ -135,7 +129,6 @@ describe("Documents tab", () => {
|
||||||
tabKind: ViewModels.CollectionTabKind.Documents,
|
tabKind: ViewModels.CollectionTabKind.Documents,
|
||||||
title: "",
|
title: "",
|
||||||
tabPath: "",
|
tabPath: "",
|
||||||
documentClientUtility: new DocumentClientUtilityBase(),
|
|
||||||
selfLink: "",
|
selfLink: "",
|
||||||
hashLocation: "",
|
hashLocation: "",
|
||||||
isActive: ko.observable<boolean>(false),
|
isActive: ko.observable<boolean>(false),
|
||||||
|
@ -154,7 +147,6 @@ describe("Documents tab", () => {
|
||||||
tabKind: ViewModels.CollectionTabKind.Documents,
|
tabKind: ViewModels.CollectionTabKind.Documents,
|
||||||
title: "",
|
title: "",
|
||||||
tabPath: "",
|
tabPath: "",
|
||||||
documentClientUtility: new DocumentClientUtilityBase(),
|
|
||||||
selfLink: "",
|
selfLink: "",
|
||||||
hashLocation: "",
|
hashLocation: "",
|
||||||
isActive: ko.observable<boolean>(false),
|
isActive: ko.observable<boolean>(false),
|
||||||
|
@ -173,7 +165,6 @@ describe("Documents tab", () => {
|
||||||
tabKind: ViewModels.CollectionTabKind.Documents,
|
tabKind: ViewModels.CollectionTabKind.Documents,
|
||||||
title: "",
|
title: "",
|
||||||
tabPath: "",
|
tabPath: "",
|
||||||
documentClientUtility: new DocumentClientUtilityBase(),
|
|
||||||
selfLink: "",
|
selfLink: "",
|
||||||
hashLocation: "",
|
hashLocation: "",
|
||||||
isActive: ko.observable<boolean>(false),
|
isActive: ko.observable<boolean>(false),
|
||||||
|
|
|
@ -26,6 +26,13 @@ import { extractPartitionKey, PartitionKeyDefinition, QueryIterator, ItemDefinit
|
||||||
import { ConsoleDataType } from "../Menus/NotificationConsole/NotificationConsoleComponent";
|
import { ConsoleDataType } from "../Menus/NotificationConsole/NotificationConsoleComponent";
|
||||||
import { NotificationConsoleUtils } from "../../Utils/NotificationConsoleUtils";
|
import { NotificationConsoleUtils } from "../../Utils/NotificationConsoleUtils";
|
||||||
import Explorer from "../Explorer";
|
import Explorer from "../Explorer";
|
||||||
|
import {
|
||||||
|
readDocument,
|
||||||
|
queryDocuments,
|
||||||
|
deleteDocument,
|
||||||
|
updateDocument,
|
||||||
|
createDocument
|
||||||
|
} from "../../Common/DocumentClientUtilityBase";
|
||||||
|
|
||||||
export default class DocumentsTab extends TabsBase implements ViewModels.DocumentsTab {
|
export default class DocumentsTab extends TabsBase implements ViewModels.DocumentsTab {
|
||||||
public selectedDocumentId: ko.Observable<ViewModels.DocumentId>;
|
public selectedDocumentId: ko.Observable<ViewModels.DocumentId>;
|
||||||
|
@ -442,8 +449,7 @@ export default class DocumentsTab extends TabsBase implements ViewModels.Documen
|
||||||
});
|
});
|
||||||
const document = JSON.parse(this.selectedDocumentContent());
|
const document = JSON.parse(this.selectedDocumentContent());
|
||||||
this.isExecuting(true);
|
this.isExecuting(true);
|
||||||
return this.documentClientUtility
|
return createDocument(this.collection, document)
|
||||||
.createDocument(this.collection, document)
|
|
||||||
.then(
|
.then(
|
||||||
(savedDocument: any) => {
|
(savedDocument: any) => {
|
||||||
const value: string = this.renderObjectForEditor(savedDocument || {}, null, 4);
|
const value: string = this.renderObjectForEditor(savedDocument || {}, null, 4);
|
||||||
|
@ -516,8 +522,7 @@ export default class DocumentsTab extends TabsBase implements ViewModels.Documen
|
||||||
tabTitle: this.tabTitle()
|
tabTitle: this.tabTitle()
|
||||||
});
|
});
|
||||||
this.isExecuting(true);
|
this.isExecuting(true);
|
||||||
return this.documentClientUtility
|
return updateDocument(this.collection, selectedDocumentId, documentContent)
|
||||||
.updateDocument(this.collection, selectedDocumentId, documentContent)
|
|
||||||
.then(
|
.then(
|
||||||
(updatedDocument: any) => {
|
(updatedDocument: any) => {
|
||||||
const value: string = this.renderObjectForEditor(updatedDocument || {}, null, 4);
|
const value: string = this.renderObjectForEditor(updatedDocument || {}, null, 4);
|
||||||
|
@ -665,7 +670,7 @@ export default class DocumentsTab extends TabsBase implements ViewModels.Documen
|
||||||
};
|
};
|
||||||
|
|
||||||
protected __deleteDocument(documentId: ViewModels.DocumentId): Q.Promise<any> {
|
protected __deleteDocument(documentId: ViewModels.DocumentId): Q.Promise<any> {
|
||||||
return this.documentClientUtility.deleteDocument(this.collection, documentId);
|
return deleteDocument(this.collection, documentId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private _deleteDocument(selectedDocumentId: ViewModels.DocumentId): Q.Promise<any> {
|
private _deleteDocument(selectedDocumentId: ViewModels.DocumentId): Q.Promise<any> {
|
||||||
|
@ -724,12 +729,12 @@ export default class DocumentsTab extends TabsBase implements ViewModels.Documen
|
||||||
options.partitionKey = this._resourceTokenPartitionKey;
|
options.partitionKey = this._resourceTokenPartitionKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.documentClientUtility.queryDocuments(this.collection.databaseId, this.collection.id(), query, options);
|
return queryDocuments(this.collection.databaseId, this.collection.id(), query, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
public selectDocument(documentId: ViewModels.DocumentId): Q.Promise<any> {
|
public selectDocument(documentId: ViewModels.DocumentId): Q.Promise<any> {
|
||||||
this.selectedDocumentId(documentId);
|
this.selectedDocumentId(documentId);
|
||||||
return this.documentClientUtility.readDocument(this.collection, documentId).then((content: any) => {
|
return readDocument(this.collection, documentId).then((content: any) => {
|
||||||
this.initDocumentEditor(documentId, content);
|
this.initDocumentEditor(documentId, content);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -83,7 +83,6 @@ export default class GraphTab extends TabsBase implements ViewModels.Tab {
|
||||||
onIsFilterQueryLoading: (isFilterQueryLoading: boolean): void => this.isFilterQueryLoading(isFilterQueryLoading),
|
onIsFilterQueryLoading: (isFilterQueryLoading: boolean): void => this.isFilterQueryLoading(isFilterQueryLoading),
|
||||||
onIsValidQuery: (isValidQuery: boolean): void => this.isValidQuery(isValidQuery),
|
onIsValidQuery: (isValidQuery: boolean): void => this.isValidQuery(isValidQuery),
|
||||||
collectionPartitionKeyProperty: options.collectionPartitionKeyProperty,
|
collectionPartitionKeyProperty: options.collectionPartitionKeyProperty,
|
||||||
documentClientUtility: this.documentClientUtility,
|
|
||||||
collectionRid: this.rid,
|
collectionRid: this.rid,
|
||||||
collectionSelfLink: options.selfLink,
|
collectionSelfLink: options.selfLink,
|
||||||
graphBackendEndpoint: GraphTab.getGremlinEndpoint(options.account),
|
graphBackendEndpoint: GraphTab.getGremlinEndpoint(options.account),
|
||||||
|
@ -101,7 +100,6 @@ export default class GraphTab extends TabsBase implements ViewModels.Tab {
|
||||||
|
|
||||||
this.isFilterQueryLoading = ko.observable(false);
|
this.isFilterQueryLoading = ko.observable(false);
|
||||||
this.isValidQuery = ko.observable(true);
|
this.isValidQuery = ko.observable(true);
|
||||||
this.documentClientUtility = options.documentClientUtility;
|
|
||||||
this.toolbarViewModel = ko.observable<Toolbar>();
|
this.toolbarViewModel = ko.observable<Toolbar>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,6 @@ describe("Query Tab", () => {
|
||||||
database: database,
|
database: database,
|
||||||
title: "",
|
title: "",
|
||||||
tabPath: "",
|
tabPath: "",
|
||||||
documentClientUtility: container.documentClientUtility,
|
|
||||||
selfLink: "",
|
selfLink: "",
|
||||||
isActive: ko.observable<boolean>(false),
|
isActive: ko.observable<boolean>(false),
|
||||||
hashLocation: "",
|
hashLocation: "",
|
||||||
|
@ -51,7 +50,7 @@ describe("Query Tab", () => {
|
||||||
let explorer: Explorer;
|
let explorer: Explorer;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
explorer = new Explorer({ documentClientUtility: null, notificationsClient: null, isEmulator: false });
|
explorer = new Explorer({ notificationsClient: null, isEmulator: false });
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should be true for accounts using SQL API", () => {
|
it("should be true for accounts using SQL API", () => {
|
||||||
|
@ -71,7 +70,7 @@ describe("Query Tab", () => {
|
||||||
let explorer: Explorer;
|
let explorer: Explorer;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
explorer = new Explorer({ documentClientUtility: null, notificationsClient: null, isEmulator: false });
|
explorer = new Explorer({ notificationsClient: null, isEmulator: false });
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should be visible when using a supported API", () => {
|
it("should be visible when using a supported API", () => {
|
||||||
|
|
|
@ -16,6 +16,7 @@ import { QueryUtils } from "../../Utils/QueryUtils";
|
||||||
import SaveQueryIcon from "../../../images/save-cosmos.svg";
|
import SaveQueryIcon from "../../../images/save-cosmos.svg";
|
||||||
|
|
||||||
import { MinimalQueryIterator } from "../../Common/IteratorUtilities";
|
import { MinimalQueryIterator } from "../../Common/IteratorUtilities";
|
||||||
|
import { queryDocuments, queryDocumentsPage } from "../../Common/DocumentClientUtilityBase";
|
||||||
|
|
||||||
enum ToggleState {
|
enum ToggleState {
|
||||||
Result,
|
Result,
|
||||||
|
@ -290,12 +291,7 @@ export default class QueryTab extends TabsBase implements ViewModels.QueryTab, V
|
||||||
options.enableCrossPartitionQuery = HeadersUtility.shouldEnableCrossPartitionKey();
|
options.enableCrossPartitionQuery = HeadersUtility.shouldEnableCrossPartitionKey();
|
||||||
|
|
||||||
const queryDocuments = (firstItemIndex: number) =>
|
const queryDocuments = (firstItemIndex: number) =>
|
||||||
this.documentClientUtility.queryDocumentsPage(
|
queryDocumentsPage(this.collection && this.collection.id(), this._iterator, firstItemIndex, options);
|
||||||
this.collection && this.collection.id(),
|
|
||||||
this._iterator,
|
|
||||||
firstItemIndex,
|
|
||||||
options
|
|
||||||
);
|
|
||||||
this.isExecuting(true);
|
this.isExecuting(true);
|
||||||
return QueryUtils.queryPagesUntilContentPresent(firstItemIndex, queryDocuments)
|
return QueryUtils.queryPagesUntilContentPresent(firstItemIndex, queryDocuments)
|
||||||
.then(
|
.then(
|
||||||
|
@ -497,9 +493,9 @@ export default class QueryTab extends TabsBase implements ViewModels.QueryTab, V
|
||||||
}
|
}
|
||||||
|
|
||||||
return Q(
|
return Q(
|
||||||
this.documentClientUtility
|
queryDocuments(this.collection.databaseId, this.collection.id(), this.sqlStatementToExecute(), options).then(
|
||||||
.queryDocuments(this.collection.databaseId, this.collection.id(), this.sqlStatementToExecute(), options)
|
iterator => (this._iterator = iterator)
|
||||||
.then(iterator => (this._iterator = iterator))
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,6 @@ import * as ko from "knockout";
|
||||||
import * as ViewModels from "../../Contracts/ViewModels";
|
import * as ViewModels from "../../Contracts/ViewModels";
|
||||||
import Collection from "../Tree/Collection";
|
import Collection from "../Tree/Collection";
|
||||||
import Database from "../Tree/Database";
|
import Database from "../Tree/Database";
|
||||||
import DocumentClientUtilityBase from "../../Common/DocumentClientUtilityBase";
|
|
||||||
import Explorer from "../Explorer";
|
import Explorer from "../Explorer";
|
||||||
import SettingsTab from "../Tabs/SettingsTab";
|
import SettingsTab from "../Tabs/SettingsTab";
|
||||||
|
|
||||||
|
@ -63,8 +62,6 @@ describe("Settings tab", () => {
|
||||||
tabKind: ViewModels.CollectionTabKind.Settings,
|
tabKind: ViewModels.CollectionTabKind.Settings,
|
||||||
title: "Scale & Settings",
|
title: "Scale & Settings",
|
||||||
tabPath: "",
|
tabPath: "",
|
||||||
documentClientUtility: undefined,
|
|
||||||
|
|
||||||
selfLink: "",
|
selfLink: "",
|
||||||
hashLocation: "",
|
hashLocation: "",
|
||||||
isActive: ko.observable(false),
|
isActive: ko.observable(false),
|
||||||
|
@ -80,7 +77,7 @@ describe("Settings tab", () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
explorer = new Explorer({ documentClientUtility: null, notificationsClient: null, isEmulator: false });
|
explorer = new Explorer({ notificationsClient: null, isEmulator: false });
|
||||||
explorer.hasAutoPilotV2FeatureFlag = ko.computed<boolean>(() => true);
|
explorer.hasAutoPilotV2FeatureFlag = ko.computed<boolean>(() => true);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -179,7 +176,7 @@ describe("Settings tab", () => {
|
||||||
let explorer: Explorer;
|
let explorer: Explorer;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
explorer = new Explorer({ documentClientUtility: null, notificationsClient: null, isEmulator: false });
|
explorer = new Explorer({ notificationsClient: null, isEmulator: false });
|
||||||
explorer.hasAutoPilotV2FeatureFlag = ko.computed<boolean>(() => true);
|
explorer.hasAutoPilotV2FeatureFlag = ko.computed<boolean>(() => true);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -188,8 +185,6 @@ describe("Settings tab", () => {
|
||||||
tabKind: ViewModels.CollectionTabKind.Settings,
|
tabKind: ViewModels.CollectionTabKind.Settings,
|
||||||
title: "Scale & Settings",
|
title: "Scale & Settings",
|
||||||
tabPath: "",
|
tabPath: "",
|
||||||
documentClientUtility: new DocumentClientUtilityBase(),
|
|
||||||
|
|
||||||
selfLink: "",
|
selfLink: "",
|
||||||
hashLocation: "",
|
hashLocation: "",
|
||||||
isActive: ko.observable(false),
|
isActive: ko.observable(false),
|
||||||
|
@ -212,7 +207,6 @@ describe("Settings tab", () => {
|
||||||
tabKind: ViewModels.CollectionTabKind.Settings,
|
tabKind: ViewModels.CollectionTabKind.Settings,
|
||||||
title: "Scale & Settings",
|
title: "Scale & Settings",
|
||||||
tabPath: "",
|
tabPath: "",
|
||||||
documentClientUtility: new DocumentClientUtilityBase(),
|
|
||||||
|
|
||||||
selfLink: "",
|
selfLink: "",
|
||||||
hashLocation: "",
|
hashLocation: "",
|
||||||
|
@ -231,7 +225,6 @@ describe("Settings tab", () => {
|
||||||
tabKind: ViewModels.CollectionTabKind.Settings,
|
tabKind: ViewModels.CollectionTabKind.Settings,
|
||||||
title: "Scale & Settings",
|
title: "Scale & Settings",
|
||||||
tabPath: "",
|
tabPath: "",
|
||||||
documentClientUtility: new DocumentClientUtilityBase(),
|
|
||||||
|
|
||||||
selfLink: "",
|
selfLink: "",
|
||||||
hashLocation: "",
|
hashLocation: "",
|
||||||
|
@ -261,7 +254,7 @@ describe("Settings tab", () => {
|
||||||
let explorer: Explorer;
|
let explorer: Explorer;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
explorer = new Explorer({ documentClientUtility: null, notificationsClient: null, isEmulator: false });
|
explorer = new Explorer({ notificationsClient: null, isEmulator: false });
|
||||||
explorer.hasAutoPilotV2FeatureFlag = ko.computed<boolean>(() => true);
|
explorer.hasAutoPilotV2FeatureFlag = ko.computed<boolean>(() => true);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -270,7 +263,6 @@ describe("Settings tab", () => {
|
||||||
tabKind: ViewModels.CollectionTabKind.Settings,
|
tabKind: ViewModels.CollectionTabKind.Settings,
|
||||||
title: "Scale & Settings",
|
title: "Scale & Settings",
|
||||||
tabPath: "",
|
tabPath: "",
|
||||||
documentClientUtility: new DocumentClientUtilityBase(),
|
|
||||||
|
|
||||||
selfLink: "",
|
selfLink: "",
|
||||||
hashLocation: "",
|
hashLocation: "",
|
||||||
|
@ -287,7 +279,6 @@ describe("Settings tab", () => {
|
||||||
tabKind: ViewModels.CollectionTabKind.Settings,
|
tabKind: ViewModels.CollectionTabKind.Settings,
|
||||||
title: "Scale & Settings",
|
title: "Scale & Settings",
|
||||||
tabPath: "",
|
tabPath: "",
|
||||||
documentClientUtility: new DocumentClientUtilityBase(),
|
|
||||||
|
|
||||||
selfLink: "",
|
selfLink: "",
|
||||||
hashLocation: "",
|
hashLocation: "",
|
||||||
|
@ -313,7 +304,6 @@ describe("Settings tab", () => {
|
||||||
tabKind: ViewModels.CollectionTabKind.Settings,
|
tabKind: ViewModels.CollectionTabKind.Settings,
|
||||||
title: "Scale & Settings",
|
title: "Scale & Settings",
|
||||||
tabPath: "",
|
tabPath: "",
|
||||||
documentClientUtility: new DocumentClientUtilityBase(),
|
|
||||||
|
|
||||||
selfLink: "",
|
selfLink: "",
|
||||||
hashLocation: "",
|
hashLocation: "",
|
||||||
|
@ -346,7 +336,6 @@ describe("Settings tab", () => {
|
||||||
|
|
||||||
function getCollection(defaultApi: string, partitionKeyOption: PartitionKeyOption) {
|
function getCollection(defaultApi: string, partitionKeyOption: PartitionKeyOption) {
|
||||||
const explorer = new Explorer({
|
const explorer = new Explorer({
|
||||||
documentClientUtility: null,
|
|
||||||
notificationsClient: null,
|
notificationsClient: null,
|
||||||
isEmulator: false
|
isEmulator: false
|
||||||
});
|
});
|
||||||
|
@ -394,7 +383,6 @@ describe("Settings tab", () => {
|
||||||
tabKind: ViewModels.CollectionTabKind.Settings,
|
tabKind: ViewModels.CollectionTabKind.Settings,
|
||||||
title: "Scale & Settings",
|
title: "Scale & Settings",
|
||||||
tabPath: "",
|
tabPath: "",
|
||||||
documentClientUtility: new DocumentClientUtilityBase(),
|
|
||||||
|
|
||||||
selfLink: "",
|
selfLink: "",
|
||||||
hashLocation: "",
|
hashLocation: "",
|
||||||
|
@ -483,7 +471,6 @@ describe("Settings tab", () => {
|
||||||
describe("AutoPilot", () => {
|
describe("AutoPilot", () => {
|
||||||
function getCollection(autoPilotTier: DataModels.AutopilotTier) {
|
function getCollection(autoPilotTier: DataModels.AutopilotTier) {
|
||||||
const explorer = new Explorer({
|
const explorer = new Explorer({
|
||||||
documentClientUtility: null,
|
|
||||||
notificationsClient: null,
|
notificationsClient: null,
|
||||||
isEmulator: false
|
isEmulator: false
|
||||||
});
|
});
|
||||||
|
@ -540,7 +527,6 @@ describe("Settings tab", () => {
|
||||||
tabKind: ViewModels.CollectionTabKind.Settings,
|
tabKind: ViewModels.CollectionTabKind.Settings,
|
||||||
title: "Scale & Settings",
|
title: "Scale & Settings",
|
||||||
tabPath: "",
|
tabPath: "",
|
||||||
documentClientUtility: new DocumentClientUtilityBase(),
|
|
||||||
|
|
||||||
selfLink: "",
|
selfLink: "",
|
||||||
hashLocation: "",
|
hashLocation: "",
|
||||||
|
|
|
@ -18,6 +18,11 @@ import { CosmosClient } from "../../Common/CosmosClient";
|
||||||
import { PlatformType } from "../../PlatformType";
|
import { PlatformType } from "../../PlatformType";
|
||||||
import { RequestOptions } from "@azure/cosmos/dist-esm";
|
import { RequestOptions } from "@azure/cosmos/dist-esm";
|
||||||
import Explorer from "../Explorer";
|
import Explorer from "../Explorer";
|
||||||
|
import {
|
||||||
|
updateOfferThroughputBeyondLimit,
|
||||||
|
updateOffer,
|
||||||
|
updateCollection
|
||||||
|
} from "../../Common/DocumentClientUtilityBase";
|
||||||
|
|
||||||
const ttlWarning: string = `
|
const ttlWarning: string = `
|
||||||
The system will automatically delete items based on the TTL value (in seconds) you provide, without needing a delete operation explicitly issued by a client application.
|
The system will automatically delete items based on the TTL value (in seconds) you provide, without needing a delete operation explicitly issued by a client application.
|
||||||
|
@ -1062,9 +1067,8 @@ export default class SettingsTab extends TabsBase implements ViewModels.WaitsFor
|
||||||
}
|
}
|
||||||
|
|
||||||
const newCollection: DataModels.Collection = _.extend({}, this.collection.rawDataModel, newCollectionAttributes);
|
const newCollection: DataModels.Collection = _.extend({}, this.collection.rawDataModel, newCollectionAttributes);
|
||||||
const updateCollectionPromise = this.container.documentClientUtility
|
const updateCollectionPromise = updateCollection(this.collection.databaseId, this.collection, newCollection).then(
|
||||||
.updateCollection(this.collection.databaseId, this.collection, newCollection)
|
(updatedCollection: DataModels.Collection) => {
|
||||||
.then((updatedCollection: DataModels.Collection) => {
|
|
||||||
this.collection.rawDataModel = updatedCollection;
|
this.collection.rawDataModel = updatedCollection;
|
||||||
this.collection.defaultTtl(updatedCollection.defaultTtl);
|
this.collection.defaultTtl(updatedCollection.defaultTtl);
|
||||||
this.collection.analyticalStorageTtl(updatedCollection.analyticalStorageTtl);
|
this.collection.analyticalStorageTtl(updatedCollection.analyticalStorageTtl);
|
||||||
|
@ -1073,7 +1077,8 @@ export default class SettingsTab extends TabsBase implements ViewModels.WaitsFor
|
||||||
this.collection.conflictResolutionPolicy(updatedCollection.conflictResolutionPolicy);
|
this.collection.conflictResolutionPolicy(updatedCollection.conflictResolutionPolicy);
|
||||||
this.collection.changeFeedPolicy(updatedCollection.changeFeedPolicy);
|
this.collection.changeFeedPolicy(updatedCollection.changeFeedPolicy);
|
||||||
this.collection.geospatialConfig(updatedCollection.geospatialConfig);
|
this.collection.geospatialConfig(updatedCollection.geospatialConfig);
|
||||||
});
|
}
|
||||||
|
);
|
||||||
|
|
||||||
promises.push(updateCollectionPromise);
|
promises.push(updateCollectionPromise);
|
||||||
}
|
}
|
||||||
|
@ -1147,48 +1152,46 @@ export default class SettingsTab extends TabsBase implements ViewModels.WaitsFor
|
||||||
throughput: newThroughput,
|
throughput: newThroughput,
|
||||||
offerIsRUPerMinuteThroughputEnabled: isRUPerMinuteThroughputEnabled
|
offerIsRUPerMinuteThroughputEnabled: isRUPerMinuteThroughputEnabled
|
||||||
};
|
};
|
||||||
const updateOfferBeyondLimitPromise: Q.Promise<void> = this.documentClientUtility
|
const updateOfferBeyondLimitPromise: Q.Promise<void> = updateOfferThroughputBeyondLimit(requestPayload).then(
|
||||||
.updateOfferThroughputBeyondLimit(requestPayload)
|
() => {
|
||||||
.then(
|
this.collection.offer().content.offerThroughput = originalThroughputValue;
|
||||||
() => {
|
this.throughput(originalThroughputValue);
|
||||||
this.collection.offer().content.offerThroughput = originalThroughputValue;
|
this.notificationStatusInfo(
|
||||||
this.throughput(originalThroughputValue);
|
throughputApplyDelayedMessage(
|
||||||
this.notificationStatusInfo(
|
this.isAutoPilotSelected(),
|
||||||
throughputApplyDelayedMessage(
|
originalThroughputValue,
|
||||||
this.isAutoPilotSelected(),
|
this._getThroughputUnit(),
|
||||||
originalThroughputValue,
|
this.collection.databaseId,
|
||||||
this._getThroughputUnit(),
|
this.collection.id(),
|
||||||
this.collection.databaseId,
|
newThroughput
|
||||||
this.collection.id(),
|
)
|
||||||
newThroughput
|
);
|
||||||
)
|
this.throughput.valueHasMutated(); // force component re-render
|
||||||
);
|
},
|
||||||
this.throughput.valueHasMutated(); // force component re-render
|
(error: any) => {
|
||||||
},
|
TelemetryProcessor.traceFailure(
|
||||||
(error: any) => {
|
Action.UpdateSettings,
|
||||||
TelemetryProcessor.traceFailure(
|
{
|
||||||
Action.UpdateSettings,
|
databaseAccountName: this.container.databaseAccount().name,
|
||||||
{
|
databaseName: this.collection && this.collection.databaseId,
|
||||||
databaseAccountName: this.container.databaseAccount().name,
|
collectionName: this.collection && this.collection.id(),
|
||||||
databaseName: this.collection && this.collection.databaseId,
|
defaultExperience: this.container.defaultExperience(),
|
||||||
collectionName: this.collection && this.collection.id(),
|
dataExplorerArea: Constants.Areas.Tab,
|
||||||
defaultExperience: this.container.defaultExperience(),
|
tabTitle: this.tabTitle(),
|
||||||
dataExplorerArea: Constants.Areas.Tab,
|
error: error
|
||||||
tabTitle: this.tabTitle(),
|
},
|
||||||
error: error
|
startKey
|
||||||
},
|
);
|
||||||
startKey
|
}
|
||||||
);
|
);
|
||||||
}
|
|
||||||
);
|
|
||||||
promises.push(updateOfferBeyondLimitPromise);
|
promises.push(updateOfferBeyondLimitPromise);
|
||||||
} else {
|
} else {
|
||||||
const updateOfferPromise = this.documentClientUtility
|
const updateOfferPromise = updateOffer(this.collection.offer(), newOffer, headerOptions).then(
|
||||||
.updateOffer(this.collection.offer(), newOffer, headerOptions)
|
(updatedOffer: DataModels.Offer) => {
|
||||||
.then((updatedOffer: DataModels.Offer) => {
|
|
||||||
this.collection.offer(updatedOffer);
|
this.collection.offer(updatedOffer);
|
||||||
this.collection.offer.valueHasMutated();
|
this.collection.offer.valueHasMutated();
|
||||||
});
|
}
|
||||||
|
);
|
||||||
|
|
||||||
promises.push(updateOfferPromise);
|
promises.push(updateOfferPromise);
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@ import ScriptTabBase from "./ScriptTabBase";
|
||||||
import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
import 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";
|
||||||
|
|
||||||
enum ToggleState {
|
enum ToggleState {
|
||||||
Result = "result",
|
Result = "result",
|
||||||
|
@ -81,8 +82,7 @@ export default class StoredProcedureTab extends ScriptTabBase implements ViewMod
|
||||||
dataExplorerArea: Constants.Areas.Tab,
|
dataExplorerArea: Constants.Areas.Tab,
|
||||||
tabTitle: this.tabTitle()
|
tabTitle: this.tabTitle()
|
||||||
});
|
});
|
||||||
return this.documentClientUtility
|
return updateStoredProcedure(this.collection, data)
|
||||||
.updateStoredProcedure(this.collection, data)
|
|
||||||
.then(
|
.then(
|
||||||
(updatedResource: DataModels.StoredProcedure) => {
|
(updatedResource: DataModels.StoredProcedure) => {
|
||||||
this.resource(updatedResource);
|
this.resource(updatedResource);
|
||||||
|
@ -240,8 +240,7 @@ export default class StoredProcedureTab extends ScriptTabBase implements ViewMod
|
||||||
tabTitle: this.tabTitle()
|
tabTitle: this.tabTitle()
|
||||||
});
|
});
|
||||||
|
|
||||||
return this.documentClientUtility
|
return createStoredProcedure(this.collection, resource)
|
||||||
.createStoredProcedure(this.collection, resource)
|
|
||||||
.then(
|
.then(
|
||||||
createdResource => {
|
createdResource => {
|
||||||
this.tabTitle(createdResource.id);
|
this.tabTitle(createdResource.id);
|
||||||
|
|
|
@ -7,13 +7,11 @@ import { RouteHandler } from "../../RouteHandlers/RouteHandler";
|
||||||
import { WaitsForTemplateViewModel } from "../WaitsForTemplateViewModel";
|
import { WaitsForTemplateViewModel } from "../WaitsForTemplateViewModel";
|
||||||
import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
||||||
import ThemeUtility from "../../Common/ThemeUtility";
|
import ThemeUtility from "../../Common/ThemeUtility";
|
||||||
import DocumentClientUtilityBase from "../../Common/DocumentClientUtilityBase";
|
|
||||||
import Explorer from "../Explorer";
|
import Explorer from "../Explorer";
|
||||||
|
|
||||||
// TODO: Use specific actions for logging telemetry data
|
// TODO: Use specific actions for logging telemetry data
|
||||||
export default class TabsBase extends WaitsForTemplateViewModel implements ViewModels.Tab {
|
export default class TabsBase extends WaitsForTemplateViewModel implements ViewModels.Tab {
|
||||||
public closeTabButton: ViewModels.Button;
|
public closeTabButton: ViewModels.Button;
|
||||||
public documentClientUtility: DocumentClientUtilityBase;
|
|
||||||
public node: ViewModels.TreeNode;
|
public node: ViewModels.TreeNode;
|
||||||
public collection: ViewModels.CollectionBase;
|
public collection: ViewModels.CollectionBase;
|
||||||
public database: ViewModels.Database;
|
public database: ViewModels.Database;
|
||||||
|
@ -39,7 +37,6 @@ export default class TabsBase extends WaitsForTemplateViewModel implements ViewM
|
||||||
const id = new Date().getTime().toString();
|
const id = new Date().getTime().toString();
|
||||||
|
|
||||||
this._theme = ThemeUtility.getMonacoTheme(options.theme);
|
this._theme = ThemeUtility.getMonacoTheme(options.theme);
|
||||||
this.documentClientUtility = options.documentClientUtility;
|
|
||||||
this.node = options.node;
|
this.node = options.node;
|
||||||
this.collection = options.collection;
|
this.collection = options.collection;
|
||||||
this.database = options.database;
|
this.database = options.database;
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import * as ko from "knockout";
|
import * as ko from "knockout";
|
||||||
import * as ViewModels from "../../Contracts/ViewModels";
|
import * as ViewModels from "../../Contracts/ViewModels";
|
||||||
import { TabsManager } from "./TabsManager";
|
import { TabsManager } from "./TabsManager";
|
||||||
import DocumentClientUtilityBase from "../../Common/DocumentClientUtilityBase";
|
|
||||||
import DocumentsTab from "./DocumentsTab";
|
import DocumentsTab from "./DocumentsTab";
|
||||||
import Explorer from "../Explorer";
|
import Explorer from "../Explorer";
|
||||||
import QueryTab from "./QueryTab";
|
import QueryTab from "./QueryTab";
|
||||||
|
@ -15,7 +14,7 @@ describe("Tabs manager tests", () => {
|
||||||
let documentsTab: DocumentsTab;
|
let documentsTab: DocumentsTab;
|
||||||
|
|
||||||
beforeAll(() => {
|
beforeAll(() => {
|
||||||
explorer = new Explorer({ documentClientUtility: undefined, notificationsClient: undefined, isEmulator: false });
|
explorer = new Explorer({ notificationsClient: undefined, isEmulator: false });
|
||||||
explorer.databaseAccount = ko.observable<ViewModels.DatabaseAccount>({
|
explorer.databaseAccount = ko.observable<ViewModels.DatabaseAccount>({
|
||||||
id: "test",
|
id: "test",
|
||||||
name: "test",
|
name: "test",
|
||||||
|
@ -49,7 +48,6 @@ describe("Tabs manager tests", () => {
|
||||||
database,
|
database,
|
||||||
title: "",
|
title: "",
|
||||||
tabPath: "",
|
tabPath: "",
|
||||||
documentClientUtility: explorer.documentClientUtility,
|
|
||||||
selfLink: "",
|
selfLink: "",
|
||||||
isActive: ko.observable<boolean>(false),
|
isActive: ko.observable<boolean>(false),
|
||||||
hashLocation: "",
|
hashLocation: "",
|
||||||
|
@ -63,7 +61,6 @@ describe("Tabs manager tests", () => {
|
||||||
collection,
|
collection,
|
||||||
title: "",
|
title: "",
|
||||||
tabPath: "",
|
tabPath: "",
|
||||||
documentClientUtility: new DocumentClientUtilityBase(),
|
|
||||||
selfLink: "",
|
selfLink: "",
|
||||||
hashLocation: "",
|
hashLocation: "",
|
||||||
isActive: ko.observable<boolean>(false),
|
isActive: ko.observable<boolean>(false),
|
||||||
|
|
|
@ -7,6 +7,7 @@ import ScriptTabBase from "./ScriptTabBase";
|
||||||
import editable from "../../Common/EditableUtility";
|
import editable from "../../Common/EditableUtility";
|
||||||
import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
||||||
import Trigger from "../Tree/Trigger";
|
import Trigger from "../Tree/Trigger";
|
||||||
|
import { createTrigger, updateTrigger } from "../../Common/DocumentClientUtilityBase";
|
||||||
|
|
||||||
export default class TriggerTab extends ScriptTabBase implements ViewModels.TriggerTab {
|
export default class TriggerTab extends ScriptTabBase implements ViewModels.TriggerTab {
|
||||||
public collection: ViewModels.Collection;
|
public collection: ViewModels.Collection;
|
||||||
|
@ -41,8 +42,7 @@ export default class TriggerTab extends ScriptTabBase implements ViewModels.Trig
|
||||||
tabTitle: this.tabTitle()
|
tabTitle: this.tabTitle()
|
||||||
});
|
});
|
||||||
|
|
||||||
return this.documentClientUtility
|
return updateTrigger(this.collection, data)
|
||||||
.updateTrigger(this.collection, data)
|
|
||||||
.then(
|
.then(
|
||||||
(createdResource: DataModels.Trigger) => {
|
(createdResource: DataModels.Trigger) => {
|
||||||
this.resource(createdResource);
|
this.resource(createdResource);
|
||||||
|
@ -119,8 +119,7 @@ export default class TriggerTab extends ScriptTabBase implements ViewModels.Trig
|
||||||
tabTitle: this.tabTitle()
|
tabTitle: this.tabTitle()
|
||||||
});
|
});
|
||||||
|
|
||||||
return this.documentClientUtility
|
return createTrigger(this.collection, resource)
|
||||||
.createTrigger(this.collection, resource)
|
|
||||||
.then(
|
.then(
|
||||||
(createdResource: DataModels.Trigger) => {
|
(createdResource: DataModels.Trigger) => {
|
||||||
this.tabTitle(createdResource.id);
|
this.tabTitle(createdResource.id);
|
||||||
|
|
|
@ -6,6 +6,7 @@ import { Action } from "../../Shared/Telemetry/TelemetryConstants";
|
||||||
import ScriptTabBase from "./ScriptTabBase";
|
import ScriptTabBase from "./ScriptTabBase";
|
||||||
import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
||||||
import UserDefinedFunction from "../Tree/UserDefinedFunction";
|
import UserDefinedFunction from "../Tree/UserDefinedFunction";
|
||||||
|
import { createUserDefinedFunction, updateUserDefinedFunction } from "../../Common/DocumentClientUtilityBase";
|
||||||
|
|
||||||
export default class UserDefinedFunctionTab extends ScriptTabBase implements ViewModels.UserDefinedFunctionTab {
|
export default class UserDefinedFunctionTab extends ScriptTabBase implements ViewModels.UserDefinedFunctionTab {
|
||||||
public collection: ViewModels.Collection;
|
public collection: ViewModels.Collection;
|
||||||
|
@ -34,8 +35,7 @@ export default class UserDefinedFunctionTab extends ScriptTabBase implements Vie
|
||||||
tabTitle: this.tabTitle()
|
tabTitle: this.tabTitle()
|
||||||
});
|
});
|
||||||
|
|
||||||
return this.documentClientUtility
|
return updateUserDefinedFunction(this.collection, data)
|
||||||
.updateUserDefinedFunction(this.collection, data)
|
|
||||||
.then(
|
.then(
|
||||||
(createdResource: DataModels.UserDefinedFunction) => {
|
(createdResource: DataModels.UserDefinedFunction) => {
|
||||||
this.resource(createdResource);
|
this.resource(createdResource);
|
||||||
|
@ -104,8 +104,7 @@ export default class UserDefinedFunctionTab extends ScriptTabBase implements Vie
|
||||||
tabTitle: this.tabTitle()
|
tabTitle: this.tabTitle()
|
||||||
});
|
});
|
||||||
|
|
||||||
return this.documentClientUtility
|
return createUserDefinedFunction(this.collection, resource)
|
||||||
.createUserDefinedFunction(this.collection, resource)
|
|
||||||
.then(
|
.then(
|
||||||
(createdResource: DataModels.UserDefinedFunction) => {
|
(createdResource: DataModels.UserDefinedFunction) => {
|
||||||
this.tabTitle(createdResource.id);
|
this.tabTitle(createdResource.id);
|
||||||
|
|
|
@ -33,6 +33,15 @@ import Trigger from "./Trigger";
|
||||||
import UserDefinedFunction from "./UserDefinedFunction";
|
import UserDefinedFunction from "./UserDefinedFunction";
|
||||||
import { config } from "../../Config";
|
import { config } from "../../Config";
|
||||||
import Explorer from "../Explorer";
|
import Explorer from "../Explorer";
|
||||||
|
import {
|
||||||
|
createDocument,
|
||||||
|
readTriggers,
|
||||||
|
readUserDefinedFunctions,
|
||||||
|
readStoredProcedures,
|
||||||
|
readCollectionQuotaInfo,
|
||||||
|
readOffer,
|
||||||
|
readOffers
|
||||||
|
} from "../../Common/DocumentClientUtilityBase";
|
||||||
|
|
||||||
export default class Collection implements ViewModels.Collection {
|
export default class Collection implements ViewModels.Collection {
|
||||||
public nodeKind: string;
|
public nodeKind: string;
|
||||||
|
@ -306,7 +315,6 @@ export default class Collection implements ViewModels.Collection {
|
||||||
documentIds: ko.observableArray<DocumentId>([]),
|
documentIds: ko.observableArray<DocumentId>([]),
|
||||||
tabKind: ViewModels.CollectionTabKind.Documents,
|
tabKind: ViewModels.CollectionTabKind.Documents,
|
||||||
title: "Items",
|
title: "Items",
|
||||||
documentClientUtility: this.container.documentClientUtility,
|
|
||||||
|
|
||||||
selfLink: this.self,
|
selfLink: this.self,
|
||||||
isActive: ko.observable<boolean>(false),
|
isActive: ko.observable<boolean>(false),
|
||||||
|
@ -358,7 +366,6 @@ export default class Collection implements ViewModels.Collection {
|
||||||
conflictIds: ko.observableArray<ConflictId>([]),
|
conflictIds: ko.observableArray<ConflictId>([]),
|
||||||
tabKind: ViewModels.CollectionTabKind.Conflicts,
|
tabKind: ViewModels.CollectionTabKind.Conflicts,
|
||||||
title: "Conflicts",
|
title: "Conflicts",
|
||||||
documentClientUtility: this.container.documentClientUtility,
|
|
||||||
|
|
||||||
selfLink: this.self,
|
selfLink: this.self,
|
||||||
isActive: ko.observable<boolean>(false),
|
isActive: ko.observable<boolean>(false),
|
||||||
|
@ -419,7 +426,7 @@ export default class Collection implements ViewModels.Collection {
|
||||||
tabKind: ViewModels.CollectionTabKind.QueryTables,
|
tabKind: ViewModels.CollectionTabKind.QueryTables,
|
||||||
title: title,
|
title: title,
|
||||||
tabPath: "",
|
tabPath: "",
|
||||||
documentClientUtility: this.container.documentClientUtility,
|
|
||||||
collection: this,
|
collection: this,
|
||||||
|
|
||||||
node: this,
|
node: this,
|
||||||
|
@ -472,7 +479,7 @@ export default class Collection implements ViewModels.Collection {
|
||||||
node: this,
|
node: this,
|
||||||
title: title,
|
title: title,
|
||||||
tabPath: "",
|
tabPath: "",
|
||||||
documentClientUtility: this.container.documentClientUtility,
|
|
||||||
collection: this,
|
collection: this,
|
||||||
selfLink: this.self,
|
selfLink: this.self,
|
||||||
masterKey: CosmosClient.masterKey() || "",
|
masterKey: CosmosClient.masterKey() || "",
|
||||||
|
@ -527,7 +534,7 @@ export default class Collection implements ViewModels.Collection {
|
||||||
tabKind: ViewModels.CollectionTabKind.Documents,
|
tabKind: ViewModels.CollectionTabKind.Documents,
|
||||||
title: "Documents",
|
title: "Documents",
|
||||||
tabPath: "",
|
tabPath: "",
|
||||||
documentClientUtility: this.container.documentClientUtility,
|
|
||||||
collection: this,
|
collection: this,
|
||||||
|
|
||||||
node: this,
|
node: this,
|
||||||
|
@ -580,7 +587,7 @@ export default class Collection implements ViewModels.Collection {
|
||||||
tabKind: ViewModels.CollectionTabKind.Settings,
|
tabKind: ViewModels.CollectionTabKind.Settings,
|
||||||
title: !this.offer() ? "Settings" : "Scale & Settings",
|
title: !this.offer() ? "Settings" : "Scale & Settings",
|
||||||
tabPath: "",
|
tabPath: "",
|
||||||
documentClientUtility: this.container.documentClientUtility,
|
|
||||||
collection: this,
|
collection: this,
|
||||||
node: this,
|
node: this,
|
||||||
selfLink: this.self,
|
selfLink: this.self,
|
||||||
|
@ -645,10 +652,8 @@ export default class Collection implements ViewModels.Collection {
|
||||||
defaultExperience: this.container.defaultExperience()
|
defaultExperience: this.container.defaultExperience()
|
||||||
});
|
});
|
||||||
// TODO: Use the collection entity cache to get quota info
|
// TODO: Use the collection entity cache to get quota info
|
||||||
const quotaInfoPromise: Q.Promise<DataModels.CollectionQuotaInfo> = this.container.documentClientUtility.readCollectionQuotaInfo(
|
const quotaInfoPromise: Q.Promise<DataModels.CollectionQuotaInfo> = readCollectionQuotaInfo(this);
|
||||||
this
|
const offerInfoPromise: Q.Promise<DataModels.Offer[]> = readOffers();
|
||||||
);
|
|
||||||
const offerInfoPromise: Q.Promise<DataModels.Offer[]> = this.container.documentClientUtility.readOffers();
|
|
||||||
Q.all([quotaInfoPromise, offerInfoPromise]).then(
|
Q.all([quotaInfoPromise, offerInfoPromise]).then(
|
||||||
() => {
|
() => {
|
||||||
this.container.isRefreshingExplorer(false);
|
this.container.isRefreshingExplorer(false);
|
||||||
|
@ -675,41 +680,39 @@ export default class Collection implements ViewModels.Collection {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.container.documentClientUtility
|
readOffer(collectionOffer).then((offerDetail: DataModels.OfferWithHeaders) => {
|
||||||
.readOffer(collectionOffer)
|
if (OfferUtils.isNotOfferV1(collectionOffer)) {
|
||||||
.then((offerDetail: DataModels.OfferWithHeaders) => {
|
const offerThroughputInfo: DataModels.OfferThroughputInfo = {
|
||||||
if (OfferUtils.isNotOfferV1(collectionOffer)) {
|
minimumRUForCollection:
|
||||||
const offerThroughputInfo: DataModels.OfferThroughputInfo = {
|
offerDetail.content &&
|
||||||
minimumRUForCollection:
|
offerDetail.content.collectionThroughputInfo &&
|
||||||
offerDetail.content &&
|
offerDetail.content.collectionThroughputInfo.minimumRUForCollection,
|
||||||
offerDetail.content.collectionThroughputInfo &&
|
numPhysicalPartitions:
|
||||||
offerDetail.content.collectionThroughputInfo.minimumRUForCollection,
|
offerDetail.content &&
|
||||||
numPhysicalPartitions:
|
offerDetail.content.collectionThroughputInfo &&
|
||||||
offerDetail.content &&
|
offerDetail.content.collectionThroughputInfo.numPhysicalPartitions
|
||||||
offerDetail.content.collectionThroughputInfo &&
|
};
|
||||||
offerDetail.content.collectionThroughputInfo.numPhysicalPartitions
|
|
||||||
};
|
|
||||||
|
|
||||||
collectionOffer.content.collectionThroughputInfo = offerThroughputInfo;
|
collectionOffer.content.collectionThroughputInfo = offerThroughputInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
(collectionOffer as DataModels.OfferWithHeaders).headers = offerDetail.headers;
|
(collectionOffer as DataModels.OfferWithHeaders).headers = offerDetail.headers;
|
||||||
this.offer(collectionOffer);
|
this.offer(collectionOffer);
|
||||||
this.offer.valueHasMutated();
|
this.offer.valueHasMutated();
|
||||||
this.quotaInfo(quotaInfo);
|
this.quotaInfo(quotaInfo);
|
||||||
TelemetryProcessor.traceSuccess(
|
TelemetryProcessor.traceSuccess(
|
||||||
Action.LoadOffers,
|
Action.LoadOffers,
|
||||||
{
|
{
|
||||||
databaseAccountName: this.container.databaseAccount().name,
|
databaseAccountName: this.container.databaseAccount().name,
|
||||||
databaseName: this.databaseId,
|
databaseName: this.databaseId,
|
||||||
collectionName: this.id(),
|
collectionName: this.id(),
|
||||||
defaultExperience: this.container.defaultExperience(),
|
defaultExperience: this.container.defaultExperience(),
|
||||||
offerVersion: collectionOffer && collectionOffer.offerVersion
|
offerVersion: collectionOffer && collectionOffer.offerVersion
|
||||||
},
|
},
|
||||||
startKey
|
startKey
|
||||||
);
|
);
|
||||||
deferred.resolve();
|
deferred.resolve();
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
(error: any) => {
|
(error: any) => {
|
||||||
this.container.isRefreshingExplorer(false);
|
this.container.isRefreshingExplorer(false);
|
||||||
|
@ -747,7 +750,6 @@ export default class Collection implements ViewModels.Collection {
|
||||||
tabKind: ViewModels.CollectionTabKind.Query,
|
tabKind: ViewModels.CollectionTabKind.Query,
|
||||||
title: title,
|
title: title,
|
||||||
tabPath: "",
|
tabPath: "",
|
||||||
documentClientUtility: this.container.documentClientUtility,
|
|
||||||
collection: this,
|
collection: this,
|
||||||
node: this,
|
node: this,
|
||||||
selfLink: this.self,
|
selfLink: this.self,
|
||||||
|
@ -780,7 +782,6 @@ export default class Collection implements ViewModels.Collection {
|
||||||
tabKind: ViewModels.CollectionTabKind.Query,
|
tabKind: ViewModels.CollectionTabKind.Query,
|
||||||
title: title,
|
title: title,
|
||||||
tabPath: "",
|
tabPath: "",
|
||||||
documentClientUtility: this.container.documentClientUtility,
|
|
||||||
collection: this,
|
collection: this,
|
||||||
node: this,
|
node: this,
|
||||||
selfLink: this.self,
|
selfLink: this.self,
|
||||||
|
@ -813,7 +814,6 @@ export default class Collection implements ViewModels.Collection {
|
||||||
node: this,
|
node: this,
|
||||||
title: title,
|
title: title,
|
||||||
tabPath: "",
|
tabPath: "",
|
||||||
documentClientUtility: this.container.documentClientUtility,
|
|
||||||
collection: this,
|
collection: this,
|
||||||
selfLink: this.self,
|
selfLink: this.self,
|
||||||
masterKey: CosmosClient.masterKey() || "",
|
masterKey: CosmosClient.masterKey() || "",
|
||||||
|
@ -836,7 +836,6 @@ export default class Collection implements ViewModels.Collection {
|
||||||
tabKind: ViewModels.CollectionTabKind.MongoShell,
|
tabKind: ViewModels.CollectionTabKind.MongoShell,
|
||||||
title: "Shell " + id,
|
title: "Shell " + id,
|
||||||
tabPath: "",
|
tabPath: "",
|
||||||
documentClientUtility: this.container.documentClientUtility,
|
|
||||||
collection: this,
|
collection: this,
|
||||||
node: this,
|
node: this,
|
||||||
hashLocation: `${Constants.HashRoutePrefixes.collectionsWithIds(this.databaseId, this.id())}/mongoShell`,
|
hashLocation: `${Constants.HashRoutePrefixes.collectionsWithIds(this.databaseId, this.id())}/mongoShell`,
|
||||||
|
@ -1075,40 +1074,34 @@ export default class Collection implements ViewModels.Collection {
|
||||||
}
|
}
|
||||||
|
|
||||||
public loadStoredProcedures(): Q.Promise<any> {
|
public loadStoredProcedures(): Q.Promise<any> {
|
||||||
return this.container.documentClientUtility
|
return readStoredProcedures(this).then((storedProcedures: DataModels.StoredProcedure[]) => {
|
||||||
.readStoredProcedures(this)
|
const storedProceduresNodes: ViewModels.TreeNode[] = storedProcedures.map(
|
||||||
.then((storedProcedures: DataModels.StoredProcedure[]) => {
|
storedProcedure => new StoredProcedure(this.container, this, storedProcedure)
|
||||||
const storedProceduresNodes: ViewModels.TreeNode[] = storedProcedures.map(
|
);
|
||||||
storedProcedure => new StoredProcedure(this.container, this, storedProcedure)
|
const otherNodes = this.children().filter(node => node.nodeKind !== "StoredProcedure");
|
||||||
);
|
const allNodes = otherNodes.concat(storedProceduresNodes);
|
||||||
const otherNodes = this.children().filter(node => node.nodeKind !== "StoredProcedure");
|
this.children(allNodes);
|
||||||
const allNodes = otherNodes.concat(storedProceduresNodes);
|
});
|
||||||
this.children(allNodes);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public loadUserDefinedFunctions(): Q.Promise<any> {
|
public loadUserDefinedFunctions(): Q.Promise<any> {
|
||||||
return this.container.documentClientUtility
|
return readUserDefinedFunctions(this).then((userDefinedFunctions: DataModels.UserDefinedFunction[]) => {
|
||||||
.readUserDefinedFunctions(this)
|
const userDefinedFunctionsNodes: ViewModels.TreeNode[] = userDefinedFunctions.map(
|
||||||
.then((userDefinedFunctions: DataModels.UserDefinedFunction[]) => {
|
udf => new UserDefinedFunction(this.container, this, udf)
|
||||||
const userDefinedFunctionsNodes: ViewModels.TreeNode[] = userDefinedFunctions.map(
|
);
|
||||||
udf => new UserDefinedFunction(this.container, this, udf)
|
const otherNodes = this.children().filter(node => node.nodeKind !== "UserDefinedFunction");
|
||||||
);
|
const allNodes = otherNodes.concat(userDefinedFunctionsNodes);
|
||||||
const otherNodes = this.children().filter(node => node.nodeKind !== "UserDefinedFunction");
|
this.children(allNodes);
|
||||||
const allNodes = otherNodes.concat(userDefinedFunctionsNodes);
|
});
|
||||||
this.children(allNodes);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public loadTriggers(): Q.Promise<any> {
|
public loadTriggers(): Q.Promise<any> {
|
||||||
return this.container.documentClientUtility
|
return readTriggers(this, null /*options*/).then((triggers: DataModels.Trigger[]) => {
|
||||||
.readTriggers(this, null /*options*/)
|
const triggerNodes: ViewModels.TreeNode[] = triggers.map(trigger => new Trigger(this.container, this, trigger));
|
||||||
.then((triggers: DataModels.Trigger[]) => {
|
const otherNodes = this.children().filter(node => node.nodeKind !== "Trigger");
|
||||||
const triggerNodes: ViewModels.TreeNode[] = triggers.map(trigger => new Trigger(this.container, this, trigger));
|
const allNodes = otherNodes.concat(triggerNodes);
|
||||||
const otherNodes = this.children().filter(node => node.nodeKind !== "Trigger");
|
this.children(allNodes);
|
||||||
const allNodes = otherNodes.concat(triggerNodes);
|
});
|
||||||
this.children(allNodes);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public onDragOver(source: Collection, event: { originalEvent: DragEvent }) {
|
public onDragOver(source: Collection, event: { originalEvent: DragEvent }) {
|
||||||
|
@ -1269,7 +1262,7 @@ export default class Collection implements ViewModels.Collection {
|
||||||
const promises: Array<Q.Promise<any>> = [];
|
const promises: Array<Q.Promise<any>> = [];
|
||||||
|
|
||||||
const triggerCreateDocument: (documentContent: any) => Q.Promise<any> = (documentContent: any) => {
|
const triggerCreateDocument: (documentContent: any) => Q.Promise<any> = (documentContent: any) => {
|
||||||
return this.container.documentClientUtility.createDocument(this, documentContent).then(
|
return createDocument(this, documentContent).then(
|
||||||
doc => {
|
doc => {
|
||||||
record.numSucceeded++;
|
record.numSucceeded++;
|
||||||
return Q.resolve();
|
return Q.resolve();
|
||||||
|
|
|
@ -6,6 +6,7 @@ import * as DataModels from "../../Contracts/DataModels";
|
||||||
import * as ViewModels from "../../Contracts/ViewModels";
|
import * as ViewModels from "../../Contracts/ViewModels";
|
||||||
import { extractPartitionKey } from "@azure/cosmos";
|
import { extractPartitionKey } from "@azure/cosmos";
|
||||||
import ConflictsTab from "../Tabs/ConflictsTab";
|
import ConflictsTab from "../Tabs/ConflictsTab";
|
||||||
|
import { readDocument } from "../../Common/DocumentClientUtilityBase";
|
||||||
|
|
||||||
export default class ConflictId implements ViewModels.ConflictId {
|
export default class ConflictId implements ViewModels.ConflictId {
|
||||||
public container: ConflictsTab;
|
public container: ConflictsTab;
|
||||||
|
@ -68,33 +69,31 @@ export default class ConflictId implements ViewModels.ConflictId {
|
||||||
}
|
}
|
||||||
|
|
||||||
this.container.loadingConflictData(true);
|
this.container.loadingConflictData(true);
|
||||||
return conflictsTab.documentClientUtility
|
return readDocument(this.container.collection, this.buildDocumentIdFromConflict(this.partitionKeyValue)).then(
|
||||||
.readDocument(this.container.collection, this.buildDocumentIdFromConflict(this.partitionKeyValue))
|
(currentDocumentContent: any) => {
|
||||||
.then(
|
this.container.loadingConflictData(false);
|
||||||
(currentDocumentContent: any) => {
|
if (this.operationType === Constants.ConflictOperationType.Replace) {
|
||||||
this.container.loadingConflictData(false);
|
this.container.initDocumentEditorForReplace(this, this.content, currentDocumentContent);
|
||||||
if (this.operationType === Constants.ConflictOperationType.Replace) {
|
} else {
|
||||||
this.container.initDocumentEditorForReplace(this, this.content, currentDocumentContent);
|
this.container.initDocumentEditorForDelete(this, currentDocumentContent);
|
||||||
} else {
|
|
||||||
this.container.initDocumentEditorForDelete(this, currentDocumentContent);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
(reason: any) => {
|
|
||||||
this.container.loadingConflictData(false);
|
|
||||||
|
|
||||||
// Document could be deleted
|
|
||||||
if (
|
|
||||||
reason &&
|
|
||||||
reason.code === Constants.HttpStatusCodes.NotFound &&
|
|
||||||
this.operationType === Constants.ConflictOperationType.Delete
|
|
||||||
) {
|
|
||||||
this.container.initDocumentEditorForNoOp(this);
|
|
||||||
return Q();
|
|
||||||
}
|
|
||||||
|
|
||||||
return Q.reject(reason);
|
|
||||||
}
|
}
|
||||||
);
|
},
|
||||||
|
(reason: any) => {
|
||||||
|
this.container.loadingConflictData(false);
|
||||||
|
|
||||||
|
// Document could be deleted
|
||||||
|
if (
|
||||||
|
reason &&
|
||||||
|
reason.code === Constants.HttpStatusCodes.NotFound &&
|
||||||
|
this.operationType === Constants.ConflictOperationType.Delete
|
||||||
|
) {
|
||||||
|
this.container.initDocumentEditorForNoOp(this);
|
||||||
|
return Q();
|
||||||
|
}
|
||||||
|
|
||||||
|
return Q.reject(reason);
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public getPartitionKeyValueAsString(): string {
|
public getPartitionKeyValueAsString(): string {
|
||||||
|
|
|
@ -12,6 +12,7 @@ import { 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";
|
||||||
import Explorer from "../Explorer";
|
import Explorer from "../Explorer";
|
||||||
|
import { readCollections, readOffers, readOffer } from "../../Common/DocumentClientUtilityBase";
|
||||||
|
|
||||||
export default class Database implements ViewModels.Database {
|
export default class Database implements ViewModels.Database {
|
||||||
public nodeKind: string;
|
public nodeKind: string;
|
||||||
|
@ -71,7 +72,6 @@ export default class Database implements ViewModels.Database {
|
||||||
tabKind: ViewModels.CollectionTabKind.DatabaseSettings,
|
tabKind: ViewModels.CollectionTabKind.DatabaseSettings,
|
||||||
title: "Scale",
|
title: "Scale",
|
||||||
tabPath: "",
|
tabPath: "",
|
||||||
documentClientUtility: this.container.documentClientUtility,
|
|
||||||
node: this,
|
node: this,
|
||||||
rid: this.rid,
|
rid: this.rid,
|
||||||
database: this,
|
database: this,
|
||||||
|
@ -137,7 +137,7 @@ export default class Database implements ViewModels.Database {
|
||||||
defaultExperience: this.container.defaultExperience()
|
defaultExperience: this.container.defaultExperience()
|
||||||
});
|
});
|
||||||
|
|
||||||
const offerInfoPromise: Q.Promise<DataModels.Offer[]> = this.container.documentClientUtility.readOffers();
|
const offerInfoPromise: Q.Promise<DataModels.Offer[]> = readOffers();
|
||||||
Q.all([offerInfoPromise]).then(
|
Q.all([offerInfoPromise]).then(
|
||||||
() => {
|
() => {
|
||||||
this.container.isRefreshingExplorer(false);
|
this.container.isRefreshingExplorer(false);
|
||||||
|
@ -146,35 +146,33 @@ export default class Database implements ViewModels.Database {
|
||||||
offerInfoPromise.valueOf(),
|
offerInfoPromise.valueOf(),
|
||||||
databaseDataModel
|
databaseDataModel
|
||||||
);
|
);
|
||||||
this.container.documentClientUtility
|
readOffer(databaseOffer).then((offerDetail: DataModels.OfferWithHeaders) => {
|
||||||
.readOffer(databaseOffer)
|
const offerThroughputInfo: DataModels.OfferThroughputInfo = {
|
||||||
.then((offerDetail: DataModels.OfferWithHeaders) => {
|
minimumRUForCollection:
|
||||||
const offerThroughputInfo: DataModels.OfferThroughputInfo = {
|
offerDetail.content &&
|
||||||
minimumRUForCollection:
|
offerDetail.content.collectionThroughputInfo &&
|
||||||
offerDetail.content &&
|
offerDetail.content.collectionThroughputInfo.minimumRUForCollection,
|
||||||
offerDetail.content.collectionThroughputInfo &&
|
numPhysicalPartitions:
|
||||||
offerDetail.content.collectionThroughputInfo.minimumRUForCollection,
|
offerDetail.content &&
|
||||||
numPhysicalPartitions:
|
offerDetail.content.collectionThroughputInfo &&
|
||||||
offerDetail.content &&
|
offerDetail.content.collectionThroughputInfo.numPhysicalPartitions
|
||||||
offerDetail.content.collectionThroughputInfo &&
|
};
|
||||||
offerDetail.content.collectionThroughputInfo.numPhysicalPartitions
|
|
||||||
};
|
|
||||||
|
|
||||||
databaseOffer.content.collectionThroughputInfo = offerThroughputInfo;
|
databaseOffer.content.collectionThroughputInfo = offerThroughputInfo;
|
||||||
(databaseOffer as DataModels.OfferWithHeaders).headers = offerDetail.headers;
|
(databaseOffer as DataModels.OfferWithHeaders).headers = offerDetail.headers;
|
||||||
this.offer(databaseOffer);
|
this.offer(databaseOffer);
|
||||||
this.offer.valueHasMutated();
|
this.offer.valueHasMutated();
|
||||||
|
|
||||||
TelemetryProcessor.traceSuccess(
|
TelemetryProcessor.traceSuccess(
|
||||||
Action.LoadOffers,
|
Action.LoadOffers,
|
||||||
{
|
{
|
||||||
databaseAccountName: this.container.databaseAccount().name,
|
databaseAccountName: this.container.databaseAccount().name,
|
||||||
defaultExperience: this.container.defaultExperience()
|
defaultExperience: this.container.defaultExperience()
|
||||||
},
|
},
|
||||||
startKey
|
startKey
|
||||||
);
|
);
|
||||||
deferred.resolve();
|
deferred.resolve();
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
(error: any) => {
|
(error: any) => {
|
||||||
this.container.isRefreshingExplorer(false);
|
this.container.isRefreshingExplorer(false);
|
||||||
|
@ -263,7 +261,7 @@ export default class Database implements ViewModels.Database {
|
||||||
let collectionVMs: Collection[] = [];
|
let collectionVMs: Collection[] = [];
|
||||||
let deferred: Q.Deferred<void> = Q.defer<void>();
|
let deferred: Q.Deferred<void> = Q.defer<void>();
|
||||||
|
|
||||||
this.container.documentClientUtility.readCollections(this).then(
|
readCollections(this).then(
|
||||||
(collections: DataModels.Collection[]) => {
|
(collections: DataModels.Collection[]) => {
|
||||||
let collectionsToAddVMPromises: Q.Promise<any>[] = [];
|
let collectionsToAddVMPromises: Q.Promise<any>[] = [];
|
||||||
let deltaCollections = this.getDeltaCollections(collections);
|
let deltaCollections = this.getDeltaCollections(collections);
|
||||||
|
|
|
@ -91,7 +91,6 @@ export default class ResourceTokenCollection implements ViewModels.CollectionBas
|
||||||
tabKind: ViewModels.CollectionTabKind.Query,
|
tabKind: ViewModels.CollectionTabKind.Query,
|
||||||
title: title,
|
title: title,
|
||||||
tabPath: "",
|
tabPath: "",
|
||||||
documentClientUtility: this.container.documentClientUtility,
|
|
||||||
collection: this,
|
collection: this,
|
||||||
node: this,
|
node: this,
|
||||||
selfLink: this.self,
|
selfLink: this.self,
|
||||||
|
@ -143,8 +142,6 @@ export default class ResourceTokenCollection implements ViewModels.CollectionBas
|
||||||
documentIds: ko.observableArray<DocumentId>([]),
|
documentIds: ko.observableArray<DocumentId>([]),
|
||||||
tabKind: ViewModels.CollectionTabKind.Documents,
|
tabKind: ViewModels.CollectionTabKind.Documents,
|
||||||
title: "Items",
|
title: "Items",
|
||||||
documentClientUtility: this.container.documentClientUtility,
|
|
||||||
|
|
||||||
selfLink: this.self,
|
selfLink: this.self,
|
||||||
isActive: ko.observable<boolean>(false),
|
isActive: ko.observable<boolean>(false),
|
||||||
collection: this,
|
collection: this,
|
||||||
|
|
|
@ -7,6 +7,7 @@ import { Action, ActionModifiers } from "../../Shared/Telemetry/TelemetryConstan
|
||||||
import StoredProcedureTab from "../Tabs/StoredProcedureTab";
|
import StoredProcedureTab from "../Tabs/StoredProcedureTab";
|
||||||
import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
||||||
import Explorer from "../Explorer";
|
import Explorer from "../Explorer";
|
||||||
|
import { deleteStoredProcedure, executeStoredProcedure } from "../../Common/DocumentClientUtilityBase";
|
||||||
|
|
||||||
const sampleStoredProcedureBody: string = `// SAMPLE STORED PROCEDURE
|
const sampleStoredProcedureBody: string = `// SAMPLE STORED PROCEDURE
|
||||||
function sample(prefix) {
|
function sample(prefix) {
|
||||||
|
@ -69,7 +70,6 @@ export default class StoredProcedure {
|
||||||
tabKind: ViewModels.CollectionTabKind.StoredProcedures,
|
tabKind: ViewModels.CollectionTabKind.StoredProcedures,
|
||||||
title: `New Stored Procedure ${id}`,
|
title: `New Stored Procedure ${id}`,
|
||||||
tabPath: `${source.databaseId}>${source.id()}>New Stored Procedure ${id}`,
|
tabPath: `${source.databaseId}>${source.id()}>New Stored Procedure ${id}`,
|
||||||
documentClientUtility: source.container.documentClientUtility,
|
|
||||||
collection: source,
|
collection: source,
|
||||||
node: source,
|
node: source,
|
||||||
hashLocation: `${Constants.HashRoutePrefixes.collectionsWithIds(source.databaseId, source.id())}/sproc`,
|
hashLocation: `${Constants.HashRoutePrefixes.collectionsWithIds(source.databaseId, source.id())}/sproc`,
|
||||||
|
@ -116,7 +116,6 @@ export default class StoredProcedure {
|
||||||
tabKind: ViewModels.CollectionTabKind.StoredProcedures,
|
tabKind: ViewModels.CollectionTabKind.StoredProcedures,
|
||||||
title: storedProcedureData.id,
|
title: storedProcedureData.id,
|
||||||
tabPath: `${this.collection.databaseId}>${this.collection.id()}>${storedProcedureData.id}`,
|
tabPath: `${this.collection.databaseId}>${this.collection.id()}>${storedProcedureData.id}`,
|
||||||
documentClientUtility: this.container.documentClientUtility,
|
|
||||||
collection: this.collection,
|
collection: this.collection,
|
||||||
node: this,
|
node: this,
|
||||||
hashLocation: `${Constants.HashRoutePrefixes.collectionsWithIds(
|
hashLocation: `${Constants.HashRoutePrefixes.collectionsWithIds(
|
||||||
|
@ -144,7 +143,7 @@ export default class StoredProcedure {
|
||||||
body: this.body()
|
body: this.body()
|
||||||
};
|
};
|
||||||
|
|
||||||
this.container.documentClientUtility.deleteStoredProcedure(this.collection, storedProcedureData).then(
|
deleteStoredProcedure(this.collection, storedProcedureData).then(
|
||||||
() => {
|
() => {
|
||||||
this.container.tabsManager.removeTabByComparator(
|
this.container.tabsManager.removeTabByComparator(
|
||||||
(tab: ViewModels.Tab) => tab.node && tab.node.rid === this.rid
|
(tab: ViewModels.Tab) => tab.node && tab.node.rid === this.rid
|
||||||
|
@ -163,8 +162,7 @@ export default class StoredProcedure {
|
||||||
const sprocTab: ViewModels.StoredProcedureTab = sprocTabs && sprocTabs.length > 0 && sprocTabs[0];
|
const sprocTab: ViewModels.StoredProcedureTab = sprocTabs && sprocTabs.length > 0 && sprocTabs[0];
|
||||||
sprocTab.isExecuting(true);
|
sprocTab.isExecuting(true);
|
||||||
this.container &&
|
this.container &&
|
||||||
this.container.documentClientUtility
|
executeStoredProcedure(this.collection, this, partitionKeyValue, params)
|
||||||
.executeStoredProcedure(this.collection, this, partitionKeyValue, params)
|
|
||||||
.then(
|
.then(
|
||||||
(result: any) => {
|
(result: any) => {
|
||||||
sprocTab.onExecuteSprocsResult(result, result.scriptLogs);
|
sprocTab.onExecuteSprocsResult(result, result.scriptLogs);
|
||||||
|
|
|
@ -6,6 +6,7 @@ import { Action, ActionModifiers } from "../../Shared/Telemetry/TelemetryConstan
|
||||||
import TriggerTab from "../Tabs/TriggerTab";
|
import TriggerTab from "../Tabs/TriggerTab";
|
||||||
import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
||||||
import Explorer from "../Explorer";
|
import Explorer from "../Explorer";
|
||||||
|
import { deleteTrigger } from "../../Common/DocumentClientUtilityBase";
|
||||||
|
|
||||||
export default class Trigger {
|
export default class Trigger {
|
||||||
public nodeKind: string;
|
public nodeKind: string;
|
||||||
|
@ -55,7 +56,6 @@ export default class Trigger {
|
||||||
tabKind: ViewModels.CollectionTabKind.Triggers,
|
tabKind: ViewModels.CollectionTabKind.Triggers,
|
||||||
title: `New Trigger ${id}`,
|
title: `New Trigger ${id}`,
|
||||||
tabPath: "",
|
tabPath: "",
|
||||||
documentClientUtility: source.container.documentClientUtility,
|
|
||||||
collection: source,
|
collection: source,
|
||||||
node: source,
|
node: source,
|
||||||
hashLocation: `${Constants.HashRoutePrefixes.collectionsWithIds(source.databaseId, source.id())}/trigger`,
|
hashLocation: `${Constants.HashRoutePrefixes.collectionsWithIds(source.databaseId, source.id())}/trigger`,
|
||||||
|
@ -94,7 +94,6 @@ export default class Trigger {
|
||||||
tabKind: ViewModels.CollectionTabKind.Triggers,
|
tabKind: ViewModels.CollectionTabKind.Triggers,
|
||||||
title: triggerData.id,
|
title: triggerData.id,
|
||||||
tabPath: "",
|
tabPath: "",
|
||||||
documentClientUtility: this.container.documentClientUtility,
|
|
||||||
collection: this.collection,
|
collection: this.collection,
|
||||||
node: this,
|
node: this,
|
||||||
hashLocation: `${Constants.HashRoutePrefixes.collectionsWithIds(
|
hashLocation: `${Constants.HashRoutePrefixes.collectionsWithIds(
|
||||||
|
@ -124,7 +123,7 @@ export default class Trigger {
|
||||||
triggerType: this.triggerType()
|
triggerType: this.triggerType()
|
||||||
};
|
};
|
||||||
|
|
||||||
this.container.documentClientUtility.deleteTrigger(this.collection, triggerData).then(
|
deleteTrigger(this.collection, triggerData).then(
|
||||||
() => {
|
() => {
|
||||||
this.container.tabsManager.removeTabByComparator(
|
this.container.tabsManager.removeTabByComparator(
|
||||||
(tab: ViewModels.Tab) => tab.node && tab.node.rid === this.rid
|
(tab: ViewModels.Tab) => tab.node && tab.node.rid === this.rid
|
||||||
|
|
|
@ -6,6 +6,7 @@ import { Action, ActionModifiers } from "../../Shared/Telemetry/TelemetryConstan
|
||||||
import UserDefinedFunctionTab from "../Tabs/UserDefinedFunctionTab";
|
import UserDefinedFunctionTab from "../Tabs/UserDefinedFunctionTab";
|
||||||
import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
||||||
import Explorer from "../Explorer";
|
import Explorer from "../Explorer";
|
||||||
|
import { deleteUserDefinedFunction } from "../../Common/DocumentClientUtilityBase";
|
||||||
|
|
||||||
export default class UserDefinedFunction {
|
export default class UserDefinedFunction {
|
||||||
public nodeKind: string;
|
public nodeKind: string;
|
||||||
|
@ -40,7 +41,6 @@ export default class UserDefinedFunction {
|
||||||
tabKind: ViewModels.CollectionTabKind.UserDefinedFunctions,
|
tabKind: ViewModels.CollectionTabKind.UserDefinedFunctions,
|
||||||
title: `New UDF ${id}`,
|
title: `New UDF ${id}`,
|
||||||
tabPath: "",
|
tabPath: "",
|
||||||
documentClientUtility: source.container.documentClientUtility,
|
|
||||||
collection: source,
|
collection: source,
|
||||||
node: source,
|
node: source,
|
||||||
hashLocation: `${Constants.HashRoutePrefixes.collectionsWithIds(source.databaseId, source.id())}/udf`,
|
hashLocation: `${Constants.HashRoutePrefixes.collectionsWithIds(source.databaseId, source.id())}/udf`,
|
||||||
|
@ -77,7 +77,6 @@ export default class UserDefinedFunction {
|
||||||
tabKind: ViewModels.CollectionTabKind.UserDefinedFunctions,
|
tabKind: ViewModels.CollectionTabKind.UserDefinedFunctions,
|
||||||
title: userDefinedFunctionData.id,
|
title: userDefinedFunctionData.id,
|
||||||
tabPath: "",
|
tabPath: "",
|
||||||
documentClientUtility: this.container.documentClientUtility,
|
|
||||||
collection: this.collection,
|
collection: this.collection,
|
||||||
node: this,
|
node: this,
|
||||||
hashLocation: `${Constants.HashRoutePrefixes.collectionsWithIds(
|
hashLocation: `${Constants.HashRoutePrefixes.collectionsWithIds(
|
||||||
|
@ -114,7 +113,7 @@ export default class UserDefinedFunction {
|
||||||
id: this.id(),
|
id: this.id(),
|
||||||
body: this.body()
|
body: this.body()
|
||||||
};
|
};
|
||||||
this.container.documentClientUtility.deleteUserDefinedFunction(this.collection, userDefinedFunctionData).then(
|
deleteUserDefinedFunction(this.collection, userDefinedFunctionData).then(
|
||||||
() => {
|
() => {
|
||||||
this.container.tabsManager.removeTabByComparator(
|
this.container.tabsManager.removeTabByComparator(
|
||||||
(tab: ViewModels.Tab) => tab.node && tab.node.rid === this.rid
|
(tab: ViewModels.Tab) => tab.node && tab.node.rid === this.rid
|
||||||
|
|
|
@ -3,15 +3,10 @@ import { AccountKind, TagNames, DefaultAccountExperience } from "../../Common/Co
|
||||||
import Explorer from "../../Explorer/Explorer";
|
import Explorer from "../../Explorer/Explorer";
|
||||||
|
|
||||||
import { NotificationsClient } from "./NotificationsClient";
|
import { NotificationsClient } from "./NotificationsClient";
|
||||||
import DocumentClientUtilityBase from "../../Common/DocumentClientUtilityBase";
|
|
||||||
|
|
||||||
export default class EmulatorExplorerFactory {
|
export default class EmulatorExplorerFactory {
|
||||||
public static createExplorer(): Explorer {
|
public static createExplorer(): Explorer {
|
||||||
DocumentClientUtilityBase;
|
|
||||||
const documentClientUtility: DocumentClientUtilityBase = new DocumentClientUtilityBase();
|
|
||||||
|
|
||||||
const explorer: Explorer = new Explorer({
|
const explorer: Explorer = new Explorer({
|
||||||
documentClientUtility: documentClientUtility,
|
|
||||||
notificationsClient: new NotificationsClient(),
|
notificationsClient: new NotificationsClient(),
|
||||||
isEmulator: true
|
isEmulator: true
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,13 +1,9 @@
|
||||||
import Explorer from "../../Explorer/Explorer";
|
import Explorer from "../../Explorer/Explorer";
|
||||||
import { NotificationsClient } from "./NotificationsClient";
|
import { NotificationsClient } from "./NotificationsClient";
|
||||||
import DocumentClientUtilityBase from "../../Common/DocumentClientUtilityBase";
|
|
||||||
|
|
||||||
export default class HostedExplorerFactory {
|
export default class HostedExplorerFactory {
|
||||||
public createExplorer(): Explorer {
|
public createExplorer(): Explorer {
|
||||||
var documentClientUtility = new DocumentClientUtilityBase();
|
|
||||||
|
|
||||||
const explorer = new Explorer({
|
const explorer = new Explorer({
|
||||||
documentClientUtility: documentClientUtility,
|
|
||||||
notificationsClient: new NotificationsClient(),
|
notificationsClient: new NotificationsClient(),
|
||||||
isEmulator: false
|
isEmulator: false
|
||||||
});
|
});
|
||||||
|
@ -17,8 +13,6 @@ export default class HostedExplorerFactory {
|
||||||
|
|
||||||
public static reInitializeDocumentClientUtilityForExplorer(explorer: Explorer): void {
|
public static reInitializeDocumentClientUtilityForExplorer(explorer: Explorer): void {
|
||||||
if (!!explorer) {
|
if (!!explorer) {
|
||||||
const documentClientUtility = new DocumentClientUtilityBase();
|
|
||||||
explorer.rebindDocumentClientUtility(documentClientUtility);
|
|
||||||
explorer.notificationConsoleData([]);
|
explorer.notificationConsoleData([]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +1,9 @@
|
||||||
import Explorer from "../../Explorer/Explorer";
|
import Explorer from "../../Explorer/Explorer";
|
||||||
|
|
||||||
import { NotificationsClient } from "./NotificationsClient";
|
import { NotificationsClient } from "./NotificationsClient";
|
||||||
import DocumentClientUtilityBase from "../../Common/DocumentClientUtilityBase";
|
|
||||||
|
|
||||||
export default class PortalExplorerFactory {
|
export default class PortalExplorerFactory {
|
||||||
public createExplorer(): Explorer {
|
public createExplorer(): Explorer {
|
||||||
var documentClientUtility = new DocumentClientUtilityBase();
|
|
||||||
|
|
||||||
var explorer = new Explorer({
|
var explorer = new Explorer({
|
||||||
documentClientUtility: documentClientUtility,
|
|
||||||
notificationsClient: new NotificationsClient(),
|
notificationsClient: new NotificationsClient(),
|
||||||
isEmulator: false
|
isEmulator: false
|
||||||
});
|
});
|
||||||
|
|
|
@ -10,7 +10,6 @@ describe("TabRouteHandler", () => {
|
||||||
|
|
||||||
beforeAll(() => {
|
beforeAll(() => {
|
||||||
(<any>window).dataExplorer = new Explorer({
|
(<any>window).dataExplorer = new Explorer({
|
||||||
documentClientUtility: null,
|
|
||||||
notificationsClient: null,
|
notificationsClient: null,
|
||||||
isEmulator: false
|
isEmulator: false
|
||||||
}); // create a mock to avoid null refs
|
}); // create a mock to avoid null refs
|
||||||
|
|
Loading…
Reference in New Issue