Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(interview): apply to all [2] #1125

Draft
wants to merge 6 commits into
base: interview-visibility
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 31 additions & 5 deletions rdmo/projects/assets/js/interview/actions/interviewActions.js
Original file line number Diff line number Diff line change
Expand Up @@ -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, isEmptyValue } from '../utils/value'
import { projectId } from '../utils/meta'

import ValueFactory from '../factories/ValueFactory'
Expand Down Expand Up @@ -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

Expand Down Expand Up @@ -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}`

Expand Down Expand Up @@ -453,9 +478,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)
}
})
}
Expand Down
12 changes: 10 additions & 2 deletions rdmo/projects/assets/js/interview/components/main/page/Page.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 = ''
Expand Down Expand Up @@ -58,6 +58,7 @@ const Page = ({ config, templates, overview, page, sets, values, fetchPage,
createValue={createValue}
updateValue={updateValue}
deleteValue={deleteValue}
copyValue={copyValue}
/>
)
} else {
Expand All @@ -71,12 +72,18 @@ 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}
createValue={createValue}
updateValue={updateValue}
deleteValue={deleteValue}
copyValue={copyValue}
/>
)
}
Expand Down Expand Up @@ -104,7 +111,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
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -71,7 +76,7 @@ const PageHead = ({ templates, page, sets, values, currentSet, activateSet, crea
})
}
<li>
<a href="#" title={gettext('Add tab')} className="add-set" onClick={openCreateModal}>
<a href="" title={gettext('Add tab')} className="add-set" onClick={handleOpenCreateModal}>
<i className="fa fa-plus fa-btn"></i> {capitalize(page.verbose_name)}
</a>
</li>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ import QuestionText from './QuestionText'
import QuestionWarning from './QuestionWarning'
import QuestionWidget from './QuestionWidget'

const Question = ({ templates, question, values, disabled, isManager,
currentSet, createValue, updateValue, deleteValue }) => {
const Question = ({ templates, question, values, siblings, disabled, isManager,
currentSet, createValue, updateValue, deleteValue, copyValue }) => {
return checkQuestion(question, currentSet) && (
<div className={`interview-question col-md-${question.width || '12'}`}>
<QuestionOptional question={question} />
Expand All @@ -26,11 +26,13 @@ const Question = ({ templates, question, values, disabled, isManager,
<QuestionWidget
question={question}
values={values}
siblings={siblings}
disabled={disabled}
currentSet={currentSet}
createValue={createValue}
updateValue={updateValue}
deleteValue={deleteValue}
copyValue={copyValue}
/>
</div>
)
Expand All @@ -40,12 +42,14 @@ Question.propTypes = {
templates: PropTypes.object.isRequired,
question: PropTypes.object.isRequired,
values: PropTypes.array.isRequired,
siblings: PropTypes.array,
disabled: PropTypes.bool.isRequired,
isManager: PropTypes.bool.isRequired,
currentSet: PropTypes.object.isRequired,
createValue: PropTypes.func.isRequired,
updateValue: PropTypes.func.isRequired,
deleteValue: PropTypes.func.isRequired,
copyValue: PropTypes.func.isRequired
}

export default Question
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ const AddValue = ({ question, values, currentSet, disabled, createValue }) => {
}

return !disabled && question.is_collection && (
<button type="button" className="btn btn-success add-value-button" onClick={handleClick}>
<button type="button" className="btn btn-success btn-xs add-value-button" onClick={handleClick}>
<i className="fa fa-plus fa-btn"></i> {capitalize(question.verbose_name)}
</button>
)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import React from 'react'
import PropTypes from 'prop-types'

import { isEmptyValue } from '../../../utils/value'

const QuestionCopyValue = ({ question, value, siblings, copyValue }) => {
return (
question.set_collection &&
!question.is_collection &&
!isEmptyValue(value) &&
siblings.some((value) => isEmptyValue(value)) && (
<button className="btn btn-link btn-apply-to-all" onClick={() => copyValue(value, siblings)}
title={gettext('Apply this answer to all tabs where this question is empty')}>
<i className="fa fa-arrow-circle-right fa-btn"></i>
</button>
)
)
}

QuestionCopyValue.propTypes = {
question: PropTypes.object.isRequired,
value: PropTypes.object.isRequired,
siblings: PropTypes.object.isRequired,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should this not be siblings: PropTypes.array.isRequired, , an array instead object? The browser showed an error about it..

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes , will fix!

copyValue: PropTypes.func.isRequired
}

export default QuestionCopyValue
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import React from 'react'
import PropTypes from 'prop-types'

import { isEmptyValue } from '../../../utils/value'

const QuestionCopyValues = ({ question, values, siblings, copyValue }) => {
const handleCopyValues = () => {
values.forEach((value) => copyValue(value))
}

const button = question.widget_type == 'checkbox' ? (
<button className="btn btn-link btn-apply-to-all" onClick={handleCopyValues}
title={gettext('Apply this answer to all tabs where this question is empty')}>
<i className="fa fa-arrow-circle-right fa-btn"></i>
</button>
) : (
<button type="button" className="btn btn-primary btn-xs copy-value-button ml-10" onClick={handleCopyValues}>
<i className="fa fa-arrow-circle-right fa-btn"></i> {gettext('Apply to all')}
</button>
)

return (
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
}

export default QuestionCopyValues
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down Expand Up @@ -58,6 +58,7 @@ const QuestionSet = ({ templates, questionset, sets, values, disabled, isManager
createValue={createValue}
updateValue={updateValue}
deleteValue={deleteValue}
copyValue={copyValue}
/>
)
} else {
Expand All @@ -71,12 +72,18 @@ 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}
createValue={createValue}
updateValue={updateValue}
deleteValue={deleteValue}
copyValue={copyValue}
/>
)
}
Expand Down Expand Up @@ -107,7 +114,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
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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, siblings, currentSet, disabled,
createValue, updateValue, deleteValue, copyValue }) => {

const handleCreateValue = (option, additionalInput) => {
const lastValue = maxBy(values, (v) => v.collection_index)
Expand Down Expand Up @@ -69,6 +71,7 @@ const CheckboxWidget = ({ question, values, currentSet, disabled, createValue, u
</div>
<div className="buttons">
<QuestionSuccess value={{ success }} />
<QuestionCopyValues question={question} values={values} siblings={siblings} copyValue={copyValue} />
</div>
</div>
</div>
Expand All @@ -80,11 +83,13 @@ const CheckboxWidget = ({ question, values, currentSet, disabled, createValue, u
CheckboxWidget.propTypes = {
question: PropTypes.object.isRequired,
values: PropTypes.array.isRequired,
siblings: PropTypes.array,
disabled: PropTypes.bool,
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
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import React from 'react'
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'
Expand All @@ -10,7 +12,7 @@ import QuestionRemoveValue from '../question/QuestionRemoveValue'

import DateInput from './DateInput'

const DateWidget = ({ question, values, currentSet, disabled, createValue, updateValue, deleteValue }) => {
const DateWidget = ({ question, values, siblings, currentSet, disabled, createValue, updateValue, deleteValue, copyValue }) => {
return (
<div className="interview-widgets">
{
Expand All @@ -33,6 +35,7 @@ const DateWidget = ({ question, values, currentSet, disabled, createValue, updat
disabled={disabled}
deleteValue={deleteValue}
/>
<QuestionCopyValue question={question} value={value} siblings={siblings} copyValue={copyValue} />
<QuestionDefault question={question} value={value} />
</div>
}
Expand All @@ -48,6 +51,13 @@ const DateWidget = ({ question, values, currentSet, disabled, createValue, updat
currentSet={currentSet}
disabled={disabled}
createValue={createValue}
copyValue={copyValue}
/>
<QuestionCopyValues
question={question}
values={values}
siblings={siblings}
copyValue={copyValue}
/>
</div>
)
Expand All @@ -56,11 +66,13 @@ 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,
updateValue: PropTypes.func.isRequired,
deleteValue: PropTypes.func.isRequired
deleteValue: PropTypes.func.isRequired,
copyValue: PropTypes.func.isRequired
}

export default DateWidget
Loading