From 3e7c639b2490980c255d85d3be4dcb0b18cfc98a Mon Sep 17 00:00:00 2001 From: Jochen Klar Date: Fri, 16 Aug 2024 14:08:51 +0200 Subject: [PATCH 01/11] Fix set creation --- .../assets/js/interview/actions/interviewActions.js | 9 +++++---- .../assets/js/interview/components/main/page/PageHead.js | 7 ++++++- rdmo/projects/assets/js/interview/utils/value.js | 9 ++++++++- 3 files changed, 19 insertions(+), 6 deletions(-) diff --git a/rdmo/projects/assets/js/interview/actions/interviewActions.js b/rdmo/projects/assets/js/interview/actions/interviewActions.js index b37c6f7838..6d27e799ed 100644 --- a/rdmo/projects/assets/js/interview/actions/interviewActions.js +++ b/rdmo/projects/assets/js/interview/actions/interviewActions.js @@ -13,7 +13,7 @@ import { updateLocation } from '../utils/location' import { updateOptions } from '../utils/options' import { initPage } from '../utils/page' import { gatherSets, getDescendants, initSets } from '../utils/set' -import { activateFirstValue, gatherDefaultValues, initValues } from '../utils/value' +import { activateFirstValue, gatherDefaultValues, initValues, compareValues } from '../utils/value' import { projectId } from '../utils/meta' import ValueFactory from '../factories/ValueFactory' @@ -453,9 +453,10 @@ export function createSet(attrs) { if (isNil(value)) { return createSetSuccess() } else { - return dispatch(storeValue(value)).then((action) => { - if (action.type === STORE_VALUE_SUCCESS) { - createSetSuccess(action.value) + return dispatch(storeValue(value)).then(() => { + const storedValue = getState().interview.values.find((v) => compareValues(v, value)) + if (!isNil(storedValue)) { + createSetSuccess(storedValue) } }) } diff --git a/rdmo/projects/assets/js/interview/components/main/page/PageHead.js b/rdmo/projects/assets/js/interview/components/main/page/PageHead.js index 57f50e430b..2b3be16650 100644 --- a/rdmo/projects/assets/js/interview/components/main/page/PageHead.js +++ b/rdmo/projects/assets/js/interview/components/main/page/PageHead.js @@ -28,6 +28,11 @@ const PageHead = ({ templates, page, sets, values, currentSet, activateSet, crea } } + const handleOpenCreateModal = (event) => { + event.preventDefault() + openCreateModal() + } + const handleCreateSet = (text) => { createSet({ attribute: page.attribute, @@ -71,7 +76,7 @@ const PageHead = ({ templates, page, sets, values, currentSet, activateSet, crea }) }
  • - + {capitalize(page.verbose_name)}
  • diff --git a/rdmo/projects/assets/js/interview/utils/value.js b/rdmo/projects/assets/js/interview/utils/value.js index f66a706073..5f2d0719b0 100644 --- a/rdmo/projects/assets/js/interview/utils/value.js +++ b/rdmo/projects/assets/js/interview/utils/value.js @@ -86,4 +86,11 @@ const activateFirstValue = (page, values) => { } } -export { isDefaultValue, gatherDefaultValues, initValues, initRange, activateFirstValue } +const compareValues = (a, b) => { + return (a.attribute == b.attribute) && + (a.set_prefix == b.set_prefix) && + (a.set_index == b.set_index) && + (a.collection_index == b.collection_index) +} + +export { isDefaultValue, gatherDefaultValues, initValues, initRange, activateFirstValue, compareValues } From f0bcc1ad2927764fcd9f47f5c35643fd02cf59c5 Mon Sep 17 00:00:00 2001 From: Jochen Klar Date: Fri, 16 Aug 2024 14:56:38 +0200 Subject: [PATCH 02/11] Fix valueIndex computation, again --- .../assets/js/interview/actions/interviewActions.js | 2 +- rdmo/projects/assets/js/interview/utils/value.js | 12 ++++++++---- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/rdmo/projects/assets/js/interview/actions/interviewActions.js b/rdmo/projects/assets/js/interview/actions/interviewActions.js index 6d27e799ed..fdba05d0f1 100644 --- a/rdmo/projects/assets/js/interview/actions/interviewActions.js +++ b/rdmo/projects/assets/js/interview/actions/interviewActions.js @@ -272,7 +272,7 @@ export function storeValue(value) { return {type: NOOP} } else { return (dispatch, getState) => { - const valueIndex = getState().interview.values.map((v) => v.id).indexOf(value.id) + const valueIndex = getState().interview.values.findIndex((v) => compareValues(v, value)) const valueFile = value.file const valueSuccess = value.success diff --git a/rdmo/projects/assets/js/interview/utils/value.js b/rdmo/projects/assets/js/interview/utils/value.js index 5f2d0719b0..2c96f179d5 100644 --- a/rdmo/projects/assets/js/interview/utils/value.js +++ b/rdmo/projects/assets/js/interview/utils/value.js @@ -87,10 +87,14 @@ const activateFirstValue = (page, values) => { } const compareValues = (a, b) => { - return (a.attribute == b.attribute) && - (a.set_prefix == b.set_prefix) && - (a.set_index == b.set_index) && - (a.collection_index == b.collection_index) + if (isNil(a.id) || isNil(b.id)) { + return (a.attribute == b.attribute) && + (a.set_prefix == b.set_prefix) && + (a.set_index == b.set_index) && + (a.collection_index == b.collection_index) + } else { + return a.id == b.id + } } export { isDefaultValue, gatherDefaultValues, initValues, initRange, activateFirstValue, compareValues } From 85a7797b9b5fd68514842ddb70f8a4dd80342d7a Mon Sep 17 00:00:00 2001 From: Jochen Klar Date: Fri, 16 Aug 2024 17:08:13 +0200 Subject: [PATCH 03/11] Fix CheckboxInput component --- .../assets/js/interview/components/main/widget/CheckboxInput.js | 1 + 1 file changed, 1 insertion(+) 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 38ed08ddea..cf7b3604a5 100644 --- a/rdmo/projects/assets/js/interview/components/main/widget/CheckboxInput.js +++ b/rdmo/projects/assets/js/interview/components/main/widget/CheckboxInput.js @@ -31,6 +31,7 @@ const CheckboxInput = ({ question, value, option, disabled, onCreate, onUpdate, }) } else { onUpdate(value, { + text: additionalInput, option: option.id, unit: question.unit, value_type: question.value_type From a0875f08572d21d3b9285c91f9539b105d09494a Mon Sep 17 00:00:00 2001 From: Jochen Klar Date: Fri, 16 Aug 2024 17:25:37 +0200 Subject: [PATCH 04/11] Fix interviewReducer --- rdmo/projects/assets/js/interview/reducers/interviewReducer.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rdmo/projects/assets/js/interview/reducers/interviewReducer.js b/rdmo/projects/assets/js/interview/reducers/interviewReducer.js index 1b48a12e97..39ac156bc2 100644 --- a/rdmo/projects/assets/js/interview/reducers/interviewReducer.js +++ b/rdmo/projects/assets/js/interview/reducers/interviewReducer.js @@ -67,7 +67,7 @@ export default function interviewReducer(state = initialState, action) { return { ...state, values: [...state.values, action.value] } } case DELETE_VALUE_SUCCESS: - return {...state, values: state.values.filter((value) => value !== action.value)} + return {...state, values: state.values.filter((value) => value.id !== action.value.id)} case CREATE_SET: return { ...state, values: action.values, sets: action.sets } case DELETE_SET_SUCCESS: From bf44cb7d694af35c8d32d25f9ac366c50bb3b9b0 Mon Sep 17 00:00:00 2001 From: Jochen Klar Date: Fri, 16 Aug 2024 17:30:37 +0200 Subject: [PATCH 05/11] Add copyValue action to interview --- .../js/interview/actions/interviewActions.js | 27 ++++++++++++++++- .../js/interview/components/main/page/Page.js | 7 +++-- .../components/main/question/Question.js | 4 ++- .../main/question/QuestionCopyValue.js | 23 +++++++++++++++ .../main/question/QuestionCopyValues.js | 29 +++++++++++++++++++ .../main/questionset/QuestionSet.js | 7 +++-- .../components/main/widget/CheckboxWidget.js | 8 +++-- .../components/main/widget/DateWidget.js | 8 +++-- .../components/main/widget/RadioWidget.js | 8 +++-- .../components/main/widget/RangeWidget.js | 8 +++-- .../components/main/widget/SelectWidget.js | 7 +++-- .../components/main/widget/TextWidget.js | 8 +++-- .../components/main/widget/TextareaWidget.js | 7 +++-- .../components/main/widget/YesNoWidget.js | 7 +++-- .../assets/js/interview/containers/Main.js | 1 + .../assets/js/interview/utils/value.js | 8 ++++- rdmo/projects/assets/scss/interview.scss | 9 ++---- 17 files changed, 147 insertions(+), 29 deletions(-) create mode 100644 rdmo/projects/assets/js/interview/components/main/question/QuestionCopyValue.js create mode 100644 rdmo/projects/assets/js/interview/components/main/question/QuestionCopyValues.js diff --git a/rdmo/projects/assets/js/interview/actions/interviewActions.js b/rdmo/projects/assets/js/interview/actions/interviewActions.js index fdba05d0f1..bf8bce4898 100644 --- a/rdmo/projects/assets/js/interview/actions/interviewActions.js +++ b/rdmo/projects/assets/js/interview/actions/interviewActions.js @@ -13,7 +13,7 @@ import { updateLocation } from '../utils/location' import { updateOptions } from '../utils/options' import { initPage } from '../utils/page' import { gatherSets, getDescendants, initSets } from '../utils/set' -import { activateFirstValue, gatherDefaultValues, initValues, compareValues } from '../utils/value' +import { activateFirstValue, gatherDefaultValues, initValues, compareValues, isEmptyValue } from '../utils/value' import { projectId } from '../utils/meta' import ValueFactory from '../factories/ValueFactory' @@ -363,6 +363,31 @@ export function updateValue(value, attrs, store = true) { } } +export function copyValue(value) { + return (dispatch, getState) => { + const sets = getState().interview.sets + const values = getState().interview.values + + sets.filter((set) => ( + (set.set_prefix == value.set_prefix) && + (set.set_index != value.set_index) + )).forEach((set) => { + const sibling = values.find((v) => ( + (v.attribute == value.attribute) && + (v.set_prefix == set.set_prefix) && + (v.set_index == set.set_index) && + (v.collection_index == value.collection_index) + )) + + if (isNil(sibling)) { + dispatch(storeValue(ValueFactory.create({ ...value, set_index: set.set_index }))) + } else if (isEmptyValue(sibling)) { + dispatch(storeValue(ValueFactory.update(sibling, value))) + } + }) + } +} + export function deleteValue(value) { const pendingId = `deleteValue/${value.id}` diff --git a/rdmo/projects/assets/js/interview/components/main/page/Page.js b/rdmo/projects/assets/js/interview/components/main/page/Page.js index 8a6155c8cf..acdcc03147 100644 --- a/rdmo/projects/assets/js/interview/components/main/page/Page.js +++ b/rdmo/projects/assets/js/interview/components/main/page/Page.js @@ -12,7 +12,7 @@ import PageButtons from './PageButtons' import PageHead from './PageHead' const Page = ({ config, templates, overview, page, sets, values, fetchPage, - createValue, updateValue, deleteValue, + createValue, updateValue, deleteValue, copyValue, activateSet, createSet, updateSet, deleteSet }) => { const currentSetPrefix = '' @@ -58,6 +58,7 @@ const Page = ({ config, templates, overview, page, sets, values, fetchPage, createValue={createValue} updateValue={updateValue} deleteValue={deleteValue} + copyValue={copyValue} /> ) } else { @@ -77,6 +78,7 @@ const Page = ({ config, templates, overview, page, sets, values, fetchPage, createValue={createValue} updateValue={updateValue} deleteValue={deleteValue} + copyValue={copyValue} /> ) } @@ -104,7 +106,8 @@ Page.propTypes = { activateSet: PropTypes.func.isRequired, createSet: PropTypes.func.isRequired, updateSet: PropTypes.func.isRequired, - deleteSet: PropTypes.func.isRequired + deleteSet: PropTypes.func.isRequired, + copyValue: PropTypes.func.isRequired } export default Page 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 cea3c70ff4..ce6c838581 100644 --- a/rdmo/projects/assets/js/interview/components/main/question/Question.js +++ b/rdmo/projects/assets/js/interview/components/main/question/Question.js @@ -13,7 +13,7 @@ import QuestionWarning from './QuestionWarning' import QuestionWidget from './QuestionWidget' const Question = ({ templates, question, values, disabled, isManager, - currentSet, createValue, updateValue, deleteValue }) => { + currentSet, createValue, updateValue, deleteValue, copyValue }) => { return checkQuestion(question, currentSet) && (
    @@ -31,6 +31,7 @@ const Question = ({ templates, question, values, disabled, isManager, createValue={createValue} updateValue={updateValue} deleteValue={deleteValue} + copyValue={copyValue} />
    ) @@ -46,6 +47,7 @@ Question.propTypes = { createValue: PropTypes.func.isRequired, updateValue: PropTypes.func.isRequired, deleteValue: PropTypes.func.isRequired, + copyValue: PropTypes.func.isRequired } export default Question diff --git a/rdmo/projects/assets/js/interview/components/main/question/QuestionCopyValue.js b/rdmo/projects/assets/js/interview/components/main/question/QuestionCopyValue.js new file mode 100644 index 0000000000..47ae6388ed --- /dev/null +++ b/rdmo/projects/assets/js/interview/components/main/question/QuestionCopyValue.js @@ -0,0 +1,23 @@ +import React from 'react' +import PropTypes from 'prop-types' + +import { isEmptyValue } from '../../../utils/value' + +const QuestionCopyValue = ({ question, value, copyValue }) => { + return ( + question.set_collection && !isEmptyValue(value) && ( + + ) + ) +} + +QuestionCopyValue.propTypes = { + question: PropTypes.object.isRequired, + value: PropTypes.object.isRequired, + copyValue: PropTypes.func.isRequired +} + +export default QuestionCopyValue diff --git a/rdmo/projects/assets/js/interview/components/main/question/QuestionCopyValues.js b/rdmo/projects/assets/js/interview/components/main/question/QuestionCopyValues.js new file mode 100644 index 0000000000..e981de95c9 --- /dev/null +++ b/rdmo/projects/assets/js/interview/components/main/question/QuestionCopyValues.js @@ -0,0 +1,29 @@ +import React from 'react' +import PropTypes from 'prop-types' + +import { isEmptyValue } from '../../../utils/value' + +const QuestionCopyValues = ({ question, values, copyValue }) => { + const handleCopyValues = () => { + values.forEach((value) => copyValue(value)) + } + + console.log(values) + + return ( + question.set_collection && values.some((v) => !isEmptyValue(v)) && ( + + ) + ) +} + +QuestionCopyValues.propTypes = { + question: PropTypes.object.isRequired, + values: PropTypes.array.isRequired, + copyValue: PropTypes.func.isRequired +} + +export default QuestionCopyValues 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 cf52efc93f..a582ffaab5 100644 --- a/rdmo/projects/assets/js/interview/components/main/questionset/QuestionSet.js +++ b/rdmo/projects/assets/js/interview/components/main/questionset/QuestionSet.js @@ -14,7 +14,7 @@ import QuestionSetRemoveSet from './QuestionSetRemoveSet' const QuestionSet = ({ templates, questionset, sets, values, disabled, isManager, parentSet, createSet, updateSet, deleteSet, - createValue, updateValue, deleteValue }) => { + createValue, updateValue, deleteValue, copyValue }) => { const setPrefix = getChildPrefix(parentSet) @@ -58,6 +58,7 @@ const QuestionSet = ({ templates, questionset, sets, values, disabled, isManager createValue={createValue} updateValue={updateValue} deleteValue={deleteValue} + copyValue={copyValue} /> ) } else { @@ -77,6 +78,7 @@ const QuestionSet = ({ templates, questionset, sets, values, disabled, isManager createValue={createValue} updateValue={updateValue} deleteValue={deleteValue} + copyValue={copyValue} /> ) } @@ -107,7 +109,8 @@ QuestionSet.propTypes = { deleteSet: PropTypes.func.isRequired, createValue: PropTypes.func.isRequired, updateValue: PropTypes.func.isRequired, - deleteValue: PropTypes.func.isRequired + deleteValue: PropTypes.func.isRequired, + copyValue: PropTypes.func.isRequired } export default QuestionSet 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 e7d8ee71cb..c995c2531d 100644 --- a/rdmo/projects/assets/js/interview/components/main/widget/CheckboxWidget.js +++ b/rdmo/projects/assets/js/interview/components/main/widget/CheckboxWidget.js @@ -4,12 +4,14 @@ import { maxBy } from 'lodash' import { gatherOptions } from '../../../utils/options' +import QuestionCopyValues from '../question/QuestionCopyValues' import QuestionError from '../question/QuestionError' import QuestionSuccess from '../question/QuestionSuccess' import CheckboxInput from './CheckboxInput' -const CheckboxWidget = ({ question, values, currentSet, disabled, createValue, updateValue, deleteValue }) => { +const CheckboxWidget = ({ question, values, currentSet, disabled, + createValue, updateValue, deleteValue, copyValue }) => { const handleCreateValue = (option, additionalInput) => { const lastValue = maxBy(values, (v) => v.collection_index) @@ -69,6 +71,7 @@ const CheckboxWidget = ({ question, values, currentSet, disabled, createValue, u
    +
    @@ -84,7 +87,8 @@ CheckboxWidget.propTypes = { currentSet: PropTypes.object.isRequired, createValue: PropTypes.func.isRequired, updateValue: PropTypes.func.isRequired, - deleteValue: PropTypes.func.isRequired + deleteValue: PropTypes.func.isRequired, + copyValue: PropTypes.func.isRequired } export default CheckboxWidget 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 09010cbc33..c4f79c3411 100644 --- a/rdmo/projects/assets/js/interview/components/main/widget/DateWidget.js +++ b/rdmo/projects/assets/js/interview/components/main/widget/DateWidget.js @@ -2,6 +2,7 @@ import React from 'react' import PropTypes from 'prop-types' import QuestionAddValue from '../question/QuestionAddValue' +import QuestionCopyValue from '../question/QuestionCopyValue' import QuestionDefault from '../question/QuestionDefault' import QuestionError from '../question/QuestionError' import QuestionEraseValue from '../question/QuestionEraseValue' @@ -10,7 +11,7 @@ import QuestionRemoveValue from '../question/QuestionRemoveValue' import DateInput from './DateInput' -const DateWidget = ({ question, values, currentSet, disabled, createValue, updateValue, deleteValue }) => { +const DateWidget = ({ question, values, currentSet, disabled, createValue, updateValue, deleteValue, copyValue }) => { return (
    { @@ -33,6 +34,7 @@ const DateWidget = ({ question, values, currentSet, disabled, createValue, updat disabled={disabled} deleteValue={deleteValue} /> +
    } @@ -48,6 +50,7 @@ const DateWidget = ({ question, values, currentSet, disabled, createValue, updat currentSet={currentSet} disabled={disabled} createValue={createValue} + copyValue={copyValue} /> ) @@ -60,7 +63,8 @@ DateWidget.propTypes = { currentSet: PropTypes.object.isRequired, createValue: PropTypes.func.isRequired, updateValue: PropTypes.func.isRequired, - deleteValue: PropTypes.func.isRequired + deleteValue: PropTypes.func.isRequired, + copyValue: PropTypes.func.isRequired } export default DateWidget diff --git a/rdmo/projects/assets/js/interview/components/main/widget/RadioWidget.js b/rdmo/projects/assets/js/interview/components/main/widget/RadioWidget.js index f1dd333a52..79497a6cad 100644 --- a/rdmo/projects/assets/js/interview/components/main/widget/RadioWidget.js +++ b/rdmo/projects/assets/js/interview/components/main/widget/RadioWidget.js @@ -4,6 +4,7 @@ import PropTypes from 'prop-types' import { gatherOptions } from '../../../utils/options' import QuestionAddValue from '../question/QuestionAddValue' +import QuestionCopyValue from '../question/QuestionCopyValue' import QuestionDefault from '../question/QuestionDefault' import QuestionError from '../question/QuestionError' import QuestionSuccess from '../question/QuestionSuccess' @@ -12,7 +13,7 @@ import QuestionRemoveValue from '../question/QuestionRemoveValue' import RadioInput from './RadioInput' -const RadioWidget = ({ question, values, currentSet, disabled, createValue, updateValue, deleteValue }) => { +const RadioWidget = ({ question, values, currentSet, disabled, createValue, updateValue, deleteValue, copyValue }) => { return (
    { @@ -36,6 +37,7 @@ const RadioWidget = ({ question, values, currentSet, disabled, createValue, upda disabled={disabled} deleteValue={deleteValue} /> +
    } @@ -51,6 +53,7 @@ const RadioWidget = ({ question, values, currentSet, disabled, createValue, upda currentSet={currentSet} disabled={disabled} createValue={createValue} + copyValue={copyValue} /> ) @@ -63,7 +66,8 @@ RadioWidget.propTypes = { currentSet: PropTypes.object.isRequired, createValue: PropTypes.func.isRequired, updateValue: PropTypes.func.isRequired, - deleteValue: PropTypes.func.isRequired + deleteValue: PropTypes.func.isRequired, + copyValue: PropTypes.func.isRequired } export default RadioWidget diff --git a/rdmo/projects/assets/js/interview/components/main/widget/RangeWidget.js b/rdmo/projects/assets/js/interview/components/main/widget/RangeWidget.js index 692f66d5a4..3bda3222ba 100644 --- a/rdmo/projects/assets/js/interview/components/main/widget/RangeWidget.js +++ b/rdmo/projects/assets/js/interview/components/main/widget/RangeWidget.js @@ -4,6 +4,7 @@ import PropTypes from 'prop-types' import { initRange } from '../../../utils/value' import QuestionAddValue from '../question/QuestionAddValue' +import QuestionCopyValue from '../question/QuestionCopyValue' import QuestionDefault from '../question/QuestionDefault' import QuestionError from '../question/QuestionError' import QuestionSuccess from '../question/QuestionSuccess' @@ -12,7 +13,7 @@ import QuestionRemoveValue from '../question/QuestionRemoveValue' import RangeInput from './RangeInput' -const RangeWidget = ({ question, values, currentSet, disabled, createValue, updateValue, deleteValue }) => { +const RangeWidget = ({ question, values, currentSet, disabled, createValue, updateValue, deleteValue, copyValue }) => { const handleCreateValue = (value) => { initRange(question, value) @@ -46,6 +47,7 @@ const RangeWidget = ({ question, values, currentSet, disabled, createValue, upda disabled={disabled} deleteValue={deleteValue} /> + } @@ -61,6 +63,7 @@ const RangeWidget = ({ question, values, currentSet, disabled, createValue, upda currentSet={currentSet} disabled={disabled} createValue={handleCreateValue} + copyValue={copyValue} /> ) @@ -73,7 +76,8 @@ RangeWidget.propTypes = { currentSet: PropTypes.object.isRequired, createValue: PropTypes.func.isRequired, updateValue: PropTypes.func.isRequired, - deleteValue: PropTypes.func.isRequired + deleteValue: PropTypes.func.isRequired, + copyValue: PropTypes.func.isRequired } export default RangeWidget diff --git a/rdmo/projects/assets/js/interview/components/main/widget/SelectWidget.js b/rdmo/projects/assets/js/interview/components/main/widget/SelectWidget.js index d1eb95347b..60dbbbc4cf 100644 --- a/rdmo/projects/assets/js/interview/components/main/widget/SelectWidget.js +++ b/rdmo/projects/assets/js/interview/components/main/widget/SelectWidget.js @@ -4,6 +4,7 @@ import PropTypes from 'prop-types' import { gatherOptions } from '../../../utils/options' import QuestionAddValue from '../question/QuestionAddValue' +import QuestionCopyValue from '../question/QuestionCopyValue' import QuestionDefault from '../question/QuestionDefault' import QuestionEraseValue from '../question/QuestionEraseValue' import QuestionError from '../question/QuestionError' @@ -13,7 +14,7 @@ import QuestionRemoveValue from '../question/QuestionRemoveValue' import SelectInput from './SelectInput' const SelectWidget = ({ question, values, currentSet, disabled, creatable, - createValue, updateValue, deleteValue }) => { + createValue, updateValue, deleteValue, copyValue }) => { return (
    { @@ -38,6 +39,7 @@ const SelectWidget = ({ question, values, currentSet, disabled, creatable, disabled={disabled} deleteValue={deleteValue} /> +
    } @@ -66,7 +68,8 @@ SelectWidget.propTypes = { currentSet: PropTypes.object.isRequired, createValue: PropTypes.func.isRequired, updateValue: PropTypes.func.isRequired, - deleteValue: PropTypes.func.isRequired + deleteValue: PropTypes.func.isRequired, + copyValue: PropTypes.func.isRequired } export default SelectWidget diff --git a/rdmo/projects/assets/js/interview/components/main/widget/TextWidget.js b/rdmo/projects/assets/js/interview/components/main/widget/TextWidget.js index 7eb55f8032..d6119b0986 100644 --- a/rdmo/projects/assets/js/interview/components/main/widget/TextWidget.js +++ b/rdmo/projects/assets/js/interview/components/main/widget/TextWidget.js @@ -2,6 +2,7 @@ import React from 'react' import PropTypes from 'prop-types' import QuestionAddValue from '../question/QuestionAddValue' +import QuestionCopyValue from '../question/QuestionCopyValue' import QuestionDefault from '../question/QuestionDefault' import QuestionError from '../question/QuestionError' import QuestionRemoveValue from '../question/QuestionRemoveValue' @@ -9,7 +10,8 @@ import QuestionSuccess from '../question/QuestionSuccess' import TextInput from './TextInput' -const TextWidget = ({ question, values, currentSet, disabled, createValue, updateValue, deleteValue }) => { +const TextWidget = ({ question, values, currentSet, disabled, + createValue, updateValue, deleteValue, copyValue }) => { return (
    { @@ -31,6 +33,7 @@ const TextWidget = ({ question, values, currentSet, disabled, createValue, updat disabled={disabled} deleteValue={deleteValue} /> +
    } @@ -58,7 +61,8 @@ TextWidget.propTypes = { currentSet: PropTypes.object.isRequired, createValue: PropTypes.func.isRequired, updateValue: PropTypes.func.isRequired, - deleteValue: PropTypes.func.isRequired + deleteValue: PropTypes.func.isRequired, + copyValue: PropTypes.func.isRequired } export default TextWidget diff --git a/rdmo/projects/assets/js/interview/components/main/widget/TextareaWidget.js b/rdmo/projects/assets/js/interview/components/main/widget/TextareaWidget.js index 751aef834d..3c70b8fb23 100644 --- a/rdmo/projects/assets/js/interview/components/main/widget/TextareaWidget.js +++ b/rdmo/projects/assets/js/interview/components/main/widget/TextareaWidget.js @@ -2,6 +2,7 @@ import React from 'react' import PropTypes from 'prop-types' import QuestionAddValue from '../question/QuestionAddValue' +import QuestionCopyValue from '../question/QuestionCopyValue' import QuestionDefault from '../question/QuestionDefault' import QuestionError from '../question/QuestionError' import QuestionSuccess from '../question/QuestionSuccess' @@ -9,7 +10,7 @@ import QuestionRemoveValue from '../question/QuestionRemoveValue' import TextareaInput from './TextareaInput' -const TextareaWidget = ({ question, values, currentSet, disabled, createValue, updateValue, deleteValue }) => { +const TextareaWidget = ({ question, values, currentSet, disabled, createValue, updateValue, deleteValue, copyValue }) => { return (
    { @@ -31,6 +32,7 @@ const TextareaWidget = ({ question, values, currentSet, disabled, createValue, u disabled={disabled} deleteValue={deleteValue} /> +
    } @@ -58,7 +60,8 @@ TextareaWidget.propTypes = { currentSet: PropTypes.object.isRequired, createValue: PropTypes.func.isRequired, updateValue: PropTypes.func.isRequired, - deleteValue: PropTypes.func.isRequired + deleteValue: PropTypes.func.isRequired, + copyValue: PropTypes.func.isRequired } export default TextareaWidget diff --git a/rdmo/projects/assets/js/interview/components/main/widget/YesNoWidget.js b/rdmo/projects/assets/js/interview/components/main/widget/YesNoWidget.js index 5ccc289ff8..7cc00576e1 100644 --- a/rdmo/projects/assets/js/interview/components/main/widget/YesNoWidget.js +++ b/rdmo/projects/assets/js/interview/components/main/widget/YesNoWidget.js @@ -2,6 +2,7 @@ import React from 'react' import PropTypes from 'prop-types' import QuestionAddValue from '../question/QuestionAddValue' +import QuestionCopyValue from '../question/QuestionCopyValue' import QuestionDefault from '../question/QuestionDefault' import QuestionError from '../question/QuestionError' import QuestionEraseValue from '../question/QuestionEraseValue' @@ -10,7 +11,7 @@ import QuestionRemoveValue from '../question/QuestionRemoveValue' import YesNoInput from './YesNoInput' -const YesNoWidget = ({ question, values, currentSet, disabled, createValue, updateValue, deleteValue }) => { +const YesNoWidget = ({ question, values, currentSet, disabled, createValue, updateValue, deleteValue, copyValue }) => { return (
    { @@ -33,6 +34,7 @@ const YesNoWidget = ({ question, values, currentSet, disabled, createValue, upda disabled={disabled} deleteValue={deleteValue} /> +
    } @@ -60,7 +62,8 @@ YesNoWidget.propTypes = { currentSet: PropTypes.object.isRequired, createValue: PropTypes.func.isRequired, updateValue: PropTypes.func.isRequired, - deleteValue: PropTypes.func.isRequired + deleteValue: PropTypes.func.isRequired, + copyValue: PropTypes.func.isRequired } export default YesNoWidget diff --git a/rdmo/projects/assets/js/interview/containers/Main.js b/rdmo/projects/assets/js/interview/containers/Main.js index 7e8c3b1c49..a8f6189fe2 100644 --- a/rdmo/projects/assets/js/interview/containers/Main.js +++ b/rdmo/projects/assets/js/interview/containers/Main.js @@ -53,6 +53,7 @@ const Main = ({ config, settings, templates, user, project, interview, configAct createSet={interviewActions.createSet} updateSet={interviewActions.updateSet} deleteSet={interviewActions.deleteSet} + copyValue={interviewActions.copyValue} /> ) } diff --git a/rdmo/projects/assets/js/interview/utils/value.js b/rdmo/projects/assets/js/interview/utils/value.js index 2c96f179d5..17d8538b93 100644 --- a/rdmo/projects/assets/js/interview/utils/value.js +++ b/rdmo/projects/assets/js/interview/utils/value.js @@ -97,4 +97,10 @@ const compareValues = (a, b) => { } } -export { isDefaultValue, gatherDefaultValues, initValues, initRange, activateFirstValue, compareValues } +const isEmptyValue = (value) => { + return isNil(value.id) || ( + isEmpty(value.text) && isNil(value.option) && isEmpty(value.external_id) + ) +} + +export { isDefaultValue, gatherDefaultValues, initValues, initRange, activateFirstValue, compareValues, isEmptyValue } diff --git a/rdmo/projects/assets/scss/interview.scss b/rdmo/projects/assets/scss/interview.scss index 4936fa30a7..20eb128e67 100644 --- a/rdmo/projects/assets/scss/interview.scss +++ b/rdmo/projects/assets/scss/interview.scss @@ -180,8 +180,7 @@ display: flex; gap: 10px; - .btn-erase-value, - .btn-remove-value, + .btn.btn-link, .success-indicator { opacity: 0.8; line-height: 20px; @@ -190,13 +189,11 @@ padding-right: 0; } - .btn-erase-value:hover, - .btn-remove-value:hover { + .btn.btn-link:hover { opacity: 1; } - .btn-erase-value:focus, - .btn-remove-value:focus { + .btn.btn-link:focus { outline: 0; } From 5ec0b8696b5313292d3ed87b79dc9b415c83c4e8 Mon Sep 17 00:00:00 2001 From: Jochen Klar Date: Tue, 20 Aug 2024 18:21:40 +0200 Subject: [PATCH 06/11] Check siblings for copyValues and use copyValues for all is_collection questions --- .../js/interview/components/main/page/Page.js | 5 ++++ .../components/main/question/Question.js | 4 ++- .../main/question/QuestionAddValue.js | 2 +- .../main/question/QuestionCopyValue.js | 10 +++++--- .../main/question/QuestionCopyValues.js | 25 +++++++++++++------ .../main/questionset/QuestionSet.js | 5 ++++ .../components/main/widget/CheckboxWidget.js | 5 ++-- .../components/main/widget/DateWidget.js | 12 +++++++-- .../components/main/widget/RadioWidget.js | 13 ++++++++-- .../components/main/widget/RangeWidget.js | 13 ++++++++-- .../components/main/widget/SelectWidget.js | 12 +++++++-- .../components/main/widget/TextWidget.js | 12 +++++++-- .../components/main/widget/TextareaWidget.js | 13 ++++++++-- .../components/main/widget/YesNoWidget.js | 8 ++++-- 14 files changed, 110 insertions(+), 29 deletions(-) diff --git a/rdmo/projects/assets/js/interview/components/main/page/Page.js b/rdmo/projects/assets/js/interview/components/main/page/Page.js index acdcc03147..dcab494514 100644 --- a/rdmo/projects/assets/js/interview/components/main/page/Page.js +++ b/rdmo/projects/assets/js/interview/components/main/page/Page.js @@ -72,6 +72,11 @@ const Page = ({ config, templates, overview, page, sets, values, fetchPage, value.set_prefix == currentSetPrefix && value.set_index == currentSetIndex ))} + siblings={values.filter((value) => ( + value.attribute == element.attribute && + value.set_prefix == currentSetPrefix && + value.set_index != currentSetIndex + ))} disabled={overview.read_only} isManager={isManager} currentSet={currentSet} 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 ce6c838581..617cfc945e 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, disabled, isManager, +const Question = ({ templates, question, values, siblings, disabled, isManager, currentSet, createValue, updateValue, deleteValue, copyValue }) => { return checkQuestion(question, currentSet) && (
    @@ -26,6 +26,7 @@ const Question = ({ templates, question, values, disabled, isManager, { } return !disabled && question.is_collection && ( - ) diff --git a/rdmo/projects/assets/js/interview/components/main/question/QuestionCopyValue.js b/rdmo/projects/assets/js/interview/components/main/question/QuestionCopyValue.js index 47ae6388ed..f943386117 100644 --- a/rdmo/projects/assets/js/interview/components/main/question/QuestionCopyValue.js +++ b/rdmo/projects/assets/js/interview/components/main/question/QuestionCopyValue.js @@ -3,10 +3,13 @@ import PropTypes from 'prop-types' import { isEmptyValue } from '../../../utils/value' -const QuestionCopyValue = ({ question, value, copyValue }) => { +const QuestionCopyValue = ({ question, value, siblings, copyValue }) => { return ( - question.set_collection && !isEmptyValue(value) && ( - @@ -17,6 +20,7 @@ const QuestionCopyValue = ({ question, value, copyValue }) => { QuestionCopyValue.propTypes = { question: PropTypes.object.isRequired, value: PropTypes.object.isRequired, + siblings: PropTypes.object.isRequired, copyValue: PropTypes.func.isRequired } diff --git a/rdmo/projects/assets/js/interview/components/main/question/QuestionCopyValues.js b/rdmo/projects/assets/js/interview/components/main/question/QuestionCopyValues.js index e981de95c9..8a08b0d016 100644 --- a/rdmo/projects/assets/js/interview/components/main/question/QuestionCopyValues.js +++ b/rdmo/projects/assets/js/interview/components/main/question/QuestionCopyValues.js @@ -3,26 +3,35 @@ import PropTypes from 'prop-types' import { isEmptyValue } from '../../../utils/value' -const QuestionCopyValues = ({ question, values, copyValue }) => { +const QuestionCopyValues = ({ question, values, siblings, copyValue }) => { const handleCopyValues = () => { values.forEach((value) => copyValue(value)) } - console.log(values) + const button = question.widget_type == 'checkbox' ? ( + + ) : ( + + ) return ( - question.set_collection && values.some((v) => !isEmptyValue(v)) && ( - - ) + question.is_collection && + question.set_collection && + values.some((v) => !isEmptyValue(v)) && + siblings.some((value) => isEmptyValue(value)) && + button ) } QuestionCopyValues.propTypes = { question: PropTypes.object.isRequired, values: PropTypes.array.isRequired, + siblings: PropTypes.array, copyValue: PropTypes.func.isRequired } 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 a582ffaab5..0a807c3663 100644 --- a/rdmo/projects/assets/js/interview/components/main/questionset/QuestionSet.js +++ b/rdmo/projects/assets/js/interview/components/main/questionset/QuestionSet.js @@ -72,6 +72,11 @@ const QuestionSet = ({ templates, questionset, sets, values, disabled, isManager value.set_prefix == set.set_prefix && value.set_index == set.set_index ))} + siblings={values.filter((value) => ( + value.attribute == element.attribute && + value.set_prefix == set.set_prefix && + value.set_index != set.set_index + ))} disabled={disabled} isManager={isManager} currentSet={set} 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 c995c2531d..eff2db4e7b 100644 --- a/rdmo/projects/assets/js/interview/components/main/widget/CheckboxWidget.js +++ b/rdmo/projects/assets/js/interview/components/main/widget/CheckboxWidget.js @@ -10,7 +10,7 @@ import QuestionSuccess from '../question/QuestionSuccess' import CheckboxInput from './CheckboxInput' -const CheckboxWidget = ({ question, values, currentSet, disabled, +const CheckboxWidget = ({ question, values, siblings, currentSet, disabled, createValue, updateValue, deleteValue, copyValue }) => { const handleCreateValue = (option, additionalInput) => { @@ -71,7 +71,7 @@ const CheckboxWidget = ({ question, values, currentSet, disabled,
    - +
    @@ -83,6 +83,7 @@ const CheckboxWidget = ({ question, values, currentSet, disabled, CheckboxWidget.propTypes = { question: PropTypes.object.isRequired, values: PropTypes.array.isRequired, + siblings: PropTypes.array, disabled: PropTypes.bool, currentSet: PropTypes.object.isRequired, createValue: PropTypes.func.isRequired, 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 c4f79c3411..ae7f8ce42b 100644 --- a/rdmo/projects/assets/js/interview/components/main/widget/DateWidget.js +++ b/rdmo/projects/assets/js/interview/components/main/widget/DateWidget.js @@ -3,6 +3,7 @@ import PropTypes from 'prop-types' 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' @@ -11,7 +12,7 @@ import QuestionRemoveValue from '../question/QuestionRemoveValue' import DateInput from './DateInput' -const DateWidget = ({ question, values, currentSet, disabled, createValue, updateValue, deleteValue, copyValue }) => { +const DateWidget = ({ question, values, siblings, currentSet, disabled, createValue, updateValue, deleteValue, copyValue }) => { return (
    { @@ -34,7 +35,7 @@ const DateWidget = ({ question, values, currentSet, disabled, createValue, updat disabled={disabled} deleteValue={deleteValue} /> - +
    } @@ -52,6 +53,12 @@ const DateWidget = ({ question, values, currentSet, disabled, createValue, updat createValue={createValue} copyValue={copyValue} /> + ) } @@ -59,6 +66,7 @@ const DateWidget = ({ question, values, currentSet, disabled, createValue, updat DateWidget.propTypes = { question: PropTypes.object.isRequired, values: PropTypes.array.isRequired, + siblings: PropTypes.array, disabled: PropTypes.bool, currentSet: PropTypes.object.isRequired, createValue: PropTypes.func.isRequired, diff --git a/rdmo/projects/assets/js/interview/components/main/widget/RadioWidget.js b/rdmo/projects/assets/js/interview/components/main/widget/RadioWidget.js index 79497a6cad..15ea8d32c8 100644 --- a/rdmo/projects/assets/js/interview/components/main/widget/RadioWidget.js +++ b/rdmo/projects/assets/js/interview/components/main/widget/RadioWidget.js @@ -5,6 +5,7 @@ import { gatherOptions } from '../../../utils/options' 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 QuestionSuccess from '../question/QuestionSuccess' @@ -13,7 +14,8 @@ import QuestionRemoveValue from '../question/QuestionRemoveValue' import RadioInput from './RadioInput' -const RadioWidget = ({ question, values, currentSet, disabled, createValue, updateValue, deleteValue, copyValue }) => { +const RadioWidget = ({ question, values, siblings, currentSet, disabled, + createValue, updateValue, deleteValue, copyValue }) => { return (
    { @@ -37,7 +39,7 @@ const RadioWidget = ({ question, values, currentSet, disabled, createValue, upda disabled={disabled} deleteValue={deleteValue} /> - +
    } @@ -55,6 +57,12 @@ const RadioWidget = ({ question, values, currentSet, disabled, createValue, upda createValue={createValue} copyValue={copyValue} /> + ) } @@ -62,6 +70,7 @@ const RadioWidget = ({ question, values, currentSet, disabled, createValue, upda RadioWidget.propTypes = { question: PropTypes.object.isRequired, values: PropTypes.array.isRequired, + siblings: PropTypes.array, disabled: PropTypes.bool, currentSet: PropTypes.object.isRequired, createValue: PropTypes.func.isRequired, diff --git a/rdmo/projects/assets/js/interview/components/main/widget/RangeWidget.js b/rdmo/projects/assets/js/interview/components/main/widget/RangeWidget.js index 3bda3222ba..6bcd8f9903 100644 --- a/rdmo/projects/assets/js/interview/components/main/widget/RangeWidget.js +++ b/rdmo/projects/assets/js/interview/components/main/widget/RangeWidget.js @@ -5,6 +5,7 @@ import { initRange } from '../../../utils/value' 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 QuestionSuccess from '../question/QuestionSuccess' @@ -13,7 +14,8 @@ import QuestionRemoveValue from '../question/QuestionRemoveValue' import RangeInput from './RangeInput' -const RangeWidget = ({ question, values, currentSet, disabled, createValue, updateValue, deleteValue, copyValue }) => { +const RangeWidget = ({ question, values, siblings, currentSet, disabled, + createValue, updateValue, deleteValue, copyValue }) => { const handleCreateValue = (value) => { initRange(question, value) @@ -47,7 +49,7 @@ const RangeWidget = ({ question, values, currentSet, disabled, createValue, upda disabled={disabled} deleteValue={deleteValue} /> - + } @@ -65,6 +67,12 @@ const RangeWidget = ({ question, values, currentSet, disabled, createValue, upda createValue={handleCreateValue} copyValue={copyValue} /> + ) } @@ -72,6 +80,7 @@ const RangeWidget = ({ question, values, currentSet, disabled, createValue, upda RangeWidget.propTypes = { question: PropTypes.object.isRequired, values: PropTypes.array.isRequired, + siblings: PropTypes.array, disabled: PropTypes.bool, currentSet: PropTypes.object.isRequired, createValue: PropTypes.func.isRequired, diff --git a/rdmo/projects/assets/js/interview/components/main/widget/SelectWidget.js b/rdmo/projects/assets/js/interview/components/main/widget/SelectWidget.js index 60dbbbc4cf..7124f1d20f 100644 --- a/rdmo/projects/assets/js/interview/components/main/widget/SelectWidget.js +++ b/rdmo/projects/assets/js/interview/components/main/widget/SelectWidget.js @@ -5,6 +5,7 @@ import { gatherOptions } from '../../../utils/options' import QuestionAddValue from '../question/QuestionAddValue' import QuestionCopyValue from '../question/QuestionCopyValue' +import QuestionCopyValues from '../question/QuestionCopyValues' import QuestionDefault from '../question/QuestionDefault' import QuestionEraseValue from '../question/QuestionEraseValue' import QuestionError from '../question/QuestionError' @@ -13,7 +14,7 @@ import QuestionRemoveValue from '../question/QuestionRemoveValue' import SelectInput from './SelectInput' -const SelectWidget = ({ question, values, currentSet, disabled, creatable, +const SelectWidget = ({ question, values, siblings, currentSet, disabled, creatable, createValue, updateValue, deleteValue, copyValue }) => { return (
    @@ -39,7 +40,7 @@ const SelectWidget = ({ question, values, currentSet, disabled, creatable, disabled={disabled} deleteValue={deleteValue} /> - +
    } @@ -56,6 +57,12 @@ const SelectWidget = ({ question, values, currentSet, disabled, creatable, disabled={disabled} createValue={createValue} /> + ) } @@ -63,6 +70,7 @@ const SelectWidget = ({ question, values, currentSet, disabled, creatable, SelectWidget.propTypes = { question: PropTypes.object.isRequired, values: PropTypes.array.isRequired, + siblings: PropTypes.array, disabled: PropTypes.bool, creatable: PropTypes.bool, currentSet: PropTypes.object.isRequired, diff --git a/rdmo/projects/assets/js/interview/components/main/widget/TextWidget.js b/rdmo/projects/assets/js/interview/components/main/widget/TextWidget.js index d6119b0986..ed823ee857 100644 --- a/rdmo/projects/assets/js/interview/components/main/widget/TextWidget.js +++ b/rdmo/projects/assets/js/interview/components/main/widget/TextWidget.js @@ -3,6 +3,7 @@ import PropTypes from 'prop-types' 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 QuestionRemoveValue from '../question/QuestionRemoveValue' @@ -10,7 +11,7 @@ import QuestionSuccess from '../question/QuestionSuccess' import TextInput from './TextInput' -const TextWidget = ({ question, values, currentSet, disabled, +const TextWidget = ({ question, values, siblings, currentSet, disabled, createValue, updateValue, deleteValue, copyValue }) => { return (
    @@ -33,7 +34,7 @@ const TextWidget = ({ question, values, currentSet, disabled, disabled={disabled} deleteValue={deleteValue} /> - +
    } @@ -50,6 +51,12 @@ const TextWidget = ({ question, values, currentSet, disabled, disabled={disabled} createValue={createValue} /> + ) } @@ -57,6 +64,7 @@ const TextWidget = ({ question, values, currentSet, disabled, TextWidget.propTypes = { question: PropTypes.object.isRequired, values: PropTypes.array.isRequired, + siblings: PropTypes.array, disabled: PropTypes.bool, currentSet: PropTypes.object.isRequired, createValue: PropTypes.func.isRequired, diff --git a/rdmo/projects/assets/js/interview/components/main/widget/TextareaWidget.js b/rdmo/projects/assets/js/interview/components/main/widget/TextareaWidget.js index 3c70b8fb23..8d67201029 100644 --- a/rdmo/projects/assets/js/interview/components/main/widget/TextareaWidget.js +++ b/rdmo/projects/assets/js/interview/components/main/widget/TextareaWidget.js @@ -3,6 +3,7 @@ import PropTypes from 'prop-types' 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 QuestionSuccess from '../question/QuestionSuccess' @@ -10,7 +11,8 @@ import QuestionRemoveValue from '../question/QuestionRemoveValue' import TextareaInput from './TextareaInput' -const TextareaWidget = ({ question, values, currentSet, disabled, createValue, updateValue, deleteValue, copyValue }) => { +const TextareaWidget = ({ question, values, siblings, currentSet, disabled, + createValue, updateValue, deleteValue, copyValue }) => { return (
    { @@ -32,7 +34,7 @@ const TextareaWidget = ({ question, values, currentSet, disabled, createValue, u disabled={disabled} deleteValue={deleteValue} /> - +
    } @@ -49,6 +51,12 @@ const TextareaWidget = ({ question, values, currentSet, disabled, createValue, u disabled={disabled} createValue={createValue} /> + ) } @@ -56,6 +64,7 @@ const TextareaWidget = ({ question, values, currentSet, disabled, createValue, u TextareaWidget.propTypes = { question: PropTypes.object.isRequired, values: PropTypes.array.isRequired, + siblings: PropTypes.array, disabled: PropTypes.bool, currentSet: PropTypes.object.isRequired, createValue: PropTypes.func.isRequired, diff --git a/rdmo/projects/assets/js/interview/components/main/widget/YesNoWidget.js b/rdmo/projects/assets/js/interview/components/main/widget/YesNoWidget.js index 7cc00576e1..5be4f02852 100644 --- a/rdmo/projects/assets/js/interview/components/main/widget/YesNoWidget.js +++ b/rdmo/projects/assets/js/interview/components/main/widget/YesNoWidget.js @@ -3,6 +3,7 @@ import PropTypes from 'prop-types' 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' @@ -11,7 +12,8 @@ import QuestionRemoveValue from '../question/QuestionRemoveValue' import YesNoInput from './YesNoInput' -const YesNoWidget = ({ question, values, currentSet, disabled, createValue, updateValue, deleteValue, copyValue }) => { +const YesNoWidget = ({ question, values, siblings, currentSet, disabled, + createValue, updateValue, deleteValue, copyValue }) => { return (
    { @@ -34,7 +36,7 @@ const YesNoWidget = ({ question, values, currentSet, disabled, createValue, upda disabled={disabled} deleteValue={deleteValue} /> - +
    } @@ -51,6 +53,7 @@ const YesNoWidget = ({ question, values, currentSet, disabled, createValue, upda disabled={disabled} createValue={createValue} /> + ) } @@ -58,6 +61,7 @@ const YesNoWidget = ({ question, values, currentSet, disabled, createValue, upda YesNoWidget.propTypes = { question: PropTypes.object.isRequired, values: PropTypes.array.isRequired, + siblings: PropTypes.array, disabled: PropTypes.bool, currentSet: PropTypes.object.isRequired, createValue: PropTypes.func.isRequired, From 7e74ab9875cf2ad1f3e8a97a0d44781dd2f7639c Mon Sep 17 00:00:00 2001 From: Jochen Klar Date: Thu, 12 Dec 2024 15:53:56 +0100 Subject: [PATCH 07/11] Fix propTypes for QuestionCopyValue --- .../js/interview/components/main/question/QuestionCopyValue.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rdmo/projects/assets/js/interview/components/main/question/QuestionCopyValue.js b/rdmo/projects/assets/js/interview/components/main/question/QuestionCopyValue.js index f943386117..57c9d40879 100644 --- a/rdmo/projects/assets/js/interview/components/main/question/QuestionCopyValue.js +++ b/rdmo/projects/assets/js/interview/components/main/question/QuestionCopyValue.js @@ -20,7 +20,7 @@ const QuestionCopyValue = ({ question, value, siblings, copyValue }) => { QuestionCopyValue.propTypes = { question: PropTypes.object.isRequired, value: PropTypes.object.isRequired, - siblings: PropTypes.object.isRequired, + siblings: PropTypes.array.isRequired, copyValue: PropTypes.func.isRequired } From c1146d484549cbbc650644afa18d50baa2028d0e Mon Sep 17 00:00:00 2001 From: Jochen Klar Date: Mon, 6 Jan 2025 13:21:06 +0100 Subject: [PATCH 08/11] Fix QuestionCopyValues --- .../js/interview/components/main/page/Page.js | 3 ++ .../components/main/question/Question.js | 4 ++- .../main/question/QuestionCopyValues.js | 25 ++++++++++++-- .../main/questionset/QuestionSet.js | 3 ++ .../components/main/widget/CheckboxWidget.js | 12 +++++-- .../components/main/widget/DateWidget.js | 6 +++- .../components/main/widget/RadioWidget.js | 5 ++- .../components/main/widget/RangeWidget.js | 5 ++- .../components/main/widget/SelectWidget.js | 5 ++- .../components/main/widget/TextWidget.js | 5 ++- .../components/main/widget/TextareaWidget.js | 5 ++- .../components/main/widget/YesNoWidget.js | 12 +++++-- .../assets/js/interview/utils/value.js | 33 +++++++++++-------- 13 files changed, 95 insertions(+), 28 deletions(-) diff --git a/rdmo/projects/assets/js/interview/components/main/page/Page.js b/rdmo/projects/assets/js/interview/components/main/page/Page.js index dcab494514..56bc9eba84 100644 --- a/rdmo/projects/assets/js/interview/components/main/page/Page.js +++ b/rdmo/projects/assets/js/interview/components/main/page/Page.js @@ -67,6 +67,9 @@ const Page = ({ config, templates, overview, page, sets, values, fetchPage, key={elementIndex} templates={templates} question={element} + sets={sets.filter((set) => ( + set.set_prefix == currentSetPrefix + ))} values={values.filter((value) => ( value.attribute == element.attribute && value.set_prefix == currentSetPrefix && 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..a74e89ba96 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, question, sets, values, siblings, disabled, isManager, currentSet, createValue, updateValue, deleteValue, copyValue }) => { return checkQuestion(question, currentSet) && (
    @@ -25,6 +25,7 @@ const Question = ({ templates, question, values, siblings, disabled, isManager, { +const QuestionCopyValues = ({ question, sets, values, siblings, currentSet, copyValue }) => { const handleCopyValues = () => { values.forEach((value) => copyValue(value)) } @@ -19,19 +20,37 @@ const QuestionCopyValues = ({ question, values, siblings, copyValue }) => { ) + const hasValues = values.some((value) => !isEmptyValue(value)) + + const hasEmptySiblings = sets.filter((set) => ( + (set.set_prefix == currentSet.set_prefix) && + (set.set_index != currentSet.set_index) + )).some((set) => { + // loop over all other sets and filter siblings accordingly + const setSiblings = siblings.filter((value) => ( + (value.set_prefix == set.set_prefix) && + (value.set_index == set.set_index) + )) + + // check if this set has no sibling at all (for checkboxes) or if they are empty + return isEmpty(setSiblings) || setSiblings.some((value) => isEmptyValue(value)) + }) + return ( question.is_collection && question.set_collection && - values.some((v) => !isEmptyValue(v)) && - siblings.some((value) => isEmptyValue(value)) && + hasValues && + hasEmptySiblings && button ) } QuestionCopyValues.propTypes = { question: PropTypes.object.isRequired, + sets: PropTypes.array.isRequired, values: PropTypes.array.isRequired, siblings: PropTypes.array, + currentSet: PropTypes.object.isRequired, copyValue: PropTypes.func.isRequired } 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 0a807c3663..a0a30396ed 100644 --- a/rdmo/projects/assets/js/interview/components/main/questionset/QuestionSet.js +++ b/rdmo/projects/assets/js/interview/components/main/questionset/QuestionSet.js @@ -67,6 +67,9 @@ const QuestionSet = ({ templates, questionset, sets, values, disabled, isManager key={elementIndex} templates={templates} question={element} + sets={sets.filter((set) => ( + set.set_prefix == setPrefix + ))} values={values.filter((value) => ( value.attribute == element.attribute && value.set_prefix == set.set_prefix && 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..625ebbcb36 100644 --- a/rdmo/projects/assets/js/interview/components/main/widget/CheckboxWidget.js +++ b/rdmo/projects/assets/js/interview/components/main/widget/CheckboxWidget.js @@ -10,7 +10,7 @@ import QuestionSuccess from '../question/QuestionSuccess' import CheckboxInput from './CheckboxInput' -const CheckboxWidget = ({ question, values, siblings, currentSet, disabled, +const CheckboxWidget = ({ question, sets, values, siblings, currentSet, disabled, createValue, updateValue, deleteValue, copyValue }) => { const handleCreateValue = (option, additionalInput) => { @@ -71,7 +71,14 @@ const CheckboxWidget = ({ question, values, siblings, currentSet, disabled,
    - +
    @@ -82,6 +89,7 @@ const CheckboxWidget = ({ question, values, siblings, currentSet, disabled, CheckboxWidget.propTypes = { question: PropTypes.object.isRequired, + sets: PropTypes.array.isRequired, values: PropTypes.array.isRequired, siblings: PropTypes.array, disabled: PropTypes.bool, 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..71903b3a2e 100644 --- a/rdmo/projects/assets/js/interview/components/main/widget/DateWidget.js +++ b/rdmo/projects/assets/js/interview/components/main/widget/DateWidget.js @@ -12,7 +12,8 @@ import QuestionRemoveValue from '../question/QuestionRemoveValue' import DateInput from './DateInput' -const DateWidget = ({ question, values, siblings, currentSet, disabled, createValue, updateValue, deleteValue, copyValue }) => { +const DateWidget = ({ question, sets, values, siblings, currentSet, disabled, + createValue, updateValue, deleteValue, copyValue }) => { return (
    { @@ -55,8 +56,10 @@ const DateWidget = ({ question, values, siblings, currentSet, disabled, createVa />
    @@ -65,6 +68,7 @@ const DateWidget = ({ question, values, siblings, currentSet, disabled, createVa DateWidget.propTypes = { question: PropTypes.object.isRequired, + sets: PropTypes.array.isRequired, values: PropTypes.array.isRequired, siblings: PropTypes.array, disabled: PropTypes.bool, diff --git a/rdmo/projects/assets/js/interview/components/main/widget/RadioWidget.js b/rdmo/projects/assets/js/interview/components/main/widget/RadioWidget.js index 15ea8d32c8..4a43ece34a 100644 --- a/rdmo/projects/assets/js/interview/components/main/widget/RadioWidget.js +++ b/rdmo/projects/assets/js/interview/components/main/widget/RadioWidget.js @@ -14,7 +14,7 @@ import QuestionRemoveValue from '../question/QuestionRemoveValue' import RadioInput from './RadioInput' -const RadioWidget = ({ question, values, siblings, currentSet, disabled, +const RadioWidget = ({ question, sets, values, siblings, currentSet, disabled, createValue, updateValue, deleteValue, copyValue }) => { return (
    @@ -59,8 +59,10 @@ const RadioWidget = ({ question, values, siblings, currentSet, disabled, />
    @@ -69,6 +71,7 @@ const RadioWidget = ({ question, values, siblings, currentSet, disabled, RadioWidget.propTypes = { question: PropTypes.object.isRequired, + sets: PropTypes.array.isRequired, values: PropTypes.array.isRequired, siblings: PropTypes.array, disabled: PropTypes.bool, diff --git a/rdmo/projects/assets/js/interview/components/main/widget/RangeWidget.js b/rdmo/projects/assets/js/interview/components/main/widget/RangeWidget.js index 6bcd8f9903..9d7d42b9bb 100644 --- a/rdmo/projects/assets/js/interview/components/main/widget/RangeWidget.js +++ b/rdmo/projects/assets/js/interview/components/main/widget/RangeWidget.js @@ -14,7 +14,7 @@ import QuestionRemoveValue from '../question/QuestionRemoveValue' import RangeInput from './RangeInput' -const RangeWidget = ({ question, values, siblings, currentSet, disabled, +const RangeWidget = ({ question, sets, values, siblings, currentSet, disabled, createValue, updateValue, deleteValue, copyValue }) => { const handleCreateValue = (value) => { @@ -69,8 +69,10 @@ const RangeWidget = ({ question, values, siblings, currentSet, disabled, /> @@ -79,6 +81,7 @@ const RangeWidget = ({ question, values, siblings, currentSet, disabled, RangeWidget.propTypes = { question: PropTypes.object.isRequired, + sets: PropTypes.array.isRequired, values: PropTypes.array.isRequired, siblings: PropTypes.array, disabled: PropTypes.bool, diff --git a/rdmo/projects/assets/js/interview/components/main/widget/SelectWidget.js b/rdmo/projects/assets/js/interview/components/main/widget/SelectWidget.js index 7124f1d20f..fce4140a7e 100644 --- a/rdmo/projects/assets/js/interview/components/main/widget/SelectWidget.js +++ b/rdmo/projects/assets/js/interview/components/main/widget/SelectWidget.js @@ -14,7 +14,7 @@ import QuestionRemoveValue from '../question/QuestionRemoveValue' import SelectInput from './SelectInput' -const SelectWidget = ({ question, values, siblings, currentSet, disabled, creatable, +const SelectWidget = ({ question, sets, values, siblings, currentSet, disabled, creatable, createValue, updateValue, deleteValue, copyValue }) => { return (
    @@ -59,8 +59,10 @@ const SelectWidget = ({ question, values, siblings, currentSet, disabled, creata />
    @@ -69,6 +71,7 @@ const SelectWidget = ({ question, values, siblings, currentSet, disabled, creata SelectWidget.propTypes = { question: PropTypes.object.isRequired, + sets: PropTypes.array.isRequired, values: PropTypes.array.isRequired, siblings: PropTypes.array, disabled: PropTypes.bool, diff --git a/rdmo/projects/assets/js/interview/components/main/widget/TextWidget.js b/rdmo/projects/assets/js/interview/components/main/widget/TextWidget.js index ed823ee857..fbee0d5235 100644 --- a/rdmo/projects/assets/js/interview/components/main/widget/TextWidget.js +++ b/rdmo/projects/assets/js/interview/components/main/widget/TextWidget.js @@ -11,7 +11,7 @@ import QuestionSuccess from '../question/QuestionSuccess' import TextInput from './TextInput' -const TextWidget = ({ question, values, siblings, currentSet, disabled, +const TextWidget = ({ question, sets, values, siblings, currentSet, disabled, createValue, updateValue, deleteValue, copyValue }) => { return (
    @@ -53,8 +53,10 @@ const TextWidget = ({ question, values, siblings, currentSet, disabled, />
    @@ -63,6 +65,7 @@ const TextWidget = ({ question, values, siblings, currentSet, disabled, TextWidget.propTypes = { question: PropTypes.object.isRequired, + sets: PropTypes.array.isRequired, values: PropTypes.array.isRequired, siblings: PropTypes.array, disabled: PropTypes.bool, diff --git a/rdmo/projects/assets/js/interview/components/main/widget/TextareaWidget.js b/rdmo/projects/assets/js/interview/components/main/widget/TextareaWidget.js index 8d67201029..cc063a3bf5 100644 --- a/rdmo/projects/assets/js/interview/components/main/widget/TextareaWidget.js +++ b/rdmo/projects/assets/js/interview/components/main/widget/TextareaWidget.js @@ -11,7 +11,7 @@ import QuestionRemoveValue from '../question/QuestionRemoveValue' import TextareaInput from './TextareaInput' -const TextareaWidget = ({ question, values, siblings, currentSet, disabled, +const TextareaWidget = ({ question, sets, values, siblings, currentSet, disabled, createValue, updateValue, deleteValue, copyValue }) => { return (
    @@ -53,8 +53,10 @@ const TextareaWidget = ({ question, values, siblings, currentSet, disabled, />
    @@ -63,6 +65,7 @@ const TextareaWidget = ({ question, values, siblings, currentSet, disabled, TextareaWidget.propTypes = { question: PropTypes.object.isRequired, + sets: PropTypes.array.isRequired, values: PropTypes.array.isRequired, siblings: PropTypes.array, disabled: PropTypes.bool, diff --git a/rdmo/projects/assets/js/interview/components/main/widget/YesNoWidget.js b/rdmo/projects/assets/js/interview/components/main/widget/YesNoWidget.js index 5be4f02852..ec7e965272 100644 --- a/rdmo/projects/assets/js/interview/components/main/widget/YesNoWidget.js +++ b/rdmo/projects/assets/js/interview/components/main/widget/YesNoWidget.js @@ -12,7 +12,7 @@ import QuestionRemoveValue from '../question/QuestionRemoveValue' import YesNoInput from './YesNoInput' -const YesNoWidget = ({ question, values, siblings, currentSet, disabled, +const YesNoWidget = ({ question, sets, values, siblings, currentSet, disabled, createValue, updateValue, deleteValue, copyValue }) => { return (
    @@ -53,13 +53,21 @@ const YesNoWidget = ({ question, values, siblings, currentSet, disabled, disabled={disabled} createValue={createValue} /> - +
    ) } YesNoWidget.propTypes = { question: PropTypes.object.isRequired, + sets: PropTypes.array.isRequired, values: PropTypes.array.isRequired, siblings: PropTypes.array, disabled: PropTypes.bool, diff --git a/rdmo/projects/assets/js/interview/utils/value.js b/rdmo/projects/assets/js/interview/utils/value.js index 17d8538b93..0c6065a8c8 100644 --- a/rdmo/projects/assets/js/interview/utils/value.js +++ b/rdmo/projects/assets/js/interview/utils/value.js @@ -39,28 +39,33 @@ const initValues = (sets, values, element, setPrefix) => { setPrefix = '' } + // loop over all sets of the current set prefix and over all questions sets.filter((set) => set.set_prefix === setPrefix).forEach((set) => { element.elements.filter((e) => (e.model === 'questions.question')).forEach((question) => { + // check if there is any value for this question and set if (isNil(values.find((value) => ( (value.attribute === question.attribute) && (value.set_prefix == set.set_prefix) && (value.set_index == set.set_index) )))) { - const value = ValueFactory.create({ - attribute: question.attribute, - set_prefix: set.set_prefix, - set_index: set.set_index, - set_collection: question.set_collection, - text: question.default_text, - option: question.default_option, - external_id: question.default_external_id - }) - - if (question.widget_class === 'range') { - initRange(question, value) + // if there is no value, create one, but not for checkboxes + if (question.widget_class !== 'checkbox') { + const value = ValueFactory.create({ + attribute: question.attribute, + set_prefix: set.set_prefix, + set_index: set.set_index, + set_collection: question.set_collection, + text: question.default_text, + option: question.default_option, + external_id: question.default_external_id + }) + + if (question.widget_class === 'range') { + initRange(question, value) + } + + values.push(value) } - - values.push(value) } }) From 39c32c365d0a5c581202b6365b77b79526e34276 Mon Sep 17 00:00:00 2001 From: Jochen Klar Date: Thu, 9 Jan 2025 10:28:19 +0100 Subject: [PATCH 09/11] Use === in initValues --- rdmo/projects/assets/js/interview/utils/value.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rdmo/projects/assets/js/interview/utils/value.js b/rdmo/projects/assets/js/interview/utils/value.js index 0c6065a8c8..5723f8644b 100644 --- a/rdmo/projects/assets/js/interview/utils/value.js +++ b/rdmo/projects/assets/js/interview/utils/value.js @@ -45,8 +45,8 @@ const initValues = (sets, values, element, setPrefix) => { // check if there is any value for this question and set if (isNil(values.find((value) => ( (value.attribute === question.attribute) && - (value.set_prefix == set.set_prefix) && - (value.set_index == set.set_index) + (value.set_prefix === set.set_prefix) && + (value.set_index === set.set_index) )))) { // if there is no value, create one, but not for checkboxes if (question.widget_class !== 'checkbox') { From ccd3cd871452b91dbcd3a8b5320d0225689cf26c Mon Sep 17 00:00:00 2001 From: Jochen Klar Date: Thu, 9 Jan 2025 10:35:37 +0100 Subject: [PATCH 10/11] Add QuestionEraseValues component for checkboxes --- .../main/question/QuestionEraseValues.js | 23 +++++++++++++++++++ .../components/main/widget/CheckboxWidget.js | 6 +++++ 2 files changed, 29 insertions(+) create mode 100644 rdmo/projects/assets/js/interview/components/main/question/QuestionEraseValues.js diff --git a/rdmo/projects/assets/js/interview/components/main/question/QuestionEraseValues.js b/rdmo/projects/assets/js/interview/components/main/question/QuestionEraseValues.js new file mode 100644 index 0000000000..d6f66f89b0 --- /dev/null +++ b/rdmo/projects/assets/js/interview/components/main/question/QuestionEraseValues.js @@ -0,0 +1,23 @@ +import React from 'react' +import PropTypes from 'prop-types' + +const QuestionEraseValues = ({ values, disabled, deleteValue }) => { + const handleEraseValue = () => { + values.forEach((value) => deleteValue(value)) + } + + return !disabled && ( + + ) +} + +QuestionEraseValues.propTypes = { + values: PropTypes.array.isRequired, + disabled: PropTypes.bool.isRequired, + deleteValue: PropTypes.func.isRequired +} + +export default QuestionEraseValues 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 625ebbcb36..e1cf9975f1 100644 --- a/rdmo/projects/assets/js/interview/components/main/widget/CheckboxWidget.js +++ b/rdmo/projects/assets/js/interview/components/main/widget/CheckboxWidget.js @@ -5,6 +5,7 @@ import { maxBy } from 'lodash' import { gatherOptions } from '../../../utils/options' import QuestionCopyValues from '../question/QuestionCopyValues' +import QuestionEraseValues from '../question/QuestionEraseValues' import QuestionError from '../question/QuestionError' import QuestionSuccess from '../question/QuestionSuccess' @@ -71,6 +72,11 @@ const CheckboxWidget = ({ question, sets, values, siblings, currentSet, disabled
    + Date: Thu, 9 Jan 2025 17:45:56 +0100 Subject: [PATCH 11/11] Fix initQuestionSet --- .../projects/assets/js/interview/utils/page.js | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/rdmo/projects/assets/js/interview/utils/page.js b/rdmo/projects/assets/js/interview/utils/page.js index f1d40c39ae..e254514e69 100644 --- a/rdmo/projects/assets/js/interview/utils/page.js +++ b/rdmo/projects/assets/js/interview/utils/page.js @@ -20,36 +20,36 @@ const initQuestionSet = (questionset) => { // aggregate questionsets from descendants questionset.questionsets = questionset.elements.reduce((questionsets, element) => { if (element.model == 'questions.questionset') { - return questionsets.concat(element.questionsets) + return [...questionsets, element, ...element.questionsets] // add this questionset and all it's questionsets } else { - return questionsets + return questionsets // do nothing } }, []) - // aggregate optionsets from descendants + // aggregate questions from descendants questionset.questions = questionset.elements.reduce((questions, element) => { if (element.model == 'questions.questionset') { - return questions.concat(element.questions) + return questions.concat(element.questions) // add the questions of this questionset } else { - return [...questions, element] + return [...questions, element] // add this question } }, []) // aggregate optionsets from descendants questionset.optionsets = questionset.elements.reduce((optionsets, element) => { if (element.model == 'questions.questionset') { - return optionsets.concat(element.optionsets) + return optionsets.concat(element.optionsets) // add all optionsets of the questions of this questionset } else { - return [...optionsets, ...element.optionsets] + return [...optionsets, ...element.optionsets] // add all optionsets of this question } }, []) // aggregate attributes from descendants questionset.attributes = questionset.elements.reduce((attributes, element) => { if (element.model == 'questions.questionset') { - return attributes.concat(element.attributes) + return attributes.concat(element.attributes) // add all attributes of this questionset and its questions } else { - return [...attributes, element.attribute] + return [...attributes, element.attribute] // add the attribute of this question } }, [questionset.attribute]).filter((a) => !isNil(a)) }