fix: Make sure "other" answers are correctly handled

In the backend it handling the "other" answer setting was not changed
after switching from object to array for extra settings.

In the frontend the value handling of the checkboxes or radio switches
was not correct as the initial values is always an empty array.
This lead to issues with radio switch answers.

Signed-off-by: Ferdinand Thiessen <opensource@fthiessen.de>
This commit is contained in:
Ferdinand Thiessen 2023-10-26 02:26:53 +02:00 коммит произвёл Christian Hartmann
Родитель 6d741652dd
Коммит 8303476b48
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 01CF79F7199D2C63
5 изменённых файлов: 27 добавлений и 26 удалений

Просмотреть файл

@ -961,7 +961,7 @@ class ApiController extends OCSController {
$optionIndex = array_search($answer, array_column($question['options'], 'id'));
if ($optionIndex !== false) {
$answerText = $question['options'][$optionIndex]['text'];
} elseif (!empty($question['extraSettings']->allowOtherAnswer) && strpos($answer, Constants::QUESTION_EXTRASETTINGS_OTHER_PREFIX) === 0) {
} elseif (!empty($question['extraSettings']['allowOtherAnswer']) && strpos($answer, Constants::QUESTION_EXTRASETTINGS_OTHER_PREFIX) === 0) {
$answerText = str_replace(Constants::QUESTION_EXTRASETTINGS_OTHER_PREFIX, "", $answer);
}
} else {

Просмотреть файл

@ -302,7 +302,7 @@ class SubmissionService {
* @return boolean If the submission is valid
*/
public function validateSubmission(array $questions, array $answers): bool {
// Check by questions
foreach ($questions as $question) {
$questionId = $question['id'];
@ -312,7 +312,7 @@ class SubmissionService {
if ($question['isRequired'] &&
(!$questionAnswered ||
!array_filter($answers[$questionId], 'strlen') ||
(!empty($question['extraSettings']->allowOtherAnswer) && !array_filter($answers[$questionId], fn ($value) => $value !== Constants::QUESTION_EXTRASETTINGS_OTHER_PREFIX)))
(!empty($question['extraSettings']['allowOtherAnswer']) && !array_filter($answers[$questionId], fn ($value) => $value !== Constants::QUESTION_EXTRASETTINGS_OTHER_PREFIX)))
) {
return false;
}
@ -334,7 +334,7 @@ class SubmissionService {
}
// Check if all answers are within the possible options
if (in_array($question['type'], Constants::ANSWER_TYPES_PREDEFINED) && empty($question['extraSettings']->allowOtherAnswer)) {
if (in_array($question['type'], Constants::ANSWER_TYPES_PREDEFINED) && empty($question['extraSettings']['allowOtherAnswer'])) {
foreach ($answers[$questionId] as $answer) {
// Search corresponding option, return false if non-existent
if (array_search($answer, array_column($question['options'], 'id')) === false) {

Просмотреть файл

@ -48,7 +48,7 @@
<fieldset :name="name || undefined" :aria-labelledby="titleId">
<NcCheckboxRadioSwitch v-for="(answer) in sortedOptions"
:key="answer.id"
:checked.sync="questionValues"
:checked="questionValues"
:value="answer.id.toString()"
:name="`${id}-answer`"
:type="isUnique ? 'radio' : 'checkbox'"
@ -58,7 +58,7 @@
{{ answer.text }}
</NcCheckboxRadioSwitch>
<div v-if="allowOtherAnswer" class="question__other-answer">
<NcCheckboxRadioSwitch :checked.sync="questionValues"
<NcCheckboxRadioSwitch :checked="questionValues"
:value="valueOtherAnswer"
:name="`${id}-answer`"
:type="isUnique ? 'radio' : 'checkbox'"
@ -149,20 +149,12 @@ export default {
data() {
return {
questionValues: this.values,
inputOtherAnswer: this.valueToInputOtherAnswer(),
QUESTION_EXTRASETTINGS_OTHER_PREFIX: 'system-other-answer:',
}
},
computed: {
placeholderOtherAnswer() {
if (this.readOnly) {
return this.answerType.submitPlaceholder
}
return this.answerType.createPlaceholder
},
contentValid() {
return this.answerType.validate(this)
},
@ -192,6 +184,17 @@ export default {
return this.isUnique ? IconRadioboxBlank : IconCheckboxBlankOutline
},
placeholderOtherAnswer() {
if (this.readOnly) {
return this.answerType.submitPlaceholder
}
return this.answerType.createPlaceholder
},
questionValues() {
return this.isUnique ? this.values?.[0] : this.values
},
titleId() {
return `q${this.$attrs.index}_title`
},
@ -205,7 +208,7 @@ export default {
},
hasRequiredOtherAnswerInput() {
const checkedOtherAnswer = this.questionValues.filter(item => item.startsWith(this.QUESTION_EXTRASETTINGS_OTHER_PREFIX))
const checkedOtherAnswer = this.values.filter(item => item.startsWith(this.QUESTION_EXTRASETTINGS_OTHER_PREFIX))
return checkedOtherAnswer[0] !== undefined
},
},
@ -229,24 +232,22 @@ export default {
inputOtherAnswer() {
if (this.isUnique) {
this.questionValues = this.valueOtherAnswer
this.onChange()
this.onChange(this.valueOtherAnswer)
return
}
this.questionValues = this.questionValues.filter(item => !item.startsWith(this.QUESTION_EXTRASETTINGS_OTHER_PREFIX))
const values = this.values.filter(item => !item.startsWith(this.QUESTION_EXTRASETTINGS_OTHER_PREFIX))
if (this.inputOtherAnswer !== '') {
this.questionValues.push(this.valueOtherAnswer)
values.push(this.valueOtherAnswer)
}
this.onChange()
this.onChange(values)
},
},
methods: {
onChange() {
this.$emit('update:values', this.isUnique ? [this.questionValues] : this.questionValues)
onChange(value) {
this.$emit('update:values', this.isUnique ? [value] : value)
},
/**

Просмотреть файл

@ -572,7 +572,7 @@ class ApiControllerTest extends TestCase {
[
'id' => 2,
'type' => Constants::ANSWER_TYPE_MULTIPLE,
'extraSettings' => (object)['allowOtherAnswer' => true],
'extraSettings' => ['allowOtherAnswer' => true],
'options' => [
['id' => 1, 'text' => 'test id 1'],
['id' => 2, 'text' => 'test id 2'],

Просмотреть файл

@ -564,7 +564,7 @@ class SubmissionServiceTest extends TestCase {
'required-empty-other-answer' => [
// Questions
[
['id' => 1, 'type' => 'multiple_unique', 'isRequired' => true, 'extraSettings' => (object)['allowOtherAnswer' => true], 'options' => [
['id' => 1, 'type' => 'multiple_unique', 'isRequired' => true, 'extraSettings' => ['allowOtherAnswer' => true], 'options' => [
['id' => 3]
]]
],
@ -664,7 +664,7 @@ class SubmissionServiceTest extends TestCase {
['id' => 6]
]],
['id' => 8, 'type' => 'time', 'isRequired' => false],
['id' => 9, 'type' => 'multiple_unique', 'isRequired' => true, 'extraSettings' => (object)['allowOtherAnswer' => true], 'options' => [
['id' => 9, 'type' => 'multiple_unique', 'isRequired' => true, 'extraSettings' => ['allowOtherAnswer' => true], 'options' => [
['id' => 3]
]],
],