Skip to content

Commit

Permalink
Merge pull request #566 from codaco/release/4.1.0
Browse files Browse the repository at this point in the history
bump version to 4.1.0
  • Loading branch information
jthrilly committed Aug 23, 2019
2 parents f4133ff + 8f2a50f commit 2319021
Show file tree
Hide file tree
Showing 23 changed files with 324 additions and 42 deletions.
2 changes: 1 addition & 1 deletion network-canvas
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "network-canvas-architect",
"version": "4.0.2",
"version": "4.1.0",
"productName": "Network Canvas Architect",
"description": "A tool for creating Network Canvas interviews.",
"author": "Complex Data Collective",
Expand All @@ -24,7 +24,7 @@
"lint": "npm run lint:js && npm run lint:sass",
"lint:js": "eslint src",
"lint:sass": "sass-lint -vc .sass-lint.yml",
"test": "node scripts/test.js --env=jsdom",
"test": "cross-env TEST=true node scripts/test.js --env=jsdom",
"test-update-snapshots": "node scripts/test.js --env=jsdom --updateSnapshot",
"build-docs": "jsdoc src -r -d docs-build -c ./jsdoc.conf.json --verbose",
"electron": "env NODE_ENV=build electron ./app",
Expand Down Expand Up @@ -252,7 +252,7 @@
"[/\\\\]node_modules[/\\\\].+\\.(js|jsx)$"
],
"moduleNameMapper": {
"App/(.*)$": "<rootDir>/src/$1",
"App/(.*)$": "<rootDir>/src/$1",
"^react-native$": "react-native-web"
}
}
Expand Down
2 changes: 1 addition & 1 deletion public/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "network-canvas-architect",
"version": "4.0.2",
"version": "4.1.0",
"productName": "Network Canvas Architect",
"description": "A tool for creating Network Canvas interviews.",
"author": "Complex Data Collective",
Expand Down
1 change: 1 addition & 0 deletions src/__mocks__/electron.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ const remote = {

const ipcRenderer = {
send: jest.fn(() => {}),
on: jest.fn(() => {}),
};

module.exports = {
Expand Down
6 changes: 5 additions & 1 deletion src/components/Form/Fields/DefaultSelectOption.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ const DefaultSelectOption = (props) => {
const label = data.__createNewOption__ ?
data.__createNewOption__ :
data.label;
const handleClickDelete = (e) => {
e.stopPropagation();
props.onDeleteOption(data.value);
};
/* eslint-enable */

return (
Expand All @@ -32,7 +36,7 @@ const DefaultSelectOption = (props) => {
{ showDelete &&
<div
className="form-fields-select__item-delete"
onClick={() => props.onDeleteOption(data.value)}
onClick={handleClickDelete}
>
<Icon name="delete" />
</div>
Expand Down
4 changes: 2 additions & 2 deletions src/components/Options.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ const mapDispatchToItemProps = dispatch => ({
openDialog: bindActionCreators(dialogsActions.openDialog, dispatch),
});

const Item = compose(
export const Item = compose(
connect(null, mapDispatchToItemProps),
withHandlers({
handleDelete: ({ fields, openDialog, index }) =>
Expand Down Expand Up @@ -108,7 +108,7 @@ Item.propTypes = {
index: PropTypes.number.isRequired,
};

const Items = compose(
export const Items = compose(
defaultProps({
lockAxis: 'y',
useDragHandle: true,
Expand Down
7 changes: 3 additions & 4 deletions src/components/sections/CategoricalBinPrompts/PromptFields.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import Options from '../../Options';
import { getSortOrderOptionGetter } from './optionGetters';
import withPromptProps from './withPromptProps';


const PromptFields = ({
variableOptions,
handleCreateNewVariable,
Expand Down Expand Up @@ -47,7 +46,7 @@ const PromptFields = ({
Tip: You can use markdown formatting in this prompt to create bold or underlined text.
</strong></p>
<ValidatedField
name={'text'}
name="text"
component={Text}
label=""
placeholder="Enter text for the prompt here..."
Expand All @@ -57,7 +56,7 @@ const PromptFields = ({
<Row>
<h3 id={getFieldId('variable')}>Categorical Variable</h3>
<ValidatedField
name={'variable'}
name="variable"
component={CreatableSelect}
label=""
options={categoricalVariableOptions}
Expand Down Expand Up @@ -139,8 +138,8 @@ const PromptFields = ({

PromptFields.propTypes = {
variableOptions: PropTypes.array,
handleCreateNewVariable: PropTypes.func.isRequired,
handleDeleteVariable: PropTypes.func.isRequired,
handleCreateNewVariable: PropTypes.func.isRequired,
entity: PropTypes.string.isRequired,
type: PropTypes.string.isRequired,
...newWindowVariablePropTypes,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
/* eslint-env jest */
import React from 'react';
import { Provider } from 'react-redux';
import { reduxForm, change } from 'redux-form';
import { mount } from 'enzyme';
import { getStore } from '../../../../ducks/store';
import Options, { Item } from '../../../Options';
import { actionCreators as codebookActions } from '../../../../ducks/modules/protocol/codebook';
import PromptFields from '../PromptFields';

const mockFormName = 'foo';

const initialState = {
protocol: {
timeline: [],
present: {
codebook: {
node: {
person: {
variables: {
bazz: {
options: ['a', 'b', 'c', 'd'],
},
buzz: {
options: [1, 2],
},
},
},
},
},
},
},
};

const MockForm = reduxForm({
form: mockFormName,
})(
({ handleSubmit, children }) => (
<form onSubmit={handleSubmit}>
{children}
</form>
),
);


const getSubject = (node, store, { form }) =>
mount((
<Provider store={store}>
<MockForm {...form}>
{node}
</MockForm>
</Provider>
));

// eslint-disable-next-line import/prefer-default-export
export const testPromptFields = (PromptFieldsComponent) => {
let mockStore;

beforeEach(() => {
mockStore = getStore(initialState);
});

describe('PromptFields', () => {
it('when variable is created, variable options are updated', () => {
const formProps = { initialValues: { variable: 'bazz', variableOptions: ['a', 'b', 'c', 'd'] } };
const additionalProps = { form: formProps };

const subject = getSubject(
(
<PromptFieldsComponent
form={mockFormName}
entity="node"
type="person"
/>
),
mockStore,
additionalProps,
);

expect(subject.find(Options).find(Item).length).toBe(4);

mockStore.dispatch(codebookActions.createVariable(
'node',
'person',
{
name: 'fizz',
type: 'foo',
options: [1, 2, 3],
},
));

mockStore.dispatch(change(
mockFormName,
'variable',
'809895df-bbd7-4c76-ac58-e6ada2625f9b',
));

subject.update();

expect(subject.find(Options).find(Item).length).toBe(3);
});

it('when variable is changed, variable options are updated', () => {
const formProps = { initialValues: { variable: 'bazz', variableOptions: ['a', 'b', 'c', 'd'] } };
const additionalProps = { form: formProps };

const subject = getSubject(
(
<PromptFieldsComponent
form={mockFormName}
entity="node"
type="person"
/>
),
mockStore,
additionalProps,
);

expect(subject.find(Options).find(Item).length).toBe(4);

mockStore.dispatch(change(
mockFormName,
'variable',
'buzz',
));

subject.update();

expect(subject.find(Options).find(Item).length).toBe(2);
});
});
};

testPromptFields(PromptFields);
6 changes: 3 additions & 3 deletions src/components/sections/CategoricalBinPrompts/helpers.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
/* eslint-disable import/prefer-default-export */

import { get } from 'lodash';
import { formValueSelector } from 'redux-form';
import { getOptionsForVariable } from '../../../selectors/codebook';

export const itemSelector = (entity, type) =>
(state, { form, editField }) => {
const prompt = formValueSelector(form)(state, editField);

if (!prompt) { return {}; }

const variableOptions = get(
const variableOptions = getOptionsForVariable(
state,
['protocol', 'present', 'codebook', entity, type, 'variables', prompt.variable, 'options'],
{ entity, type, variable: prompt.variable },
);

return {
Expand Down
40 changes: 35 additions & 5 deletions src/components/sections/CategoricalBinPrompts/withPromptProps.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,20 @@
import { connect } from 'react-redux';
import { change, formValueSelector } from 'redux-form';
import { compose, withHandlers } from 'recompose';
import { getVariableOptionsForSubject } from '../../../selectors/codebook';
import { compose, withHandlers, lifecycle } from 'recompose';
import { get } from 'lodash';
import { getVariableOptionsForSubject, getVariablesForSubject } from '../../../selectors/codebook';
import { actionCreators as codebookActions } from '../../../ducks/modules/protocol/codebook';

const mapStateToProps = (state, { form, type, entity }) => {
const variableOptions = getVariableOptionsForSubject(state, { type, entity });
const variable = formValueSelector(form)(state, 'variable');
const variables = getVariablesForSubject(state, { type, entity });
const optionsForVariable = get(variables, [variable, 'options'], []);

return {
variable,
variableOptions,
optionsForVariable,
};
};

Expand All @@ -21,19 +25,45 @@ const mapDispatchToProps = {

const variableOptions = connect(mapStateToProps, mapDispatchToProps);

// Fix to keep redux 'sub-form' fields in sync
const updateFormVariableOptions = lifecycle({
componentDidUpdate(previousProps) {
const {
changeForm,
form,
optionsForVariable,
variable,
} = this.props;
if (previousProps.variable === variable) { return; }
changeForm(form, 'variableOptions', optionsForVariable);
},
});

const variableHandlers = withHandlers({
handleCreateNewVariable: ({ closeNewVariableWindow, changeForm, form }) =>
(variable) => {
// update form
changeForm(form, 'variable', variable);
closeNewVariableWindow();
},
handleDeleteVariable: ({ entity, type, deleteVariable }) =>
variable => deleteVariable(entity, type, variable),
handleDeleteVariable: ({
entity,
type,
deleteVariable,
changeForm,
form,
variable: selectedVariable,
}) =>
(variable) => {
const variableDeleted = deleteVariable(entity, type, variable);
if (variableDeleted && variable === selectedVariable) {
changeForm(form, 'variable', null);
}
},
});

const withPromptProps = compose(
variableOptions,
updateFormVariableOptions,
variableHandlers,
);

Expand Down
2 changes: 1 addition & 1 deletion src/components/sections/OrdinalBinPrompts/PromptFields.js
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ const PromptFields = ({
<Row>
{ variable &&
<Section>
<h3 id={getFieldId('options')}>Variable Options</h3>
<h3 id={getFieldId('variableOptions')}>Variable Options</h3>
<p>Create some options for this variable</p>
<Options
name="variableOptions"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/* eslint-env jest */
import { testPromptFields } from '../../CategoricalBinPrompts/__tests__/PromptFields.test';
import PromptFields from '../PromptFields';

testPromptFields(PromptFields);
3 changes: 2 additions & 1 deletion src/components/sections/Row.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,14 @@ Row.propTypes = {
disabled: PropTypes.bool,
contentId: PropTypes.string,
focus: PropTypes.bool,
children: PropTypes.node.isRequired,
children: PropTypes.node,
};

Row.defaultProps = {
focus: false,
contentId: null,
disabled: false,
children: null,
};

export default Row;

0 comments on commit 2319021

Please sign in to comment.