Skip to content

Commit

Permalink
Clear interventions after they've been displayed (#5341)
Browse files Browse the repository at this point in the history
* Add a clearIntervention action creator
Add a CLEAR_INTERVENTION action to clear any stored interventions. Don't clear interventions on next subject. Update tests.

* Add onUnmount to Intervention
Add an onUnmount callback to the Intervention component, and call it on component cleanup. Memo-ise Intervention to prevent unnecessary renders. Update tests.

* Clear interventions on unmount
Call the clearIntervention action when the Intervention component unmounts.
  • Loading branch information
eatyourgreens authored May 16, 2019
1 parent 33eb94a commit 9461eb8
Show file tree
Hide file tree
Showing 5 changed files with 69 additions and 13 deletions.
1 change: 1 addition & 0 deletions app/classifier/classifier.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,7 @@ class Classifier extends React.Component {
{showIntervention &&
<Intervention
intervention={intervention}
onUnmount={actions.classify.clearIntervention}
user={user}
/>
}
Expand Down
17 changes: 14 additions & 3 deletions app/classifier/components/Intervention/Intervention.jsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React from 'react';
import React, { memo, useEffect } from 'react';
import PropTypes from 'prop-types';
import counterpart from 'counterpart';
import styled from 'styled-components';
Expand All @@ -14,10 +14,15 @@ const StyledInterventionMessage = styled.div`
}
`;

function Intervention({ intervention, user }) {
function Intervention({ onUnmount, intervention, user }) {
const { message } = intervention;
const checkbox = React.createRef();

useEffect(() => {
// the return value of an effect will be called to clean up after the component
return onUnmount;
});

function onChange() {
// Invert the checked value because true means do not send me messages.
user
Expand All @@ -40,13 +45,19 @@ function Intervention({ intervention, user }) {
);
}

Intervention.defaultProps = {
onUnmount: () => true
};

Intervention.propTypes = {
intervention: PropTypes.shape({
message: PropTypes.string
}).isRequired,
onUnmount: PropTypes.func,
user: PropTypes.shape({
intervention_notifications: PropTypes.bool
}).isRequired
};

export default Intervention;
export default memo(Intervention);
export { Intervention }
15 changes: 14 additions & 1 deletion app/classifier/components/Intervention/Intervention.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React from 'react';
import { mount } from 'enzyme';
import { expect } from 'chai';
import sinon from 'sinon';
import Intervention from './Intervention';
import { Intervention } from './Intervention';
import { Markdown } from 'markdownz';

describe('Intervention', function () {
Expand All @@ -15,10 +15,13 @@ describe('Intervention', function () {
return { save: () => true };
})
};
const onUnmount = sinon.stub()

before(function () {
wrapper = mount(
<Intervention
intervention={intervention}
onUnmount={onUnmount}
user={user}
/>);
});
Expand Down Expand Up @@ -46,4 +49,14 @@ describe('Intervention', function () {
expect(user.update.calledWith(changes)).to.be.true;
})
});

describe('on unmount', function () {
before(function () {
wrapper.unmount()
});

it('should call onUnmount', function () {
expect(onUnmount).to.have.been.calledOnce
})
})
});
15 changes: 12 additions & 3 deletions app/redux/ducks/classify.js
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ const initialState = {
};

const ADD_INTERVENTION = 'pfe/classify/ADD_INTERVENTION';
const CLEAR_INTERVENTION = 'pfe/classify/CLEAR_INTERVENTION';
const APPEND_SUBJECTS = 'pfe/classify/APPEND_SUBJECTS';
const FETCH_SUBJECTS = 'pfe/classify/FETCH_SUBJECTS';
const PREPEND_SUBJECTS = 'pfe/classify/PREPEND_SUBJECTS';
Expand All @@ -147,6 +148,10 @@ export default function reducer(state = initialState, action = {}) {
}
return state;
}
case CLEAR_INTERVENTION: {
const intervention = null;
return Object.assign({}, state, { intervention });
}
case APPEND_SUBJECTS: {
const { subjects, workflowID } = action.payload;
const { workflow } = state;
Expand Down Expand Up @@ -190,12 +195,10 @@ export default function reducer(state = initialState, action = {}) {
const subject = upcomingSubjects[0];
if (subject) {
const classification = createNewClassification(project, workflow, subject, goldStandardMode);
const intervention = null;
return Object.assign({}, state, { classification, intervention, upcomingSubjects });
return Object.assign({}, state, { classification, upcomingSubjects });
}
return Object.assign({}, state, {
classification: null,
intervention: null,
upcomingSubjects: []
});
}
Expand Down Expand Up @@ -260,6 +263,12 @@ export function addIntervention(data) {
};
}

export function clearIntervention() {
return {
type: CLEAR_INTERVENTION
};
}

export function appendSubjects(subjects, workflowID) {
return {
type: APPEND_SUBJECTS,
Expand Down
34 changes: 28 additions & 6 deletions app/redux/ducks/classify.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,22 @@ describe('Classifier actions', function () {
});
});
});

describe('clear intervention', function () {
const action = {
type: 'pfe/classify/CLEAR_INTERVENTION',
};
const state = {
intervention: {
message: 'this is an intervention'
}
};
it('should clear intervention messages', function () {
const newState = reducer(state, action);
expect(newState.intervention).to.be.null;
});
});

describe('append subjects', function () {
const subjects = [
mockSubject('3'),
Expand Down Expand Up @@ -157,7 +173,10 @@ describe('Classifier actions', function () {
const state = {
classification: { id: '1' },
workflow: { id: '1' },
upcomingSubjects: [subjects[0]]
upcomingSubjects: [subjects[0]],
intervention: {
message: 'This is a test intervention'
}
};
it('should empty the queue', function () {
const newState = reducer(state, action);
Expand All @@ -167,15 +186,18 @@ describe('Classifier actions', function () {
const newState = reducer(state, action);
expect(newState.classification).to.be.null;
});
it('should clear any stored interventions', function () {
it('should not clear any stored interventions', function () {
const newState = reducer(state, action);
expect(newState.intervention).to.be.null;
expect(newState.intervention).to.eql(state.intervention);
});
});
describe('with multiple subjects in the queue', function () {
const state = {
workflow: { id: '1' },
upcomingSubjects: subjects
upcomingSubjects: subjects,
intervention: {
message: 'This is a test intervention'
}
};
it('should shift the first subject off the queue', function () {
const newState = reducer(state, action);
Expand All @@ -185,9 +207,9 @@ describe('Classifier actions', function () {
const newState = reducer(state, action);
expect(newState.classification.links.subjects).to.deep.equal(['2']);
});
it('should clear any stored interventions', function () {
it('should not clear any stored interventions', function () {
const newState = reducer(state, action);
expect(newState.intervention).to.be.null;
expect(newState.intervention).to.eql(state.intervention);
});
});
});
Expand Down

0 comments on commit 9461eb8

Please sign in to comment.