Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds search functionality to select elements in the add edge form #47

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 27 additions & 15 deletions app/components/AddEdgeForm.jsx
Original file line number Diff line number Diff line change
@@ -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';
Expand Down Expand Up @@ -33,32 +34,43 @@ 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 (
<div id="addEdgeForm" className="editForm">
<HotKeys keyMap={keyMap} handlers={keyHandlers}>
<form onSubmit={this._handleSubmit}>
<select defaultValue={node1Id} className="form-control input-sm" ref="node1Id">
<option value="">Node 1</option>
{ nodes.map((node, i) =>
<option key={node.id} value={node.id}>{node.display.name}</option>
) }
</select>
<select defaultValue={node2Id} className="form-control input-sm" ref="node2Id">
<option value="">Node 2</option>
{ nodes.map((node, i) =>
<option key={node.id} value={node.id}>{node.display.name}</option>
) }
</select>
<input type="text" placeholder="label" className="form-control input-sm" ref="label" />
<Select
ref="node1Id"
value={node1Id}
name="node 1"
options={nodesMapped}
placeholder="First node"
/>
<Select
ref="node2Id"
value={node2Id}
name="node 2"
options={nodesMapped}
placeholder="Second node"
/>
<input type="text" placeholder="label" className="form-control input-sm" ref="label"
onKeyPress={(e) => e.key == "Enter" ? this._handleSubmit(e) : null } />
</form>
</HotKeys>
</div>
);
}

_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) {
Expand Down
119 changes: 119 additions & 0 deletions app/components/__tests__/AddEdgeForm-test.js
Original file line number Diff line number Diff line change
@@ -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(
<AddEdgeForm
data={null}
nodes={nodes} />
);
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(
<AddEdgeForm
data={null}
nodes={nodes} />
);
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(
<AddEdgeForm
data={null}
nodes={nodes} />
);
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(
<AddEdgeForm
data={[{ id: 1, display: { name: "Node 1" } }, { id: 2, display: { name: "Node 2"} }]}
nodes={nodes} />
);
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(
<AddEdgeForm
data={{ id: 1, display: { name: "Node 1" } }}
nodes={nodes} />
);
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(
<AddEdgeForm
nodes={nodes} />
);
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(
<AddEdgeForm
addEdge= {addEdgeFunction}
closeAddForm= {closeAddFormFunction}
data={[{ id: 1, display: { name: "Node 1" } }, { id: 2, display: { name: "Node 2"} }]}
nodes={nodes} />
);

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);

});


})



})
1 change: 1 addition & 0 deletions app/main.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -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 = {}) {
Expand Down
29 changes: 28 additions & 1 deletion app/styles/oligrapher.editor.css
Original file line number Diff line number Diff line change
Expand Up @@ -212,4 +212,31 @@ button#toggleEditTools {

#edgeUrlInput {
width: 337px;
}
}

/*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;
}
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down Expand Up @@ -72,4 +73,4 @@
"<rootDir>/node_modules/"
]
}
}
}