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

Templates form migration #81

Merged
merged 11 commits into from
Jun 3, 2016
4 changes: 0 additions & 4 deletions app/react/App/scss/fixes.scss
Original file line number Diff line number Diff line change
Expand Up @@ -85,10 +85,6 @@ header ul .btn .fa {
}
}

.well .col-sm-8 {
min-height: 61px;
}

.search__filter > li label {
font-weight: bold;
}
10 changes: 7 additions & 3 deletions app/react/Form/components/Select.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,16 @@ import React, {Component, PropTypes} from 'react';
export class Select extends Component {

render() {
const {properties, label, options} = this.props;
let {properties, label, options, optionsValue, optionsLabel} = this.props;
optionsValue = optionsValue || 'value';
optionsLabel = optionsLabel || 'label';
return (
<ul className="search__filter">
<li><label>{label}</label></li>
<li>
<select className="form-control" {...properties}>
{options.map((option, index) => {
return <option key={index} value={option.value}>{option.label}</option>;
return <option key={index} value={option[optionsValue]}>{option[optionsLabel]}</option>;
})}
</select>
</li>
Expand All @@ -23,7 +25,9 @@ export class Select extends Component {
Select.propTypes = {
properties: PropTypes.object,
label: PropTypes.string,
options: PropTypes.array
options: PropTypes.array,
optionsValue: PropTypes.string,
optionsLabel: PropTypes.string
};

export default Select;
17 changes: 17 additions & 0 deletions app/react/Form/components/specs/Select.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,21 @@ describe('Select', () => {
expect(optionElements.last().props().value).toBe('option2');
expect(optionElements.last().text()).toBe('Option2');
});

describe('different key name for label and value', () => {
beforeEach(() => {
options = [{name: 'Option1', id: 'option1'}, {name: 'Option2', id: 'option2'}];
component = shallow(<Select label='special select' options={options} optionsValue="id" optionsLabel="name"/>);
});

it('should render the options', () => {
let optionElements = component.find('option');

expect(optionElements.length).toBe(2);
expect(optionElements.first().props().value).toBe('option1');
expect(optionElements.first().text()).toBe('Option1');
expect(optionElements.last().props().value).toBe('option2');
expect(optionElements.last().text()).toBe('Option2');
});
});
});
7 changes: 4 additions & 3 deletions app/react/Forms/components/FormField.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ const FieldController = createFieldClass({

class FormField extends Component {
render() {
let field = React.cloneElement(this.props.children, {className: 'form-control'});
let field = React.cloneElement(this.props.children);
if (this.props.model) {
field = <FieldController model={this.props.model}>{field}</FieldController>;
field = <FieldController model={this.props.model} validators={this.props.validators}>{field}</FieldController>;
}

return field;
Expand All @@ -18,7 +18,8 @@ class FormField extends Component {

FormField.propTypes = {
model: PropTypes.string,
children: PropTypes.object.isRequired
children: PropTypes.object.isRequired,
validators: PropTypes.object
};

export default FormField;
Expand Down
10 changes: 7 additions & 3 deletions app/react/Forms/components/Select.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@ import {createFieldClass, controls} from 'react-redux-form';
export class Select extends Component {

render() {
const {options} = this.props;
let {options, optionsValue, optionsLabel} = this.props;
optionsValue = optionsValue || 'value';
optionsLabel = optionsLabel || 'label';
return (
<select className="form-control" onChange={this.props.onChange} value={this.props.value}>
{options.map((option, index) => {
return <option key={index} value={option.value}>{option.label}</option>;
return <option key={index} value={option[optionsValue]}>{option[optionsLabel]}</option>;
})}
</select>
);
Expand All @@ -20,7 +22,9 @@ Select.propTypes = {
onChange: PropTypes.func,
label: PropTypes.string,
options: PropTypes.array,
value: PropTypes.string
value: PropTypes.string,
optionsValue: PropTypes.string,
optionsLabel: PropTypes.string
};

export default Select;
Expand Down
8 changes: 1 addition & 7 deletions app/react/Forms/components/specs/FormField.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,10 @@ describe('FormField', () => {
component = shallow(<FormField model={model} {...props}><input /></FormField>);
};

it('should render child field and add "form-control" className', () => {
render();
let input = component.find('input.form-control');
expect(input.length).toBe(1);
});

describe('when passing a model', () => {
it('should render the field inside a FieldController with model passed', () => {
render('model');
let field = component.find('input.form-control').parents(FieldController);
let field = component.find('input').parents(FieldController);
expect(field.props().model).toBe('model');
});
});
Expand Down
22 changes: 22 additions & 0 deletions app/react/Forms/components/specs/Select.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,26 @@ describe('Select', () => {
expect(optionElements.last().props().value).toBe('option2');
expect(optionElements.last().text()).toBe('Option2');
});

describe('different key name for label and value', () => {
beforeEach(() => {
props = {
label: 'input label',
options: [{name: 'Option1', id: 'option1'}, {name: 'Option2', id: 'option2'}],
optionsValue: 'id',
optionsLabel: 'name'
};
component = shallow(<Select {...props}/>);
});

it('should render the options', () => {
let optionElements = component.find('option');

expect(optionElements.length).toBe(2);
expect(optionElements.first().props().value).toBe('option1');
expect(optionElements.first().text()).toBe('Option1');
expect(optionElements.last().props().value).toBe('option2');
expect(optionElements.last().text()).toBe('Option2');
});
});
});
3 changes: 2 additions & 1 deletion app/react/Forms/index.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import Select from './components/Select';
import Select, {SelectField} from './components/Select';
import FormField from './components/FormField';
import FormGroup from './components/FormGroup';

export {
Select,
SelectField,
FormField,
FormGroup
};
3 changes: 1 addition & 2 deletions app/react/RelationTypes/components/RelationTypeForm.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import React, {Component, PropTypes} from 'react';
import {bindActionCreators} from 'redux';
import {Field, Form} from 'react-redux-form';
import {Field, Form, actions as formActions} from 'react-redux-form';
import {connect} from 'react-redux';
import {Link} from 'react-router';
import {actions as formActions} from 'react-redux-form';

import FormGroup from 'app/DocumentForm/components/FormGroup';
import {saveRelationType, resetRelationType} from 'app/RelationTypes/actions/relationTypeActions';
Expand Down
3 changes: 2 additions & 1 deletion app/react/Templates/EditTemplate.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import React from 'react';
import {actions as formActions} from 'react-redux-form';

import templatesAPI from 'app/Templates/TemplatesAPI';
import thesaurisAPI from 'app/Thesauris/ThesaurisAPI';
Expand Down Expand Up @@ -37,7 +38,7 @@ export default class EditTemplate extends RouteHandler {
}

setReduxState({template}) {
this.context.store.dispatch(setTemplate(template.data));
this.context.store.dispatch(formActions.load('template.data', template.data));
this.context.store.dispatch(setThesauris(template.uiState.thesauris));
this.context.store.dispatch(setTemplates(template.uiState.templates));
}
Expand Down
72 changes: 36 additions & 36 deletions app/react/Templates/actions/specs/templateActions.spec.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import configureMockStore from 'redux-mock-store';
import thunk from 'redux-thunk';
import backend from 'fetch-mock';
import {actions as formActions} from 'react-redux-form';

import {APIURL} from 'app/config.js';
import * as actions from 'app/Templates/actions/templateActions';
Expand All @@ -12,35 +13,41 @@ import {mockID} from 'shared/uniqueID';
const middlewares = [thunk];
const mockStore = configureMockStore(middlewares);

describe('templatesActions', () => {
describe('templateActions', () => {
let dispatch;
let getState;
let formModel;
beforeEach(() => {
mockID();
formModel = {
template: {data: {properties: [{name: 'property1'}, {name: 'property2'}]}}
};
dispatch = jasmine.createSpy('dispatch');
getState = jasmine.createSpy('getState').and.returnValue(formModel);
spyOn(formActions, 'change');
spyOn(formActions, 'move');
spyOn(formActions, 'remove');
spyOn(formActions, 'reset');
});

describe('addProperty()', () => {
it('should return an ADD_PROPERTY type action with config, unique config.id and index passed', () => {
let action = actions.addProperty({name: 'test'}, 'index !');
expect(action).toEqual({type: types.ADD_PROPERTY, config: {name: 'test', localID: 'unique_id'}, index: 'index !'});
});

it('should return default config object and index if nothing passed', () => {
let action = actions.addProperty();
expect(action).toEqual({type: types.ADD_PROPERTY, config: {localID: 'unique_id'}, index: 0});
});
});

describe('updateTemplate()', () => {
it('should return an UPDATE_TEMPLATE type action with template passed', () => {
let action = actions.updateTemplate({name: 'test'});
expect(action).toEqual({type: types.UPDATE_TEMPLATE, template: {name: 'test'}});
it('should add the property to the form data with a unique id in the index provided', () => {
actions.addProperty({name: 'property3'}, 0)(dispatch, getState);
expect(formActions.change).toHaveBeenCalledWith('template.data.properties', [
{name: 'property3', localID: 'unique_id'},
{name: 'property1'},
{name: 'property2'}
]);
});
});

describe('updateProperty()', () => {
it('should return an UPDATE_PROPERTY type action with the new property config', () => {
let config = {name: 'super name'};
let action = actions.updateProperty(config, 2);
expect(action).toEqual({type: types.UPDATE_PROPERTY, config: {name: 'super name'}, index: 2});
it('should update the property in the index provided', () => {
actions.updateProperty({name: 'new name'}, 0)(dispatch, getState);
expect(formActions.change).toHaveBeenCalledWith('template.data.properties', [
{name: 'new name'},
{name: 'property2'}
]);
});
});

Expand All @@ -51,31 +58,24 @@ describe('templatesActions', () => {
});
});

describe('setTemplate()', () => {
it('should return a SET_TEMPLATE type action with the template passed', () => {
let action = actions.setTemplate('template');
expect(action).toEqual({type: types.SET_TEMPLATE, template: 'template'});
});
});

describe('resetTemplate()', () => {
it('should return a RESET_TEMPLATE type action with the template passed', () => {
let action = actions.resetTemplate();
expect(action).toEqual({type: types.RESET_TEMPLATE});
it('should reset the form data', () => {
actions.resetTemplate()(dispatch);
expect(formActions.reset).toHaveBeenCalledWith('template.data');
});
});

describe('removeProperty', () => {
it('should return a REMOVE_FIELD type action with index passed', () => {
let action = actions.removeProperty(55);
expect(action).toEqual({type: types.REMOVE_PROPERTY, index: 55});
it('should remove the property from the data', () => {
actions.removeProperty(1)(dispatch, getState);
expect(formActions.change).toHaveBeenCalledWith('template.data.properties', [{name: 'property1'}]);
});
});

describe('reorderProperty', () => {
it('should return a REORDER_PROPERTY type action with origin and target indexes', () => {
let action = actions.reorderProperty(1, 2);
expect(action).toEqual({type: types.REORDER_PROPERTY, originIndex: 1, targetIndex: 2});
it('should reorder the properties in the form data', () => {
actions.reorderProperty(1, 2)(dispatch);
expect(formActions.move).toHaveBeenCalledWith('template.data.properties', 1, 2);
});
});

Expand Down
Loading