diff --git a/app/components/AddEdgeForm.jsx b/app/components/AddEdgeForm.jsx
index 4e5931e..7f7035a 100644
--- a/app/components/AddEdgeForm.jsx
+++ b/app/components/AddEdgeForm.jsx
@@ -1,5 +1,6 @@
import React, { Component, PropTypes } from 'react';
import BaseComponent from './BaseComponent';
+import Select from 'react-select';
import values from 'lodash/object/values';
import sortBy from 'lodash/collection/sortBy';
import { HotKeys } from 'react-hotkeys';
@@ -33,23 +34,34 @@ export default class AddEdgeForm extends BaseComponent {
let nodes = sortBy(values(this.props.nodes), (node) => node.display.name);
+ let nodesMapped = nodes.map(function(node, i) {
+ return (
+ { key: node.id, value: node.id, label: node.display.name }
+ );
+ });
+
+ //note the keypress listener on input so it submits the form on enter
+ //due to Select library elements containing input forms
return (
@@ -57,8 +69,8 @@ export default class AddEdgeForm extends BaseComponent {
}
_handleSubmit(e) {
- let node1Id = this.refs.node1Id.value;
- let node2Id = this.refs.node2Id.value;
+ let node1Id = this.refs.node1Id.state.value;
+ let node2Id = this.refs.node2Id.state.value;
let label = this.refs.label.value.trim();
if (node1Id && node2Id && label) {
diff --git a/app/components/__tests__/AddEdgeForm-test.js b/app/components/__tests__/AddEdgeForm-test.js
new file mode 100644
index 0000000..0740514
--- /dev/null
+++ b/app/components/__tests__/AddEdgeForm-test.js
@@ -0,0 +1,119 @@
+jest.unmock('../BaseComponent');
+jest.unmock('../AddEdgeForm');
+jest.unmock('react-select');
+
+import React from 'react';
+import { mount } from "enzyme";
+
+import AddEdgeForm from "../AddEdgeForm";
+
+describe("AddEdgeForm", () => {
+
+ let nodes = { 1: { id: 1, display: { name: "Node 1" } }, 2: { id: 2, display: { name: "Node 2"} }, 3: { id: 3, display: { name: "Node 3" } } };
+
+ describe("rendering", () => {
+
+ it("renders two react-select elements", () => {
+ let wrapper = mount(
+
+ );
+ expect(wrapper.find("Select").length).toBe(2);
+
+ let firstReactSelect = wrapper.ref("node1Id");
+ expect(firstReactSelect.is("Select")).toBe(true);
+
+ let secondReactSelect = wrapper.ref("node2Id");
+ expect(secondReactSelect.is("Select")).toBe(true);
+ });
+
+ it("renders one an additional input element (not part of React-Selects)", () => {
+ let wrapper = mount(
+
+ );
+ expect(wrapper.find(".form-control.input-sm").length).toBe(1);
+ });
+
+ it("returns empty string values for the two Select elements if data is null", () => {
+ let wrapper = mount(
+
+ );
+ let firstReactSelect = wrapper.ref("node1Id");
+ expect(firstReactSelect.get(0).state.value).toBe('');
+
+ let secondReactSelect = wrapper.ref("node2Id");
+ expect(secondReactSelect.get(0).state.value).toBe('');
+ });
+
+ it("returns the first two node values from the data array for the two Select elements if data array > 1", () => {
+ let wrapper = mount(
+
+ );
+ let firstReactSelect = wrapper.ref("node1Id");
+ expect(firstReactSelect.get(0).state.value).toBe(1);
+
+ let secondReactSelect = wrapper.ref("node2Id");
+ expect(secondReactSelect.get(0).state.value).toBe(2);
+ });
+
+ it("sets the state of only the first Select component to equal the id of a single passed in node data", () => {
+ let wrapper = mount(
+
+ );
+ let firstReactSelect = wrapper.ref("node1Id");
+ expect(firstReactSelect.get(0).state.value).toBe(1);
+
+ let secondReactSelect = wrapper.ref("node2Id");
+ expect(secondReactSelect.get(0).state.value).toBe('');
+ });
+
+ it("sets the Select components options to correspond to the nodes prop", () => {
+ let wrapper = mount(
+
+ );
+ let firstReactSelect = wrapper.ref("node1Id");
+ expect(firstReactSelect.get(0).props.options.length).toBe(Object.keys(nodes).length);
+
+ let secondReactSelect = wrapper.ref("node2Id");
+ expect(secondReactSelect.get(0).props.options.length).toBe(Object.keys(nodes).length);
+
+ });
+ })
+
+ describe("behaviour", () => {
+ let addEdgeFunction = jest.genMockFunction();
+ let closeAddFormFunction = jest.genMockFunction();;
+
+ it("calls to both addEdge and to closeAddForm when enter is pressed on a non-empty label input field", () => {
+ let wrapper = mount(
+
+ );
+
+ let selectForm = wrapper.find(".form-control.input-sm");
+ selectForm.get(0).value = 'label';
+ selectForm.simulate('keyPress', { key: "Enter" });
+ expect(addEdgeFunction.mock.calls.length).toBe(1);
+ expect(closeAddFormFunction.mock.calls.length).toBe(1);
+
+ });
+
+
+ })
+
+
+
+})
\ No newline at end of file
diff --git a/app/main.jsx b/app/main.jsx
index 4f7f303..3657d23 100644
--- a/app/main.jsx
+++ b/app/main.jsx
@@ -21,6 +21,7 @@ import merge from 'lodash/object/merge';
import assign from 'lodash/object/assign';
import difference from 'lodash/array/difference';
require ('./styles/oligrapher.css');
+import 'react-select/dist/react-select.css';
class Oligrapher {
constructor(config = {}) {
diff --git a/app/styles/oligrapher.editor.css b/app/styles/oligrapher.editor.css
index 93a42ee..5de107b 100755
--- a/app/styles/oligrapher.editor.css
+++ b/app/styles/oligrapher.editor.css
@@ -212,4 +212,31 @@ button#toggleEditTools {
#edgeUrlInput {
width: 337px;
-}
\ No newline at end of file
+}
+
+/*overwriting react-select styles*/
+
+.Select .Select-control {
+ font-size: 12px;
+ height: 32px;
+}
+
+.Select-menu-outer {
+ font-size: 0.8em;
+}
+
+.Select .Select-input {
+ height: 30px;
+}
+
+.Select .Select-placeholder{
+ line-height: 30px;
+}
+
+.Select .Select-input > input {
+ height: 30px;
+}
+
+.Select {
+ margin-bottom: 10px;
+}
diff --git a/package.json b/package.json
index 265fde5..69fa9ec 100644
--- a/package.json
+++ b/package.json
@@ -37,7 +37,8 @@
"redux-undo": "^0.6.0",
"shortid": "^2.2.4",
"springy": "^2.7.1",
- "titleize": "^1.0.0"
+ "titleize": "^1.0.0",
+ "react-select": "^0.9.1"
},
"devDependencies": {
"babel-core": "^6.7.7",
@@ -72,4 +73,4 @@
"/node_modules/"
]
}
-}
+}
\ No newline at end of file