aboutsummaryrefslogtreecommitdiff
path: root/resources/vue/components/questionnaires
diff options
context:
space:
mode:
Diffstat (limited to 'resources/vue/components/questionnaires')
-rw-r--r--resources/vue/components/questionnaires/FreetextEdit.vue39
-rw-r--r--resources/vue/components/questionnaires/InputArray.vue279
-rw-r--r--resources/vue/components/questionnaires/LikertEdit.vue189
-rw-r--r--resources/vue/components/questionnaires/QuestionnaireInfoEdit.vue44
-rw-r--r--resources/vue/components/questionnaires/RangescaleEdit.vue216
-rw-r--r--resources/vue/components/questionnaires/VoteEdit.vue51
6 files changed, 239 insertions, 579 deletions
diff --git a/resources/vue/components/questionnaires/FreetextEdit.vue b/resources/vue/components/questionnaires/FreetextEdit.vue
index 29c6f34..58848ed 100644
--- a/resources/vue/components/questionnaires/FreetextEdit.vue
+++ b/resources/vue/components/questionnaires/FreetextEdit.vue
@@ -2,7 +2,7 @@
<div>
<div class="formpart" tabindex="0" ref="autofocus">
{{ $gettext('Frage') }}
- <studip-wysiwyg v-model="val_clone.description" :key="question_id"></studip-wysiwyg>
+ <StudipWysiwyg v-model="val_clone.description" />
</div>
<label>
@@ -13,40 +13,19 @@
</template>
<script>
-import StudipWysiwyg from "../StudipWysiwyg.vue";
+import { QuestionnaireComponent } from '../../mixins/QuestionnaireComponent';
export default {
name: 'freetext-edit',
- components: {
- StudipWysiwyg
+ mixins: [ QuestionnaireComponent ],
+ created() {
+ this.setDefaultValues({
+ description: '',
+ mandatory: '0',
+ });
},
- props: {
- value: {
- type: Object,
- required: false,
- default: function () {
- return {};
- }
- },
- question_id: {
- type: String,
- required: false
- }
- },
- data: function () {
- return {
- val_clone: ''
- };
- },
- mounted: function () {
- this.val_clone = this.value;
+ mounted() {
this.$refs.autofocus.focus();
- },
- watch: {
- value (new_val) {
- this.val_clone = new_val;
- }
}
-
}
</script>
diff --git a/resources/vue/components/questionnaires/InputArray.vue b/resources/vue/components/questionnaires/InputArray.vue
index 37fa6fc..896418f 100644
--- a/resources/vue/components/questionnaires/InputArray.vue
+++ b/resources/vue/components/questionnaires/InputArray.vue
@@ -1,177 +1,170 @@
<template>
<div class="input-array">
<span aria-live="assertive" class="sr-only">{{ assistiveLive }}</span>
- <draggable v-model="options" handle=".dragarea" tag="ol" class="clean options">
- <li v-for="(option, index) in options" :key="index">
- <a class="dragarea"
- v-if="options.length > 1"
- tabindex="0"
- :ref="'draghandle_' + index"
- :title="$gettextInterpolate('Sortierelement für Option %{option}. Drücken Sie die Tasten Pfeil-nach-oben oder Pfeil-nach-unten, um dieses Element in der Liste zu verschieben.', {option: option})"
- @keydown="keyHandler($event, index)">
- <span class="drag-handle"></span>
- </a>
- <input type="text"
- :placeholder="$gettext('Option')"
- :ref="'option_' + index"
- @paste="(ev) => onPaste(ev, index)"
- v-model="options[index]">
- <button class="as-link"
- :title="$gettext('Option löschen')"
- @click.prevent="askForDeletingOption(index)">
- <studip-icon shape="trash" role="clickable" :size="20" alt=""></studip-icon>
- </button>
- <button v-if="index == options.length - 1"
- class="as-link"
- :title="$gettext('Option hinzufügen')"
- @click.prevent="addOption">
- <studip-icon shape="add" role="clickable" :size="20" alt=""></studip-icon>
- </button>
- </li>
- </draggable>
- <studip-dialog
- v-if="askForDeleting"
- :title="$gettext('Bitte bestätigen Sie die Aktion.')"
- :question="$gettext('Wirklich löschen?')"
- :confirmText="$gettext('Ja')"
- :closeText="$gettext('Nein')"
- closeClass="cancel"
- height="180"
- @confirm="deleteOption"
- @close="askForDeleting = false"
- >
- </studip-dialog>
+ <table class="default nohover">
+ <colgroup>
+ <col style="width: 16px">
+ <col>
+ <col v-for="i in additionalColspan" :key="`colspan-${i}`">
+ <col style="width: 24px">
+ </colgroup>
+ <thead>
+ <tr>
+ <th class="dragcolumn"></th>
+ <th>{{ labelPlural }}</th>
+ <slot name="header-cells" />
+ <th class="actions"></th>
+ </tr>
+ </thead>
+ <Draggable v-model="options" handle=".dragarea" tag="tbody" class="statements">
+ <tr v-for="(option, index) in options" :key="index">
+ <td class="dragcolumn">
+ <a class="dragarea"
+ tabindex="0"
+ :title="$gettextInterpolate($gettext(`Sortierelement für %{label} %{option}. Drücken Sie die Tasten Pfeil-nach-oben oder Pfeil-nach-unten, um dieses Element in der Liste zu verschieben.`), {option, label}, true)"
+ @keydown="keyHandler($event, index)"
+ ref="draghandle">
+ <span class="drag-handle"></span>
+ </a>
+ </td>
+ <td>
+ <input type="text"
+ ref="inputs"
+ :placeholder="label"
+ @paste="(ev) => onPaste(ev, index)"
+ v-model="options[index]">
+ </td>
+ <slot name="body-cells" />
+ <td class="actions">
+ <StudipIcon name="delete"
+ shape="trash"
+ :size="20"
+ @click.prevent="deleteOption(index)"
+ :title="$gettextInterpolate($gettext('%{label} löschen'), {label}, true)"
+ />
+ </td>
+ </tr>
+ </Draggable>
+ <tfoot>
+ <tr>
+ <td :colspan="3 + additionalColspan">
+ <button class="as-link"
+ :title="$gettextInterpolate($gettext('%{label} hinzufügen'), {label}, true)"
+ @click.prevent="addOption()">
+ <StudipIcon shape="add" :size="20" alt="" />
+ </button>
+ </td>
+ </tr>
+ </tfoot>
+ </table>
</div>
</template>
<script>
-import StudipIcon from "../StudipIcon.vue";
-import StudipDialog from "../StudipDialog.vue";
-import draggable from 'vuedraggable';
+import Draggable from 'vuedraggable';
+import { $gettext } from '../../../assets/javascripts/lib/gettext';
+
export default {
name: 'input-array',
- components: {
- StudipIcon,
- StudipDialog,
- draggable
- },
+ components: { Draggable },
props: {
- value: {
- type: Array,
- required: false
- }
+ additionalColspan: {
+ type: Number,
+ default: 0,
+ },
+ label: {
+ type: String,
+ default: $gettext('Option'),
+ },
+ labelPlural: {
+ type: String,
+ default: $gettext('Optionen'),
+ },
+ value: Array,
},
- data: function () {
+ data() {
return {
options: [],
- askForDeleting: false,
- indexOfDeletingOption: 0,
- unique_id: null,
- assistiveLive: ''
+ assistiveLive: '',
};
},
methods: {
- addOption: function (val, position) {
- let data = this.value;
- if (val.target) {
- val = '';
- }
- if (typeof position === "undefined") {
- data.push(val || '');
- position = this.value.length - 1
- } else {
- data.splice(position, 0, val || '');
- }
- this.$emit('input', data);
- let v = this;
- this.$nextTick(function () {
- v.$refs['option_' + position][0].focus();
+ addOption(val = '', position = this.options.length) {
+ this.$set(this.options, position, val.trim());
+
+ this.$nextTick(() => {
+ this.$refs.inputs[position].focus();
});
},
- askForDeletingOption: function (index) {
- this.indexOfDeletingOption = index;
- if (this.value[index]) {
- this.askForDeleting = true;
- } else {
- this.deleteOption();
- }
- },
- deleteOption: function () {
- this.$delete(this.value, this.indexOfDeletingOption);
- this.askForDeleting = false;
+ deleteOption(index) {
+ const question = this.options[index] ? this.$gettext('Wirklich löschen?') : true;
+ STUDIP.Dialog.confirm(question).done(() => {
+ this.$delete(this.options, index);
+ });
},
- onPaste: function (ev, position) {
- let data = ev.clipboardData.getData("text").split("\n");
- for (let i = 0; i < data.length; i++) {
- if (data[i].trim()) {
- this.addOption(data[i], position + i);
- }
- }
+ onPaste(ev, position) {
+ ev.clipboardData
+ .getData('text')
+ .split("\n")
+ .filter(str => str.trim().length > 0)
+ .forEach((value, index) => this.addOption(value, position + index));
+ ev.preventDefault();
},
keyHandler(e, index) {
- switch (e.keyCode) {
- case 38: // up
- e.preventDefault();
- if (index > 0) {
- this.moveUp(index);
- this.$nextTick(function () {
- this.$refs['draghandle_' + (index - 1)][0].focus();
- this.assistiveLive = this.$gettextInterpolate(
- 'Aktuelle Position in der Liste: %{pos} von %{listLength}.'
- , {pos: index, listLength: this.options.length}
- );
- });
- }
- break;
- case 40: // down
- e.preventDefault();
- if (index < this.options.length - 1) {
- this.moveDown(index);
- this.$nextTick(function () {
- this.$refs['draghandle_' + (index + 1)][0].focus();
- this.assistiveLive = this.$gettextInterpolate(
- 'Aktuelle Position in der Liste: %{pos} von %{listLength}.'
- , {pos: index + 2, listLength: this.options.length}
- );
- });
- }
- break;
- }
- },
- moveDown: function (index) {
- if (index == this.options.length - 1) {
+ if (e.keyCode !== 38 && e.keyCode !== 40) {
return;
}
- let option = this.options[index];
- this.options[index] = this.options[index + 1];
- this.options[index + 1] = option;
- this.$forceUpdate();
+
+ e.preventDefault();
+
+ const moveUp = e.keyCode === 38;
+
+ this.moveElement(index, moveUp ? -1 : 1).then((newIndex) => {
+ this.assistiveLive = this.$gettextInterpolate(
+ this.$gettext('Aktuelle Position in der Liste: %{pos} von %{listLength}.'),
+ {pos: newIndex + 1, listLength: this.options.length}
+ );
+
+ this.$nextTick(() => {
+ this.$refs['draghandle'][newIndex].focus();
+ });
+ })
},
- moveUp: function (index) {
- if (index === 0) {
- return;
+ moveElement(index, direction) {
+ if (this.options[index + direction] === undefined) {
+ return Promise.resolve(index);
}
- let option = this.options[index];
- this.options[index] = this.options[index - 1];
- this.options[index - 1] = option;
- this.$forceUpdate();
+
+ const indices = [index, index + direction].sort();
+
+ this.options.splice(
+ Math.min(...indices),
+ 2,
+ ...indices.reverse().map(idx => this.options[idx])
+ );
+
+ return Promise.resolve(index + direction);
}
},
- mounted: function () {
- this.options = this.value;
- this.unique_id = 'array_input_' + Math.floor(Math.random() * 100000000);
- },
watch: {
- options (new_data, old_data) {
- if (typeof old_data === 'undefined' || typeof new_data === 'undefined') {
- return;
- }
- this.$emit('input', new_data);
+ options: {
+ handler(current) {
+ this.$emit('input', current);
+ },
+ deep: true
},
- value (new_val) {
- this.options = new_val;
+ value: {
+ handler(current) {
+ this.options = current;
+ },
+ immediate: true
}
}
}
</script>
+<style scoped>
+.input-array input[type="text"] {
+ max-width: unset;
+}
+</style>
diff --git a/resources/vue/components/questionnaires/LikertEdit.vue b/resources/vue/components/questionnaires/LikertEdit.vue
index c87f9fe..736be6b 100644
--- a/resources/vue/components/questionnaires/LikertEdit.vue
+++ b/resources/vue/components/questionnaires/LikertEdit.vue
@@ -1,66 +1,27 @@
<template>
<div class="likert_edit">
-
<div class="formpart" tabindex="0" ref="autofocus">
{{ $gettext('Einleitungstext' )}}
- <studip-wysiwyg v-model="val_clone.description"></studip-wysiwyg>
+ <StudipWysiwyg v-model="val_clone.description" />
</div>
- <span aria-live="assertive" class="sr-only">{{ assistiveLive }}</span>
+ <InputArray v-model="val_clone.statements"
+ :label="$gettext('Aussage')"
+ :label-plural="$gettext('Aussagen')"
+ :additional-colspan="val_clone.options.length"
+ >
+ <template #header-cells>
+ <th v-for="(option, index) in val_clone.options" class="option-cell" :key="index">
+ {{ option }}
+ </th>
+ </template>
- <table class="default nohover">
- <thead>
- <tr>
- <th class="dragcolumn"></th>
- <th>{{ $gettext('Aussagen') }}</th>
- <th v-for="(option, index) in val_clone.options" :key="index">{{ option }}</th>
- <th class="actions"></th>
- </tr>
- </thead>
- <draggable v-model="val_clone.statements" handle=".dragarea" tag="tbody" class="statements">
- <tr v-for="(statement, index) in val_clone.statements" :key="index">
- <td class="dragcolumn">
- <a class="dragarea"
- tabindex="0"
- :title="$gettextInterpolate($gettext('Sortierelement für Aussage %{statement}. Drücken Sie die Tasten Pfeil-nach-oben oder Pfeil-nach-unten, um dieses Element in der Liste zu verschieben.'), {statement: statement})"
- @keydown="keyHandler($event, index)"
- :ref="'draghandle_' + index">
- <span class="drag-handle"></span>
- </a>
- </td>
- <td>
- <input type="text"
- :ref="'statement_' + index"
- :placeholder="$gettext('Aussage')"
- @paste="(ev) => onPaste(ev, index)"
- v-model="val_clone.statements[index]">
- </td>
- <td v-for="(option, index2) in val_clone.options" :key="index2">
- <input type="radio" disabled :title="option">
- </td>
- <td class="actions">
- <studip-icon name="delete"
- shape="trash"
- :size="20"
- @click.prevent="deleteStatement(index)"
- :title="$gettext('Aussage löschen')"
- ></studip-icon>
- </td>
- </tr>
- </draggable>
- <tfoot>
- <tr>
- <td :colspan="val_clone.options.length + 3">
- <studip-icon name="add"
- shape="add"
- :size="20"
- @click.prevent="addStatement()"
- :title="$gettext('Aussage hinzufügen')"
- ></studip-icon>
- </td>
- </tr>
- </tfoot>
- </table>
+ <template #body-cells>
+ <td v-for="(option, index) in val_clone.options" class="option-cell" :key="index">
+ <input type="radio" disabled :title="option">
+ </td>
+ </template>
+ </InputArray>
<label>
<input type="checkbox" v-model.number="val_clone.mandatory" true-value="1" false-value="0">
@@ -73,17 +34,18 @@
<div>
<div>{{ $gettext('Antwortmöglichkeiten konfigurieren') }}</div>
- <input-array v-model="val_clone.options"></input-array>
+ <InputArray v-model="val_clone.options" />
</div>
</div>
</template>
<script>
-import draggable from 'vuedraggable';
-import InputArray from "./InputArray.vue";
import { $gettext } from '../../../assets/javascripts/lib/gettext';
+import InputArray from "./InputArray.vue";
+import { QuestionnaireComponent } from '../../mixins/QuestionnaireComponent';
-const default_value = () => ({
+// This is necesssar since $gettext does not seem to work in data() or created()
+const default_values = () => ({
description: '',
statements: ['', '', '', ''],
mandatory: 0,
@@ -96,115 +58,16 @@ const default_value = () => ({
$gettext('trifft nicht zu'),
],
});
+
export default {
name: 'likert-edit',
- components: {
- draggable,
- InputArray
- },
- props: {
- value: {
- type: Object,
- required: false,
- default() {
- return {...default_value()};
- }
- },
- question_id: {
- type: String,
- required: false
- }
- },
- data() {
- return {
- val_clone: null,
- assistiveLive: ''
- };
- },
- methods: {
- addStatement(val = '', position = null) {
- if (position === null) {
- this.val_clone.statements.push(val || '');
- } else {
- this.val_clone.statements.splice(position, 0, val || '');
- }
- this.$nextTick(() => {
- this.$refs['statement_' + (this.val_clone.statements.length - 1)][0].focus();
- });
- },
- deleteStatement(index) {
- STUDIP.Dialog.confirm(this.$gettext('Wirklich löschen?')).done(() => {
- this.$delete(this.val_clone.statements, index);
- });
- },
- onPaste(ev, position) {
- let data = ev.clipboardData.getData("text").split("\n");
- for (let i = 0; i < data.length; i++) {
- if (data[i].trim()) {
- this.addStatement(data[i], position + i);
- }
- }
- },
- keyHandler(e, index) {
- switch (e.keyCode) {
- case 38: // up
- e.preventDefault();
- if (index > 0) {
- this.moveUp(index);
- this.$nextTick(() => {
- this.$refs['draghandle_' + (index - 1)][0].focus();
- this.assistiveLive = this.$gettextInterpolate(
- this.$gettext('Aktuelle Position in der Liste: %{pos} von %{listLength}.'),
- {pos: index, listLength: this.val_clone.statements.length}
- );
- });
- }
- break;
- case 40: // down
- e.preventDefault();
- if (index < this.val_clone.statements.length - 1) {
- this.moveDown(index);
- this.$nextTick(() => {
- this.$refs['draghandle_' + (index + 1)][0].focus();
- this.assistiveLive = this.$gettextInterpolate(
- this.$gettext('Aktuelle Position in der Liste: %{pos} von %{listLength}.'),
- {pos: index + 2, listLength: this.val_clone.statements.length}
- );
- });
- }
- break;
- }
- },
- moveDown(index) {
- this.val_clone.statements.splice(
- index,
- 2,
- this.val_clone.statements[index + 1],
- this.val_clone.statements[index]
- )
- },
- moveUp(index) {
- this.val_clone.statements.splice(
- index - 1,
- 2,
- this.val_clone.statements[index],
- this.val_clone.statements[index - 1]
- )
- }
- },
+ components: { InputArray },
+ mixins: [ QuestionnaireComponent ],
created() {
- this.val_clone = Object.assign({}, default_value(), this.value ?? {});
+ this.setDefaultValues(default_values());
},
mounted() {
this.$refs.autofocus.focus();
- },
- watch: {
- val_clone: {
- handler(current) {
- this.$emit('input', current);
- },
- deep: true
- }
}
}
</script>
diff --git a/resources/vue/components/questionnaires/QuestionnaireInfoEdit.vue b/resources/vue/components/questionnaires/QuestionnaireInfoEdit.vue
index bc5e829..83d5fa2 100644
--- a/resources/vue/components/questionnaires/QuestionnaireInfoEdit.vue
+++ b/resources/vue/components/questionnaires/QuestionnaireInfoEdit.vue
@@ -8,39 +8,26 @@
<div class="formpart">
{{ $gettext('Hinweistext (optional)') }}
- <studip-wysiwyg v-model="val_clone.description" :key="question_id"></studip-wysiwyg>
+ <StudipWysiwyg v-model="val_clone.description" />
</div>
</div>
</template>
<script>
-import StudipWysiwyg from "../StudipWysiwyg.vue";
+import { QuestionnaireComponent } from '../../mixins/QuestionnaireComponent';
export default {
name: 'questionnaire-info-edit',
- components: {
- StudipWysiwyg
+ mixins: [ QuestionnaireComponent ],
+ created() {
+ this.setDefaultValues({
+ url: '',
+ description: ''
+ });
},
- props: {
- value: {
- type: Object,
- required: false,
- default() {
- return {
- url: '',
- description: ''
- };
- }
- },
- question_id: {
- type: String,
- required: false
- }
- },
- data () {
- return {
- val_clone: this.value,
- };
+ mounted() {
+ this.$refs.infoUrl.focus();
+ this.checkValidity();
},
methods: {
checkValidity() {
@@ -53,15 +40,6 @@ export default {
this.$refs.infoUrl.reportValidity();
}
}
- },
- mounted() {
- this.$refs.infoUrl.focus();
- this.checkValidity();
- },
- watch: {
- value (new_val) {
- this.val_clone = new_val;
- }
}
}
</script>
diff --git a/resources/vue/components/questionnaires/RangescaleEdit.vue b/resources/vue/components/questionnaires/RangescaleEdit.vue
index 91aec1c..cd7ce3b 100644
--- a/resources/vue/components/questionnaires/RangescaleEdit.vue
+++ b/resources/vue/components/questionnaires/RangescaleEdit.vue
@@ -3,68 +3,25 @@
<div class="formpart" tabindex="0" ref="autofocus">
{{ $gettext('Einleitungstext') }}
- <studip-wysiwyg v-model="val_clone.description"></studip-wysiwyg>
+ <StudipWysiwyg v-model="val_clone.description" />
</div>
- <span aria-live="assertive" class="sr-only">{{ assistiveLive }}</span>
-
- <table class="default nohover">
- <thead>
- <tr>
- <th class="dragcolumn"></th>
- <th>{{ $gettext('Aussagen') }}</th>
- <th v-for="i in (val_clone.maximum - val_clone.minimum + 1)" :key="i" class="number">{{ (val_clone.minimum - 1 + i) }}</th>
- <th v-if="val_clone.alternative_answer.trim().length > 0">{{ val_clone.alternative_answer }}</th>
- <th class="actions"></th>
- </tr>
- </thead>
- <draggable v-model="val_clone.statements" handle=".dragarea" tag="tbody" class="statements">
- <tr v-for="(statement, index) in val_clone.statements" :key="index">
- <td class="dragcolumn">
- <a class="dragarea"
- tabindex="0"
- :title="$gettextInterpolate($gettext('Sortierelement für Aussage %{statement}. Drücken Sie die Tasten Pfeil-nach-oben oder Pfeil-nach-unten, um dieses Element in der Liste zu verschieben.'), {statement: statement})"
- @keydown="keyHandler($event, index)"
- :ref="'draghandle_' + index">
- <span class="drag-handle"></span>
- </a>
- </td>
- <td>
- <input type="text"
- :ref="'statement_' + index"
- :placeholder="$gettext('Aussage')"
- @paste="(ev) => onPaste(ev, index)"
- v-model="val_clone.statements[index]">
- </td>
- <td v-for="i in (val_clone.maximum - val_clone.minimum + 1)" :key="i">
- <input type="radio" disabled :title="i + val_clone.minimum - 1">
- </td>
- <td v-if="val_clone.alternative_answer.trim().length > 0">
- <input type="radio" disabled :title="val_clone.alternative_answer">
- </td>
- <td class="actions">
- <studip-icon name="delete"
- shape="trash"
- :size="20"
- @click.prevent="deleteStatement(index)"
- :title="$gettext('Aussage löschen')"
- ></studip-icon>
- </td>
- </tr>
- </draggable>
- <tfoot>
- <tr>
- <td :colspan="val_clone.maximum - val_clone.minimum + 4 + (val_clone.alternative_answer.trim().length > 0 ? 1 : 0)">
- <studip-icon name="add"
- shape="add"
- :size="20"
- @click.prevent="addStatement()"
- :title="$gettext('Aussage hinzufügen')"
- ></studip-icon>
- </td>
- </tr>
- </tfoot>
- </table>
+ <InputArray v-model="val_clone.statements"
+ :label="$gettext('Aussage')"
+ :label-plural="$gettext('Aussagen')"
+ :additional-colspan="options.length"
+ >
+ <template #header-cells>
+ <th v-for="(option, index) in options" class="option-cell" :key="index">
+ {{ option }}
+ </th>
+ </template>
+ <template #body-cells>
+ <td v-for="(option, index) in options" class="option-cell" :key="index">
+ <input type="radio" disabled :title="option">
+ </td>
+ </template>
+ </InputArray>
<label>
<input type="checkbox" v-model.number="val_clone.mandatory" true-value="1" false-value="0">
@@ -82,135 +39,48 @@
<label>
{{ $gettext('Minimum') }}
- <input type="number" v-model.number="val_clone.minimum" min="1">
+ <input type="number" v-model.number="val_clone.minimum" min="1" :max="val_clone.maximum">
</label>
<label>
{{ $gettext('Ausweichantwort (leer lassen für keine)') }}
- <input type="text" v-model="val_clone.alternative_answer">
+ <input type="text" v-model.trim="val_clone.alternative_answer">
</label>
</div>
</template>
<script>
-import draggable from 'vuedraggable';
+import InputArray from './InputArray.vue';
+import { QuestionnaireComponent } from '../../mixins/QuestionnaireComponent';
-const default_value = () => ({
- description: '',
- statements: ['', '', '', ''],
- mandatory: 0,
- randomize: 0,
- minimum: 1,
- maximum: 5,
- alternative_answer: ''
-});
export default {
- name: 'likert-edit',
- components: {
- draggable,
- },
- props: {
- value: {
- type: Object,
- required: false,
- default() {
- return default_value();
- }
- },
- question_id: {
- type: String,
- required: false
- }
- },
- data() {
- return {
- val_clone: null,
- assistiveLive: ''
- };
- },
- methods: {
- addStatement(val = '', position = null) {
- if (position === null) {
- this.val_clone.statements.push(val || '');
- } else {
- this.val_clone.statements.splice(position, 0, val || '');
- }
- this.$nextTick(() => {
- this.$refs['statement_' + (this.value.statements.length - 1)][0].focus();
- });
- },
- deleteStatement(index) {
- STUDIP.Dialog.confirm(this.$gettext('Wirklich löschen?')).done(() => {
- this.$delete(this.value.statements, index);
- });
- },
- onPaste(ev, position) {
- let data = ev.clipboardData.getData('text').split("\n");
- for (let i = 0; i < data.length; i++) {
- if (data[i].trim()) {
- this.addStatement(data[i], position + i);
- }
- }
- },
- keyHandler(e, index) {
- switch (e.keyCode) {
- case 38: // up
- e.preventDefault();
- if (index > 0) {
- this.moveUp(index);
- this.$nextTick(() => {
- this.$refs['draghandle_' + (index - 1)][0].focus();
- this.assistiveLive = this.$gettextInterpolate(
- this.$gettext('Aktuelle Position in der Liste: %{pos} von %{listLength}.'),
- {pos: index, listLength: this.val_clone.statements.length}
- );
- });
- }
- break;
- case 40: // down
- e.preventDefault();
- if (index < this.val_clone.statements.length - 1) {
- this.moveDown(index);
- this.$nextTick(() => {
- this.$refs['draghandle_' + (index + 1)][0].focus();
- this.assistiveLive = this.$gettextInterpolate(
- this.$gettext('Aktuelle Position in der Liste: %{pos} von %{listLength}.'),
- {pos: index + 2, listLength: this.val_clone.statements.length}
- );
- });
- }
- break;
- }
- },
- moveDown(index) {
- this.val_clone.statements.splice(
- index,
- 2,
- this.val_clone.statements[index + 1],
- this.val_clone.statements[index]
- );
- },
- moveUp(index) {
- this.val_clone.statements.splice(
- index - 1,
- 2,
- this.val_clone.statements[index],
- this.val_clone.statements[index - 1]
- );
- },
- },
+ name: 'rangescale-edit',
+ components: { InputArray },
+ mixins: [ QuestionnaireComponent ],
created() {
- this.val_clone = Object.assign({}, default_value(), this.value ?? {});
+ this.setDefaultValues({
+ alternative_answer: '',
+ description: '',
+ mandatory: 0,
+ maximum: 5,
+ minimum: 1,
+ randomize: 0,
+ statements: ['', '', '', '']
+ });
},
mounted() {
this.$refs.autofocus.focus();
},
- watch: {
- val_clone: {
- handler(current) {
- this.$emit('input', current);
- },
- deep: true
+ computed: {
+ options() {
+ let result = [];
+ for (let i = this.val_clone.minimum; i <= this.val_clone.maximum; i += 1) {
+ result.push(i);
+ }
+ if (this.val_clone.alternative_answer.length > 0) {
+ result.push(this.val_clone.alternative_answer);
+ }
+ return result;
}
}
}
diff --git a/resources/vue/components/questionnaires/VoteEdit.vue b/resources/vue/components/questionnaires/VoteEdit.vue
index 9acb01f..1d6d9cf 100644
--- a/resources/vue/components/questionnaires/VoteEdit.vue
+++ b/resources/vue/components/questionnaires/VoteEdit.vue
@@ -2,10 +2,10 @@
<div class="vote_edit">
<div class="formpart" tabindex="0" ref="autofocus">
{{ $gettext('Frage') }}
- <studip-wysiwyg v-model="val_clone.description" :key="question_id"></studip-wysiwyg>
+ <StudipWysiwyg v-model="val_clone.description" />
</div>
- <input-array v-model="val_clone.options"></input-array>
+ <InputArray v-model="val_clone.options" />
<label>
<input type="checkbox" v-model.number="val_clone.multiplechoice" true-value="1" false-value="0">
@@ -24,47 +24,24 @@
</template>
<script>
-import StudipWysiwyg from "../StudipWysiwyg.vue";
import InputArray from "./InputArray.vue";
+import { QuestionnaireComponent } from '../../mixins/QuestionnaireComponent';
export default {
name: 'vote-edit',
- components: {
- StudipWysiwyg,
- InputArray
+ components: { InputArray },
+ mixins: [QuestionnaireComponent],
+ created() {
+ this.setDefaultValues({
+ description: '',
+ mandatory: '0',
+ multiplechoice: '1',
+ options: ['', '', '', ''],
+ randomize: '0',
+ });
},
- props: {
- value: {
- type: Object,
- required: false,
- default: function () {
- return {};
- }
- },
- question_id: {
- type: String,
- required: false
- }
- },
- data: function () {
- return {
- val_clone: {}
- };
- },
- mounted: function () {
- this.val_clone = this.value;
- if (!this.value.description) {
- this.$emit('input', {
- multiplechoice: 1,
- options: ['', '', '', '']
- });
- }
+ mounted() {
this.$refs.autofocus.focus();
- },
- watch: {
- value (new_val) {
- this.val_clone = new_val;
- }
}
}
</script>