mirror of
https://github.com/Azure/cosmos-explorer.git
synced 2025-02-16 17:25:58 +00:00
Migrate new graph vertex panel to react (#702)
Co-authored-by: Steve Faulkner <southpolesteve@gmail.com>
This commit is contained in:
parent
9d411c57b0
commit
c6766dd69e
@ -90,8 +90,7 @@ src/Explorer/Graph/GraphExplorerComponent/GremlinSimpleClient.test.ts
|
|||||||
src/Explorer/Graph/GraphExplorerComponent/GremlinSimpleClient.ts
|
src/Explorer/Graph/GraphExplorerComponent/GremlinSimpleClient.ts
|
||||||
src/Explorer/Graph/GraphStyleComponent/GraphStyle.test.ts
|
src/Explorer/Graph/GraphStyleComponent/GraphStyle.test.ts
|
||||||
src/Explorer/Graph/GraphStyleComponent/GraphStyleComponent.ts
|
src/Explorer/Graph/GraphStyleComponent/GraphStyleComponent.ts
|
||||||
src/Explorer/Graph/NewVertexComponent/NewVertex.test.ts
|
|
||||||
src/Explorer/Graph/NewVertexComponent/NewVertexComponent.ts
|
|
||||||
src/Explorer/Menus/CommandBar/CommandBarComponentButtonFactory.test.ts
|
src/Explorer/Menus/CommandBar/CommandBarComponentButtonFactory.test.ts
|
||||||
src/Explorer/Menus/CommandBar/CommandBarComponentButtonFactory.ts
|
src/Explorer/Menus/CommandBar/CommandBarComponentButtonFactory.ts
|
||||||
src/Explorer/Menus/ContextMenu.ts
|
src/Explorer/Menus/ContextMenu.ts
|
||||||
@ -123,7 +122,7 @@ src/Explorer/Panes/ContextualPaneBase.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
|
||||||
src/Explorer/Panes/NewVertexPane.ts
|
# src/Explorer/Panes/NewVertexPane.ts
|
||||||
src/Explorer/Panes/PaneComponents.ts
|
src/Explorer/Panes/PaneComponents.ts
|
||||||
src/Explorer/Panes/RenewAdHocAccessPane.ts
|
src/Explorer/Panes/RenewAdHocAccessPane.ts
|
||||||
src/Explorer/Panes/StringInputPane.ts
|
src/Explorer/Panes/StringInputPane.ts
|
||||||
|
@ -8,10 +8,6 @@ describe("Component Registerer", () => {
|
|||||||
expect(ko.components.isRegistered("input-typeahead")).toBe(true);
|
expect(ko.components.isRegistered("input-typeahead")).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should register new-vertex-form component", () => {
|
|
||||||
expect(ko.components.isRegistered("new-vertex-form")).toBe(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should register error-display component", () => {
|
it("should register error-display component", () => {
|
||||||
expect(ko.components.isRegistered("error-display")).toBe(true);
|
expect(ko.components.isRegistered("error-display")).toBe(true);
|
||||||
});
|
});
|
||||||
@ -73,10 +69,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 graph-new-vertex-pane component", () => {
|
|
||||||
expect(ko.components.isRegistered("graph-new-vertex-pane")).toBe(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should register graph-styling-pane component", () => {
|
it("should register graph-styling-pane component", () => {
|
||||||
expect(ko.components.isRegistered("graph-styling-pane")).toBe(true);
|
expect(ko.components.isRegistered("graph-styling-pane")).toBe(true);
|
||||||
});
|
});
|
||||||
|
@ -7,7 +7,6 @@ import { InputTypeaheadComponent } from "./Controls/InputTypeahead/InputTypeahea
|
|||||||
import { JsonEditorComponent } from "./Controls/JsonEditor/JsonEditorComponent";
|
import { JsonEditorComponent } from "./Controls/JsonEditor/JsonEditorComponent";
|
||||||
import { ThroughputInputComponentAutoPilotV3 } from "./Controls/ThroughputInput/ThroughputInputComponentAutoPilotV3";
|
import { ThroughputInputComponentAutoPilotV3 } from "./Controls/ThroughputInput/ThroughputInputComponentAutoPilotV3";
|
||||||
import { GraphStyleComponent } from "./Graph/GraphStyleComponent/GraphStyleComponent";
|
import { GraphStyleComponent } from "./Graph/GraphStyleComponent/GraphStyleComponent";
|
||||||
import { NewVertexComponent } from "./Graph/NewVertexComponent/NewVertexComponent";
|
|
||||||
import * as PaneComponents from "./Panes/PaneComponents";
|
import * as PaneComponents from "./Panes/PaneComponents";
|
||||||
import ConflictsTab from "./Tabs/ConflictsTab";
|
import ConflictsTab from "./Tabs/ConflictsTab";
|
||||||
import DocumentsTab from "./Tabs/DocumentsTab";
|
import DocumentsTab from "./Tabs/DocumentsTab";
|
||||||
@ -25,7 +24,6 @@ import TriggerTab from "./Tabs/TriggerTab";
|
|||||||
import UserDefinedFunctionTab from "./Tabs/UserDefinedFunctionTab";
|
import UserDefinedFunctionTab from "./Tabs/UserDefinedFunctionTab";
|
||||||
|
|
||||||
ko.components.register("input-typeahead", new InputTypeaheadComponent());
|
ko.components.register("input-typeahead", new InputTypeaheadComponent());
|
||||||
ko.components.register("new-vertex-form", NewVertexComponent);
|
|
||||||
ko.components.register("error-display", new ErrorDisplayComponent());
|
ko.components.register("error-display", new ErrorDisplayComponent());
|
||||||
ko.components.register("graph-style", GraphStyleComponent);
|
ko.components.register("graph-style", GraphStyleComponent);
|
||||||
ko.components.register("editor", new EditorComponent());
|
ko.components.register("editor", new EditorComponent());
|
||||||
@ -56,7 +54,6 @@ ko.components.register("throughput-input-autopilot-v3", ThroughputInputComponent
|
|||||||
// 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("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());
|
||||||
ko.components.register("table-add-entity-pane", new PaneComponents.TableAddEntityPaneComponent());
|
ko.components.register("table-add-entity-pane", new PaneComponents.TableAddEntityPaneComponent());
|
||||||
ko.components.register("table-edit-entity-pane", new PaneComponents.TableEditEntityPaneComponent());
|
ko.components.register("table-edit-entity-pane", new PaneComponents.TableEditEntityPaneComponent());
|
||||||
|
@ -211,22 +211,6 @@ exports[`SettingsComponent renders 1`] = `
|
|||||||
"title": [Function],
|
"title": [Function],
|
||||||
"visible": [Function],
|
"visible": [Function],
|
||||||
},
|
},
|
||||||
NewVertexPane {
|
|
||||||
"buildString": [Function],
|
|
||||||
"container": [Circular],
|
|
||||||
"firstFieldHasFocus": [Function],
|
|
||||||
"formErrors": [Function],
|
|
||||||
"formErrorsDetails": [Function],
|
|
||||||
"id": "newvertexpane",
|
|
||||||
"isExecuting": [Function],
|
|
||||||
"isTemplateReady": [Function],
|
|
||||||
"onMoreDetailsKeyPress": [Function],
|
|
||||||
"onSubmitCreateCallback": null,
|
|
||||||
"partitionKeyProperty": [Function],
|
|
||||||
"tempVertexData": [Function],
|
|
||||||
"title": [Function],
|
|
||||||
"visible": [Function],
|
|
||||||
},
|
|
||||||
CassandraAddCollectionPane {
|
CassandraAddCollectionPane {
|
||||||
"autoPilotUsageCost": [Function],
|
"autoPilotUsageCost": [Function],
|
||||||
"canConfigureThroughput": [Function],
|
"canConfigureThroughput": [Function],
|
||||||
@ -571,22 +555,6 @@ exports[`SettingsComponent renders 1`] = `
|
|||||||
"isSynapseLinkUpdating": [Function],
|
"isSynapseLinkUpdating": [Function],
|
||||||
"isTabsContentExpanded": [Function],
|
"isTabsContentExpanded": [Function],
|
||||||
"memoryUsageInfo": [Function],
|
"memoryUsageInfo": [Function],
|
||||||
"newVertexPane": NewVertexPane {
|
|
||||||
"buildString": [Function],
|
|
||||||
"container": [Circular],
|
|
||||||
"firstFieldHasFocus": [Function],
|
|
||||||
"formErrors": [Function],
|
|
||||||
"formErrorsDetails": [Function],
|
|
||||||
"id": "newvertexpane",
|
|
||||||
"isExecuting": [Function],
|
|
||||||
"isTemplateReady": [Function],
|
|
||||||
"onMoreDetailsKeyPress": [Function],
|
|
||||||
"onSubmitCreateCallback": null,
|
|
||||||
"partitionKeyProperty": [Function],
|
|
||||||
"tempVertexData": [Function],
|
|
||||||
"title": [Function],
|
|
||||||
"visible": [Function],
|
|
||||||
},
|
|
||||||
"notebookBasePath": [Function],
|
"notebookBasePath": [Function],
|
||||||
"notebookServerInfo": [Function],
|
"notebookServerInfo": [Function],
|
||||||
"onRefreshDatabasesKeyPress": [Function],
|
"onRefreshDatabasesKeyPress": [Function],
|
||||||
@ -871,22 +839,6 @@ exports[`SettingsComponent renders 1`] = `
|
|||||||
"title": [Function],
|
"title": [Function],
|
||||||
"visible": [Function],
|
"visible": [Function],
|
||||||
},
|
},
|
||||||
NewVertexPane {
|
|
||||||
"buildString": [Function],
|
|
||||||
"container": [Circular],
|
|
||||||
"firstFieldHasFocus": [Function],
|
|
||||||
"formErrors": [Function],
|
|
||||||
"formErrorsDetails": [Function],
|
|
||||||
"id": "newvertexpane",
|
|
||||||
"isExecuting": [Function],
|
|
||||||
"isTemplateReady": [Function],
|
|
||||||
"onMoreDetailsKeyPress": [Function],
|
|
||||||
"onSubmitCreateCallback": null,
|
|
||||||
"partitionKeyProperty": [Function],
|
|
||||||
"tempVertexData": [Function],
|
|
||||||
"title": [Function],
|
|
||||||
"visible": [Function],
|
|
||||||
},
|
|
||||||
CassandraAddCollectionPane {
|
CassandraAddCollectionPane {
|
||||||
"autoPilotUsageCost": [Function],
|
"autoPilotUsageCost": [Function],
|
||||||
"canConfigureThroughput": [Function],
|
"canConfigureThroughput": [Function],
|
||||||
@ -1231,22 +1183,6 @@ exports[`SettingsComponent renders 1`] = `
|
|||||||
"isSynapseLinkUpdating": [Function],
|
"isSynapseLinkUpdating": [Function],
|
||||||
"isTabsContentExpanded": [Function],
|
"isTabsContentExpanded": [Function],
|
||||||
"memoryUsageInfo": [Function],
|
"memoryUsageInfo": [Function],
|
||||||
"newVertexPane": NewVertexPane {
|
|
||||||
"buildString": [Function],
|
|
||||||
"container": [Circular],
|
|
||||||
"firstFieldHasFocus": [Function],
|
|
||||||
"formErrors": [Function],
|
|
||||||
"formErrorsDetails": [Function],
|
|
||||||
"id": "newvertexpane",
|
|
||||||
"isExecuting": [Function],
|
|
||||||
"isTemplateReady": [Function],
|
|
||||||
"onMoreDetailsKeyPress": [Function],
|
|
||||||
"onSubmitCreateCallback": null,
|
|
||||||
"partitionKeyProperty": [Function],
|
|
||||||
"tempVertexData": [Function],
|
|
||||||
"title": [Function],
|
|
||||||
"visible": [Function],
|
|
||||||
},
|
|
||||||
"notebookBasePath": [Function],
|
"notebookBasePath": [Function],
|
||||||
"notebookServerInfo": [Function],
|
"notebookServerInfo": [Function],
|
||||||
"onRefreshDatabasesKeyPress": [Function],
|
"onRefreshDatabasesKeyPress": [Function],
|
||||||
@ -1544,22 +1480,6 @@ exports[`SettingsComponent renders 1`] = `
|
|||||||
"title": [Function],
|
"title": [Function],
|
||||||
"visible": [Function],
|
"visible": [Function],
|
||||||
},
|
},
|
||||||
NewVertexPane {
|
|
||||||
"buildString": [Function],
|
|
||||||
"container": [Circular],
|
|
||||||
"firstFieldHasFocus": [Function],
|
|
||||||
"formErrors": [Function],
|
|
||||||
"formErrorsDetails": [Function],
|
|
||||||
"id": "newvertexpane",
|
|
||||||
"isExecuting": [Function],
|
|
||||||
"isTemplateReady": [Function],
|
|
||||||
"onMoreDetailsKeyPress": [Function],
|
|
||||||
"onSubmitCreateCallback": null,
|
|
||||||
"partitionKeyProperty": [Function],
|
|
||||||
"tempVertexData": [Function],
|
|
||||||
"title": [Function],
|
|
||||||
"visible": [Function],
|
|
||||||
},
|
|
||||||
CassandraAddCollectionPane {
|
CassandraAddCollectionPane {
|
||||||
"autoPilotUsageCost": [Function],
|
"autoPilotUsageCost": [Function],
|
||||||
"canConfigureThroughput": [Function],
|
"canConfigureThroughput": [Function],
|
||||||
@ -1904,22 +1824,6 @@ exports[`SettingsComponent renders 1`] = `
|
|||||||
"isSynapseLinkUpdating": [Function],
|
"isSynapseLinkUpdating": [Function],
|
||||||
"isTabsContentExpanded": [Function],
|
"isTabsContentExpanded": [Function],
|
||||||
"memoryUsageInfo": [Function],
|
"memoryUsageInfo": [Function],
|
||||||
"newVertexPane": NewVertexPane {
|
|
||||||
"buildString": [Function],
|
|
||||||
"container": [Circular],
|
|
||||||
"firstFieldHasFocus": [Function],
|
|
||||||
"formErrors": [Function],
|
|
||||||
"formErrorsDetails": [Function],
|
|
||||||
"id": "newvertexpane",
|
|
||||||
"isExecuting": [Function],
|
|
||||||
"isTemplateReady": [Function],
|
|
||||||
"onMoreDetailsKeyPress": [Function],
|
|
||||||
"onSubmitCreateCallback": null,
|
|
||||||
"partitionKeyProperty": [Function],
|
|
||||||
"tempVertexData": [Function],
|
|
||||||
"title": [Function],
|
|
||||||
"visible": [Function],
|
|
||||||
},
|
|
||||||
"notebookBasePath": [Function],
|
"notebookBasePath": [Function],
|
||||||
"notebookServerInfo": [Function],
|
"notebookServerInfo": [Function],
|
||||||
"onRefreshDatabasesKeyPress": [Function],
|
"onRefreshDatabasesKeyPress": [Function],
|
||||||
@ -2204,22 +2108,6 @@ exports[`SettingsComponent renders 1`] = `
|
|||||||
"title": [Function],
|
"title": [Function],
|
||||||
"visible": [Function],
|
"visible": [Function],
|
||||||
},
|
},
|
||||||
NewVertexPane {
|
|
||||||
"buildString": [Function],
|
|
||||||
"container": [Circular],
|
|
||||||
"firstFieldHasFocus": [Function],
|
|
||||||
"formErrors": [Function],
|
|
||||||
"formErrorsDetails": [Function],
|
|
||||||
"id": "newvertexpane",
|
|
||||||
"isExecuting": [Function],
|
|
||||||
"isTemplateReady": [Function],
|
|
||||||
"onMoreDetailsKeyPress": [Function],
|
|
||||||
"onSubmitCreateCallback": null,
|
|
||||||
"partitionKeyProperty": [Function],
|
|
||||||
"tempVertexData": [Function],
|
|
||||||
"title": [Function],
|
|
||||||
"visible": [Function],
|
|
||||||
},
|
|
||||||
CassandraAddCollectionPane {
|
CassandraAddCollectionPane {
|
||||||
"autoPilotUsageCost": [Function],
|
"autoPilotUsageCost": [Function],
|
||||||
"canConfigureThroughput": [Function],
|
"canConfigureThroughput": [Function],
|
||||||
@ -2564,22 +2452,6 @@ exports[`SettingsComponent renders 1`] = `
|
|||||||
"isSynapseLinkUpdating": [Function],
|
"isSynapseLinkUpdating": [Function],
|
||||||
"isTabsContentExpanded": [Function],
|
"isTabsContentExpanded": [Function],
|
||||||
"memoryUsageInfo": [Function],
|
"memoryUsageInfo": [Function],
|
||||||
"newVertexPane": NewVertexPane {
|
|
||||||
"buildString": [Function],
|
|
||||||
"container": [Circular],
|
|
||||||
"firstFieldHasFocus": [Function],
|
|
||||||
"formErrors": [Function],
|
|
||||||
"formErrorsDetails": [Function],
|
|
||||||
"id": "newvertexpane",
|
|
||||||
"isExecuting": [Function],
|
|
||||||
"isTemplateReady": [Function],
|
|
||||||
"onMoreDetailsKeyPress": [Function],
|
|
||||||
"onSubmitCreateCallback": null,
|
|
||||||
"partitionKeyProperty": [Function],
|
|
||||||
"tempVertexData": [Function],
|
|
||||||
"title": [Function],
|
|
||||||
"visible": [Function],
|
|
||||||
},
|
|
||||||
"notebookBasePath": [Function],
|
"notebookBasePath": [Function],
|
||||||
"notebookServerInfo": [Function],
|
"notebookServerInfo": [Function],
|
||||||
"onRefreshDatabasesKeyPress": [Function],
|
"onRefreshDatabasesKeyPress": [Function],
|
||||||
|
@ -59,7 +59,6 @@ import { DeleteDatabaseConfirmationPanel } from "./Panes/DeleteDatabaseConfirmat
|
|||||||
import { ExecuteSprocParamsPane } from "./Panes/ExecuteSprocParamsPane/ExecuteSprocParamsPane";
|
import { ExecuteSprocParamsPane } from "./Panes/ExecuteSprocParamsPane/ExecuteSprocParamsPane";
|
||||||
import GraphStylingPane from "./Panes/GraphStylingPane";
|
import GraphStylingPane from "./Panes/GraphStylingPane";
|
||||||
import { LoadQueryPane } from "./Panes/LoadQueryPane/LoadQueryPane";
|
import { LoadQueryPane } from "./Panes/LoadQueryPane/LoadQueryPane";
|
||||||
import NewVertexPane from "./Panes/NewVertexPane";
|
|
||||||
import { SaveQueryPane } from "./Panes/SaveQueryPane/SaveQueryPane";
|
import { SaveQueryPane } from "./Panes/SaveQueryPane/SaveQueryPane";
|
||||||
import { SettingsPane } from "./Panes/SettingsPane/SettingsPane";
|
import { SettingsPane } from "./Panes/SettingsPane/SettingsPane";
|
||||||
import { SetupNoteBooksPanel } from "./Panes/SetupNotebooksPanel/SetupNotebooksPanel";
|
import { SetupNoteBooksPanel } from "./Panes/SetupNotebooksPanel/SetupNotebooksPanel";
|
||||||
@ -175,7 +174,6 @@ export default class Explorer {
|
|||||||
public addCollectionPane: AddCollectionPane;
|
public addCollectionPane: AddCollectionPane;
|
||||||
public graphStylingPane: GraphStylingPane;
|
public graphStylingPane: GraphStylingPane;
|
||||||
public editTableEntityPane: EditTableEntityPane;
|
public editTableEntityPane: EditTableEntityPane;
|
||||||
public newVertexPane: NewVertexPane;
|
|
||||||
public cassandraAddCollectionPane: CassandraAddCollectionPane;
|
public cassandraAddCollectionPane: CassandraAddCollectionPane;
|
||||||
public stringInputPane: StringInputPane;
|
public stringInputPane: StringInputPane;
|
||||||
public gitHubReposPane: ContextualPaneBase;
|
public gitHubReposPane: ContextualPaneBase;
|
||||||
@ -509,13 +507,6 @@ export default class Explorer {
|
|||||||
container: this,
|
container: this,
|
||||||
});
|
});
|
||||||
|
|
||||||
this.newVertexPane = new NewVertexPane({
|
|
||||||
id: "newvertexpane",
|
|
||||||
visible: ko.observable<boolean>(false),
|
|
||||||
|
|
||||||
container: this,
|
|
||||||
});
|
|
||||||
|
|
||||||
this.cassandraAddCollectionPane = new CassandraAddCollectionPane({
|
this.cassandraAddCollectionPane = new CassandraAddCollectionPane({
|
||||||
id: "cassandraaddcollectionpane",
|
id: "cassandraaddcollectionpane",
|
||||||
visible: ko.observable<boolean>(false),
|
visible: ko.observable<boolean>(false),
|
||||||
@ -543,7 +534,6 @@ export default class Explorer {
|
|||||||
this.addCollectionPane,
|
this.addCollectionPane,
|
||||||
this.graphStylingPane,
|
this.graphStylingPane,
|
||||||
this.editTableEntityPane,
|
this.editTableEntityPane,
|
||||||
this.newVertexPane,
|
|
||||||
this.cassandraAddCollectionPane,
|
this.cassandraAddCollectionPane,
|
||||||
this.stringInputPane,
|
this.stringInputPane,
|
||||||
];
|
];
|
||||||
|
@ -1,75 +0,0 @@
|
|||||||
import * as ko from "knockout";
|
|
||||||
import { NewVertexComponent, NewVertexViewModel } from "./NewVertexComponent";
|
|
||||||
|
|
||||||
const component = NewVertexComponent;
|
|
||||||
|
|
||||||
describe("New Vertex Component", () => {
|
|
||||||
let vm: NewVertexViewModel;
|
|
||||||
let partitionKeyProperty: ko.Observable<string>;
|
|
||||||
|
|
||||||
beforeEach(async () => {
|
|
||||||
document.body.innerHTML = component.template as any;
|
|
||||||
partitionKeyProperty = ko.observable(null);
|
|
||||||
vm = new component.viewModel({
|
|
||||||
newVertexData: null,
|
|
||||||
partitionKeyProperty,
|
|
||||||
});
|
|
||||||
ko.applyBindings(vm);
|
|
||||||
});
|
|
||||||
|
|
||||||
afterEach(() => {
|
|
||||||
ko.cleanNode(document);
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("Rendering", () => {
|
|
||||||
it("should display property list with input and +Add Property", () => {
|
|
||||||
expect(document.querySelector(".newVertexComponent .newVertexForm")).not.toBeNull();
|
|
||||||
expect(document.querySelector(".newVertexComponent .edgeInput")).not.toBeNull();
|
|
||||||
expect(document.querySelector(".newVertexComponent .rightPaneAddPropertyBtn")).not.toBeNull();
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should display partition key property if set", () => {
|
|
||||||
partitionKeyProperty("testKey");
|
|
||||||
expect(
|
|
||||||
(document.querySelector(".newVertexComponent .newVertexForm .labelCol input") as HTMLInputElement).value
|
|
||||||
).toEqual("testKey");
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should NOT display partition key property if NOT set", () => {
|
|
||||||
expect(document.getElementsByClassName("valueCol").length).toBe(0);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("Behavior", () => {
|
|
||||||
let clickSpy: jasmine.Spy;
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
clickSpy = jasmine.createSpy("Command button click spy");
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should add new property row when +Add property button is pressed", () => {
|
|
||||||
document.querySelector(".newVertexComponent .rightPaneAddPropertyBtn").dispatchEvent(new Event("click"));
|
|
||||||
document.querySelector(".newVertexComponent .rightPaneAddPropertyBtn").dispatchEvent(new Event("click"));
|
|
||||||
document.querySelector(".newVertexComponent .rightPaneAddPropertyBtn").dispatchEvent(new Event("click"));
|
|
||||||
expect(document.getElementsByClassName("valueCol").length).toBe(3);
|
|
||||||
expect(document.getElementsByClassName("rightPaneTrashIcon").length).toBe(3);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should remove property row when trash button is pressed", () => {
|
|
||||||
document.querySelector(".newVertexComponent .rightPaneAddPropertyBtn").dispatchEvent(new Event("click"));
|
|
||||||
document.querySelector(".newVertexComponent .rightPaneAddPropertyBtn").dispatchEvent(new Event("click"));
|
|
||||||
|
|
||||||
// Mark this one to delete
|
|
||||||
const elts = document.querySelectorAll(".newVertexComponent .rightPaneTrashIconImg");
|
|
||||||
elts[elts.length - 1].className += " deleteme";
|
|
||||||
|
|
||||||
document.querySelector(".newVertexComponent .rightPaneAddPropertyBtn").dispatchEvent(new Event("click"));
|
|
||||||
document
|
|
||||||
.querySelector(".newVertexComponent .rightPaneTrashIconImg.deleteme")
|
|
||||||
.parentElement.dispatchEvent(new Event("click"));
|
|
||||||
expect(document.getElementsByClassName("valueCol").length).toBe(2);
|
|
||||||
expect(document.getElementsByClassName("rightPaneTrashIcon").length).toBe(2);
|
|
||||||
expect(document.querySelectorAll(".newVertexComponent .rightPaneTrashIconImg.deleteme").length).toBe(0);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,74 +0,0 @@
|
|||||||
<div class="newVertexComponent" data-bind="setTemplateReady: true">
|
|
||||||
<div class="newVertexForm">
|
|
||||||
<div class="newVertexFormRow">
|
|
||||||
<label for="VertexLabel" class="labelCol">Label</label>
|
|
||||||
<input
|
|
||||||
class="edgeInput"
|
|
||||||
type="text"
|
|
||||||
data-bind="textInput:$data.newVertexData().label, hasFocus: $data.firstFieldHasFocus"
|
|
||||||
aria-label="Enter vertex label"
|
|
||||||
role="textbox"
|
|
||||||
tabindex="0"
|
|
||||||
placeholder="Enter vertex label"
|
|
||||||
autocomplete="off"
|
|
||||||
id="VertexLabel"
|
|
||||||
/>
|
|
||||||
<div class="actionCol"></div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- ko foreach:{ data:newVertexData().properties, as: 'property' } -->
|
|
||||||
<div class="newVertexFormRow">
|
|
||||||
<div class="labelCol">
|
|
||||||
<input
|
|
||||||
type="text"
|
|
||||||
id="propertyKeyNewVertexPane"
|
|
||||||
data-bind="textInput: property.key, attr: { 'aria-label': 'Enter key for property '+ ($index() + 1) }"
|
|
||||||
placeholder="Key"
|
|
||||||
autocomplete="off"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div class="valueCol">
|
|
||||||
<input
|
|
||||||
class="edgeInput"
|
|
||||||
type="text"
|
|
||||||
data-bind="textInput: property.values[0].value, , attr: { 'aria-label': 'Enter value for property '+ ($index() + 1) }"
|
|
||||||
placeholder="Value"
|
|
||||||
autocomplete="off"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<select
|
|
||||||
class="typeSelect"
|
|
||||||
required
|
|
||||||
data-bind="options:$parent.propertyTypes, value:property.values[0].type, attr: { 'aria-label': property.values[0].type + ': for property '+ ($index() + 1) }"
|
|
||||||
></select>
|
|
||||||
</div>
|
|
||||||
<div class="actionCol">
|
|
||||||
<div
|
|
||||||
class="rightPaneTrashIcon rightPaneBtns"
|
|
||||||
data-bind="click:$parent.removeNewVertexProperty.bind($parent, $index()), event: { keypress: $parent.removeNewVertexPropertyKeyPress.bind($parent, $index()) }, attr: { 'aria-label': 'Remove property '+ ($index() + 1) }"
|
|
||||||
tabindex="0"
|
|
||||||
role="button"
|
|
||||||
>
|
|
||||||
<img class="refreshcol rightPaneTrashIconImg" src="/delete.svg" alt="Remove property" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<!-- /ko -->
|
|
||||||
|
|
||||||
<div class="newVertexFormRow">
|
|
||||||
<span class="rightPaneAddPropertyBtnPadding">
|
|
||||||
<span
|
|
||||||
class="rightPaneAddPropertyBtn rightPaneBtns"
|
|
||||||
id="addProperyNewVertexBtn"
|
|
||||||
data-bind="click:onAddNewProperty, event: { keypress: onAddNewPropertyKeyPress }"
|
|
||||||
tabindex="0"
|
|
||||||
role="button"
|
|
||||||
>
|
|
||||||
<img class="refreshcol rightPaneAddPropertyImg" src="/Add-property.svg" alt="Add property" /> Add
|
|
||||||
Property</span
|
|
||||||
>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
@ -0,0 +1,97 @@
|
|||||||
|
@import "../../../../less/Common/Constants";
|
||||||
|
|
||||||
|
.newVertexComponent {
|
||||||
|
padding: @LargeSpace 20px 20px 0px;
|
||||||
|
width: 400px;
|
||||||
|
|
||||||
|
.newVertexForm {
|
||||||
|
width: 100%;
|
||||||
|
.flex-display();
|
||||||
|
.flex-direction();
|
||||||
|
|
||||||
|
.newVertexFormRow {
|
||||||
|
.flex-display();
|
||||||
|
.flex-direction(@direction: row);
|
||||||
|
padding: 4px 5px;
|
||||||
|
|
||||||
|
label {
|
||||||
|
padding: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.valueCol {
|
||||||
|
flex-grow: 1;
|
||||||
|
padding-right: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rightPaneAddPropertyBtnPadding {
|
||||||
|
padding-top: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.edgeLabel {
|
||||||
|
padding-right: 41px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.actionCol {
|
||||||
|
min-width: 30px;
|
||||||
|
padding: 0px 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.labelCol {
|
||||||
|
width: 72px;
|
||||||
|
min-width: 72px;
|
||||||
|
|
||||||
|
input {
|
||||||
|
max-width: 65px;
|
||||||
|
padding-left: 4px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.edgeInput {
|
||||||
|
width: 100%;
|
||||||
|
padding-left: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.typeSelect {
|
||||||
|
height: 23px;
|
||||||
|
width: 70px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rightPaneTrashIcon {
|
||||||
|
padding: 4px 1px 0px 4px;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rightPaneTrashIconImg {
|
||||||
|
vertical-align: top;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rightPaneAddPropertyBtn {
|
||||||
|
padding: 7px 7px 8px 8px;
|
||||||
|
margin-left: -8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rightPaneBtns {
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: @BaseLow;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
background-color: @AccentMediumLow;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.rightPaneAddPropertyImg {
|
||||||
|
margin-right: 5px;
|
||||||
|
margin-bottom: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.contentScroll {
|
||||||
|
overflow-y: auto;
|
||||||
|
overflow-x: hidden;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,118 @@
|
|||||||
|
import { fireEvent, render, screen } from "@testing-library/react";
|
||||||
|
import React from "react";
|
||||||
|
import * as ViewModels from "../../../Contracts/ViewModels";
|
||||||
|
import { NewVertexComponent } from "./NewVertexComponent";
|
||||||
|
|
||||||
|
describe("New Vertex Component", () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
const fakeNewVertexData: ViewModels.NewVertexData = {
|
||||||
|
label: "",
|
||||||
|
properties: [
|
||||||
|
{
|
||||||
|
key: "test1",
|
||||||
|
values: [
|
||||||
|
{
|
||||||
|
value: "",
|
||||||
|
type: "string",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
const props = {
|
||||||
|
newVertexDataProp: fakeNewVertexData,
|
||||||
|
partitionKeyPropertyProp: "test1",
|
||||||
|
onChangeProp: (): void => undefined,
|
||||||
|
};
|
||||||
|
|
||||||
|
render(<NewVertexComponent {...props} />);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should render default prpoerty", () => {
|
||||||
|
const fakeNewVertexData: ViewModels.NewVertexData = {
|
||||||
|
label: "",
|
||||||
|
properties: [],
|
||||||
|
};
|
||||||
|
const props = {
|
||||||
|
newVertexDataProp: fakeNewVertexData,
|
||||||
|
partitionKeyPropertyProp: "",
|
||||||
|
onChangeProp: (): void => undefined,
|
||||||
|
};
|
||||||
|
|
||||||
|
const { asFragment } = render(<NewVertexComponent {...props} />);
|
||||||
|
expect(asFragment).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should render Add property button", () => {
|
||||||
|
const span = screen.getByText("Add Property");
|
||||||
|
expect(span).toBeDefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should call onAddNewProperty method on span click", () => {
|
||||||
|
const onAddNewProperty = jest.fn();
|
||||||
|
const span = screen.getByText("Add Property");
|
||||||
|
span.onclick = onAddNewProperty();
|
||||||
|
fireEvent.click(span);
|
||||||
|
expect(onAddNewProperty).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should call onAddNewPropertyKeyPress method on span keyPress", () => {
|
||||||
|
const onAddNewPropertyKeyPress = jest.fn();
|
||||||
|
const span = screen.getByText("Add Property");
|
||||||
|
span.onkeypress = onAddNewPropertyKeyPress();
|
||||||
|
fireEvent.keyPress(span, { key: "Enter", code: 13, charCode: 13 });
|
||||||
|
expect(onAddNewPropertyKeyPress).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should call onLabelChange method on input change", () => {
|
||||||
|
const onLabelChange = jest.fn();
|
||||||
|
const input = screen.getByLabelText("Label");
|
||||||
|
input.onchange = onLabelChange();
|
||||||
|
fireEvent.change(input, { target: { value: "Label" } });
|
||||||
|
expect(onLabelChange).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should call onKeyChange method on key input change", () => {
|
||||||
|
const onKeyChange = jest.fn();
|
||||||
|
const input = screen.queryByPlaceholderText("Key");
|
||||||
|
input.onchange = onKeyChange();
|
||||||
|
fireEvent.change(input, { target: { value: "pk1" } });
|
||||||
|
expect(onKeyChange).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should call onValueChange method on value input change", () => {
|
||||||
|
const onValueChange = jest.fn();
|
||||||
|
const input = screen.queryByPlaceholderText("Value");
|
||||||
|
input.onchange = onValueChange();
|
||||||
|
fireEvent.change(input, { target: { value: "abc" } });
|
||||||
|
expect(onValueChange).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should call removeNewVertexProperty method on remove button click", () => {
|
||||||
|
const removeNewVertexProperty = jest.fn();
|
||||||
|
const div = screen.getAllByRole("button");
|
||||||
|
div[0].onclick = removeNewVertexProperty();
|
||||||
|
fireEvent.click(div[0]);
|
||||||
|
expect(removeNewVertexProperty).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should call removeNewVertexProperty method on remove button keyPress", () => {
|
||||||
|
const removeNewVertexPropertyKeyPress = jest.fn();
|
||||||
|
const div = screen.getAllByRole("button");
|
||||||
|
div[0].onkeypress = removeNewVertexPropertyKeyPress();
|
||||||
|
fireEvent.keyPress(div[0], { key: "Enter", code: 13, charCode: 13 });
|
||||||
|
expect(removeNewVertexPropertyKeyPress).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should call onTypeChange method on type dropdown change", () => {
|
||||||
|
const DOWN_ARROW = { keyCode: 40 };
|
||||||
|
const onTypeChange = jest.fn();
|
||||||
|
const dropdown = screen.getByRole("listbox");
|
||||||
|
dropdown.onclick = onTypeChange();
|
||||||
|
dropdown.onkeydown = onTypeChange();
|
||||||
|
|
||||||
|
fireEvent.keyDown(screen.getByRole("listbox"), DOWN_ARROW);
|
||||||
|
fireEvent.click(screen.getByText(/number/));
|
||||||
|
expect(onTypeChange).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
});
|
@ -1,99 +0,0 @@
|
|||||||
import * as ko from "knockout";
|
|
||||||
import { EditorNodePropertiesComponent } from "../GraphExplorerComponent/EditorNodePropertiesComponent";
|
|
||||||
import { NewVertexData, InputProperty } from "../../../Contracts/ViewModels";
|
|
||||||
import { WaitsForTemplateViewModel } from "../../WaitsForTemplateViewModel";
|
|
||||||
import * as Constants from "../../../Common/Constants";
|
|
||||||
import template from "./NewVertexComponent.html";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parameters for this component
|
|
||||||
*/
|
|
||||||
export interface NewVertexParams {
|
|
||||||
// Data to be edited by the component
|
|
||||||
newVertexData: ko.Observable<NewVertexData>;
|
|
||||||
partitionKeyProperty: ko.Observable<string>;
|
|
||||||
firstFieldHasFocus?: ko.Observable<boolean>;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Callback triggered when the template is bound to the component (for testing purposes)
|
|
||||||
*/
|
|
||||||
onTemplateReady?: () => void;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class NewVertexViewModel extends WaitsForTemplateViewModel {
|
|
||||||
private static readonly DEFAULT_PROPERTY_TYPE = "string";
|
|
||||||
|
|
||||||
private newVertexData: ko.Observable<NewVertexData>;
|
|
||||||
private firstFieldHasFocus: ko.Observable<boolean>;
|
|
||||||
private propertyTypes: string[];
|
|
||||||
|
|
||||||
public constructor(params: NewVertexParams) {
|
|
||||||
super();
|
|
||||||
super.onTemplateReady((isTemplateReady: boolean) => {
|
|
||||||
if (isTemplateReady && params.onTemplateReady) {
|
|
||||||
params.onTemplateReady();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
this.newVertexData =
|
|
||||||
params.newVertexData ||
|
|
||||||
ko.observable({
|
|
||||||
label: "",
|
|
||||||
properties: <InputProperty[]>[],
|
|
||||||
});
|
|
||||||
this.firstFieldHasFocus = params.firstFieldHasFocus || ko.observable(false);
|
|
||||||
this.propertyTypes = EditorNodePropertiesComponent.VERTEX_PROPERTY_TYPES;
|
|
||||||
if (params.partitionKeyProperty) {
|
|
||||||
params.partitionKeyProperty.subscribe((newKeyProp: string) => {
|
|
||||||
if (!newKeyProp) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.addNewVertexProperty(newKeyProp);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public onAddNewProperty() {
|
|
||||||
this.addNewVertexProperty();
|
|
||||||
document.getElementById("propertyKeyNewVertexPane").focus();
|
|
||||||
}
|
|
||||||
|
|
||||||
public onAddNewPropertyKeyPress = (source: any, event: KeyboardEvent): boolean => {
|
|
||||||
if (event.keyCode === Constants.KeyCodes.Enter || event.keyCode === Constants.KeyCodes.Space) {
|
|
||||||
this.onAddNewProperty();
|
|
||||||
event.stopPropagation();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
public addNewVertexProperty(key?: string) {
|
|
||||||
let ap = this.newVertexData().properties;
|
|
||||||
ap.push({ key: key || "", values: [{ value: "", type: NewVertexViewModel.DEFAULT_PROPERTY_TYPE }] });
|
|
||||||
this.newVertexData.valueHasMutated();
|
|
||||||
}
|
|
||||||
|
|
||||||
public removeNewVertexProperty(index: number) {
|
|
||||||
let ap = this.newVertexData().properties;
|
|
||||||
ap.splice(index, 1);
|
|
||||||
this.newVertexData.valueHasMutated();
|
|
||||||
document.getElementById("addProperyNewVertexBtn").focus();
|
|
||||||
}
|
|
||||||
|
|
||||||
public removeNewVertexPropertyKeyPress = (index: number, source: any, event: KeyboardEvent): boolean => {
|
|
||||||
if (event.keyCode === Constants.KeyCodes.Enter || event.keyCode === Constants.KeyCodes.Space) {
|
|
||||||
this.removeNewVertexProperty(index);
|
|
||||||
event.stopPropagation();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Helper class for ko component registration
|
|
||||||
*/
|
|
||||||
export const NewVertexComponent = {
|
|
||||||
viewModel: NewVertexViewModel,
|
|
||||||
template,
|
|
||||||
};
|
|
213
src/Explorer/Graph/NewVertexComponent/NewVertexComponent.tsx
Normal file
213
src/Explorer/Graph/NewVertexComponent/NewVertexComponent.tsx
Normal file
@ -0,0 +1,213 @@
|
|||||||
|
import { Dropdown, IDropdownOption, Stack, TextField } from "office-ui-fabric-react";
|
||||||
|
import React, { FunctionComponent, useRef, useState } from "react";
|
||||||
|
import AddIcon from "../../../../images/Add-property.svg";
|
||||||
|
import DeleteIcon from "../../../../images/delete.svg";
|
||||||
|
import { NormalizedEventKey } from "../../../Common/Constants";
|
||||||
|
import { GremlinPropertyValueType, InputPropertyValueTypeString, NewVertexData } from "../../../Contracts/ViewModels";
|
||||||
|
import { EditorNodePropertiesComponent } from "../GraphExplorerComponent/EditorNodePropertiesComponent";
|
||||||
|
import "./NewVertexComponent.less";
|
||||||
|
export interface INewVertexComponentProps {
|
||||||
|
newVertexDataProp: NewVertexData;
|
||||||
|
partitionKeyPropertyProp: string;
|
||||||
|
onChangeProp: (labelData: NewVertexData) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const NewVertexComponent: FunctionComponent<INewVertexComponentProps> = ({
|
||||||
|
newVertexDataProp,
|
||||||
|
partitionKeyPropertyProp,
|
||||||
|
onChangeProp,
|
||||||
|
}: INewVertexComponentProps): JSX.Element => {
|
||||||
|
const DEFAULT_PROPERTY_TYPE = "string";
|
||||||
|
const [newVertexData, setNewVertexData] = useState<NewVertexData>(
|
||||||
|
newVertexDataProp || {
|
||||||
|
label: "",
|
||||||
|
properties: [
|
||||||
|
{
|
||||||
|
key: partitionKeyPropertyProp,
|
||||||
|
values: [{ value: "", type: DEFAULT_PROPERTY_TYPE }],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
const propertyTypes: string[] = EditorNodePropertiesComponent.VERTEX_PROPERTY_TYPES;
|
||||||
|
const input = useRef(undefined);
|
||||||
|
|
||||||
|
const onAddNewProperty = () => {
|
||||||
|
addNewVertexProperty();
|
||||||
|
setTimeout(() => {
|
||||||
|
input.current.focus();
|
||||||
|
}, 100);
|
||||||
|
};
|
||||||
|
|
||||||
|
const onAddNewPropertyKeyPress = (event: React.KeyboardEvent) => {
|
||||||
|
if (event.key === NormalizedEventKey.Space || event.key === NormalizedEventKey.Enter) {
|
||||||
|
onAddNewProperty();
|
||||||
|
event.stopPropagation();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const addNewVertexProperty = () => {
|
||||||
|
let key: string;
|
||||||
|
const ap = newVertexData.properties;
|
||||||
|
if (ap.length === 0) {
|
||||||
|
key = partitionKeyPropertyProp;
|
||||||
|
}
|
||||||
|
ap.push({
|
||||||
|
key: key || "",
|
||||||
|
values: [{ value: "", type: DEFAULT_PROPERTY_TYPE }],
|
||||||
|
});
|
||||||
|
setNewVertexData((prevData) => ({
|
||||||
|
...prevData,
|
||||||
|
properties: ap,
|
||||||
|
}));
|
||||||
|
onChangeProp(newVertexData);
|
||||||
|
};
|
||||||
|
|
||||||
|
const removeNewVertexProperty = (event?: React.MouseEvent<HTMLDivElement>, index?: number) => {
|
||||||
|
const ap = newVertexData.properties;
|
||||||
|
ap.splice(index, 1);
|
||||||
|
setNewVertexData((prevData) => ({
|
||||||
|
...prevData,
|
||||||
|
properties: ap,
|
||||||
|
}));
|
||||||
|
onChangeProp(newVertexData);
|
||||||
|
document.getElementById("addProperyNewVertexBtn").focus();
|
||||||
|
};
|
||||||
|
|
||||||
|
const removeNewVertexPropertyKeyPress = (event: React.KeyboardEvent<HTMLDivElement>, index: number) => {
|
||||||
|
if (event.key === NormalizedEventKey.Space || event.key === NormalizedEventKey.Enter) {
|
||||||
|
removeNewVertexProperty(undefined, index);
|
||||||
|
event.stopPropagation();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const onLabelChange = (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
|
setNewVertexData((prevData) => ({
|
||||||
|
...prevData,
|
||||||
|
label: event.target.value,
|
||||||
|
}));
|
||||||
|
onChangeProp(newVertexData);
|
||||||
|
};
|
||||||
|
|
||||||
|
const onKeyChange = (event: React.ChangeEvent<HTMLInputElement>, index: number) => {
|
||||||
|
const newState = { ...newVertexData };
|
||||||
|
newState.properties[index].key = event.target.value;
|
||||||
|
setNewVertexData(newState);
|
||||||
|
onChangeProp(newVertexData);
|
||||||
|
};
|
||||||
|
|
||||||
|
const onValueChange = (event: React.ChangeEvent<HTMLInputElement>, index: number) => {
|
||||||
|
const newState = { ...newVertexData };
|
||||||
|
newState.properties[index].values[0].value = event.target.value as GremlinPropertyValueType;
|
||||||
|
setNewVertexData(newState);
|
||||||
|
onChangeProp(newVertexData);
|
||||||
|
};
|
||||||
|
|
||||||
|
const onTypeChange = (option: string, index: number) => {
|
||||||
|
const newState = { ...newVertexData };
|
||||||
|
if (newState.properties[index]) {
|
||||||
|
newState.properties[index].values[0].type = option as InputPropertyValueTypeString;
|
||||||
|
setNewVertexData(newState);
|
||||||
|
onChangeProp(newVertexData);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Stack>
|
||||||
|
<div className="newVertexComponent">
|
||||||
|
<div className="newVertexForm">
|
||||||
|
<div className="newVertexFormRow">
|
||||||
|
<TextField
|
||||||
|
label="Label"
|
||||||
|
className="edgeInput"
|
||||||
|
type="text"
|
||||||
|
ariaLabel="Enter vertex label"
|
||||||
|
role="textbox"
|
||||||
|
tabIndex={0}
|
||||||
|
placeholder="Enter vertex label"
|
||||||
|
autoComplete="off"
|
||||||
|
id="VertexLabel"
|
||||||
|
value={newVertexData.label}
|
||||||
|
onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
|
onLabelChange(event);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<div className="actionCol"></div>
|
||||||
|
</div>
|
||||||
|
{newVertexData.properties.map((data, index) => {
|
||||||
|
return (
|
||||||
|
<div key={index} className="newVertexFormRow">
|
||||||
|
<div className="labelCol">
|
||||||
|
<TextField
|
||||||
|
className="edgeInput"
|
||||||
|
type="text"
|
||||||
|
id="propertyKeyNewVertexPane"
|
||||||
|
componentRef={input}
|
||||||
|
placeholder="Key"
|
||||||
|
autoComplete="off"
|
||||||
|
aria-label={`Enter value for propery ${index + 1}`}
|
||||||
|
value={data.key}
|
||||||
|
onChange={(event: React.ChangeEvent<HTMLInputElement>) => onKeyChange(event, index)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="valueCol">
|
||||||
|
<TextField
|
||||||
|
className="edgeInput"
|
||||||
|
type="text"
|
||||||
|
placeholder="Value"
|
||||||
|
autoComplete="off"
|
||||||
|
aria-label={`Enter value for propery ${index + 1}`}
|
||||||
|
value={data.values[0].value.toString()}
|
||||||
|
onChange={(event: React.ChangeEvent<HTMLInputElement>) => onValueChange(event, index)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<Dropdown
|
||||||
|
role="listbox"
|
||||||
|
placeholder="Select an option"
|
||||||
|
defaultSelectedKey={data.values[0].type}
|
||||||
|
style={{ width: 100 }}
|
||||||
|
options={propertyTypes.map((type) => ({
|
||||||
|
key: type,
|
||||||
|
text: type,
|
||||||
|
}))}
|
||||||
|
onChange={(_, options: IDropdownOption) => onTypeChange(options.key.toString(), index)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="actionCol">
|
||||||
|
<div
|
||||||
|
className="rightPaneTrashIcon rightPaneBtns"
|
||||||
|
tabIndex={0}
|
||||||
|
role="button"
|
||||||
|
onClick={(event: React.MouseEvent<HTMLDivElement>) => removeNewVertexProperty(event, index)}
|
||||||
|
onKeyPress={(event: React.KeyboardEvent<HTMLDivElement>) =>
|
||||||
|
removeNewVertexPropertyKeyPress(event, index)
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<img className="refreshcol rightPaneTrashIconImg" src={DeleteIcon} alt="Remove property" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
|
||||||
|
<div className="newVertexFormRow">
|
||||||
|
<span className="rightPaneAddPropertyBtnPadding">
|
||||||
|
<span
|
||||||
|
className="rightPaneAddPropertyBtn rightPaneBtns"
|
||||||
|
id="addProperyNewVertexBtn"
|
||||||
|
tabIndex={0}
|
||||||
|
role="button"
|
||||||
|
onClick={onAddNewProperty}
|
||||||
|
onKeyPress={(event: React.KeyboardEvent<HTMLSpanElement>) => onAddNewPropertyKeyPress(event)}
|
||||||
|
>
|
||||||
|
<img className="refreshcol rightPaneAddPropertyImg" src={AddIcon} alt="Add property" /> Add Property
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Stack>
|
||||||
|
);
|
||||||
|
};
|
@ -0,0 +1,3 @@
|
|||||||
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
|
exports[`New Vertex Component should render default prpoerty 1`] = `[Function]`;
|
@ -1,97 +0,0 @@
|
|||||||
@import "../../../../less/Common/Constants";
|
|
||||||
|
|
||||||
.newVertexComponent {
|
|
||||||
padding: @LargeSpace 20px 20px 0px;
|
|
||||||
width: 400px;
|
|
||||||
|
|
||||||
.newVertexForm {
|
|
||||||
width: 100%;
|
|
||||||
.flex-display();
|
|
||||||
.flex-direction();
|
|
||||||
|
|
||||||
.newVertexFormRow {
|
|
||||||
.flex-display();
|
|
||||||
.flex-direction(@direction: row);
|
|
||||||
padding: 4px 5px;
|
|
||||||
|
|
||||||
label {
|
|
||||||
padding: 0px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.valueCol {
|
|
||||||
flex-grow: 1;
|
|
||||||
padding-right: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rightPaneAddPropertyBtnPadding {
|
|
||||||
padding-top: 14px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.edgeLabel {
|
|
||||||
padding-right: 41px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.actionCol {
|
|
||||||
min-width: 30px;
|
|
||||||
padding: 0px 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.labelCol {
|
|
||||||
width: 72px;
|
|
||||||
min-width: 72px;
|
|
||||||
|
|
||||||
input {
|
|
||||||
max-width: 65px;
|
|
||||||
padding-left: 4px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.edgeInput {
|
|
||||||
width: 100%;
|
|
||||||
padding-left: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.typeSelect {
|
|
||||||
height: 23px;
|
|
||||||
width: 70px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rightPaneTrashIcon {
|
|
||||||
padding: 4px 1px 0px 4px;
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rightPaneTrashIconImg {
|
|
||||||
vertical-align: top;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rightPaneAddPropertyBtn {
|
|
||||||
padding: 7px 7px 8px 8px;
|
|
||||||
margin-left: -8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rightPaneBtns {
|
|
||||||
cursor: pointer;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background-color: @BaseLow ;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:active {
|
|
||||||
background-color: @AccentMediumLow;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.rightPaneAddPropertyImg {
|
|
||||||
margin-right: 5px;
|
|
||||||
margin-bottom: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.contentScroll {
|
|
||||||
overflow-y: auto;
|
|
||||||
overflow-x: hidden;
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,60 +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" data-bind="attr: { id: id }">
|
|
||||||
<!-- New Vertex form - Start -->
|
|
||||||
<div class="contextual-pane-in">
|
|
||||||
<form class="paneContentContainer" data-bind="submit: submit">
|
|
||||||
<!-- New Vertex header - Start -->
|
|
||||||
<div class="firstdivbg headerline">
|
|
||||||
<span role="heading" aria-level="2">New Vertex</span>
|
|
||||||
<div
|
|
||||||
class="closeImg"
|
|
||||||
role="button"
|
|
||||||
aria-label="Close pane"
|
|
||||||
data-bind="click: cancel, event: { keypress: onCloseKeyPress }"
|
|
||||||
tabindex="0"
|
|
||||||
>
|
|
||||||
<img src="../../../images/close-black.svg" title="Close" alt="Close" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<!-- New Vertex header - End -->
|
|
||||||
|
|
||||||
<!-- New Vertex errors - Start -->
|
|
||||||
<div
|
|
||||||
aria-live="assertive"
|
|
||||||
class="warningErrorContainer"
|
|
||||||
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="visible: formErrorsDetails() && formErrorsDetails() !== '' , click: showErrorDetails, event: { keypress: onMoreDetailsKeyPress }"
|
|
||||||
tabindex="0"
|
|
||||||
>
|
|
||||||
More details
|
|
||||||
</a>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<!-- New Vertex errors - End -->
|
|
||||||
|
|
||||||
<!-- New Vertex inputs - Start -->
|
|
||||||
<div class="paneMainContent">
|
|
||||||
<new-vertex-form
|
|
||||||
class="newvertexContainer"
|
|
||||||
params="{ newVertexData: tempVertexData, firstFieldHasFocus: firstFieldHasFocus, partitionKeyProperty: partitionKeyProperty }"
|
|
||||||
></new-vertex-form>
|
|
||||||
</div>
|
|
||||||
<div class="paneFooter">
|
|
||||||
<div class="leftpanel-okbut"><input type="submit" value="OK" class="btncreatecoll1" /></div>
|
|
||||||
</div>
|
|
||||||
<!-- New Vertex inputs - End -->
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
<!-- New Vertex form - End -->
|
|
||||||
</div>
|
|
||||||
</div>
|
|
@ -1,10 +0,0 @@
|
|||||||
@import "../../../less/Common/Constants";
|
|
||||||
|
|
||||||
.newvertexContainer {
|
|
||||||
height:100%;
|
|
||||||
overflow-y: auto;
|
|
||||||
overflow-x: hidden;
|
|
||||||
white-space: nowrap;
|
|
||||||
.flex-display();
|
|
||||||
.flex-direction();
|
|
||||||
}
|
|
@ -1,65 +0,0 @@
|
|||||||
import * as ko from "knockout";
|
|
||||||
import * as ViewModels from "../../Contracts/ViewModels";
|
|
||||||
import { ContextualPaneBase } from "./ContextualPaneBase";
|
|
||||||
import { KeyCodes } from "../../Common/Constants";
|
|
||||||
import Explorer from "../Explorer";
|
|
||||||
|
|
||||||
export default class NewVertexPane extends ContextualPaneBase {
|
|
||||||
public container: Explorer;
|
|
||||||
public visible: ko.Observable<boolean>;
|
|
||||||
public formErrors: ko.Observable<string>;
|
|
||||||
public formErrorsDetails: ko.Observable<string>;
|
|
||||||
|
|
||||||
// Graph style stuff
|
|
||||||
public tempVertexData: ko.Observable<ViewModels.NewVertexData>; // vertex data being edited
|
|
||||||
private onSubmitCreateCallback: (newVertexData: ViewModels.NewVertexData) => void;
|
|
||||||
private partitionKeyProperty: ko.Observable<string>;
|
|
||||||
|
|
||||||
constructor(options: ViewModels.PaneOptions) {
|
|
||||||
super(options);
|
|
||||||
this.tempVertexData = ko.observable<ViewModels.NewVertexData>(null);
|
|
||||||
this.partitionKeyProperty = ko.observable(null);
|
|
||||||
this.resetData();
|
|
||||||
}
|
|
||||||
|
|
||||||
public submit() {
|
|
||||||
// Commit edited changes
|
|
||||||
if (this.onSubmitCreateCallback != null) {
|
|
||||||
this.onSubmitCreateCallback(this.tempVertexData());
|
|
||||||
}
|
|
||||||
|
|
||||||
// this.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
public resetData() {
|
|
||||||
super.resetData();
|
|
||||||
|
|
||||||
this.onSubmitCreateCallback = null;
|
|
||||||
|
|
||||||
this.tempVertexData({
|
|
||||||
label: "",
|
|
||||||
properties: <ViewModels.InputProperty[]>[],
|
|
||||||
});
|
|
||||||
this.partitionKeyProperty(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public subscribeOnSubmitCreate(callback: (newVertexData: ViewModels.NewVertexData) => void): void {
|
|
||||||
this.onSubmitCreateCallback = callback;
|
|
||||||
}
|
|
||||||
|
|
||||||
public setPartitionKeyProperty(pKeyProp: string): void {
|
|
||||||
this.partitionKeyProperty(pKeyProp);
|
|
||||||
}
|
|
||||||
|
|
||||||
public onMoreDetailsKeyPress = (source: any, event: KeyboardEvent): boolean => {
|
|
||||||
if (event.keyCode === KeyCodes.Space || event.keyCode === KeyCodes.Enter) {
|
|
||||||
this.showErrorDetails();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
public buildString = (prefix: string, index: number): string => {
|
|
||||||
return `${prefix}${index}`;
|
|
||||||
};
|
|
||||||
}
|
|
10
src/Explorer/Panes/NewVertexPanel/NewVertexPanel.less
Normal file
10
src/Explorer/Panes/NewVertexPanel/NewVertexPanel.less
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
@import "../../../../less/Common/Constants";
|
||||||
|
|
||||||
|
.newvertexContainer {
|
||||||
|
height: 100%;
|
||||||
|
overflow-y: auto;
|
||||||
|
overflow-x: hidden;
|
||||||
|
white-space: nowrap;
|
||||||
|
.flex-display();
|
||||||
|
.flex-direction();
|
||||||
|
}
|
78
src/Explorer/Panes/NewVertexPanel/NewVertexPanel.test.tsx
Normal file
78
src/Explorer/Panes/NewVertexPanel/NewVertexPanel.test.tsx
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
import { shallow, ShallowWrapper } from "enzyme";
|
||||||
|
import React from "react";
|
||||||
|
import * as ViewModels from "../../../Contracts/ViewModels";
|
||||||
|
import Explorer from "../../Explorer";
|
||||||
|
import { NewVertexPanel } from "./NewVertexPanel";
|
||||||
|
|
||||||
|
describe("New Vertex Panel", () => {
|
||||||
|
let fakeExplorer: Explorer;
|
||||||
|
let wrapper: ShallowWrapper;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fakeExplorer = new Explorer();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should render default property", () => {
|
||||||
|
const props = {
|
||||||
|
explorer: fakeExplorer,
|
||||||
|
partitionKeyPropertyProp: "",
|
||||||
|
onSubmit: (): void => undefined,
|
||||||
|
openNotificationConsole: (): void => undefined,
|
||||||
|
};
|
||||||
|
wrapper = shallow(<NewVertexPanel {...props} />);
|
||||||
|
expect(wrapper).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should render button in footer", () => {
|
||||||
|
const button = wrapper.find("PrimaryButton").first();
|
||||||
|
expect(button).toBeDefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should render form", () => {
|
||||||
|
const form = wrapper.find("form").first();
|
||||||
|
expect(form).toBeDefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should call form submit method", () => {
|
||||||
|
const onSubmitSpy = jest.fn();
|
||||||
|
|
||||||
|
const newWrapper = shallow(
|
||||||
|
<NewVertexPanel
|
||||||
|
explorer={fakeExplorer}
|
||||||
|
partitionKeyPropertyProp={undefined}
|
||||||
|
openNotificationConsole={(): void => undefined}
|
||||||
|
onSubmit={onSubmitSpy}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
//eslint-disable-next-line
|
||||||
|
newWrapper.find("form").simulate("submit", { preventDefault: () => {} });
|
||||||
|
|
||||||
|
expect(onSubmitSpy).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should call error and success scenario method", () => {
|
||||||
|
const onSubmitSpy = jest.fn();
|
||||||
|
const onErrorSpy = jest.fn();
|
||||||
|
const onSuccessSpy = jest.fn();
|
||||||
|
const fakeNewVertexData: ViewModels.NewVertexData = {
|
||||||
|
label: "",
|
||||||
|
properties: [],
|
||||||
|
};
|
||||||
|
|
||||||
|
const result = onSubmitSpy(fakeNewVertexData, onErrorSpy, onSuccessSpy);
|
||||||
|
|
||||||
|
const newWrapper = shallow(
|
||||||
|
<NewVertexPanel
|
||||||
|
explorer={fakeExplorer}
|
||||||
|
partitionKeyPropertyProp={undefined}
|
||||||
|
openNotificationConsole={(): void => undefined}
|
||||||
|
onSubmit={onSubmitSpy}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
//eslint-disable-next-line
|
||||||
|
newWrapper.find("form").simulate("submit", { preventDefault: () => {} });
|
||||||
|
|
||||||
|
expect(result).toBeUndefined();
|
||||||
|
expect(onSubmitSpy).toHaveBeenCalledWith(fakeNewVertexData, onErrorSpy, onSuccessSpy);
|
||||||
|
});
|
||||||
|
});
|
74
src/Explorer/Panes/NewVertexPanel/NewVertexPanel.tsx
Normal file
74
src/Explorer/Panes/NewVertexPanel/NewVertexPanel.tsx
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
import { useBoolean } from "@uifabric/react-hooks";
|
||||||
|
import React, { FunctionComponent, useState } from "react";
|
||||||
|
import * as ViewModels from "../../../Contracts/ViewModels";
|
||||||
|
import Explorer from "../../Explorer";
|
||||||
|
import { NewVertexComponent } from "../../Graph/NewVertexComponent/NewVertexComponent";
|
||||||
|
import { PanelFooterComponent } from "../PanelFooterComponent";
|
||||||
|
import { PanelInfoErrorComponent } from "../PanelInfoErrorComponent";
|
||||||
|
import { PanelLoadingScreen } from "../PanelLoadingScreen";
|
||||||
|
export interface INewVertexPanelProps {
|
||||||
|
explorer: Explorer;
|
||||||
|
partitionKeyPropertyProp: string;
|
||||||
|
onSubmit: (result: ViewModels.NewVertexData, onError: (errorMsg: string) => void, onSuccess: () => void) => void;
|
||||||
|
openNotificationConsole: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const NewVertexPanel: FunctionComponent<INewVertexPanelProps> = ({
|
||||||
|
explorer,
|
||||||
|
partitionKeyPropertyProp,
|
||||||
|
onSubmit,
|
||||||
|
openNotificationConsole,
|
||||||
|
}: INewVertexPanelProps): JSX.Element => {
|
||||||
|
let newVertexDataValue: ViewModels.NewVertexData;
|
||||||
|
const [errorMessage, setErrorMessage] = useState<string>("");
|
||||||
|
const [showErrorDetails, setShowErrorDetails] = useState<boolean>(false);
|
||||||
|
const [isLoading, { setTrue: setLoadingTrue, setFalse: setLoadingFalse }] = useBoolean(false);
|
||||||
|
const buttonLabel = "OK";
|
||||||
|
|
||||||
|
const submit = (event: React.MouseEvent<HTMLFormElement>) => {
|
||||||
|
event.preventDefault();
|
||||||
|
setErrorMessage(undefined);
|
||||||
|
setShowErrorDetails(false);
|
||||||
|
if (onSubmit !== undefined) {
|
||||||
|
setLoadingTrue();
|
||||||
|
onSubmit(newVertexDataValue, onError, onSuccess);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const onError = (errorMsg: string) => {
|
||||||
|
setErrorMessage(errorMsg);
|
||||||
|
setShowErrorDetails(true);
|
||||||
|
setLoadingFalse();
|
||||||
|
};
|
||||||
|
|
||||||
|
const onSuccess = () => {
|
||||||
|
setLoadingFalse();
|
||||||
|
explorer.closeSidePanel();
|
||||||
|
};
|
||||||
|
|
||||||
|
const onChange = (newVertexData: ViewModels.NewVertexData) => {
|
||||||
|
newVertexDataValue = newVertexData;
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<form className="panelFormWrapper" onSubmit={(event: React.MouseEvent<HTMLFormElement>) => submit(event)}>
|
||||||
|
{errorMessage && (
|
||||||
|
<PanelInfoErrorComponent
|
||||||
|
message={errorMessage}
|
||||||
|
messageType="error"
|
||||||
|
showErrorDetails={showErrorDetails}
|
||||||
|
openNotificationConsole={openNotificationConsole}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
<div className="panelMainContent">
|
||||||
|
<NewVertexComponent
|
||||||
|
newVertexDataProp={newVertexDataValue}
|
||||||
|
partitionKeyPropertyProp={partitionKeyPropertyProp}
|
||||||
|
onChangeProp={onChange}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<PanelFooterComponent buttonLabel={buttonLabel} />
|
||||||
|
{isLoading && <PanelLoadingScreen />}
|
||||||
|
</form>
|
||||||
|
);
|
||||||
|
};
|
@ -0,0 +1,20 @@
|
|||||||
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
|
exports[`New Vertex Panel should render default property 1`] = `
|
||||||
|
<form
|
||||||
|
className="panelFormWrapper"
|
||||||
|
onSubmit={[Function]}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
className="panelMainContent"
|
||||||
|
>
|
||||||
|
<NewVertexComponent
|
||||||
|
onChangeProp={[Function]}
|
||||||
|
partitionKeyPropertyProp=""
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<PanelFooterComponent
|
||||||
|
buttonLabel="OK"
|
||||||
|
/>
|
||||||
|
</form>
|
||||||
|
`;
|
@ -2,7 +2,6 @@ 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 GitHubReposPaneTemplate from "./GitHubReposPane.html";
|
import GitHubReposPaneTemplate from "./GitHubReposPane.html";
|
||||||
import GraphNewVertexPaneTemplate from "./GraphNewVertexPane.html";
|
|
||||||
import GraphStylingPaneTemplate from "./GraphStylingPane.html";
|
import GraphStylingPaneTemplate from "./GraphStylingPane.html";
|
||||||
import StringInputPaneTemplate from "./StringInputPane.html";
|
import StringInputPaneTemplate from "./StringInputPane.html";
|
||||||
import TableAddEntityPaneTemplate from "./Tables/TableAddEntityPane.html";
|
import TableAddEntityPaneTemplate from "./Tables/TableAddEntityPane.html";
|
||||||
@ -32,15 +31,6 @@ export class AddCollectionPaneComponent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class GraphNewVertexPaneComponent {
|
|
||||||
constructor() {
|
|
||||||
return {
|
|
||||||
viewModel: PaneComponent,
|
|
||||||
template: GraphNewVertexPaneTemplate,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class GraphStylingPaneComponent {
|
export class GraphStylingPaneComponent {
|
||||||
constructor() {
|
constructor() {
|
||||||
return {
|
return {
|
||||||
|
@ -187,22 +187,6 @@ exports[`Settings Pane should render Default properly 1`] = `
|
|||||||
"title": [Function],
|
"title": [Function],
|
||||||
"visible": [Function],
|
"visible": [Function],
|
||||||
},
|
},
|
||||||
NewVertexPane {
|
|
||||||
"buildString": [Function],
|
|
||||||
"container": [Circular],
|
|
||||||
"firstFieldHasFocus": [Function],
|
|
||||||
"formErrors": [Function],
|
|
||||||
"formErrorsDetails": [Function],
|
|
||||||
"id": "newvertexpane",
|
|
||||||
"isExecuting": [Function],
|
|
||||||
"isTemplateReady": [Function],
|
|
||||||
"onMoreDetailsKeyPress": [Function],
|
|
||||||
"onSubmitCreateCallback": null,
|
|
||||||
"partitionKeyProperty": [Function],
|
|
||||||
"tempVertexData": [Function],
|
|
||||||
"title": [Function],
|
|
||||||
"visible": [Function],
|
|
||||||
},
|
|
||||||
CassandraAddCollectionPane {
|
CassandraAddCollectionPane {
|
||||||
"autoPilotUsageCost": [Function],
|
"autoPilotUsageCost": [Function],
|
||||||
"canConfigureThroughput": [Function],
|
"canConfigureThroughput": [Function],
|
||||||
@ -547,22 +531,6 @@ exports[`Settings Pane should render Default properly 1`] = `
|
|||||||
"isSynapseLinkUpdating": [Function],
|
"isSynapseLinkUpdating": [Function],
|
||||||
"isTabsContentExpanded": [Function],
|
"isTabsContentExpanded": [Function],
|
||||||
"memoryUsageInfo": [Function],
|
"memoryUsageInfo": [Function],
|
||||||
"newVertexPane": NewVertexPane {
|
|
||||||
"buildString": [Function],
|
|
||||||
"container": [Circular],
|
|
||||||
"firstFieldHasFocus": [Function],
|
|
||||||
"formErrors": [Function],
|
|
||||||
"formErrorsDetails": [Function],
|
|
||||||
"id": "newvertexpane",
|
|
||||||
"isExecuting": [Function],
|
|
||||||
"isTemplateReady": [Function],
|
|
||||||
"onMoreDetailsKeyPress": [Function],
|
|
||||||
"onSubmitCreateCallback": null,
|
|
||||||
"partitionKeyProperty": [Function],
|
|
||||||
"tempVertexData": [Function],
|
|
||||||
"title": [Function],
|
|
||||||
"visible": [Function],
|
|
||||||
},
|
|
||||||
"notebookBasePath": [Function],
|
"notebookBasePath": [Function],
|
||||||
"notebookServerInfo": [Function],
|
"notebookServerInfo": [Function],
|
||||||
"onRefreshDatabasesKeyPress": [Function],
|
"onRefreshDatabasesKeyPress": [Function],
|
||||||
@ -970,22 +938,6 @@ exports[`Settings Pane should render Gremlin properly 1`] = `
|
|||||||
"title": [Function],
|
"title": [Function],
|
||||||
"visible": [Function],
|
"visible": [Function],
|
||||||
},
|
},
|
||||||
NewVertexPane {
|
|
||||||
"buildString": [Function],
|
|
||||||
"container": [Circular],
|
|
||||||
"firstFieldHasFocus": [Function],
|
|
||||||
"formErrors": [Function],
|
|
||||||
"formErrorsDetails": [Function],
|
|
||||||
"id": "newvertexpane",
|
|
||||||
"isExecuting": [Function],
|
|
||||||
"isTemplateReady": [Function],
|
|
||||||
"onMoreDetailsKeyPress": [Function],
|
|
||||||
"onSubmitCreateCallback": null,
|
|
||||||
"partitionKeyProperty": [Function],
|
|
||||||
"tempVertexData": [Function],
|
|
||||||
"title": [Function],
|
|
||||||
"visible": [Function],
|
|
||||||
},
|
|
||||||
CassandraAddCollectionPane {
|
CassandraAddCollectionPane {
|
||||||
"autoPilotUsageCost": [Function],
|
"autoPilotUsageCost": [Function],
|
||||||
"canConfigureThroughput": [Function],
|
"canConfigureThroughput": [Function],
|
||||||
@ -1330,22 +1282,6 @@ exports[`Settings Pane should render Gremlin properly 1`] = `
|
|||||||
"isSynapseLinkUpdating": [Function],
|
"isSynapseLinkUpdating": [Function],
|
||||||
"isTabsContentExpanded": [Function],
|
"isTabsContentExpanded": [Function],
|
||||||
"memoryUsageInfo": [Function],
|
"memoryUsageInfo": [Function],
|
||||||
"newVertexPane": NewVertexPane {
|
|
||||||
"buildString": [Function],
|
|
||||||
"container": [Circular],
|
|
||||||
"firstFieldHasFocus": [Function],
|
|
||||||
"formErrors": [Function],
|
|
||||||
"formErrorsDetails": [Function],
|
|
||||||
"id": "newvertexpane",
|
|
||||||
"isExecuting": [Function],
|
|
||||||
"isTemplateReady": [Function],
|
|
||||||
"onMoreDetailsKeyPress": [Function],
|
|
||||||
"onSubmitCreateCallback": null,
|
|
||||||
"partitionKeyProperty": [Function],
|
|
||||||
"tempVertexData": [Function],
|
|
||||||
"title": [Function],
|
|
||||||
"visible": [Function],
|
|
||||||
},
|
|
||||||
"notebookBasePath": [Function],
|
"notebookBasePath": [Function],
|
||||||
"notebookServerInfo": [Function],
|
"notebookServerInfo": [Function],
|
||||||
"onRefreshDatabasesKeyPress": [Function],
|
"onRefreshDatabasesKeyPress": [Function],
|
||||||
|
@ -187,22 +187,6 @@ exports[`Upload Items Pane should render Default properly 1`] = `
|
|||||||
"title": [Function],
|
"title": [Function],
|
||||||
"visible": [Function],
|
"visible": [Function],
|
||||||
},
|
},
|
||||||
NewVertexPane {
|
|
||||||
"buildString": [Function],
|
|
||||||
"container": [Circular],
|
|
||||||
"firstFieldHasFocus": [Function],
|
|
||||||
"formErrors": [Function],
|
|
||||||
"formErrorsDetails": [Function],
|
|
||||||
"id": "newvertexpane",
|
|
||||||
"isExecuting": [Function],
|
|
||||||
"isTemplateReady": [Function],
|
|
||||||
"onMoreDetailsKeyPress": [Function],
|
|
||||||
"onSubmitCreateCallback": null,
|
|
||||||
"partitionKeyProperty": [Function],
|
|
||||||
"tempVertexData": [Function],
|
|
||||||
"title": [Function],
|
|
||||||
"visible": [Function],
|
|
||||||
},
|
|
||||||
CassandraAddCollectionPane {
|
CassandraAddCollectionPane {
|
||||||
"autoPilotUsageCost": [Function],
|
"autoPilotUsageCost": [Function],
|
||||||
"canConfigureThroughput": [Function],
|
"canConfigureThroughput": [Function],
|
||||||
@ -547,22 +531,6 @@ exports[`Upload Items Pane should render Default properly 1`] = `
|
|||||||
"isSynapseLinkUpdating": [Function],
|
"isSynapseLinkUpdating": [Function],
|
||||||
"isTabsContentExpanded": [Function],
|
"isTabsContentExpanded": [Function],
|
||||||
"memoryUsageInfo": [Function],
|
"memoryUsageInfo": [Function],
|
||||||
"newVertexPane": NewVertexPane {
|
|
||||||
"buildString": [Function],
|
|
||||||
"container": [Circular],
|
|
||||||
"firstFieldHasFocus": [Function],
|
|
||||||
"formErrors": [Function],
|
|
||||||
"formErrorsDetails": [Function],
|
|
||||||
"id": "newvertexpane",
|
|
||||||
"isExecuting": [Function],
|
|
||||||
"isTemplateReady": [Function],
|
|
||||||
"onMoreDetailsKeyPress": [Function],
|
|
||||||
"onSubmitCreateCallback": null,
|
|
||||||
"partitionKeyProperty": [Function],
|
|
||||||
"tempVertexData": [Function],
|
|
||||||
"title": [Function],
|
|
||||||
"visible": [Function],
|
|
||||||
},
|
|
||||||
"notebookBasePath": [Function],
|
"notebookBasePath": [Function],
|
||||||
"notebookServerInfo": [Function],
|
"notebookServerInfo": [Function],
|
||||||
"onRefreshDatabasesKeyPress": [Function],
|
"onRefreshDatabasesKeyPress": [Function],
|
||||||
|
@ -188,22 +188,6 @@ exports[`Delete Database Confirmation Pane submit() Should call delete database
|
|||||||
"title": [Function],
|
"title": [Function],
|
||||||
"visible": [Function],
|
"visible": [Function],
|
||||||
},
|
},
|
||||||
NewVertexPane {
|
|
||||||
"buildString": [Function],
|
|
||||||
"container": [Circular],
|
|
||||||
"firstFieldHasFocus": [Function],
|
|
||||||
"formErrors": [Function],
|
|
||||||
"formErrorsDetails": [Function],
|
|
||||||
"id": "newvertexpane",
|
|
||||||
"isExecuting": [Function],
|
|
||||||
"isTemplateReady": [Function],
|
|
||||||
"onMoreDetailsKeyPress": [Function],
|
|
||||||
"onSubmitCreateCallback": null,
|
|
||||||
"partitionKeyProperty": [Function],
|
|
||||||
"tempVertexData": [Function],
|
|
||||||
"title": [Function],
|
|
||||||
"visible": [Function],
|
|
||||||
},
|
|
||||||
CassandraAddCollectionPane {
|
CassandraAddCollectionPane {
|
||||||
"autoPilotUsageCost": [Function],
|
"autoPilotUsageCost": [Function],
|
||||||
"canConfigureThroughput": [Function],
|
"canConfigureThroughput": [Function],
|
||||||
@ -551,22 +535,6 @@ exports[`Delete Database Confirmation Pane submit() Should call delete database
|
|||||||
"isSynapseLinkUpdating": [Function],
|
"isSynapseLinkUpdating": [Function],
|
||||||
"isTabsContentExpanded": [Function],
|
"isTabsContentExpanded": [Function],
|
||||||
"memoryUsageInfo": [Function],
|
"memoryUsageInfo": [Function],
|
||||||
"newVertexPane": NewVertexPane {
|
|
||||||
"buildString": [Function],
|
|
||||||
"container": [Circular],
|
|
||||||
"firstFieldHasFocus": [Function],
|
|
||||||
"formErrors": [Function],
|
|
||||||
"formErrorsDetails": [Function],
|
|
||||||
"id": "newvertexpane",
|
|
||||||
"isExecuting": [Function],
|
|
||||||
"isTemplateReady": [Function],
|
|
||||||
"onMoreDetailsKeyPress": [Function],
|
|
||||||
"onSubmitCreateCallback": null,
|
|
||||||
"partitionKeyProperty": [Function],
|
|
||||||
"tempVertexData": [Function],
|
|
||||||
"title": [Function],
|
|
||||||
"visible": [Function],
|
|
||||||
},
|
|
||||||
"notebookBasePath": [Function],
|
"notebookBasePath": [Function],
|
||||||
"notebookServerInfo": [Function],
|
"notebookServerInfo": [Function],
|
||||||
"onRefreshDatabasesKeyPress": [Function],
|
"onRefreshDatabasesKeyPress": [Function],
|
||||||
|
@ -1,24 +1,24 @@
|
|||||||
import * as ko from "knockout";
|
import * as ko from "knockout";
|
||||||
import * as Q from "q";
|
import React from "react";
|
||||||
import * as ViewModels from "../../Contracts/ViewModels";
|
|
||||||
import TabsBase from "./TabsBase";
|
|
||||||
import { GraphExplorerAdapter } from "../Graph/GraphExplorerComponent/GraphExplorerAdapter";
|
|
||||||
import { GraphAccessor, GraphExplorerError } from "../Graph/GraphExplorerComponent/GraphExplorer";
|
|
||||||
import NewVertexIcon from "../../../images/NewVertex.svg";
|
import NewVertexIcon from "../../../images/NewVertex.svg";
|
||||||
import StyleIcon from "../../../images/Style.svg";
|
import StyleIcon from "../../../images/Style.svg";
|
||||||
import GraphStylingPane from "../Panes/GraphStylingPane";
|
|
||||||
import NewVertexPane from "../Panes/NewVertexPane";
|
|
||||||
import { DatabaseAccount } from "../../Contracts/DataModels";
|
import { DatabaseAccount } from "../../Contracts/DataModels";
|
||||||
|
import * as ViewModels from "../../Contracts/ViewModels";
|
||||||
import { CommandButtonComponentProps } from "../Controls/CommandButton/CommandButtonComponent";
|
import { CommandButtonComponentProps } from "../Controls/CommandButton/CommandButtonComponent";
|
||||||
|
import { GraphAccessor, GraphExplorerError } from "../Graph/GraphExplorerComponent/GraphExplorer";
|
||||||
|
import { GraphExplorerAdapter } from "../Graph/GraphExplorerComponent/GraphExplorerAdapter";
|
||||||
|
import { ContextualPaneBase } from "../Panes/ContextualPaneBase";
|
||||||
|
import GraphStylingPane from "../Panes/GraphStylingPane";
|
||||||
|
import { NewVertexPanel } from "../Panes/NewVertexPanel/NewVertexPanel";
|
||||||
import template from "./GraphTab.html";
|
import template from "./GraphTab.html";
|
||||||
|
import TabsBase from "./TabsBase";
|
||||||
export interface GraphIconMap {
|
export interface GraphIconMap {
|
||||||
[key: string]: { data: string; format: string };
|
[key: string]: { data: string; format: string };
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface GraphConfig {
|
export interface GraphConfig {
|
||||||
nodeColor: ko.Observable<string>;
|
nodeColor: ko.Observable<string>;
|
||||||
nodeColorKey: ko.Observable<string>; // map property to node color. Takes precedence over nodeColor unless null
|
nodeColorKey: ko.Observable<string>; // map property to node color. Takes precedence over nodeColor unless undefined
|
||||||
linkColor: ko.Observable<string>;
|
linkColor: ko.Observable<string>;
|
||||||
showNeighborType: ko.Observable<ViewModels.NeighborType>;
|
showNeighborType: ko.Observable<ViewModels.NeighborType>;
|
||||||
nodeCaption: ko.Observable<string>;
|
nodeCaption: ko.Observable<string>;
|
||||||
@ -53,21 +53,20 @@ export default class GraphTab extends TabsBase {
|
|||||||
private graphConfigUiData: ViewModels.GraphConfigUiData;
|
private graphConfigUiData: ViewModels.GraphConfigUiData;
|
||||||
private isFilterQueryLoading: ko.Observable<boolean>;
|
private isFilterQueryLoading: ko.Observable<boolean>;
|
||||||
private isValidQuery: ko.Observable<boolean>;
|
private isValidQuery: ko.Observable<boolean>;
|
||||||
private newVertexPane: NewVertexPane;
|
|
||||||
private graphStylingPane: GraphStylingPane;
|
private graphStylingPane: GraphStylingPane;
|
||||||
private collectionPartitionKeyProperty: string;
|
private collectionPartitionKeyProperty: string;
|
||||||
|
private contextualPane: ContextualPaneBase;
|
||||||
|
|
||||||
constructor(options: GraphTabOptions) {
|
constructor(options: GraphTabOptions) {
|
||||||
super(options);
|
super(options);
|
||||||
|
|
||||||
this.newVertexPane = options.collection && options.collection.container.newVertexPane;
|
|
||||||
this.graphStylingPane = options.collection && options.collection.container.graphStylingPane;
|
this.graphStylingPane = options.collection && options.collection.container.graphStylingPane;
|
||||||
this.collectionPartitionKeyProperty = options.collectionPartitionKeyProperty;
|
this.collectionPartitionKeyProperty = options.collectionPartitionKeyProperty;
|
||||||
|
|
||||||
this.isNewVertexDisabled = ko.observable(false);
|
this.isNewVertexDisabled = ko.observable(false);
|
||||||
this.isPropertyEditing = ko.observable(false);
|
this.isPropertyEditing = ko.observable(false);
|
||||||
this.isGraphDisplayed = ko.observable(false);
|
this.isGraphDisplayed = ko.observable(false);
|
||||||
this.graphAccessor = null;
|
this.graphAccessor = undefined;
|
||||||
this.graphConfig = GraphTab.createGraphConfig();
|
this.graphConfig = GraphTab.createGraphConfig();
|
||||||
// TODO Merge this with this.graphConfig
|
// TODO Merge this with this.graphConfig
|
||||||
this.graphConfigUiData = GraphTab.createGraphConfigUiData(this.graphConfig);
|
this.graphConfigUiData = GraphTab.createGraphConfigUiData(this.graphConfig);
|
||||||
@ -99,8 +98,8 @@ export default class GraphTab extends TabsBase {
|
|||||||
masterKey: options.masterKey,
|
masterKey: options.masterKey,
|
||||||
onLoadStartKey: options.onLoadStartKey,
|
onLoadStartKey: options.onLoadStartKey,
|
||||||
onLoadStartKeyChange: (onLoadStartKey: number): void => {
|
onLoadStartKeyChange: (onLoadStartKey: number): void => {
|
||||||
if (onLoadStartKey == null) {
|
if (onLoadStartKey === undefined) {
|
||||||
this.onLoadStartKey = null;
|
this.onLoadStartKey = undefined;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
resourceId: options.account.id,
|
resourceId: options.account.id,
|
||||||
@ -135,26 +134,31 @@ export default class GraphTab extends TabsBase {
|
|||||||
|
|
||||||
/* Command bar */
|
/* Command bar */
|
||||||
private showNewVertexEditor(): void {
|
private showNewVertexEditor(): void {
|
||||||
this.newVertexPane.open();
|
this.collection.container.openSidePanel(
|
||||||
this.newVertexPane.setPartitionKeyProperty(this.collectionPartitionKeyProperty);
|
"New Vertex",
|
||||||
// TODO Must update GraphExplorer properties
|
<NewVertexPanel
|
||||||
this.newVertexPane.subscribeOnSubmitCreate((result: ViewModels.NewVertexData) => {
|
explorer={this.collection.container}
|
||||||
this.newVertexPane.formErrors(null);
|
partitionKeyPropertyProp={this.collectionPartitionKeyProperty}
|
||||||
this.newVertexPane.formErrorsDetails(null);
|
openNotificationConsole={() => this.collection.container.expandConsole()}
|
||||||
this.graphAccessor.addVertex(result).then(
|
onSubmit={(
|
||||||
() => {
|
result: ViewModels.NewVertexData,
|
||||||
this.newVertexPane.cancel();
|
onError: (errorMessage: string) => void,
|
||||||
},
|
onSuccess: () => void
|
||||||
(error: GraphExplorerError) => {
|
): void => {
|
||||||
this.newVertexPane.formErrors(error.title);
|
this.graphAccessor.addVertex(result).then(
|
||||||
if (!!error.details) {
|
() => {
|
||||||
this.newVertexPane.formErrorsDetails(error.details);
|
onSuccess();
|
||||||
}
|
this.contextualPane.cancel();
|
||||||
}
|
},
|
||||||
);
|
(error: GraphExplorerError) => {
|
||||||
});
|
onError(error.title);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
public openStyling() {
|
public openStyling(): void {
|
||||||
this.setDefaultGraphConfigValues();
|
this.setDefaultGraphConfigValues();
|
||||||
// Update the styling pane with this instance
|
// Update the styling pane with this instance
|
||||||
this.graphStylingPane.setData(this.graphConfigUiData);
|
this.graphStylingPane.setData(this.graphConfigUiData);
|
||||||
@ -164,13 +168,13 @@ export default class GraphTab extends TabsBase {
|
|||||||
public static createGraphConfig(): GraphConfig {
|
public static createGraphConfig(): GraphConfig {
|
||||||
return {
|
return {
|
||||||
nodeColor: ko.observable(GraphTab.NODE_COLOR),
|
nodeColor: ko.observable(GraphTab.NODE_COLOR),
|
||||||
nodeColorKey: ko.observable(null),
|
nodeColorKey: ko.observable(undefined),
|
||||||
linkColor: ko.observable(GraphTab.LINK_COLOR),
|
linkColor: ko.observable(GraphTab.LINK_COLOR),
|
||||||
showNeighborType: ko.observable(ViewModels.NeighborType.TARGETS_ONLY),
|
showNeighborType: ko.observable(ViewModels.NeighborType.TARGETS_ONLY),
|
||||||
nodeCaption: ko.observable(GraphTab.DEFAULT_NODE_CAPTION),
|
nodeCaption: ko.observable(GraphTab.DEFAULT_NODE_CAPTION),
|
||||||
nodeSize: ko.observable(GraphTab.NODE_SIZE),
|
nodeSize: ko.observable(GraphTab.NODE_SIZE),
|
||||||
linkWidth: ko.observable(GraphTab.LINK_WIDTH),
|
linkWidth: ko.observable(GraphTab.LINK_WIDTH),
|
||||||
nodeIconKey: ko.observable(null),
|
nodeIconKey: ko.observable(undefined),
|
||||||
iconsMap: ko.observable({}),
|
iconsMap: ko.observable({}),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -183,26 +187,29 @@ export default class GraphTab extends TabsBase {
|
|||||||
nodeCaptionChoice: ko.observable(graphConfig.nodeCaption()),
|
nodeCaptionChoice: ko.observable(graphConfig.nodeCaption()),
|
||||||
nodeColorKeyChoice: ko.observable(graphConfig.nodeColorKey()),
|
nodeColorKeyChoice: ko.observable(graphConfig.nodeColorKey()),
|
||||||
nodeIconChoice: ko.observable(graphConfig.nodeIconKey()),
|
nodeIconChoice: ko.observable(graphConfig.nodeIconKey()),
|
||||||
nodeIconSet: ko.observable(null),
|
nodeIconSet: ko.observable(undefined),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Make sure graph config values are not null
|
* Make sure graph config values are not undefined
|
||||||
*/
|
*/
|
||||||
private setDefaultGraphConfigValues() {
|
private setDefaultGraphConfigValues() {
|
||||||
// Assign default values if null
|
// Assign default values if undefined
|
||||||
if (this.graphConfigUiData.nodeCaptionChoice() === null && this.graphConfigUiData.nodeProperties().length > 1) {
|
if (
|
||||||
|
this.graphConfigUiData.nodeCaptionChoice() === undefined &&
|
||||||
|
this.graphConfigUiData.nodeProperties().length > 1
|
||||||
|
) {
|
||||||
this.graphConfigUiData.nodeCaptionChoice(this.graphConfigUiData.nodeProperties()[0]);
|
this.graphConfigUiData.nodeCaptionChoice(this.graphConfigUiData.nodeProperties()[0]);
|
||||||
}
|
}
|
||||||
if (
|
if (
|
||||||
this.graphConfigUiData.nodeColorKeyChoice() === null &&
|
this.graphConfigUiData.nodeColorKeyChoice() === undefined &&
|
||||||
this.graphConfigUiData.nodePropertiesWithNone().length > 1
|
this.graphConfigUiData.nodePropertiesWithNone().length > 1
|
||||||
) {
|
) {
|
||||||
this.graphConfigUiData.nodeColorKeyChoice(this.graphConfigUiData.nodePropertiesWithNone()[0]);
|
this.graphConfigUiData.nodeColorKeyChoice(this.graphConfigUiData.nodePropertiesWithNone()[0]);
|
||||||
}
|
}
|
||||||
if (
|
if (
|
||||||
this.graphConfigUiData.nodeIconChoice() === null &&
|
this.graphConfigUiData.nodeIconChoice() === undefined &&
|
||||||
this.graphConfigUiData.nodePropertiesWithNone().length > 1
|
this.graphConfigUiData.nodePropertiesWithNone().length > 1
|
||||||
) {
|
) {
|
||||||
this.graphConfigUiData.nodeIconChoice(this.graphConfigUiData.nodePropertiesWithNone()[0]);
|
this.graphConfigUiData.nodeIconChoice(this.graphConfigUiData.nodePropertiesWithNone()[0]);
|
@ -39,12 +39,10 @@ import "./Explorer/Controls/ThroughputInput/ThroughputInput.less";
|
|||||||
import "./Explorer/Controls/TreeComponent/treeComponent.less";
|
import "./Explorer/Controls/TreeComponent/treeComponent.less";
|
||||||
import { ExplorerParams } from "./Explorer/Explorer";
|
import { ExplorerParams } from "./Explorer/Explorer";
|
||||||
import "./Explorer/Graph/GraphExplorerComponent/graphExplorer.less";
|
import "./Explorer/Graph/GraphExplorerComponent/graphExplorer.less";
|
||||||
import "./Explorer/Graph/NewVertexComponent/newVertexComponent.less";
|
|
||||||
import "./Explorer/Menus/CommandBar/CommandBarComponent.less";
|
import "./Explorer/Menus/CommandBar/CommandBarComponent.less";
|
||||||
import "./Explorer/Menus/CommandBar/MemoryTrackerComponent.less";
|
import "./Explorer/Menus/CommandBar/MemoryTrackerComponent.less";
|
||||||
import "./Explorer/Menus/NotificationConsole/NotificationConsole.less";
|
import "./Explorer/Menus/NotificationConsole/NotificationConsole.less";
|
||||||
import { NotificationConsoleComponent } from "./Explorer/Menus/NotificationConsole/NotificationConsoleComponent";
|
import { NotificationConsoleComponent } from "./Explorer/Menus/NotificationConsole/NotificationConsoleComponent";
|
||||||
import "./Explorer/Panes/GraphNewVertexPane.less";
|
|
||||||
import "./Explorer/Panes/PanelComponent.less";
|
import "./Explorer/Panes/PanelComponent.less";
|
||||||
import { PanelContainerComponent } from "./Explorer/Panes/PanelContainerComponent";
|
import { PanelContainerComponent } from "./Explorer/Panes/PanelContainerComponent";
|
||||||
import { SplashScreen } from "./Explorer/SplashScreen/SplashScreen";
|
import { SplashScreen } from "./Explorer/SplashScreen/SplashScreen";
|
||||||
@ -232,7 +230,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: "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-edit-entity-pane", params: { data: editTableEntityPane} }' />
|
<div data-bind='component: { name: "table-edit-entity-pane", params: { data: editTableEntityPane} }' />
|
||||||
<div data-bind='component: { name: "cassandra-add-collection-pane", params: { data: cassandraAddCollectionPane} }' />
|
<div data-bind='component: { name: "cassandra-add-collection-pane", params: { data: cassandraAddCollectionPane} }' />
|
||||||
|
Loading…
x
Reference in New Issue
Block a user