Migrate Delete Collection Panel to React (#628)
This commit is contained in:
parent
e8033f0bbc
commit
56f430ebd8
|
@ -121,8 +121,6 @@ src/Explorer/Panes/AddDatabasePane.ts
|
||||||
src/Explorer/Panes/BrowseQueriesPane.ts
|
src/Explorer/Panes/BrowseQueriesPane.ts
|
||||||
src/Explorer/Panes/CassandraAddCollectionPane.ts
|
src/Explorer/Panes/CassandraAddCollectionPane.ts
|
||||||
src/Explorer/Panes/ContextualPaneBase.ts
|
src/Explorer/Panes/ContextualPaneBase.ts
|
||||||
src/Explorer/Panes/DeleteCollectionConfirmationPane.test.ts
|
|
||||||
src/Explorer/Panes/DeleteCollectionConfirmationPane.ts
|
|
||||||
src/Explorer/Panes/DeleteDatabaseConfirmationPane.test.ts
|
src/Explorer/Panes/DeleteDatabaseConfirmationPane.test.ts
|
||||||
src/Explorer/Panes/DeleteDatabaseConfirmationPane.ts
|
src/Explorer/Panes/DeleteDatabaseConfirmationPane.ts
|
||||||
src/Explorer/Panes/GraphStylingPane.ts
|
src/Explorer/Panes/GraphStylingPane.ts
|
||||||
|
|
|
@ -73,10 +73,6 @@ describe("Component Registerer", () => {
|
||||||
expect(ko.components.isRegistered("add-collection-pane")).toBe(true);
|
expect(ko.components.isRegistered("add-collection-pane")).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should register delete-collection-confirmation-pane component", () => {
|
|
||||||
expect(ko.components.isRegistered("delete-collection-confirmation-pane")).toBe(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should register graph-new-vertex-pane component", () => {
|
it("should register graph-new-vertex-pane component", () => {
|
||||||
expect(ko.components.isRegistered("graph-new-vertex-pane")).toBe(true);
|
expect(ko.components.isRegistered("graph-new-vertex-pane")).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
|
@ -58,10 +58,6 @@ ko.components.register("tabs-manager", { template: TabsManagerTemplate });
|
||||||
// Panes
|
// Panes
|
||||||
ko.components.register("add-database-pane", new PaneComponents.AddDatabasePaneComponent());
|
ko.components.register("add-database-pane", new PaneComponents.AddDatabasePaneComponent());
|
||||||
ko.components.register("add-collection-pane", new PaneComponents.AddCollectionPaneComponent());
|
ko.components.register("add-collection-pane", new PaneComponents.AddCollectionPaneComponent());
|
||||||
ko.components.register(
|
|
||||||
"delete-collection-confirmation-pane",
|
|
||||||
new PaneComponents.DeleteCollectionConfirmationPaneComponent()
|
|
||||||
);
|
|
||||||
|
|
||||||
ko.components.register("graph-new-vertex-pane", new PaneComponents.GraphNewVertexPaneComponent());
|
ko.components.register("graph-new-vertex-pane", new PaneComponents.GraphNewVertexPaneComponent());
|
||||||
ko.components.register("graph-styling-pane", new PaneComponents.GraphStylingPaneComponent());
|
ko.components.register("graph-styling-pane", new PaneComponents.GraphStylingPaneComponent());
|
||||||
|
|
|
@ -157,21 +157,6 @@ exports[`SettingsComponent renders 1`] = `
|
||||||
"useIndexingForSharedThroughput": [Function],
|
"useIndexingForSharedThroughput": [Function],
|
||||||
"visible": [Function],
|
"visible": [Function],
|
||||||
},
|
},
|
||||||
DeleteCollectionConfirmationPane {
|
|
||||||
"collectionIdConfirmation": [Function],
|
|
||||||
"collectionIdConfirmationText": [Function],
|
|
||||||
"container": [Circular],
|
|
||||||
"containerDeleteFeedback": [Function],
|
|
||||||
"firstFieldHasFocus": [Function],
|
|
||||||
"formErrors": [Function],
|
|
||||||
"formErrorsDetails": [Function],
|
|
||||||
"id": "deletecollectionconfirmationpane",
|
|
||||||
"isExecuting": [Function],
|
|
||||||
"isTemplateReady": [Function],
|
|
||||||
"recordDeleteFeedback": [Function],
|
|
||||||
"title": [Function],
|
|
||||||
"visible": [Function],
|
|
||||||
},
|
|
||||||
GraphStylingPane {
|
GraphStylingPane {
|
||||||
"container": [Circular],
|
"container": [Circular],
|
||||||
"firstFieldHasFocus": [Function],
|
"firstFieldHasFocus": [Function],
|
||||||
|
@ -594,21 +579,6 @@ exports[`SettingsComponent renders 1`] = `
|
||||||
"databaseAccount": [Function],
|
"databaseAccount": [Function],
|
||||||
"databases": [Function],
|
"databases": [Function],
|
||||||
"defaultExperience": [Function],
|
"defaultExperience": [Function],
|
||||||
"deleteCollectionConfirmationPane": DeleteCollectionConfirmationPane {
|
|
||||||
"collectionIdConfirmation": [Function],
|
|
||||||
"collectionIdConfirmationText": [Function],
|
|
||||||
"container": [Circular],
|
|
||||||
"containerDeleteFeedback": [Function],
|
|
||||||
"firstFieldHasFocus": [Function],
|
|
||||||
"formErrors": [Function],
|
|
||||||
"formErrorsDetails": [Function],
|
|
||||||
"id": "deletecollectionconfirmationpane",
|
|
||||||
"isExecuting": [Function],
|
|
||||||
"isTemplateReady": [Function],
|
|
||||||
"recordDeleteFeedback": [Function],
|
|
||||||
"title": [Function],
|
|
||||||
"visible": [Function],
|
|
||||||
},
|
|
||||||
"deleteCollectionText": [Function],
|
"deleteCollectionText": [Function],
|
||||||
"deleteDatabaseText": [Function],
|
"deleteDatabaseText": [Function],
|
||||||
"editTableEntityPane": EditTableEntityPane {
|
"editTableEntityPane": EditTableEntityPane {
|
||||||
|
@ -952,21 +922,6 @@ exports[`SettingsComponent renders 1`] = `
|
||||||
"useIndexingForSharedThroughput": [Function],
|
"useIndexingForSharedThroughput": [Function],
|
||||||
"visible": [Function],
|
"visible": [Function],
|
||||||
},
|
},
|
||||||
DeleteCollectionConfirmationPane {
|
|
||||||
"collectionIdConfirmation": [Function],
|
|
||||||
"collectionIdConfirmationText": [Function],
|
|
||||||
"container": [Circular],
|
|
||||||
"containerDeleteFeedback": [Function],
|
|
||||||
"firstFieldHasFocus": [Function],
|
|
||||||
"formErrors": [Function],
|
|
||||||
"formErrorsDetails": [Function],
|
|
||||||
"id": "deletecollectionconfirmationpane",
|
|
||||||
"isExecuting": [Function],
|
|
||||||
"isTemplateReady": [Function],
|
|
||||||
"recordDeleteFeedback": [Function],
|
|
||||||
"title": [Function],
|
|
||||||
"visible": [Function],
|
|
||||||
},
|
|
||||||
GraphStylingPane {
|
GraphStylingPane {
|
||||||
"container": [Circular],
|
"container": [Circular],
|
||||||
"firstFieldHasFocus": [Function],
|
"firstFieldHasFocus": [Function],
|
||||||
|
@ -1389,21 +1344,6 @@ exports[`SettingsComponent renders 1`] = `
|
||||||
"databaseAccount": [Function],
|
"databaseAccount": [Function],
|
||||||
"databases": [Function],
|
"databases": [Function],
|
||||||
"defaultExperience": [Function],
|
"defaultExperience": [Function],
|
||||||
"deleteCollectionConfirmationPane": DeleteCollectionConfirmationPane {
|
|
||||||
"collectionIdConfirmation": [Function],
|
|
||||||
"collectionIdConfirmationText": [Function],
|
|
||||||
"container": [Circular],
|
|
||||||
"containerDeleteFeedback": [Function],
|
|
||||||
"firstFieldHasFocus": [Function],
|
|
||||||
"formErrors": [Function],
|
|
||||||
"formErrorsDetails": [Function],
|
|
||||||
"id": "deletecollectionconfirmationpane",
|
|
||||||
"isExecuting": [Function],
|
|
||||||
"isTemplateReady": [Function],
|
|
||||||
"recordDeleteFeedback": [Function],
|
|
||||||
"title": [Function],
|
|
||||||
"visible": [Function],
|
|
||||||
},
|
|
||||||
"deleteCollectionText": [Function],
|
"deleteCollectionText": [Function],
|
||||||
"deleteDatabaseText": [Function],
|
"deleteDatabaseText": [Function],
|
||||||
"editTableEntityPane": EditTableEntityPane {
|
"editTableEntityPane": EditTableEntityPane {
|
||||||
|
@ -1760,21 +1700,6 @@ exports[`SettingsComponent renders 1`] = `
|
||||||
"useIndexingForSharedThroughput": [Function],
|
"useIndexingForSharedThroughput": [Function],
|
||||||
"visible": [Function],
|
"visible": [Function],
|
||||||
},
|
},
|
||||||
DeleteCollectionConfirmationPane {
|
|
||||||
"collectionIdConfirmation": [Function],
|
|
||||||
"collectionIdConfirmationText": [Function],
|
|
||||||
"container": [Circular],
|
|
||||||
"containerDeleteFeedback": [Function],
|
|
||||||
"firstFieldHasFocus": [Function],
|
|
||||||
"formErrors": [Function],
|
|
||||||
"formErrorsDetails": [Function],
|
|
||||||
"id": "deletecollectionconfirmationpane",
|
|
||||||
"isExecuting": [Function],
|
|
||||||
"isTemplateReady": [Function],
|
|
||||||
"recordDeleteFeedback": [Function],
|
|
||||||
"title": [Function],
|
|
||||||
"visible": [Function],
|
|
||||||
},
|
|
||||||
GraphStylingPane {
|
GraphStylingPane {
|
||||||
"container": [Circular],
|
"container": [Circular],
|
||||||
"firstFieldHasFocus": [Function],
|
"firstFieldHasFocus": [Function],
|
||||||
|
@ -2197,21 +2122,6 @@ exports[`SettingsComponent renders 1`] = `
|
||||||
"databaseAccount": [Function],
|
"databaseAccount": [Function],
|
||||||
"databases": [Function],
|
"databases": [Function],
|
||||||
"defaultExperience": [Function],
|
"defaultExperience": [Function],
|
||||||
"deleteCollectionConfirmationPane": DeleteCollectionConfirmationPane {
|
|
||||||
"collectionIdConfirmation": [Function],
|
|
||||||
"collectionIdConfirmationText": [Function],
|
|
||||||
"container": [Circular],
|
|
||||||
"containerDeleteFeedback": [Function],
|
|
||||||
"firstFieldHasFocus": [Function],
|
|
||||||
"formErrors": [Function],
|
|
||||||
"formErrorsDetails": [Function],
|
|
||||||
"id": "deletecollectionconfirmationpane",
|
|
||||||
"isExecuting": [Function],
|
|
||||||
"isTemplateReady": [Function],
|
|
||||||
"recordDeleteFeedback": [Function],
|
|
||||||
"title": [Function],
|
|
||||||
"visible": [Function],
|
|
||||||
},
|
|
||||||
"deleteCollectionText": [Function],
|
"deleteCollectionText": [Function],
|
||||||
"deleteDatabaseText": [Function],
|
"deleteDatabaseText": [Function],
|
||||||
"editTableEntityPane": EditTableEntityPane {
|
"editTableEntityPane": EditTableEntityPane {
|
||||||
|
@ -2555,21 +2465,6 @@ exports[`SettingsComponent renders 1`] = `
|
||||||
"useIndexingForSharedThroughput": [Function],
|
"useIndexingForSharedThroughput": [Function],
|
||||||
"visible": [Function],
|
"visible": [Function],
|
||||||
},
|
},
|
||||||
DeleteCollectionConfirmationPane {
|
|
||||||
"collectionIdConfirmation": [Function],
|
|
||||||
"collectionIdConfirmationText": [Function],
|
|
||||||
"container": [Circular],
|
|
||||||
"containerDeleteFeedback": [Function],
|
|
||||||
"firstFieldHasFocus": [Function],
|
|
||||||
"formErrors": [Function],
|
|
||||||
"formErrorsDetails": [Function],
|
|
||||||
"id": "deletecollectionconfirmationpane",
|
|
||||||
"isExecuting": [Function],
|
|
||||||
"isTemplateReady": [Function],
|
|
||||||
"recordDeleteFeedback": [Function],
|
|
||||||
"title": [Function],
|
|
||||||
"visible": [Function],
|
|
||||||
},
|
|
||||||
GraphStylingPane {
|
GraphStylingPane {
|
||||||
"container": [Circular],
|
"container": [Circular],
|
||||||
"firstFieldHasFocus": [Function],
|
"firstFieldHasFocus": [Function],
|
||||||
|
@ -2992,21 +2887,6 @@ exports[`SettingsComponent renders 1`] = `
|
||||||
"databaseAccount": [Function],
|
"databaseAccount": [Function],
|
||||||
"databases": [Function],
|
"databases": [Function],
|
||||||
"defaultExperience": [Function],
|
"defaultExperience": [Function],
|
||||||
"deleteCollectionConfirmationPane": DeleteCollectionConfirmationPane {
|
|
||||||
"collectionIdConfirmation": [Function],
|
|
||||||
"collectionIdConfirmationText": [Function],
|
|
||||||
"container": [Circular],
|
|
||||||
"containerDeleteFeedback": [Function],
|
|
||||||
"firstFieldHasFocus": [Function],
|
|
||||||
"formErrors": [Function],
|
|
||||||
"formErrorsDetails": [Function],
|
|
||||||
"id": "deletecollectionconfirmationpane",
|
|
||||||
"isExecuting": [Function],
|
|
||||||
"isTemplateReady": [Function],
|
|
||||||
"recordDeleteFeedback": [Function],
|
|
||||||
"title": [Function],
|
|
||||||
"visible": [Function],
|
|
||||||
},
|
|
||||||
"deleteCollectionText": [Function],
|
"deleteCollectionText": [Function],
|
||||||
"deleteDatabaseText": [Function],
|
"deleteDatabaseText": [Function],
|
||||||
"editTableEntityPane": EditTableEntityPane {
|
"editTableEntityPane": EditTableEntityPane {
|
||||||
|
|
|
@ -36,6 +36,7 @@ import { decryptJWTToken, getAuthorizationHeader } from "../Utils/AuthorizationU
|
||||||
import { stringToBlob } from "../Utils/BlobUtils";
|
import { stringToBlob } from "../Utils/BlobUtils";
|
||||||
import { fromContentUri, toRawContentUri } from "../Utils/GitHubUtils";
|
import { fromContentUri, toRawContentUri } from "../Utils/GitHubUtils";
|
||||||
import * as NotificationConsoleUtils from "../Utils/NotificationConsoleUtils";
|
import * as NotificationConsoleUtils from "../Utils/NotificationConsoleUtils";
|
||||||
|
import * as PricingUtils from "../Utils/PricingUtils";
|
||||||
import * as ComponentRegisterer from "./ComponentRegisterer";
|
import * as ComponentRegisterer from "./ComponentRegisterer";
|
||||||
import { ArcadiaWorkspaceItem } from "./Controls/Arcadia/ArcadiaMenuPicker";
|
import { ArcadiaWorkspaceItem } from "./Controls/Arcadia/ArcadiaMenuPicker";
|
||||||
import { CommandButtonComponentProps } from "./Controls/CommandButton/CommandButtonComponent";
|
import { CommandButtonComponentProps } from "./Controls/CommandButton/CommandButtonComponent";
|
||||||
|
@ -52,7 +53,6 @@ import AddDatabasePane from "./Panes/AddDatabasePane";
|
||||||
import { BrowseQueriesPanel } from "./Panes/BrowseQueriesPanel";
|
import { BrowseQueriesPanel } from "./Panes/BrowseQueriesPanel";
|
||||||
import CassandraAddCollectionPane from "./Panes/CassandraAddCollectionPane";
|
import CassandraAddCollectionPane from "./Panes/CassandraAddCollectionPane";
|
||||||
import { ContextualPaneBase } from "./Panes/ContextualPaneBase";
|
import { ContextualPaneBase } from "./Panes/ContextualPaneBase";
|
||||||
import DeleteCollectionConfirmationPane from "./Panes/DeleteCollectionConfirmationPane";
|
|
||||||
import { DeleteCollectionConfirmationPanel } from "./Panes/DeleteCollectionConfirmationPanel";
|
import { DeleteCollectionConfirmationPanel } from "./Panes/DeleteCollectionConfirmationPanel";
|
||||||
import { DeleteDatabaseConfirmationPanel } from "./Panes/DeleteDatabaseConfirmationPanel";
|
import { DeleteDatabaseConfirmationPanel } from "./Panes/DeleteDatabaseConfirmationPanel";
|
||||||
import { ExecuteSprocParamsPanel } from "./Panes/ExecuteSprocParamsPanel";
|
import { ExecuteSprocParamsPanel } from "./Panes/ExecuteSprocParamsPanel";
|
||||||
|
@ -190,7 +190,6 @@ export default class Explorer {
|
||||||
// Contextual panes
|
// Contextual panes
|
||||||
public addDatabasePane: AddDatabasePane;
|
public addDatabasePane: AddDatabasePane;
|
||||||
public addCollectionPane: AddCollectionPane;
|
public addCollectionPane: AddCollectionPane;
|
||||||
public deleteCollectionConfirmationPane: DeleteCollectionConfirmationPane;
|
|
||||||
public graphStylingPane: GraphStylingPane;
|
public graphStylingPane: GraphStylingPane;
|
||||||
public addTableEntityPane: AddTableEntityPane;
|
public addTableEntityPane: AddTableEntityPane;
|
||||||
public editTableEntityPane: EditTableEntityPane;
|
public editTableEntityPane: EditTableEntityPane;
|
||||||
|
@ -536,13 +535,6 @@ export default class Explorer {
|
||||||
container: this,
|
container: this,
|
||||||
});
|
});
|
||||||
|
|
||||||
this.deleteCollectionConfirmationPane = new DeleteCollectionConfirmationPane({
|
|
||||||
id: "deletecollectionconfirmationpane",
|
|
||||||
visible: ko.observable<boolean>(false),
|
|
||||||
|
|
||||||
container: this,
|
|
||||||
});
|
|
||||||
|
|
||||||
this.graphStylingPane = new GraphStylingPane({
|
this.graphStylingPane = new GraphStylingPane({
|
||||||
id: "graphstylingpane",
|
id: "graphstylingpane",
|
||||||
visible: ko.observable<boolean>(false),
|
visible: ko.observable<boolean>(false),
|
||||||
|
@ -597,7 +589,6 @@ export default class Explorer {
|
||||||
this._panes = [
|
this._panes = [
|
||||||
this.addDatabasePane,
|
this.addDatabasePane,
|
||||||
this.addCollectionPane,
|
this.addCollectionPane,
|
||||||
this.deleteCollectionConfirmationPane,
|
|
||||||
this.graphStylingPane,
|
this.graphStylingPane,
|
||||||
this.addTableEntityPane,
|
this.addTableEntityPane,
|
||||||
this.editTableEntityPane,
|
this.editTableEntityPane,
|
||||||
|
@ -634,8 +625,6 @@ export default class Explorer {
|
||||||
this.addCollectionPane.collectionWithThroughputInSharedTitle(
|
this.addCollectionPane.collectionWithThroughputInSharedTitle(
|
||||||
"Provision dedicated throughput for this container"
|
"Provision dedicated throughput for this container"
|
||||||
);
|
);
|
||||||
this.deleteCollectionConfirmationPane.title("Delete Container");
|
|
||||||
this.deleteCollectionConfirmationPane.collectionIdConfirmationText("Confirm by typing the container id");
|
|
||||||
this.refreshTreeTitle("Refresh containers");
|
this.refreshTreeTitle("Refresh containers");
|
||||||
break;
|
break;
|
||||||
case "Mongo":
|
case "Mongo":
|
||||||
|
@ -662,8 +651,6 @@ export default class Explorer {
|
||||||
this.addCollectionPane.title("Add Graph");
|
this.addCollectionPane.title("Add Graph");
|
||||||
this.addCollectionPane.collectionIdTitle("Graph id");
|
this.addCollectionPane.collectionIdTitle("Graph id");
|
||||||
this.addCollectionPane.collectionWithThroughputInSharedTitle("Provision dedicated throughput for this graph");
|
this.addCollectionPane.collectionWithThroughputInSharedTitle("Provision dedicated throughput for this graph");
|
||||||
this.deleteCollectionConfirmationPane.title("Delete Graph");
|
|
||||||
this.deleteCollectionConfirmationPane.collectionIdConfirmationText("Confirm by typing the graph id");
|
|
||||||
this.refreshTreeTitle("Refresh graphs");
|
this.refreshTreeTitle("Refresh graphs");
|
||||||
break;
|
break;
|
||||||
case "Tables":
|
case "Tables":
|
||||||
|
@ -679,8 +666,6 @@ export default class Explorer {
|
||||||
this.refreshTreeTitle("Refresh tables");
|
this.refreshTreeTitle("Refresh tables");
|
||||||
this.addTableEntityPane.title("Add Table Entity");
|
this.addTableEntityPane.title("Add Table Entity");
|
||||||
this.editTableEntityPane.title("Edit Table Entity");
|
this.editTableEntityPane.title("Edit Table Entity");
|
||||||
this.deleteCollectionConfirmationPane.title("Delete Table");
|
|
||||||
this.deleteCollectionConfirmationPane.collectionIdConfirmationText("Confirm by typing the table id");
|
|
||||||
this.tableDataClient = new TablesAPIDataClient();
|
this.tableDataClient = new TablesAPIDataClient();
|
||||||
break;
|
break;
|
||||||
case "Cassandra":
|
case "Cassandra":
|
||||||
|
@ -696,8 +681,6 @@ export default class Explorer {
|
||||||
this.refreshTreeTitle("Refresh tables");
|
this.refreshTreeTitle("Refresh tables");
|
||||||
this.addTableEntityPane.title("Add Table Row");
|
this.addTableEntityPane.title("Add Table Row");
|
||||||
this.editTableEntityPane.title("Edit Table Row");
|
this.editTableEntityPane.title("Edit Table Row");
|
||||||
this.deleteCollectionConfirmationPane.title("Delete Table");
|
|
||||||
this.deleteCollectionConfirmationPane.collectionIdConfirmationText("Confirm by typing the table id");
|
|
||||||
this.tableDataClient = new CassandraAPIDataClient();
|
this.tableDataClient = new CassandraAPIDataClient();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -2234,14 +2217,13 @@ export default class Explorer {
|
||||||
}
|
}
|
||||||
|
|
||||||
public openDeleteCollectionConfirmationPane(): void {
|
public openDeleteCollectionConfirmationPane(): void {
|
||||||
userContext.features.enableKOPanel
|
let collectionName = PricingUtils.getCollectionName(userContext.defaultExperience);
|
||||||
? this.deleteCollectionConfirmationPane.open()
|
this.openSidePanel(
|
||||||
: this.openSidePanel(
|
"Delete " + collectionName,
|
||||||
"Delete Collection",
|
|
||||||
<DeleteCollectionConfirmationPanel
|
<DeleteCollectionConfirmationPanel
|
||||||
explorer={this}
|
explorer={this}
|
||||||
closePanel={() => this.closeSidePanel()}
|
collectionName={collectionName}
|
||||||
openNotificationConsole={() => this.expandConsole()}
|
closePanel={this.closeSidePanel}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,108 +0,0 @@
|
||||||
<div data-bind="visible: visible, event: { keydown: onPaneKeyDown }">
|
|
||||||
<div
|
|
||||||
class="contextual-pane-out"
|
|
||||||
data-bind="
|
|
||||||
click: cancel,
|
|
||||||
clickBubble: false"
|
|
||||||
></div>
|
|
||||||
<div class="contextual-pane" id="deletecollectionconfirmationpane">
|
|
||||||
<!-- Delete Collection Confirmation form - Start -->
|
|
||||||
<div class="contextual-pane-in">
|
|
||||||
<form
|
|
||||||
class="paneContentContainer"
|
|
||||||
data-bind="
|
|
||||||
submit: submit"
|
|
||||||
>
|
|
||||||
<!-- Delete Collection Confirmation header - Start -->
|
|
||||||
<div class="firstdivbg headerline">
|
|
||||||
<span role="heading" aria-level="2" data-bind="text: title"></span>
|
|
||||||
<div
|
|
||||||
class="closeImg"
|
|
||||||
role="button"
|
|
||||||
aria-label="Close pane"
|
|
||||||
tabindex="0"
|
|
||||||
data-bind="
|
|
||||||
click: cancel, event: { keypress: onCloseKeyPress }"
|
|
||||||
>
|
|
||||||
<img src="../../../images/close-black.svg" title="Close" alt="Close" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<!-- Delete Collection Confirmation header - End -->
|
|
||||||
|
|
||||||
<div class="warningErrorContainer" data-bind="visible: !formErrors()">
|
|
||||||
<div class="warningErrorContent">
|
|
||||||
<span><img class="paneWarningIcon" src="/warning.svg" alt="Warning" /></span>
|
|
||||||
<span class="warningErrorDetailsLinkContainer">
|
|
||||||
Warning! The action you are about to take cannot be undone. Continuing will permanently delete this
|
|
||||||
resource and all of its children resources.
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Delete Collection Confirmation errors - Start -->
|
|
||||||
<div
|
|
||||||
class="warningErrorContainer"
|
|
||||||
aria-live="assertive"
|
|
||||||
data-bind="
|
|
||||||
visible: formErrors() && formErrors() !== ''"
|
|
||||||
>
|
|
||||||
<div class="warningErrorContent">
|
|
||||||
<span><img class="paneErrorIcon" src="/error_red.svg" alt="Error" /></span>
|
|
||||||
<span class="warningErrorDetailsLinkContainer">
|
|
||||||
<span class="formErrors" data-bind="text: formErrors, attr: { title: formErrors }"></span>
|
|
||||||
<a class="errorLink" role="link" data-bind="click: showErrorDetails">More details</a>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<!-- Delete Collection Confirmation errors - End -->
|
|
||||||
|
|
||||||
<!-- Delete Collection Confirmation inputs - Start -->
|
|
||||||
<div class="paneMainContent">
|
|
||||||
<div>
|
|
||||||
<span class="mandatoryStar">*</span> <span data-bind="text: collectionIdConfirmationText"></span>
|
|
||||||
<p>
|
|
||||||
<input
|
|
||||||
type="text"
|
|
||||||
data-test="confirmCollectionId"
|
|
||||||
name="collectionIdConfirmation"
|
|
||||||
required
|
|
||||||
class="collid"
|
|
||||||
data-bind="value: collectionIdConfirmation, hasFocus: firstFieldHasFocus, attr: { 'aria-label': collectionIdConfirmationText }"
|
|
||||||
/>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div data-bind="visible: recordDeleteFeedback">
|
|
||||||
<div>Help us improve Azure Cosmos DB!</div>
|
|
||||||
<div>What is the reason why you are deleting this container?</div>
|
|
||||||
<p>
|
|
||||||
<textarea
|
|
||||||
type="text"
|
|
||||||
data-test="containerDeleteFeedback"
|
|
||||||
name="containerDeleteFeedback"
|
|
||||||
rows="3"
|
|
||||||
cols="53"
|
|
||||||
class="collid"
|
|
||||||
maxlength="512"
|
|
||||||
data-bind="value: containerDeleteFeedback"
|
|
||||||
aria-label="Help us improve Azure Cosmos DB! What is the reason why you are deleting this container?"
|
|
||||||
>
|
|
||||||
</textarea>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="paneFooter">
|
|
||||||
<div class="leftpanel-okbut">
|
|
||||||
<input type="submit" data-test="deleteCollection" value="OK" class="btncreatecoll1" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<!-- Delete Collection Confirmation inputs - End -->
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
<!-- Delete Collection Confirmation form - End -->
|
|
||||||
<!-- Loader - Start -->
|
|
||||||
<div class="dataExplorerLoaderContainer dataExplorerPaneLoaderContainer" data-bind="visible: isExecuting">
|
|
||||||
<img class="dataExplorerLoader" src="/LoadingIndicator_3Squares.gif" />
|
|
||||||
</div>
|
|
||||||
<!-- Loader - End -->
|
|
||||||
</div>
|
|
||||||
</div>
|
|
|
@ -1,128 +0,0 @@
|
||||||
import * as ko from "knockout";
|
|
||||||
import * as ViewModels from "../../Contracts/ViewModels";
|
|
||||||
import * as Constants from "../../Common/Constants";
|
|
||||||
import { Action, ActionModifiers } from "../../Shared/Telemetry/TelemetryConstants";
|
|
||||||
import { ConsoleDataType } from "../Menus/NotificationConsole/NotificationConsoleComponent";
|
|
||||||
import { ContextualPaneBase } from "./ContextualPaneBase";
|
|
||||||
import { DefaultExperienceUtility } from "../../Shared/DefaultExperienceUtility";
|
|
||||||
import DeleteFeedback from "../../Common/DeleteFeedback";
|
|
||||||
import * as NotificationConsoleUtils from "../../Utils/NotificationConsoleUtils";
|
|
||||||
import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
|
||||||
import { deleteCollection } from "../../Common/dataAccess/deleteCollection";
|
|
||||||
import { getErrorMessage, getErrorStack } from "../../Common/ErrorHandlingUtils";
|
|
||||||
|
|
||||||
export default class DeleteCollectionConfirmationPane extends ContextualPaneBase {
|
|
||||||
public collectionIdConfirmationText: ko.Observable<string>;
|
|
||||||
public collectionIdConfirmation: ko.Observable<string>;
|
|
||||||
public containerDeleteFeedback: ko.Observable<string>;
|
|
||||||
public recordDeleteFeedback: ko.Observable<boolean>;
|
|
||||||
|
|
||||||
constructor(options: ViewModels.PaneOptions) {
|
|
||||||
super(options);
|
|
||||||
this.collectionIdConfirmationText = ko.observable<string>("Confirm by typing the collection id");
|
|
||||||
this.collectionIdConfirmation = ko.observable<string>();
|
|
||||||
this.containerDeleteFeedback = ko.observable<string>();
|
|
||||||
this.recordDeleteFeedback = ko.observable<boolean>(false);
|
|
||||||
this.title("Delete Collection");
|
|
||||||
this.resetData();
|
|
||||||
}
|
|
||||||
|
|
||||||
public submit(): Promise<any> {
|
|
||||||
if (!this._isValid()) {
|
|
||||||
const selectedCollection: ViewModels.Collection = this.container.findSelectedCollection();
|
|
||||||
this.formErrors("Input collection name does not match the selected collection");
|
|
||||||
NotificationConsoleUtils.logConsoleMessage(
|
|
||||||
ConsoleDataType.Error,
|
|
||||||
`Error while deleting collection ${selectedCollection && selectedCollection.id()}: ${this.formErrors()}`
|
|
||||||
);
|
|
||||||
return Promise.resolve();
|
|
||||||
}
|
|
||||||
|
|
||||||
this.formErrors("");
|
|
||||||
this.isExecuting(true);
|
|
||||||
const selectedCollection = <ViewModels.Collection>this.container.findSelectedCollection();
|
|
||||||
const startKey: number = TelemetryProcessor.traceStart(Action.DeleteCollection, {
|
|
||||||
collectionId: selectedCollection.id(),
|
|
||||||
dataExplorerArea: Constants.Areas.ContextualPane,
|
|
||||||
paneTitle: this.title(),
|
|
||||||
});
|
|
||||||
return deleteCollection(selectedCollection.databaseId, selectedCollection.id()).then(
|
|
||||||
() => {
|
|
||||||
this.isExecuting(false);
|
|
||||||
this.close();
|
|
||||||
this.container.selectedNode(selectedCollection.database);
|
|
||||||
this.container.tabsManager?.closeTabsByComparator(
|
|
||||||
(tab) =>
|
|
||||||
tab.node?.id() === selectedCollection.id() &&
|
|
||||||
(tab.node as ViewModels.Collection).databaseId === selectedCollection.databaseId
|
|
||||||
);
|
|
||||||
this.container.refreshAllDatabases();
|
|
||||||
this.resetData();
|
|
||||||
TelemetryProcessor.traceSuccess(
|
|
||||||
Action.DeleteCollection,
|
|
||||||
{
|
|
||||||
collectionId: selectedCollection.id(),
|
|
||||||
dataExplorerArea: Constants.Areas.ContextualPane,
|
|
||||||
paneTitle: this.title(),
|
|
||||||
},
|
|
||||||
startKey
|
|
||||||
);
|
|
||||||
if (this.shouldRecordFeedback()) {
|
|
||||||
let deleteFeedback = new DeleteFeedback(
|
|
||||||
this.container.databaseAccount().id,
|
|
||||||
this.container.databaseAccount().name,
|
|
||||||
DefaultExperienceUtility.getApiKindFromDefaultExperience(this.container.defaultExperience()),
|
|
||||||
this.containerDeleteFeedback()
|
|
||||||
);
|
|
||||||
|
|
||||||
TelemetryProcessor.trace(Action.DeleteCollection, ActionModifiers.Mark, {
|
|
||||||
message: JSON.stringify(deleteFeedback, Object.getOwnPropertyNames(deleteFeedback)),
|
|
||||||
});
|
|
||||||
|
|
||||||
this.containerDeleteFeedback("");
|
|
||||||
}
|
|
||||||
},
|
|
||||||
(error: any) => {
|
|
||||||
this.isExecuting(false);
|
|
||||||
const errorMessage = getErrorMessage(error);
|
|
||||||
this.formErrors(errorMessage);
|
|
||||||
this.formErrorsDetails(errorMessage);
|
|
||||||
TelemetryProcessor.traceFailure(
|
|
||||||
Action.DeleteCollection,
|
|
||||||
{
|
|
||||||
collectionId: selectedCollection.id(),
|
|
||||||
dataExplorerArea: Constants.Areas.ContextualPane,
|
|
||||||
paneTitle: this.title(),
|
|
||||||
error: errorMessage,
|
|
||||||
errorStack: getErrorStack(error),
|
|
||||||
},
|
|
||||||
startKey
|
|
||||||
);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public resetData() {
|
|
||||||
this.collectionIdConfirmation("");
|
|
||||||
super.resetData();
|
|
||||||
}
|
|
||||||
|
|
||||||
public open() {
|
|
||||||
this.recordDeleteFeedback(this.shouldRecordFeedback());
|
|
||||||
super.open();
|
|
||||||
}
|
|
||||||
|
|
||||||
public shouldRecordFeedback(): boolean {
|
|
||||||
return this.container.isLastCollection() && !this.container.isSelectedDatabaseShared();
|
|
||||||
}
|
|
||||||
|
|
||||||
private _isValid(): boolean {
|
|
||||||
const selectedCollection: ViewModels.Collection = this.container.findSelectedCollection();
|
|
||||||
|
|
||||||
if (!selectedCollection) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.collectionIdConfirmation() === selectedCollection.id();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,178 +0,0 @@
|
||||||
import { Text, TextField } from "office-ui-fabric-react";
|
|
||||||
import * as React from "react";
|
|
||||||
import { Areas } from "../../Common/Constants";
|
|
||||||
import { deleteCollection } from "../../Common/dataAccess/deleteCollection";
|
|
||||||
import DeleteFeedback from "../../Common/DeleteFeedback";
|
|
||||||
import { getErrorMessage, getErrorStack } from "../../Common/ErrorHandlingUtils";
|
|
||||||
import { Collection } from "../../Contracts/ViewModels";
|
|
||||||
import { DefaultExperienceUtility } from "../../Shared/DefaultExperienceUtility";
|
|
||||||
import { Action, ActionModifiers } from "../../Shared/Telemetry/TelemetryConstants";
|
|
||||||
import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
|
||||||
import { userContext } from "../../UserContext";
|
|
||||||
import * as NotificationConsoleUtils from "../../Utils/NotificationConsoleUtils";
|
|
||||||
import Explorer from "../Explorer";
|
|
||||||
import { PanelFooterComponent } from "./PanelFooterComponent";
|
|
||||||
import { PanelInfoErrorComponent, PanelInfoErrorProps } from "./PanelInfoErrorComponent";
|
|
||||||
import { PanelLoadingScreen } from "./PanelLoadingScreen";
|
|
||||||
export interface DeleteCollectionConfirmationPanelProps {
|
|
||||||
explorer: Explorer;
|
|
||||||
closePanel: () => void;
|
|
||||||
openNotificationConsole: () => void;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface DeleteCollectionConfirmationPanelState {
|
|
||||||
formError: string;
|
|
||||||
isExecuting: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class DeleteCollectionConfirmationPanel extends React.Component<
|
|
||||||
DeleteCollectionConfirmationPanelProps,
|
|
||||||
DeleteCollectionConfirmationPanelState
|
|
||||||
> {
|
|
||||||
private inputCollectionName: string;
|
|
||||||
private deleteCollectionFeedback: string;
|
|
||||||
|
|
||||||
constructor(props: DeleteCollectionConfirmationPanelProps) {
|
|
||||||
super(props);
|
|
||||||
|
|
||||||
this.state = {
|
|
||||||
formError: "",
|
|
||||||
isExecuting: false,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
render(): JSX.Element {
|
|
||||||
return (
|
|
||||||
<form className="panelFormWrapper" onSubmit={this.submit.bind(this)}>
|
|
||||||
<PanelInfoErrorComponent {...this.getPanelErrorProps()} />
|
|
||||||
<div className="panelMainContent">
|
|
||||||
<div className="confirmDeleteInput">
|
|
||||||
<span className="mandatoryStar">* </span>
|
|
||||||
<Text variant="small">Confirm by typing the collection id</Text>
|
|
||||||
<TextField
|
|
||||||
id="confirmCollectionId"
|
|
||||||
autoFocus
|
|
||||||
styles={{ fieldGroup: { width: 300 } }}
|
|
||||||
onChange={(event, newInput?: string) => {
|
|
||||||
this.inputCollectionName = newInput;
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
{this.shouldRecordFeedback() && (
|
|
||||||
<div className="deleteCollectionFeedback">
|
|
||||||
<Text variant="small" block>
|
|
||||||
Help us improve Azure Cosmos DB!
|
|
||||||
</Text>
|
|
||||||
<Text variant="small" block>
|
|
||||||
What is the reason why you are deleting this container?
|
|
||||||
</Text>
|
|
||||||
<TextField
|
|
||||||
id="deleteCollectionFeedbackInput"
|
|
||||||
styles={{ fieldGroup: { width: 300 } }}
|
|
||||||
multiline
|
|
||||||
rows={3}
|
|
||||||
onChange={(event, newInput?: string) => {
|
|
||||||
this.deleteCollectionFeedback = newInput;
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
<PanelFooterComponent buttonLabel="OK" />
|
|
||||||
{this.state.isExecuting && <PanelLoadingScreen />}
|
|
||||||
</form>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
private getPanelErrorProps(): PanelInfoErrorProps {
|
|
||||||
if (this.state.formError) {
|
|
||||||
return {
|
|
||||||
messageType: "error",
|
|
||||||
message: this.state.formError,
|
|
||||||
showErrorDetails: true,
|
|
||||||
openNotificationConsole: this.props.openNotificationConsole,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
messageType: "warning",
|
|
||||||
showErrorDetails: false,
|
|
||||||
message:
|
|
||||||
"Warning! The action you are about to take cannot be undone. Continuing will permanently delete this resource and all of its children resources.",
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
private shouldRecordFeedback(): boolean {
|
|
||||||
return this.props.explorer.isLastCollection() && !this.props.explorer.isSelectedDatabaseShared();
|
|
||||||
}
|
|
||||||
|
|
||||||
public async submit(event: React.FormEvent<HTMLFormElement>): Promise<void> {
|
|
||||||
event.preventDefault();
|
|
||||||
|
|
||||||
const collection = this.props.explorer.findSelectedCollection();
|
|
||||||
if (!collection || this.inputCollectionName !== collection.id()) {
|
|
||||||
const errorMessage = "Input collection name does not match the selected collection";
|
|
||||||
this.setState({ formError: errorMessage });
|
|
||||||
NotificationConsoleUtils.logConsoleError(`Error while deleting collection ${collection.id()}: ${errorMessage}`);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.setState({ formError: "", isExecuting: true });
|
|
||||||
|
|
||||||
const startKey: number = TelemetryProcessor.traceStart(Action.DeleteCollection, {
|
|
||||||
collectionId: collection.id(),
|
|
||||||
dataExplorerArea: Areas.ContextualPane,
|
|
||||||
paneTitle: "Delete Collection",
|
|
||||||
});
|
|
||||||
|
|
||||||
try {
|
|
||||||
await deleteCollection(collection.databaseId, collection.id());
|
|
||||||
|
|
||||||
this.setState({ isExecuting: false });
|
|
||||||
this.props.explorer.selectedNode(collection.database);
|
|
||||||
this.props.explorer.tabsManager?.closeTabsByComparator(
|
|
||||||
(tab) => tab.node?.id() === collection.id() && (tab.node as Collection).databaseId === collection.databaseId
|
|
||||||
);
|
|
||||||
this.props.explorer.refreshAllDatabases();
|
|
||||||
|
|
||||||
TelemetryProcessor.traceSuccess(
|
|
||||||
Action.DeleteCollection,
|
|
||||||
{
|
|
||||||
collectionId: collection.id(),
|
|
||||||
dataExplorerArea: Areas.ContextualPane,
|
|
||||||
paneTitle: "Delete Collection",
|
|
||||||
},
|
|
||||||
startKey
|
|
||||||
);
|
|
||||||
|
|
||||||
if (this.shouldRecordFeedback()) {
|
|
||||||
const deleteFeedback = new DeleteFeedback(
|
|
||||||
userContext.databaseAccount?.id,
|
|
||||||
userContext.databaseAccount?.name,
|
|
||||||
DefaultExperienceUtility.getApiKindFromDefaultExperience(userContext.defaultExperience),
|
|
||||||
this.deleteCollectionFeedback
|
|
||||||
);
|
|
||||||
|
|
||||||
TelemetryProcessor.trace(Action.DeleteCollection, ActionModifiers.Mark, {
|
|
||||||
message: JSON.stringify(deleteFeedback, Object.getOwnPropertyNames(deleteFeedback)),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
this.props.closePanel();
|
|
||||||
} catch (error) {
|
|
||||||
const errorMessage = getErrorMessage(error);
|
|
||||||
this.setState({ formError: errorMessage, isExecuting: false });
|
|
||||||
TelemetryProcessor.traceFailure(
|
|
||||||
Action.DeleteCollection,
|
|
||||||
{
|
|
||||||
collectionId: collection.id(),
|
|
||||||
dataExplorerArea: Areas.ContextualPane,
|
|
||||||
paneTitle: "Delete Collection",
|
|
||||||
error: errorMessage,
|
|
||||||
errorStack: getErrorStack(error),
|
|
||||||
},
|
|
||||||
startKey
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,19 +1,18 @@
|
||||||
jest.mock("../../Common/dataAccess/deleteCollection");
|
jest.mock("../../../Common/dataAccess/deleteCollection");
|
||||||
jest.mock("../../Shared/Telemetry/TelemetryProcessor");
|
jest.mock("../../../Shared/Telemetry/TelemetryProcessor");
|
||||||
import * as ko from "knockout";
|
|
||||||
import { ApiKind, DatabaseAccount } from "../../Contracts/DataModels";
|
|
||||||
import { Collection, Database } from "../../Contracts/ViewModels";
|
|
||||||
import { Action, ActionModifiers } from "../../Shared/Telemetry/TelemetryConstants";
|
|
||||||
import { mount, ReactWrapper, shallow } from "enzyme";
|
import { mount, ReactWrapper, shallow } from "enzyme";
|
||||||
|
import * as ko from "knockout";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import DeleteFeedback from "../../Common/DeleteFeedback";
|
import { DeleteCollectionConfirmationPanel } from ".";
|
||||||
import Explorer from "../Explorer";
|
import { deleteCollection } from "../../../Common/dataAccess/deleteCollection";
|
||||||
import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
import DeleteFeedback from "../../../Common/DeleteFeedback";
|
||||||
import { TreeNode } from "../../Contracts/ViewModels";
|
import { ApiKind, DatabaseAccount } from "../../../Contracts/DataModels";
|
||||||
import { deleteCollection } from "../../Common/dataAccess/deleteCollection";
|
import { Collection, Database, TreeNode } from "../../../Contracts/ViewModels";
|
||||||
import { DeleteCollectionConfirmationPanel } from "./DeleteCollectionConfirmationPanel";
|
import { DefaultAccountExperienceType } from "../../../DefaultAccountExperienceType";
|
||||||
import { DefaultAccountExperienceType } from "../../DefaultAccountExperienceType";
|
import { Action, ActionModifiers } from "../../../Shared/Telemetry/TelemetryConstants";
|
||||||
import { updateUserContext } from "../../UserContext";
|
import * as TelemetryProcessor from "../../../Shared/Telemetry/TelemetryProcessor";
|
||||||
|
import { updateUserContext } from "../../../UserContext";
|
||||||
|
import Explorer from "../../Explorer";
|
||||||
|
|
||||||
describe("Delete Collection Confirmation Pane", () => {
|
describe("Delete Collection Confirmation Pane", () => {
|
||||||
describe("Explorer.isLastCollection()", () => {
|
describe("Explorer.isLastCollection()", () => {
|
||||||
|
@ -64,7 +63,7 @@ describe("Delete Collection Confirmation Pane", () => {
|
||||||
const props = {
|
const props = {
|
||||||
explorer: fakeExplorer,
|
explorer: fakeExplorer,
|
||||||
closePanel: (): void => undefined,
|
closePanel: (): void => undefined,
|
||||||
openNotificationConsole: (): void => undefined,
|
collectionName: "container",
|
||||||
};
|
};
|
||||||
const wrapper = shallow(<DeleteCollectionConfirmationPanel {...props} />);
|
const wrapper = shallow(<DeleteCollectionConfirmationPanel {...props} />);
|
||||||
expect(wrapper.exists(".deleteCollectionFeedback")).toBe(true);
|
expect(wrapper.exists(".deleteCollectionFeedback")).toBe(true);
|
||||||
|
@ -118,7 +117,7 @@ describe("Delete Collection Confirmation Pane", () => {
|
||||||
const props = {
|
const props = {
|
||||||
explorer: fakeExplorer,
|
explorer: fakeExplorer,
|
||||||
closePanel: (): void => undefined,
|
closePanel: (): void => undefined,
|
||||||
openNotificationConsole: (): void => undefined,
|
collectionName: "container",
|
||||||
};
|
};
|
||||||
wrapper = mount(<DeleteCollectionConfirmationPanel {...props} />);
|
wrapper = mount(<DeleteCollectionConfirmationPanel {...props} />);
|
||||||
});
|
});
|
||||||
|
@ -132,8 +131,8 @@ describe("Delete Collection Confirmation Pane", () => {
|
||||||
.hostNodes()
|
.hostNodes()
|
||||||
.simulate("change", { target: { value: selectedCollectionId } });
|
.simulate("change", { target: { value: selectedCollectionId } });
|
||||||
|
|
||||||
expect(wrapper.exists("#sidePanelOkButton")).toBe(true);
|
expect(wrapper.exists(".genericPaneSubmitBtn")).toBe(true);
|
||||||
wrapper.find("#sidePanelOkButton").hostNodes().simulate("submit");
|
wrapper.find(".genericPaneSubmitBtn").hostNodes().simulate("click");
|
||||||
expect(deleteCollection).toHaveBeenCalledWith(databaseId, selectedCollectionId);
|
expect(deleteCollection).toHaveBeenCalledWith(databaseId, selectedCollectionId);
|
||||||
|
|
||||||
wrapper.unmount();
|
wrapper.unmount();
|
||||||
|
@ -153,8 +152,8 @@ describe("Delete Collection Confirmation Pane", () => {
|
||||||
.hostNodes()
|
.hostNodes()
|
||||||
.simulate("change", { target: { value: feedbackText } });
|
.simulate("change", { target: { value: feedbackText } });
|
||||||
|
|
||||||
expect(wrapper.exists("#sidePanelOkButton")).toBe(true);
|
expect(wrapper.exists(".genericPaneSubmitBtn")).toBe(true);
|
||||||
wrapper.find("#sidePanelOkButton").hostNodes().simulate("submit");
|
wrapper.find(".genericPaneSubmitBtn").hostNodes().simulate("click");
|
||||||
expect(deleteCollection).toHaveBeenCalledWith(databaseId, selectedCollectionId);
|
expect(deleteCollection).toHaveBeenCalledWith(databaseId, selectedCollectionId);
|
||||||
|
|
||||||
const deleteFeedback = new DeleteFeedback(
|
const deleteFeedback = new DeleteFeedback(
|
|
@ -0,0 +1,152 @@
|
||||||
|
import { Text, TextField } from "office-ui-fabric-react";
|
||||||
|
import React, { FunctionComponent, useState } from "react";
|
||||||
|
import { Areas } from "../../../Common/Constants";
|
||||||
|
import { deleteCollection } from "../../../Common/dataAccess/deleteCollection";
|
||||||
|
import DeleteFeedback from "../../../Common/DeleteFeedback";
|
||||||
|
import { getErrorMessage, getErrorStack } from "../../../Common/ErrorHandlingUtils";
|
||||||
|
import { Collection } from "../../../Contracts/ViewModels";
|
||||||
|
import { DefaultExperienceUtility } from "../../../Shared/DefaultExperienceUtility";
|
||||||
|
import { Action, ActionModifiers } from "../../../Shared/Telemetry/TelemetryConstants";
|
||||||
|
import * as TelemetryProcessor from "../../../Shared/Telemetry/TelemetryProcessor";
|
||||||
|
import { userContext } from "../../../UserContext";
|
||||||
|
import * as NotificationConsoleUtils from "../../../Utils/NotificationConsoleUtils";
|
||||||
|
import Explorer from "../../Explorer";
|
||||||
|
import { GenericRightPaneComponent, GenericRightPaneProps } from "../GenericRightPaneComponent";
|
||||||
|
export interface DeleteCollectionConfirmationPanelProps {
|
||||||
|
explorer: Explorer;
|
||||||
|
collectionName: string;
|
||||||
|
closePanel: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const DeleteCollectionConfirmationPanel: FunctionComponent<DeleteCollectionConfirmationPanelProps> = ({
|
||||||
|
explorer,
|
||||||
|
closePanel,
|
||||||
|
collectionName,
|
||||||
|
}: DeleteCollectionConfirmationPanelProps) => {
|
||||||
|
const [deleteCollectionFeedback, setDeleteCollectionFeedback] = useState<string>("");
|
||||||
|
const [inputCollectionName, setInputCollectionName] = useState<string>("");
|
||||||
|
const [formError, setFormError] = useState<string>("");
|
||||||
|
const [isExecuting, setIsExecuting] = useState(false);
|
||||||
|
|
||||||
|
const shouldRecordFeedback = (): boolean => {
|
||||||
|
return explorer.isLastCollection() && !explorer.isSelectedDatabaseShared();
|
||||||
|
};
|
||||||
|
const paneTitle = "Delete " + collectionName;
|
||||||
|
const submit = async (): Promise<void> => {
|
||||||
|
const collection = explorer.findSelectedCollection();
|
||||||
|
if (!collection || inputCollectionName !== collection.id()) {
|
||||||
|
const errorMessage = "Input " + collectionName + " name does not match the selected " + collectionName;
|
||||||
|
setFormError(errorMessage);
|
||||||
|
NotificationConsoleUtils.logConsoleError(
|
||||||
|
`Error while deleting ${collectionName} ${collection.id()}: ${errorMessage}`
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const paneInfo = {
|
||||||
|
collectionId: collection.id(),
|
||||||
|
dataExplorerArea: Areas.ContextualPane,
|
||||||
|
paneTitle,
|
||||||
|
};
|
||||||
|
|
||||||
|
setFormError("");
|
||||||
|
setIsExecuting(true);
|
||||||
|
|
||||||
|
const startKey: number = TelemetryProcessor.traceStart(Action.DeleteCollection, paneInfo);
|
||||||
|
|
||||||
|
try {
|
||||||
|
await deleteCollection(collection.databaseId, collection.id());
|
||||||
|
|
||||||
|
setIsExecuting(false);
|
||||||
|
explorer.selectedNode(collection.database);
|
||||||
|
explorer.tabsManager?.closeTabsByComparator(
|
||||||
|
(tab) => tab.node?.id() === collection.id() && (tab.node as Collection).databaseId === collection.databaseId
|
||||||
|
);
|
||||||
|
explorer.refreshAllDatabases();
|
||||||
|
|
||||||
|
TelemetryProcessor.traceSuccess(Action.DeleteCollection, paneInfo, startKey);
|
||||||
|
|
||||||
|
if (shouldRecordFeedback()) {
|
||||||
|
const deleteFeedback = new DeleteFeedback(
|
||||||
|
userContext.databaseAccount?.id,
|
||||||
|
userContext.databaseAccount?.name,
|
||||||
|
DefaultExperienceUtility.getApiKindFromDefaultExperience(userContext.defaultExperience),
|
||||||
|
deleteCollectionFeedback
|
||||||
|
);
|
||||||
|
|
||||||
|
TelemetryProcessor.trace(Action.DeleteCollection, ActionModifiers.Mark, {
|
||||||
|
message: JSON.stringify(deleteFeedback, Object.getOwnPropertyNames(deleteFeedback)),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
closePanel();
|
||||||
|
} catch (error) {
|
||||||
|
const errorMessage = getErrorMessage(error);
|
||||||
|
|
||||||
|
setFormError(errorMessage);
|
||||||
|
setIsExecuting(false);
|
||||||
|
|
||||||
|
TelemetryProcessor.traceFailure(
|
||||||
|
Action.DeleteCollection,
|
||||||
|
{
|
||||||
|
...paneInfo,
|
||||||
|
error: errorMessage,
|
||||||
|
errorStack: getErrorStack(error),
|
||||||
|
},
|
||||||
|
startKey
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const genericPaneProps: GenericRightPaneProps = {
|
||||||
|
container: explorer,
|
||||||
|
formError: formError,
|
||||||
|
formErrorDetail: formError,
|
||||||
|
id: "deleteCollectionpane",
|
||||||
|
isExecuting,
|
||||||
|
title: paneTitle,
|
||||||
|
submitButtonText: "OK",
|
||||||
|
onClose: closePanel,
|
||||||
|
onSubmit: submit,
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
<GenericRightPaneComponent {...genericPaneProps}>
|
||||||
|
<div className="panelFormWrapper">
|
||||||
|
<div className="panelMainContent">
|
||||||
|
<div className="confirmDeleteInput">
|
||||||
|
<span className="mandatoryStar">* </span>
|
||||||
|
<Text variant="small">Confirm by typing the {collectionName.toLowerCase()} id</Text>
|
||||||
|
<TextField
|
||||||
|
id="confirmCollectionId"
|
||||||
|
autoFocus
|
||||||
|
value={inputCollectionName}
|
||||||
|
styles={{ fieldGroup: { width: 300 } }}
|
||||||
|
onChange={(event, newInput?: string) => {
|
||||||
|
setInputCollectionName(newInput);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
{shouldRecordFeedback() && (
|
||||||
|
<div className="deleteCollectionFeedback">
|
||||||
|
<Text variant="small" block>
|
||||||
|
Help us improve Azure Cosmos DB!
|
||||||
|
</Text>
|
||||||
|
<Text variant="small" block>
|
||||||
|
What is the reason why you are deleting this {collectionName}?
|
||||||
|
</Text>
|
||||||
|
<TextField
|
||||||
|
id="deleteCollectionFeedbackInput"
|
||||||
|
styles={{ fieldGroup: { width: 300 } }}
|
||||||
|
multiline
|
||||||
|
value={deleteCollectionFeedback}
|
||||||
|
rows={3}
|
||||||
|
onChange={(event, newInput?: string) => {
|
||||||
|
setDeleteCollectionFeedback(newInput);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</GenericRightPaneComponent>
|
||||||
|
);
|
||||||
|
};
|
|
@ -1,142 +0,0 @@
|
||||||
import { Subscription } from "knockout";
|
|
||||||
import { IconButton, PrimaryButton } from "office-ui-fabric-react/lib/Button";
|
|
||||||
import * as React from "react";
|
|
||||||
import ErrorRedIcon from "../../../images/error_red.svg";
|
|
||||||
import LoadingIndicatorIcon from "../../../images/LoadingIndicator_3Squares.gif";
|
|
||||||
import { KeyCodes } from "../../Common/Constants";
|
|
||||||
import Explorer from "../Explorer";
|
|
||||||
|
|
||||||
export interface GenericRightPaneProps {
|
|
||||||
container: Explorer;
|
|
||||||
formError: string;
|
|
||||||
formErrorDetail: string;
|
|
||||||
id: string;
|
|
||||||
isExecuting: boolean;
|
|
||||||
onClose: () => void;
|
|
||||||
onSubmit: () => void;
|
|
||||||
submitButtonText: string;
|
|
||||||
title: string;
|
|
||||||
isSubmitButtonHidden?: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface GenericRightPaneState {
|
|
||||||
panelHeight: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class GenericRightPaneComponent extends React.Component<GenericRightPaneProps, GenericRightPaneState> {
|
|
||||||
private notificationConsoleSubscription: Subscription;
|
|
||||||
|
|
||||||
constructor(props: GenericRightPaneProps) {
|
|
||||||
super(props);
|
|
||||||
|
|
||||||
this.state = {
|
|
||||||
panelHeight: this.getPanelHeight(),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public componentWillUnmount(): void {
|
|
||||||
this.notificationConsoleSubscription && this.notificationConsoleSubscription.dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
public render(): JSX.Element {
|
|
||||||
return (
|
|
||||||
<div tabIndex={-1} onKeyDown={this.onKeyDown}>
|
|
||||||
<div className="contextual-pane-out" onClick={this.props.onClose}></div>
|
|
||||||
<div
|
|
||||||
className="contextual-pane"
|
|
||||||
id={this.props.id}
|
|
||||||
style={{ height: this.state.panelHeight }}
|
|
||||||
onKeyDown={this.onKeyDown}
|
|
||||||
>
|
|
||||||
<div className="panelContentWrapper">
|
|
||||||
{this.renderPanelHeader()}
|
|
||||||
{this.renderErrorSection()}
|
|
||||||
{this.props.children}
|
|
||||||
{this.renderPanelFooter()}
|
|
||||||
</div>
|
|
||||||
{this.renderLoadingScreen()}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
private renderPanelHeader = (): JSX.Element => {
|
|
||||||
return (
|
|
||||||
<div className="firstdivbg headerline">
|
|
||||||
<span id="databaseTitle" role="heading" aria-level={2}>
|
|
||||||
{this.props.title}
|
|
||||||
</span>
|
|
||||||
<IconButton
|
|
||||||
ariaLabel="Close pane"
|
|
||||||
title="Close pane"
|
|
||||||
onClick={this.props.onClose}
|
|
||||||
tabIndex={0}
|
|
||||||
className="closePaneBtn"
|
|
||||||
iconProps={{ iconName: "Cancel" }}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
private renderErrorSection = (): JSX.Element => {
|
|
||||||
return (
|
|
||||||
<div className="warningErrorContainer" aria-live="assertive" hidden={!this.props.formError}>
|
|
||||||
<div className="warningErrorContent">
|
|
||||||
<span>
|
|
||||||
<img className="paneErrorIcon" src={ErrorRedIcon} alt="Error" />
|
|
||||||
</span>
|
|
||||||
<span className="warningErrorDetailsLinkContainer">
|
|
||||||
<span className="formErrors" title={this.props.formError}>
|
|
||||||
{this.props.formError}
|
|
||||||
</span>
|
|
||||||
<a className="errorLink" role="link" hidden={!this.props.formErrorDetail} onClick={this.showErrorDetail}>
|
|
||||||
More details
|
|
||||||
</a>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
private renderPanelFooter = (): JSX.Element => {
|
|
||||||
return (
|
|
||||||
<div className="paneFooter">
|
|
||||||
<div className="leftpanel-okbut">
|
|
||||||
<PrimaryButton
|
|
||||||
style={{ visibility: this.props.isSubmitButtonHidden ? "hidden" : "visible" }}
|
|
||||||
ariaLabel="Submit"
|
|
||||||
title="Submit"
|
|
||||||
onClick={this.props.onSubmit}
|
|
||||||
tabIndex={0}
|
|
||||||
className="genericPaneSubmitBtn"
|
|
||||||
text={this.props.submitButtonText}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
private renderLoadingScreen = (): JSX.Element => {
|
|
||||||
return (
|
|
||||||
<div className="dataExplorerLoaderContainer dataExplorerPaneLoaderContainer" hidden={!this.props.isExecuting}>
|
|
||||||
<img className="dataExplorerLoader" src={LoadingIndicatorIcon} />
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
private onKeyDown = (event: React.KeyboardEvent<HTMLDivElement>): void => {
|
|
||||||
if (event.keyCode === KeyCodes.Escape) {
|
|
||||||
this.props.onClose();
|
|
||||||
event.stopPropagation();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
private showErrorDetail = (): void => {
|
|
||||||
this.props.container.expandConsole();
|
|
||||||
};
|
|
||||||
|
|
||||||
private getPanelHeight = (): number => {
|
|
||||||
const notificationConsoleElement: HTMLElement = document.getElementById("explorerNotificationConsole");
|
|
||||||
return window.innerHeight - $(notificationConsoleElement).height();
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -0,0 +1,135 @@
|
||||||
|
import { IconButton, PrimaryButton } from "office-ui-fabric-react/lib/Button";
|
||||||
|
import React, { FunctionComponent, ReactNode } from "react";
|
||||||
|
import ErrorRedIcon from "../../../../images/error_red.svg";
|
||||||
|
import LoadingIndicatorIcon from "../../../../images/LoadingIndicator_3Squares.gif";
|
||||||
|
import { KeyCodes } from "../../../Common/Constants";
|
||||||
|
import Explorer from "../../Explorer";
|
||||||
|
|
||||||
|
export interface GenericRightPaneProps {
|
||||||
|
container: Explorer;
|
||||||
|
formError: string;
|
||||||
|
formErrorDetail: string;
|
||||||
|
id: string;
|
||||||
|
isExecuting: boolean;
|
||||||
|
onClose: () => void;
|
||||||
|
onSubmit: () => void;
|
||||||
|
submitButtonText: string;
|
||||||
|
title: string;
|
||||||
|
isSubmitButtonHidden?: boolean;
|
||||||
|
children?: ReactNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GenericRightPaneState {
|
||||||
|
panelHeight: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const GenericRightPaneComponent: FunctionComponent<GenericRightPaneProps> = ({
|
||||||
|
container,
|
||||||
|
formError,
|
||||||
|
formErrorDetail,
|
||||||
|
id,
|
||||||
|
isExecuting,
|
||||||
|
onClose,
|
||||||
|
onSubmit,
|
||||||
|
submitButtonText,
|
||||||
|
title,
|
||||||
|
isSubmitButtonHidden,
|
||||||
|
children,
|
||||||
|
}: GenericRightPaneProps) => {
|
||||||
|
const getPanelHeight = (): number => {
|
||||||
|
const notificationConsoleElement: HTMLElement = document.getElementById("explorerNotificationConsole");
|
||||||
|
return window.innerHeight - $(notificationConsoleElement).height();
|
||||||
|
};
|
||||||
|
|
||||||
|
const panelHeight: number = getPanelHeight();
|
||||||
|
|
||||||
|
const renderPanelHeader = (): JSX.Element => {
|
||||||
|
return (
|
||||||
|
<div className="firstdivbg headerline">
|
||||||
|
<span id="databaseTitle" role="heading" aria-level={2}>
|
||||||
|
{title}
|
||||||
|
</span>
|
||||||
|
<IconButton
|
||||||
|
ariaLabel="Close pane"
|
||||||
|
title="Close pane"
|
||||||
|
onClick={onClose}
|
||||||
|
tabIndex={0}
|
||||||
|
className="closePaneBtn"
|
||||||
|
iconProps={{ iconName: "Cancel" }}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const renderErrorSection = (): JSX.Element => {
|
||||||
|
return (
|
||||||
|
<div className="warningErrorContainer" aria-live="assertive" hidden={!formError}>
|
||||||
|
<div className="warningErrorContent">
|
||||||
|
<span>
|
||||||
|
<img className="paneErrorIcon" src={ErrorRedIcon} alt="Error" />
|
||||||
|
</span>
|
||||||
|
<span className="warningErrorDetailsLinkContainer">
|
||||||
|
<span className="formErrors" title={formError}>
|
||||||
|
{formError}
|
||||||
|
</span>
|
||||||
|
<a className="errorLink" role="link" hidden={!formErrorDetail} onClick={showErrorDetail}>
|
||||||
|
More details
|
||||||
|
</a>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const renderPanelFooter = (): JSX.Element => {
|
||||||
|
return (
|
||||||
|
<div className="paneFooter">
|
||||||
|
<div className="leftpanel-okbut">
|
||||||
|
<PrimaryButton
|
||||||
|
style={{ visibility: isSubmitButtonHidden ? "hidden" : "visible" }}
|
||||||
|
ariaLabel="Submit"
|
||||||
|
title="Submit"
|
||||||
|
onClick={onSubmit}
|
||||||
|
tabIndex={0}
|
||||||
|
className="genericPaneSubmitBtn"
|
||||||
|
text={submitButtonText}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const renderLoadingScreen = (): JSX.Element => {
|
||||||
|
return (
|
||||||
|
<div className="dataExplorerLoaderContainer dataExplorerPaneLoaderContainer" hidden={!isExecuting}>
|
||||||
|
<img className="dataExplorerLoader" src={LoadingIndicatorIcon} />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const onKeyDown = (event: React.KeyboardEvent<HTMLDivElement>): void => {
|
||||||
|
if (event.keyCode === KeyCodes.Escape) {
|
||||||
|
onClose();
|
||||||
|
event.stopPropagation();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const showErrorDetail = (): void => {
|
||||||
|
container.expandConsole();
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div tabIndex={-1} onKeyDown={onKeyDown}>
|
||||||
|
<div className="contextual-pane-out" onClick={onClose}></div>
|
||||||
|
<div className="contextual-pane" id={id} style={{ height: panelHeight }} onKeyDown={onKeyDown}>
|
||||||
|
<div className="panelContentWrapper">
|
||||||
|
{renderPanelHeader()}
|
||||||
|
{renderErrorSection()}
|
||||||
|
{children}
|
||||||
|
{renderPanelFooter()}
|
||||||
|
</div>
|
||||||
|
{renderLoadingScreen()}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
|
@ -1,7 +1,6 @@
|
||||||
import AddCollectionPaneTemplate from "./AddCollectionPane.html";
|
import AddCollectionPaneTemplate from "./AddCollectionPane.html";
|
||||||
import AddDatabasePaneTemplate from "./AddDatabasePane.html";
|
import AddDatabasePaneTemplate from "./AddDatabasePane.html";
|
||||||
import CassandraAddCollectionPaneTemplate from "./CassandraAddCollectionPane.html";
|
import CassandraAddCollectionPaneTemplate from "./CassandraAddCollectionPane.html";
|
||||||
import DeleteCollectionConfirmationPaneTemplate from "./DeleteCollectionConfirmationPane.html";
|
|
||||||
import GitHubReposPaneTemplate from "./GitHubReposPane.html";
|
import GitHubReposPaneTemplate from "./GitHubReposPane.html";
|
||||||
import GraphNewVertexPaneTemplate from "./GraphNewVertexPane.html";
|
import GraphNewVertexPaneTemplate from "./GraphNewVertexPane.html";
|
||||||
import GraphStylingPaneTemplate from "./GraphStylingPane.html";
|
import GraphStylingPaneTemplate from "./GraphStylingPane.html";
|
||||||
|
@ -34,15 +33,6 @@ export class AddCollectionPaneComponent {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class DeleteCollectionConfirmationPaneComponent {
|
|
||||||
constructor() {
|
|
||||||
return {
|
|
||||||
viewModel: PaneComponent,
|
|
||||||
template: DeleteCollectionConfirmationPaneTemplate,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class GraphNewVertexPaneComponent {
|
export class GraphNewVertexPaneComponent {
|
||||||
constructor() {
|
constructor() {
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -133,21 +133,6 @@ exports[`Settings Pane should render Default properly 1`] = `
|
||||||
"useIndexingForSharedThroughput": [Function],
|
"useIndexingForSharedThroughput": [Function],
|
||||||
"visible": [Function],
|
"visible": [Function],
|
||||||
},
|
},
|
||||||
DeleteCollectionConfirmationPane {
|
|
||||||
"collectionIdConfirmation": [Function],
|
|
||||||
"collectionIdConfirmationText": [Function],
|
|
||||||
"container": [Circular],
|
|
||||||
"containerDeleteFeedback": [Function],
|
|
||||||
"firstFieldHasFocus": [Function],
|
|
||||||
"formErrors": [Function],
|
|
||||||
"formErrorsDetails": [Function],
|
|
||||||
"id": "deletecollectionconfirmationpane",
|
|
||||||
"isExecuting": [Function],
|
|
||||||
"isTemplateReady": [Function],
|
|
||||||
"recordDeleteFeedback": [Function],
|
|
||||||
"title": [Function],
|
|
||||||
"visible": [Function],
|
|
||||||
},
|
|
||||||
GraphStylingPane {
|
GraphStylingPane {
|
||||||
"container": [Circular],
|
"container": [Circular],
|
||||||
"firstFieldHasFocus": [Function],
|
"firstFieldHasFocus": [Function],
|
||||||
|
@ -570,21 +555,6 @@ exports[`Settings Pane should render Default properly 1`] = `
|
||||||
"databaseAccount": [Function],
|
"databaseAccount": [Function],
|
||||||
"databases": [Function],
|
"databases": [Function],
|
||||||
"defaultExperience": [Function],
|
"defaultExperience": [Function],
|
||||||
"deleteCollectionConfirmationPane": DeleteCollectionConfirmationPane {
|
|
||||||
"collectionIdConfirmation": [Function],
|
|
||||||
"collectionIdConfirmationText": [Function],
|
|
||||||
"container": [Circular],
|
|
||||||
"containerDeleteFeedback": [Function],
|
|
||||||
"firstFieldHasFocus": [Function],
|
|
||||||
"formErrors": [Function],
|
|
||||||
"formErrorsDetails": [Function],
|
|
||||||
"id": "deletecollectionconfirmationpane",
|
|
||||||
"isExecuting": [Function],
|
|
||||||
"isTemplateReady": [Function],
|
|
||||||
"recordDeleteFeedback": [Function],
|
|
||||||
"title": [Function],
|
|
||||||
"visible": [Function],
|
|
||||||
},
|
|
||||||
"deleteCollectionText": [Function],
|
"deleteCollectionText": [Function],
|
||||||
"deleteDatabaseText": [Function],
|
"deleteDatabaseText": [Function],
|
||||||
"editTableEntityPane": EditTableEntityPane {
|
"editTableEntityPane": EditTableEntityPane {
|
||||||
|
@ -1016,21 +986,6 @@ exports[`Settings Pane should render Gremlin properly 1`] = `
|
||||||
"useIndexingForSharedThroughput": [Function],
|
"useIndexingForSharedThroughput": [Function],
|
||||||
"visible": [Function],
|
"visible": [Function],
|
||||||
},
|
},
|
||||||
DeleteCollectionConfirmationPane {
|
|
||||||
"collectionIdConfirmation": [Function],
|
|
||||||
"collectionIdConfirmationText": [Function],
|
|
||||||
"container": [Circular],
|
|
||||||
"containerDeleteFeedback": [Function],
|
|
||||||
"firstFieldHasFocus": [Function],
|
|
||||||
"formErrors": [Function],
|
|
||||||
"formErrorsDetails": [Function],
|
|
||||||
"id": "deletecollectionconfirmationpane",
|
|
||||||
"isExecuting": [Function],
|
|
||||||
"isTemplateReady": [Function],
|
|
||||||
"recordDeleteFeedback": [Function],
|
|
||||||
"title": [Function],
|
|
||||||
"visible": [Function],
|
|
||||||
},
|
|
||||||
GraphStylingPane {
|
GraphStylingPane {
|
||||||
"container": [Circular],
|
"container": [Circular],
|
||||||
"firstFieldHasFocus": [Function],
|
"firstFieldHasFocus": [Function],
|
||||||
|
@ -1453,21 +1408,6 @@ exports[`Settings Pane should render Gremlin properly 1`] = `
|
||||||
"databaseAccount": [Function],
|
"databaseAccount": [Function],
|
||||||
"databases": [Function],
|
"databases": [Function],
|
||||||
"defaultExperience": [Function],
|
"defaultExperience": [Function],
|
||||||
"deleteCollectionConfirmationPane": DeleteCollectionConfirmationPane {
|
|
||||||
"collectionIdConfirmation": [Function],
|
|
||||||
"collectionIdConfirmationText": [Function],
|
|
||||||
"container": [Circular],
|
|
||||||
"containerDeleteFeedback": [Function],
|
|
||||||
"firstFieldHasFocus": [Function],
|
|
||||||
"formErrors": [Function],
|
|
||||||
"formErrorsDetails": [Function],
|
|
||||||
"id": "deletecollectionconfirmationpane",
|
|
||||||
"isExecuting": [Function],
|
|
||||||
"isTemplateReady": [Function],
|
|
||||||
"recordDeleteFeedback": [Function],
|
|
||||||
"title": [Function],
|
|
||||||
"visible": [Function],
|
|
||||||
},
|
|
||||||
"deleteCollectionText": [Function],
|
"deleteCollectionText": [Function],
|
||||||
"deleteDatabaseText": [Function],
|
"deleteDatabaseText": [Function],
|
||||||
"editTableEntityPane": EditTableEntityPane {
|
"editTableEntityPane": EditTableEntityPane {
|
||||||
|
|
|
@ -133,21 +133,6 @@ exports[`Upload Items Pane should render Default properly 1`] = `
|
||||||
"useIndexingForSharedThroughput": [Function],
|
"useIndexingForSharedThroughput": [Function],
|
||||||
"visible": [Function],
|
"visible": [Function],
|
||||||
},
|
},
|
||||||
DeleteCollectionConfirmationPane {
|
|
||||||
"collectionIdConfirmation": [Function],
|
|
||||||
"collectionIdConfirmationText": [Function],
|
|
||||||
"container": [Circular],
|
|
||||||
"containerDeleteFeedback": [Function],
|
|
||||||
"firstFieldHasFocus": [Function],
|
|
||||||
"formErrors": [Function],
|
|
||||||
"formErrorsDetails": [Function],
|
|
||||||
"id": "deletecollectionconfirmationpane",
|
|
||||||
"isExecuting": [Function],
|
|
||||||
"isTemplateReady": [Function],
|
|
||||||
"recordDeleteFeedback": [Function],
|
|
||||||
"title": [Function],
|
|
||||||
"visible": [Function],
|
|
||||||
},
|
|
||||||
GraphStylingPane {
|
GraphStylingPane {
|
||||||
"container": [Circular],
|
"container": [Circular],
|
||||||
"firstFieldHasFocus": [Function],
|
"firstFieldHasFocus": [Function],
|
||||||
|
@ -570,21 +555,6 @@ exports[`Upload Items Pane should render Default properly 1`] = `
|
||||||
"databaseAccount": [Function],
|
"databaseAccount": [Function],
|
||||||
"databases": [Function],
|
"databases": [Function],
|
||||||
"defaultExperience": [Function],
|
"defaultExperience": [Function],
|
||||||
"deleteCollectionConfirmationPane": DeleteCollectionConfirmationPane {
|
|
||||||
"collectionIdConfirmation": [Function],
|
|
||||||
"collectionIdConfirmationText": [Function],
|
|
||||||
"container": [Circular],
|
|
||||||
"containerDeleteFeedback": [Function],
|
|
||||||
"firstFieldHasFocus": [Function],
|
|
||||||
"formErrors": [Function],
|
|
||||||
"formErrorsDetails": [Function],
|
|
||||||
"id": "deletecollectionconfirmationpane",
|
|
||||||
"isExecuting": [Function],
|
|
||||||
"isTemplateReady": [Function],
|
|
||||||
"recordDeleteFeedback": [Function],
|
|
||||||
"title": [Function],
|
|
||||||
"visible": [Function],
|
|
||||||
},
|
|
||||||
"deleteCollectionText": [Function],
|
"deleteCollectionText": [Function],
|
||||||
"deleteDatabaseText": [Function],
|
"deleteDatabaseText": [Function],
|
||||||
"editTableEntityPane": EditTableEntityPane {
|
"editTableEntityPane": EditTableEntityPane {
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -134,21 +134,6 @@ exports[`Delete Database Confirmation Pane submit() Should call delete database
|
||||||
"useIndexingForSharedThroughput": [Function],
|
"useIndexingForSharedThroughput": [Function],
|
||||||
"visible": [Function],
|
"visible": [Function],
|
||||||
},
|
},
|
||||||
DeleteCollectionConfirmationPane {
|
|
||||||
"collectionIdConfirmation": [Function],
|
|
||||||
"collectionIdConfirmationText": [Function],
|
|
||||||
"container": [Circular],
|
|
||||||
"containerDeleteFeedback": [Function],
|
|
||||||
"firstFieldHasFocus": [Function],
|
|
||||||
"formErrors": [Function],
|
|
||||||
"formErrorsDetails": [Function],
|
|
||||||
"id": "deletecollectionconfirmationpane",
|
|
||||||
"isExecuting": [Function],
|
|
||||||
"isTemplateReady": [Function],
|
|
||||||
"recordDeleteFeedback": [Function],
|
|
||||||
"title": [Function],
|
|
||||||
"visible": [Function],
|
|
||||||
},
|
|
||||||
GraphStylingPane {
|
GraphStylingPane {
|
||||||
"container": [Circular],
|
"container": [Circular],
|
||||||
"firstFieldHasFocus": [Function],
|
"firstFieldHasFocus": [Function],
|
||||||
|
@ -571,21 +556,6 @@ exports[`Delete Database Confirmation Pane submit() Should call delete database
|
||||||
"databaseAccount": [Function],
|
"databaseAccount": [Function],
|
||||||
"databases": [Function],
|
"databases": [Function],
|
||||||
"defaultExperience": [Function],
|
"defaultExperience": [Function],
|
||||||
"deleteCollectionConfirmationPane": DeleteCollectionConfirmationPane {
|
|
||||||
"collectionIdConfirmation": [Function],
|
|
||||||
"collectionIdConfirmationText": [Function],
|
|
||||||
"container": [Circular],
|
|
||||||
"containerDeleteFeedback": [Function],
|
|
||||||
"firstFieldHasFocus": [Function],
|
|
||||||
"formErrors": [Function],
|
|
||||||
"formErrorsDetails": [Function],
|
|
||||||
"id": "deletecollectionconfirmationpane",
|
|
||||||
"isExecuting": [Function],
|
|
||||||
"isTemplateReady": [Function],
|
|
||||||
"recordDeleteFeedback": [Function],
|
|
||||||
"title": [Function],
|
|
||||||
"visible": [Function],
|
|
||||||
},
|
|
||||||
"deleteCollectionText": [Function],
|
"deleteCollectionText": [Function],
|
||||||
"deleteDatabaseText": [Function],
|
"deleteDatabaseText": [Function],
|
||||||
"editTableEntityPane": EditTableEntityPane {
|
"editTableEntityPane": EditTableEntityPane {
|
||||||
|
|
|
@ -231,7 +231,6 @@ const App: React.FunctionComponent = () => {
|
||||||
/>
|
/>
|
||||||
<div data-bind='component: { name: "add-database-pane", params: {data: addDatabasePane} }' />
|
<div data-bind='component: { name: "add-database-pane", params: {data: addDatabasePane} }' />
|
||||||
<div data-bind='component: { name: "add-collection-pane", params: { data: addCollectionPane} }' />
|
<div data-bind='component: { name: "add-collection-pane", params: { data: addCollectionPane} }' />
|
||||||
<div data-bind='component: { name: "delete-collection-confirmation-pane", params: { data: deleteCollectionConfirmationPane} }' />
|
|
||||||
<div data-bind='component: { name: "graph-new-vertex-pane", params: { data: newVertexPane} }' />
|
<div data-bind='component: { name: "graph-new-vertex-pane", params: { data: newVertexPane} }' />
|
||||||
<div data-bind='component: { name: "graph-styling-pane", params: { data: graphStylingPane} }' />
|
<div data-bind='component: { name: "graph-styling-pane", params: { data: graphStylingPane} }' />
|
||||||
<div data-bind='component: { name: "table-add-entity-pane", params: { data: addTableEntityPane} }' />
|
<div data-bind='component: { name: "table-add-entity-pane", params: { data: addTableEntityPane} }' />
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import * as AutoPilotUtils from "../Utils/AutoPilotUtils";
|
|
||||||
import * as Constants from "../Shared/Constants";
|
|
||||||
import { DefaultAccountExperienceType } from "../DefaultAccountExperienceType";
|
import { DefaultAccountExperienceType } from "../DefaultAccountExperienceType";
|
||||||
|
import * as Constants from "../Shared/Constants";
|
||||||
|
import * as AutoPilotUtils from "../Utils/AutoPilotUtils";
|
||||||
|
|
||||||
interface ComputeRUUsagePriceHourlyArgs {
|
interface ComputeRUUsagePriceHourlyArgs {
|
||||||
serverId: string;
|
serverId: string;
|
||||||
|
@ -282,7 +282,7 @@ export function getUpsellMessage(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function getCollectionName(defaultExperience: string): string {
|
export function getCollectionName(defaultExperience: string): string {
|
||||||
switch (defaultExperience) {
|
switch (defaultExperience) {
|
||||||
case DefaultAccountExperienceType.DocumentDB:
|
case DefaultAccountExperienceType.DocumentDB:
|
||||||
return "container";
|
return "container";
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import "expect-puppeteer";
|
import "expect-puppeteer";
|
||||||
import { Frame } from "puppeteer";
|
import { Frame } from "puppeteer";
|
||||||
import { generateDatabaseName, generateUniqueName, login } from "../utils/shared";
|
import { generateDatabaseName, generateUniqueName } from "../utils/shared";
|
||||||
|
|
||||||
jest.setTimeout(300000);
|
jest.setTimeout(300000);
|
||||||
const LOADING_STATE_DELAY = 2500;
|
const LOADING_STATE_DELAY = 2500;
|
||||||
|
@ -14,7 +14,9 @@ describe("Collection Add and Delete SQL spec", () => {
|
||||||
const dbId = generateDatabaseName();
|
const dbId = generateDatabaseName();
|
||||||
const collectionId = generateUniqueName("col");
|
const collectionId = generateUniqueName("col");
|
||||||
const sharedKey = `/skey${generateUniqueName()}`;
|
const sharedKey = `/skey${generateUniqueName()}`;
|
||||||
const frame = await login(process.env.PORTAL_RUNNER_CONNECTION_STRING);
|
await page.goto("https://localhost:1234/testExplorer.html?accountName=portal-sql-runner");
|
||||||
|
const handle = await page.waitForSelector("iframe");
|
||||||
|
const frame = await handle.contentFrame();
|
||||||
|
|
||||||
// create new collection
|
// create new collection
|
||||||
await frame.waitFor('button[data-test="New Container"]', { visible: true });
|
await frame.waitFor('button[data-test="New Container"]', { visible: true });
|
||||||
|
@ -99,8 +101,8 @@ describe("Collection Add and Delete SQL spec", () => {
|
||||||
await frame.type('input[id="confirmCollectionId"]', textId);
|
await frame.type('input[id="confirmCollectionId"]', textId);
|
||||||
|
|
||||||
// click delete
|
// click delete
|
||||||
await frame.waitFor('button[id="sidePanelOkButton"]', { visible: true });
|
await frame.waitFor("button.genericPaneSubmitBtn", { visible: true });
|
||||||
await frame.click('button[id="sidePanelOkButton"]');
|
await frame.click("button.genericPaneSubmitBtn");
|
||||||
await frame.waitFor(LOADING_STATE_DELAY);
|
await frame.waitFor(LOADING_STATE_DELAY);
|
||||||
await frame.waitForSelector('div[class="splashScreen"] > div[class="title"]', { visible: true });
|
await frame.waitForSelector('div[class="splashScreen"] > div[class="title"]', { visible: true });
|
||||||
|
|
||||||
|
@ -109,25 +111,25 @@ describe("Collection Add and Delete SQL spec", () => {
|
||||||
|
|
||||||
// click context menu for database
|
// click context menu for database
|
||||||
await frame.waitFor(`div[data-test="${selectedDbId}"] > div > button`);
|
await frame.waitFor(`div[data-test="${selectedDbId}"] > div > button`);
|
||||||
await frame.waitFor(RENDER_DELAY);
|
await frame.waitFor(CREATE_DELAY);
|
||||||
const button = await frame.$(`div[data-test="${selectedDbId}"] > div > button`);
|
const button = await frame.$(`div[data-test="${selectedDbId}"] > div > button`);
|
||||||
await button.focus();
|
await button.focus();
|
||||||
await button.asElement().click();
|
await button.asElement().click();
|
||||||
|
|
||||||
// click delete database
|
// click delete database
|
||||||
await frame.waitFor(RENDER_DELAY);
|
await frame.waitFor(CREATE_DELAY);
|
||||||
await frame.waitFor('span[class="treeComponentMenuItemLabel deleteDatabaseMenuItemLabel"]');
|
await frame.waitFor('span[class="treeComponentMenuItemLabel deleteDatabaseMenuItemLabel"]');
|
||||||
await frame.click('span[class="treeComponentMenuItemLabel deleteDatabaseMenuItemLabel"]');
|
await frame.click('span[class="treeComponentMenuItemLabel deleteDatabaseMenuItemLabel"]');
|
||||||
|
|
||||||
// confirm delete database
|
// confirm delete database
|
||||||
await frame.waitForSelector('input[id="confirmDatabaseId"]', { visible: true });
|
await frame.waitForSelector('input[id="confirmDatabaseId"]', { visible: true });
|
||||||
await frame.waitFor(RENDER_DELAY);
|
await frame.waitFor(CREATE_DELAY);
|
||||||
await frame.type('input[id="confirmDatabaseId"]', selectedDbId);
|
await frame.type('input[id="confirmDatabaseId"]', selectedDbId);
|
||||||
|
|
||||||
// click delete
|
// click delete
|
||||||
await frame.click('button[id="sidePanelOkButton"]');
|
await frame.click('button[id="sidePanelOkButton"]');
|
||||||
await frame.waitForSelector('div[class="splashScreen"] > div[class="title"]', { visible: true });
|
await frame.waitForSelector('div[class="splashScreen"] > div[class="title"]', { visible: true });
|
||||||
await frame.waitFor(LOADING_STATE_DELAY);
|
await frame.waitFor(CREATE_DELAY);
|
||||||
await frame.waitForSelector('div[class="splashScreen"] > div[class="title"]', { visible: true });
|
await frame.waitForSelector('div[class="splashScreen"] > div[class="title"]', { visible: true });
|
||||||
await expect(page).not.toMatchElement(`div[data-test="${selectedDbId}"]`);
|
await expect(page).not.toMatchElement(`div[data-test="${selectedDbId}"]`);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|
|
@ -72,8 +72,8 @@ describe("Collection Add and Delete Tables spec", () => {
|
||||||
await frame.type('input[id="confirmCollectionId"]', textId);
|
await frame.type('input[id="confirmCollectionId"]', textId);
|
||||||
|
|
||||||
// click delete
|
// click delete
|
||||||
await frame.waitFor('button[id="sidePanelOkButton"]', { visible: true });
|
await frame.waitFor("button.genericPaneSubmitBtn", { visible: true });
|
||||||
await frame.click('button[id="sidePanelOkButton"]');
|
await frame.click("button.genericPaneSubmitBtn");
|
||||||
await frame.waitFor(LOADING_STATE_DELAY);
|
await frame.waitFor(LOADING_STATE_DELAY);
|
||||||
await frame.waitForSelector('div[class="splashScreen"] > div[class="title"]', { visible: true });
|
await frame.waitForSelector('div[class="splashScreen"] > div[class="title"]', { visible: true });
|
||||||
await frame.waitFor(LOADING_STATE_DELAY);
|
await frame.waitFor(LOADING_STATE_DELAY);
|
||||||
|
|
Loading…
Reference in New Issue