diff --git a/app/classifier/classifier.jsx b/app/classifier/classifier.jsx
index 68c9fbcd5f..60e2ab6436 100644
--- a/app/classifier/classifier.jsx
+++ b/app/classifier/classifier.jsx
@@ -370,6 +370,7 @@ class Classifier extends React.Component {
{showIntervention &&
}
diff --git a/app/classifier/components/Intervention/Intervention.jsx b/app/classifier/components/Intervention/Intervention.jsx
index 1d58f766a4..8dd31d2d85 100644
--- a/app/classifier/components/Intervention/Intervention.jsx
+++ b/app/classifier/components/Intervention/Intervention.jsx
@@ -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';
@@ -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
@@ -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 }
diff --git a/app/classifier/components/Intervention/Intervention.spec.js b/app/classifier/components/Intervention/Intervention.spec.js
index bdcb32ae3e..ae72c088d9 100644
--- a/app/classifier/components/Intervention/Intervention.spec.js
+++ b/app/classifier/components/Intervention/Intervention.spec.js
@@ -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 () {
@@ -15,10 +15,13 @@ describe('Intervention', function () {
return { save: () => true };
})
};
+ const onUnmount = sinon.stub()
+
before(function () {
wrapper = mount(
);
});
@@ -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
+ })
+ })
});
diff --git a/app/redux/ducks/classify.js b/app/redux/ducks/classify.js
index acdcecd5ee..3eb1bf5c2b 100644
--- a/app/redux/ducks/classify.js
+++ b/app/redux/ducks/classify.js
@@ -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';
@@ -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;
@@ -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: []
});
}
@@ -260,6 +263,12 @@ export function addIntervention(data) {
};
}
+export function clearIntervention() {
+ return {
+ type: CLEAR_INTERVENTION
+ };
+}
+
export function appendSubjects(subjects, workflowID) {
return {
type: APPEND_SUBJECTS,
diff --git a/app/redux/ducks/classify.spec.js b/app/redux/ducks/classify.spec.js
index 42af3908f6..da7fcd4104 100644
--- a/app/redux/ducks/classify.spec.js
+++ b/app/redux/ducks/classify.spec.js
@@ -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'),
@@ -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);
@@ -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);
@@ -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);
});
});
});