diff --git a/.gitignore b/.gitignore index 3d2c0d88b1..e7bb3b170f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,9 @@ +__pycache__ +*.pyc +*~ +*.swp +.DS_Store + testing/config/settings/local.py testing/log/ .pytest*/ @@ -6,19 +12,12 @@ static_root media_root components_root -docs/_build* - -__pycache__ -*.pyc -*~ -*.swp -.DS_Store -.ruff_cache - env env2 env3 +Makefile + .coverage .coverage.* htmlcov @@ -32,16 +31,18 @@ dist .imdone/ .pytest_cache +.ruff_cache .on-save.json rdmo/management/static -rdmo/core/static/core/js/base.js +rdmo/core/static/core/js/base.js* rdmo/core/static/core/fonts rdmo/core/static/core/css/base.css -rdmo/projects/static/projects/js/*.js +rdmo/projects/static/projects/js/interview.js* +rdmo/projects/static/projects/js/projects.js* rdmo/projects/static/projects/fonts -rdmo/projects/static/projects/css/*.css +rdmo/projects/static/projects/css screenshots diff --git a/rdmo/core/assets/js/components/Modal.js b/rdmo/core/assets/js/components/Modal.js index 2ef42a543b..5524a7c4d9 100644 --- a/rdmo/core/assets/js/components/Modal.js +++ b/rdmo/core/assets/js/components/Modal.js @@ -2,7 +2,7 @@ import React from 'react' import PropTypes from 'prop-types' import { Modal as BootstrapModal } from 'react-bootstrap' -const Modal = ({ title, show, modalProps, submitLabel, submitProps, onClose, onSubmit, children }) => { +const Modal = ({ title, show, modalProps, submitLabel, submitProps, onClose, onSubmit, children, buttons }) => { return ( @@ -19,6 +19,7 @@ const Modal = ({ title, show, modalProps, submitLabel, submitProps, onClose, onS + {buttons} { onSubmit && ( ) } { currentSetValue && ( + ) + } + { + currentSetValue && ( + ) } ) diff --git a/rdmo/projects/assets/js/interview/components/main/page/PageHeadDeleteModal.js b/rdmo/projects/assets/js/interview/components/main/page/PageHeadDeleteModal.js index bb82035f9a..f39813f03f 100644 --- a/rdmo/projects/assets/js/interview/components/main/page/PageHeadDeleteModal.js +++ b/rdmo/projects/assets/js/interview/components/main/page/PageHeadDeleteModal.js @@ -3,9 +3,10 @@ import PropTypes from 'prop-types' import Modal from 'rdmo/core/assets/js/components/Modal' -const PageHeadDeleteModal = ({ title, show, onClose, onSubmit }) => { +const PageHeadDeleteModal = ({ show, onClose, onSubmit }) => { return ( -

{gettext('You are about to permanently delete this tab.')}

{gettext('This includes all given answers for this tab on all pages, not just this one.')}

diff --git a/rdmo/projects/assets/js/interview/components/main/page/PageHeadFormModal.js b/rdmo/projects/assets/js/interview/components/main/page/PageHeadFormModal.js index fee6feda62..f77420583e 100644 --- a/rdmo/projects/assets/js/interview/components/main/page/PageHeadFormModal.js +++ b/rdmo/projects/assets/js/interview/components/main/page/PageHeadFormModal.js @@ -3,70 +3,96 @@ import PropTypes from 'prop-types' import classNames from 'classnames' import { isEmpty, isNil } from 'lodash' -import Modal from 'rdmo/core/assets/js/components/Modal' +import useLsState from 'rdmo/core/assets/js/hooks/useLsState' import useFocusEffect from '../../../hooks/useFocusEffect' +import Modal from 'rdmo/core/assets/js/components/Modal' +import Search from '../Search' -const PageHeadFormModal = ({ title, submitLabel, submitColor, show, initial, onClose, onSubmit }) => { +const PageHeadFormModal = ({ title, submitLabel, submitColor, show, attribute, reuse, initial, onClose, onSubmit }) => { const ref = useRef(null) - const [inputValue, setInputValue] = useState('') - const [hasError, setHasError] = useState(false) + + const initialValues = { + text: initial || '', + value: '' + } + + const [values, setValues, initValues] = useLsState('rdmo.interview.reuse', initialValues, ['text', 'value']) + const [errors, setErrors] = useState([]) const handleSubmit = () => { - if (isEmpty(inputValue) && !isNil(initial)) { - setHasError(true) + if (isEmpty(values.text)) { + setErrors({ text: true }) } else { - onSubmit(inputValue) + onSubmit(values.text, values.value) } } - // update the inputValue + // init the form values useEffect(() => { - if (show) { - setInputValue(initial || '') + if (show && !isNil(attribute)) { + initValues() } }, [show]) // remove the hasError flag if an inputValue is entered useEffect(() => { - if (!isEmpty(inputValue)) { - setHasError(false) + if (!isEmpty(values.text)) { + setErrors({ text: false }) } - }, [inputValue]) + }, [values.text]) // focus when the modal is shown useFocusEffect(ref, show) return ( + onClose={onClose} onSubmit={handleSubmit} disableSubmit={errors}> { - isNil(initial) ? ( + isNil(attribute) ? (
{gettext('You can add a new tab using the create button.')}
) : ( -
- - setInputValue(event.target.value)} - onKeyPress={(event) => { - if (event.code === 'Enter') { - handleSubmit() - } - }} - /> - -

{gettext('Please give the tab a meaningful name.')}

-
+ <> +
+ + setValues({ ...values, text: event.target.value })} + onKeyPress={(event) => { + if (event.code === 'Enter') { + handleSubmit() + } + }} + /> + +

{gettext('Please give the tab a meaningful name.')}

+
+ { + reuse && ( +
+ + + + +

+ {gettext('You can populate this tab with answers from a similar tab in any ' + + 'project you are allowed to access.')} +

+
+ ) + } + ) }
@@ -78,7 +104,9 @@ PageHeadFormModal.propTypes = { submitLabel: PropTypes.string.isRequired, submitColor: PropTypes.string.isRequired, show: PropTypes.bool.isRequired, - initial: PropTypes.string, + attribute: PropTypes.number, + reuse: PropTypes.bool, + initial: PropTypes.object, onClose: PropTypes.func.isRequired, onSubmit: PropTypes.func.isRequired } diff --git a/rdmo/projects/assets/js/interview/components/main/page/PageHeadReuseModal.js b/rdmo/projects/assets/js/interview/components/main/page/PageHeadReuseModal.js new file mode 100644 index 0000000000..61039a667d --- /dev/null +++ b/rdmo/projects/assets/js/interview/components/main/page/PageHeadReuseModal.js @@ -0,0 +1,71 @@ +import React, { useState, useEffect } from 'react' +import PropTypes from 'prop-types' +import classNames from 'classnames' +import { isEmpty } from 'lodash' + +import useLsState from 'rdmo/core/assets/js/hooks/useLsState' + +import Modal from 'rdmo/core/assets/js/components/Modal' + +import Search from '../Search' + +const PageHeadReuseModal = ({ show, attribute, onClose, onSubmit }) => { + + const initialValues = { + value: '' + } + + const [values, setValues, initValues] = useLsState('rdmo.interview.reuse', initialValues, ['value']) + const [errors, setErrors] = useState([]) + + const handleSubmit = () => { + if (isEmpty(values.value)) { + setErrors({ value: true }) + } else { + onSubmit(values.value) + } + } + + useEffect(() => { + if (show) { + initValues() + } + }, [show]) + + useEffect(() => { + if (!isEmpty(values.value)) { + // remove the hasError flag if an inputValue is entered + setErrors({ value: false }) + } + }, [values, values.value]) + + return ( + +
+ + + + +

+ {gettext('You can populate this tab with answers from a similar tab in any ' + + 'project you have access to. This only affects questions that ' + + 'don\'t already have an answer.')} +

+
+
+ ) +} + +PageHeadReuseModal.propTypes = { + title: PropTypes.string.isRequired, + show: PropTypes.bool.isRequired, + attribute: PropTypes.number, + onClose: PropTypes.func.isRequired, + onSubmit: PropTypes.func.isRequired +} + +export default PageHeadReuseModal diff --git a/rdmo/projects/assets/js/interview/components/main/question/Question.js b/rdmo/projects/assets/js/interview/components/main/question/Question.js index 617cfc945e..1b7315c81c 100644 --- a/rdmo/projects/assets/js/interview/components/main/question/Question.js +++ b/rdmo/projects/assets/js/interview/components/main/question/Question.js @@ -12,7 +12,7 @@ import QuestionText from './QuestionText' import QuestionWarning from './QuestionWarning' import QuestionWidget from './QuestionWidget' -const Question = ({ templates, question, values, siblings, disabled, isManager, +const Question = ({ templates, page, question, values, siblings, disabled, isManager, currentSet, createValue, updateValue, deleteValue, copyValue }) => { return checkQuestion(question, currentSet) && (
@@ -24,6 +24,7 @@ const Question = ({ templates, question, values, siblings, disabled, isManager, { + const initialFormValues = { + value: '' + } + + const [show, setShow] = useState(false) + const [ + formValues, setFormValues, initFormValues + ] = useLsState('rdmo.interview.reuse', initialFormValues, ['value']) + const [formErrors, setFormErrors] = useState([]) + + const handleSubmit = (mode) => { + if (isEmpty(formValues.value)) { + setFormErrors({ value: true }) + } else { + const { text, option, external_id } = formValues.value + + if (mode == 'append') { + updateValue(value, { text: `${value.text} ${text}`, option, external_id }) + } else if (mode == 'replace') { + updateValue(value, { text, option, external_id }) + } + + setShow(false) + } + } + + // init the form values + useEffect(() => { + if (show) { + initFormValues() + } + }, [show]) + + // remove the hasError flag if an inputValue is entered + useEffect(() => { + if (!isEmpty(formValues.value)) { + setFormErrors({ value: false }) + } + }, [formValues, formValues.value]) + + const modalButtons = <> + { + ['text', 'textarea'].includes(question.widget_type) && ( + + ) + } + + + + return <> + + + setShow(false)} > +
+ + + + +

+ {gettext('You can reuse an answer from a similar question in any ' + + 'project you have access to.')} +

+
+
+ +} + +QuestionReuseValue.propTypes = { + page: PropTypes.object.isRequired, + question: PropTypes.object.isRequired, + value: PropTypes.object.isRequired, + updateValue: PropTypes.func.isRequired +} + +export default QuestionReuseValue diff --git a/rdmo/projects/assets/js/interview/components/main/question/QuestionReuseValues.js b/rdmo/projects/assets/js/interview/components/main/question/QuestionReuseValues.js new file mode 100644 index 0000000000..50fd0d5651 --- /dev/null +++ b/rdmo/projects/assets/js/interview/components/main/question/QuestionReuseValues.js @@ -0,0 +1,117 @@ +import React, { useState, useEffect } from 'react' +import PropTypes from 'prop-types' +import classNames from 'classnames' +import { isEmpty, isNil } from 'lodash' + +import useLsState from 'rdmo/core/assets/js/hooks/useLsState' + +import Modal from 'rdmo/core/assets/js/components/Modal' + +import Search from '../Search' + +const QuestionReuseValues = ({ page, question, values, createValues, updateValue, deleteValue }) => { + + const initialFormValues = { + value: '', + collection: true + } + + const [show, setShow] = useState(false) + const [ + formValues, setFormValues, initFormValues + ] = useLsState('rdmo.interview.reuse', initialFormValues, ['value', 'collection']) + const [formErrors, setFormErrors] = useState([]) + + const compareValues = (a, b) => ( + (a.set_prefix == b.set_prefix) && + (a.set_index == b.set_index) && + ( + (!isNil(a.option) && (a.option == b.option)) || + (!isEmpty(a.external_id) && (a.external_id == b.external_id)) + ) + ) + + const handleSubmit = () => { + if (isEmpty(formValues.value)) { + setFormErrors({ value: true }) + } else { + values.forEach(value => { + // look for the "same" value in the list of values from the search component + const reusedValue = formValues.value.values.find(reusedValue => compareValues(value, reusedValue)) + if (isNil(reusedValue)) { + // delete the value if it does not exist in the reused value + deleteValue(value) + } else if (value.text != reusedValue.text) { + // update the value if the additional text changed + updateValue(value, { text: reusedValue.text, option: value.option, external_id: value.external_id }) + } + }) + + const newValues = [] + formValues.value.values.forEach(reusedValue => { + // look for the "same" value in the existing values + const value = values.find(value => compareValues(value, reusedValue)) + if (isNil(value)) { + newValues.push({ text: reusedValue.text, option: reusedValue.option, external_id: reusedValue.external_id }) + } + }) + + createValues(newValues) + setShow(false) + } + } + + // init the form values + useEffect(() => { + if (show) { + initFormValues() + } + }, [show]) + + // remove the hasError flag if an inputValue is entered + useEffect(() => { + if (!isEmpty(formValues.value)) { + setFormErrors({ value: false }) + } + }, [formValues, formValues.value]) + + return <> + + + setShow(false)} onSubmit={handleSubmit}> +
+ + + + +

+ {gettext('You can reuse an answer from a similar question in any ' + + 'project you have access to.')} +

+
+
+ +} + +QuestionReuseValues.propTypes = { + page: PropTypes.object.isRequired, + question: PropTypes.object.isRequired, + values: PropTypes.array.isRequired, + createValues: PropTypes.func.isRequired, + updateValue: PropTypes.func.isRequired, + deleteValue: PropTypes.func.isRequired +} + +export default QuestionReuseValues diff --git a/rdmo/projects/assets/js/interview/components/main/questionset/QuestionSet.js b/rdmo/projects/assets/js/interview/components/main/questionset/QuestionSet.js index 78b81bde9b..47ee81a038 100644 --- a/rdmo/projects/assets/js/interview/components/main/questionset/QuestionSet.js +++ b/rdmo/projects/assets/js/interview/components/main/questionset/QuestionSet.js @@ -13,7 +13,7 @@ import QuestionSetHelp from './QuestionSetHelp' import QuestionSetHelpTemplate from './QuestionSetHelpTemplate' import QuestionSetRemoveSet from './QuestionSetRemoveSet' -const QuestionSet = ({ templates, questionset, sets, values, disabled, isManager, +const QuestionSet = ({ templates, page, questionset, sets, values, disabled, isManager, parentSet, createSet, updateSet, deleteSet, copySet, createValue, updateValue, deleteValue, copyValue }) => { @@ -48,6 +48,7 @@ const QuestionSet = ({ templates, questionset, sets, values, disabled, isManager element.attributes.includes(value.attribute))} @@ -69,6 +70,7 @@ const QuestionSet = ({ templates, questionset, sets, values, disabled, isManager ( value.attribute == element.attribute && @@ -106,6 +108,7 @@ const QuestionSet = ({ templates, questionset, sets, values, disabled, isManager QuestionSet.propTypes = { templates: PropTypes.object.isRequired, + page: PropTypes.object.isRequired, questionset: PropTypes.object.isRequired, sets: PropTypes.array.isRequired, values: PropTypes.array.isRequired, diff --git a/rdmo/projects/assets/js/interview/components/main/questionset/QuestionSetCopyModal.js b/rdmo/projects/assets/js/interview/components/main/questionset/QuestionSetCopyModal.js deleted file mode 100644 index 151059eb60..0000000000 --- a/rdmo/projects/assets/js/interview/components/main/questionset/QuestionSetCopyModal.js +++ /dev/null @@ -1,21 +0,0 @@ -import React from 'react' -import PropTypes from 'prop-types' - -import Modal from 'rdmo/core/assets/js/components/Modal' - -const QuestionSetCopyModal = ({ title, show, onClose, onSubmit }) => { - return ( - - - ) -} - -QuestionSetCopyModal.propTypes = { - title: PropTypes.string.isRequired, - show: PropTypes.bool.isRequired, - onClose: PropTypes.func.isRequired, - onSubmit: PropTypes.func.isRequired, -} - -export default QuestionSetCopyModal diff --git a/rdmo/projects/assets/js/interview/components/main/questionset/QuestionSetCopySet.js b/rdmo/projects/assets/js/interview/components/main/questionset/QuestionSetCopySet.js index f472b099c8..3c5b1fc24b 100644 --- a/rdmo/projects/assets/js/interview/components/main/questionset/QuestionSetCopySet.js +++ b/rdmo/projects/assets/js/interview/components/main/questionset/QuestionSetCopySet.js @@ -1,35 +1,33 @@ import React from 'react' import PropTypes from 'prop-types' -import { capitalize, last } from 'lodash' +import { last } from 'lodash' -import useModal from 'rdmo/core/assets/js/hooks/useModal' +import Modal from 'rdmo/core/assets/js/components/Modal' -import QuestionSetCopyModal from './QuestionSetCopyModal' +import useModal from 'rdmo/core/assets/js/hooks/useModal' const QuestionCopySet = ({ questionset, sets, currentSet, copySet }) => { - const [showCopyModal, openCopyModal, closeCopyModal] = useModal() + const modal = useModal() const handleCopySet = () => { copySet(currentSet, null, { set_prefix: currentSet.set_prefix, set_index: last(sets) ? last(sets).set_index + 1 : 0, }) - closeCopyModal() + modal.close() } return questionset.is_collection && ( <> - - + + ) } diff --git a/rdmo/projects/assets/js/interview/components/main/questionset/QuestionSetDeleteModal.js b/rdmo/projects/assets/js/interview/components/main/questionset/QuestionSetDeleteModal.js deleted file mode 100644 index 78e9e244be..0000000000 --- a/rdmo/projects/assets/js/interview/components/main/questionset/QuestionSetDeleteModal.js +++ /dev/null @@ -1,23 +0,0 @@ -import React from 'react' -import PropTypes from 'prop-types' - -import Modal from 'rdmo/core/assets/js/components/Modal' - -const QuestionSetDeleteModal = ({ title, show, onClose, onSubmit }) => { - return ( - -

{gettext('You are about to permanently delete this block.')}

-

{gettext('This action cannot be undone!')}

-
- ) -} - -QuestionSetDeleteModal.propTypes = { - title: PropTypes.string.isRequired, - show: PropTypes.bool.isRequired, - onClose: PropTypes.func.isRequired, - onSubmit: PropTypes.func.isRequired, -} - -export default QuestionSetDeleteModal diff --git a/rdmo/projects/assets/js/interview/components/main/questionset/QuestionSetRemoveSet.js b/rdmo/projects/assets/js/interview/components/main/questionset/QuestionSetRemoveSet.js index 06a0dcae61..de8bc8377b 100644 --- a/rdmo/projects/assets/js/interview/components/main/questionset/QuestionSetRemoveSet.js +++ b/rdmo/projects/assets/js/interview/components/main/questionset/QuestionSetRemoveSet.js @@ -1,32 +1,31 @@ import React from 'react' import PropTypes from 'prop-types' -import { capitalize } from 'lodash' import useModal from 'rdmo/core/assets/js/hooks/useModal' -import QuestionSetDeleteModal from './QuestionSetDeleteModal' +import Modal from 'rdmo/core/assets/js/components/Modal' const QuestionRemoveSet = ({ questionset, currentSet, deleteSet }) => { - const {show: showDeleteModal, open: openDeleteModal, close: closeDeleteModal} = useModal() + const modal = useModal() - const handleDeleteSet = () => { + const handleRemoveSet = () => { deleteSet(currentSet) - closeDeleteModal() + modal.close() } return questionset.is_collection && ( <> - - + +

{gettext('You are about to permanently remove this block.')}

+

{gettext('This action cannot be undone!')}

+
) } diff --git a/rdmo/projects/assets/js/interview/components/main/widget/CheckboxInput.js b/rdmo/projects/assets/js/interview/components/main/widget/CheckboxInput.js index cf7b3604a5..23d1311494 100644 --- a/rdmo/projects/assets/js/interview/components/main/widget/CheckboxInput.js +++ b/rdmo/projects/assets/js/interview/components/main/widget/CheckboxInput.js @@ -12,11 +12,25 @@ const CheckboxInput = ({ question, value, option, disabled, onCreate, onUpdate, const checked = !isNil(value) + const handleCreate = (option, additionalInput) => { + if (option.has_provider) { + onCreate([{ + external_id: option.id, + text: option.text + }]) + } else { + onCreate([{ + option: option.id, + text: additionalInput + }]) + } + } + const handleChange = () => { if (checked) { onDelete(value) } else { - onCreate(option) + handleCreate(option) } } @@ -38,7 +52,7 @@ const CheckboxInput = ({ question, value, option, disabled, onCreate, onUpdate, }) } } else { - onCreate(option, additionalInput) + handleCreate(option, additionalInput) } }, 500) diff --git a/rdmo/projects/assets/js/interview/components/main/widget/CheckboxWidget.js b/rdmo/projects/assets/js/interview/components/main/widget/CheckboxWidget.js index eff2db4e7b..2fb36963d7 100644 --- a/rdmo/projects/assets/js/interview/components/main/widget/CheckboxWidget.js +++ b/rdmo/projects/assets/js/interview/components/main/widget/CheckboxWidget.js @@ -6,36 +6,31 @@ import { gatherOptions } from '../../../utils/options' import QuestionCopyValues from '../question/QuestionCopyValues' import QuestionError from '../question/QuestionError' +import QuestionReuseValues from '../question/QuestionReuseValues' import QuestionSuccess from '../question/QuestionSuccess' import CheckboxInput from './CheckboxInput' -const CheckboxWidget = ({ question, values, siblings, currentSet, disabled, +const CheckboxWidget = ({ page, question, values, siblings, currentSet, disabled, createValue, updateValue, deleteValue, copyValue }) => { - const handleCreateValue = (option, additionalInput) => { + const handleCreateValue = (attrsList) => { const lastValue = maxBy(values, (v) => v.collection_index) - const collectionIndex = lastValue ? lastValue.collection_index + 1 : 0 - const value = { - attribute: question.attribute, - set_prefix: currentSet.set_prefix, - set_index: currentSet.set_index, - collection_index: collectionIndex, - set_collection: question.set_collection, - unit: question.unit, - value_type: question.value_type - } - - if (option.has_provider) { - value.external_id = option.id - value.text = option.text - } else { - value.option = option.id - value.text = additionalInput - } - - createValue(value, true) + let collectionIndex = lastValue ? lastValue.collection_index + 1 : 0 + attrsList.forEach(attrs => { + createValue({ + attribute: question.attribute, + set_prefix: currentSet.set_prefix, + set_index: currentSet.set_index, + collection_index: collectionIndex, + set_collection: question.set_collection, + unit: question.unit, + value_type: question.value_type, + ...attrs + }, true) + collectionIndex += 1 + }) } const success = values.some((value) => value.success) @@ -71,7 +66,20 @@ const CheckboxWidget = ({ question, values, siblings, currentSet, disabled,
- + +
@@ -81,6 +89,7 @@ const CheckboxWidget = ({ question, values, siblings, currentSet, disabled, } CheckboxWidget.propTypes = { + page: PropTypes.object.isRequired, question: PropTypes.object.isRequired, values: PropTypes.array.isRequired, siblings: PropTypes.array, diff --git a/rdmo/projects/assets/js/interview/components/main/widget/DateWidget.js b/rdmo/projects/assets/js/interview/components/main/widget/DateWidget.js index ae7f8ce42b..8cff8635e6 100644 --- a/rdmo/projects/assets/js/interview/components/main/widget/DateWidget.js +++ b/rdmo/projects/assets/js/interview/components/main/widget/DateWidget.js @@ -5,14 +5,15 @@ import QuestionAddValue from '../question/QuestionAddValue' import QuestionCopyValue from '../question/QuestionCopyValue' import QuestionCopyValues from '../question/QuestionCopyValues' import QuestionDefault from '../question/QuestionDefault' -import QuestionError from '../question/QuestionError' import QuestionEraseValue from '../question/QuestionEraseValue' -import QuestionSuccess from '../question/QuestionSuccess' +import QuestionError from '../question/QuestionError' import QuestionRemoveValue from '../question/QuestionRemoveValue' +import QuestionReuseValue from '../question/QuestionReuseValue' +import QuestionSuccess from '../question/QuestionSuccess' import DateInput from './DateInput' -const DateWidget = ({ question, values, siblings, currentSet, disabled, createValue, updateValue, deleteValue, copyValue }) => { +const DateWidget = ({ page, question, values, siblings, currentSet, disabled, createValue, updateValue, deleteValue, copyValue }) => { return (
{ @@ -27,6 +28,7 @@ const DateWidget = ({ question, values, siblings, currentSet, disabled, createVa buttons={
+ { return (
@@ -31,6 +32,7 @@ const RadioWidget = ({ question, values, siblings, currentSet, disabled, buttons={
+ { const handleCreateValue = (value) => { @@ -41,6 +42,7 @@ const RangeWidget = ({ question, values, siblings, currentSet, disabled, buttons={
+ { return (
@@ -32,7 +32,7 @@ const SelectWidget = ({ question, values, siblings, currentSet, disabled, creata buttons={
- + { return (
@@ -27,6 +28,7 @@ const TextWidget = ({ question, values, siblings, currentSet, disabled, buttons={
+ { return (
@@ -27,6 +28,7 @@ const TextareaWidget = ({ question, values, siblings, currentSet, disabled, buttons={
+ { return (
@@ -28,6 +29,7 @@ const YesNoWidget = ({ question, values, siblings, currentSet, disabled, buttons={
+ diff --git a/rdmo/projects/assets/js/interview/components/main/widget/common/AdditionalTextareaInput.js b/rdmo/projects/assets/js/interview/components/main/widget/common/AdditionalTextareaInput.js index 83c9df6275..761f2f15a6 100644 --- a/rdmo/projects/assets/js/interview/components/main/widget/common/AdditionalTextareaInput.js +++ b/rdmo/projects/assets/js/interview/components/main/widget/common/AdditionalTextareaInput.js @@ -11,7 +11,7 @@ const AdditionalTextareaInput = ({ value, option, disabled, onChange }) => { } else { setInputValue(value.option == option.id ? value.text : '') } - }, [get(value, 'id'), get(value, 'option'), get(value, 'external_id')]) + }, [get(value, 'id'), get(value, 'text'), get(value, 'option'), get(value, 'external_id')]) return (