diff --git a/resources/vue/components/courseware/CoursewareTasksDialogDistribute.vue b/resources/vue/components/courseware/CoursewareTasksDialogDistribute.vue index 9de8f3d540a291b0c4171e7cd105e2ff06e2fcf0..36ad58b01a56929874d0cb608294f2afec2ff51e 100644 --- a/resources/vue/components/courseware/CoursewareTasksDialogDistribute.vue +++ b/resources/vue/components/courseware/CoursewareTasksDialogDistribute.vue @@ -22,8 +22,12 @@ :key="'radio-' + unit.id" :aria-description="unit.element.attributes.title" /> - <label @click="selectedSourceUnit = unit" :key="'label-' + unit.id" :for="'cw-task-dist-source-unit' + unit.id"> - <div class="icon"><studip-icon shape="courseware" size="32"/></div> + <label + @click="selectedSourceUnit = unit" + :key="'label-' + unit.id" + :for="'cw-task-dist-source-unit' + unit.id" + > + <div class="icon"><studip-icon shape="courseware" size="32" /></div> <div class="text">{{ unit.element.attributes.title }}</div> <studip-icon shape="radiobutton-unchecked" size="24" class="unchecked" /> <studip-icon shape="check-circle" size="24" class="check" /> @@ -40,32 +44,27 @@ <template v-slot:task> <form v-if="selectedSourceUnit" class="default" @submit.prevent=""> <fieldset class="radiobutton-set"> - <input id="cw-task-dist-task" type="radio" :checked="selectedTaskIsTask" :aria-description="selectedTaskTitle"/> - <label for="cw-task-dist-task" @click="e => e.preventDefault()"> - <div class="icon"><studip-icon shape="content2" size="32"/></div> + <input + id="cw-task-dist-task" + type="radio" + :checked="selectedTaskIsTask" + :aria-description="selectedTaskTitle" + /> + <label for="cw-task-dist-task" @click="(e) => e.preventDefault()"> + <div class="icon"><studip-icon shape="content2" size="32" /></div> <div class="text">{{ selectedTaskTitle }}</div> <studip-icon v-if="selectedTaskIsTask" shape="check-circle" size="24" class="check" /> <studip-icon v-else shape="decline-circle" size="24" class="unchecked" /> </label> </fieldset> - <button - v-if="selectedTaskParent" - class="button" - @click="selectTask(selectedTaskParent.id)" - > - {{ $gettext('zurück zur übergeordneten Seite') }} + <button v-if="selectedTaskParent" class="button" @click="selectTask(selectedTaskParent.id)"> + {{ $gettext('zurück zur übergeordneten Seite') }} </button> <fieldset> <legend>{{ $gettext('Unterseiten') }}</legend> <ul class="cw-element-selector-list"> - <li - v-for="child in taskChildren" - :key="child.id" - > - <button - class="cw-element-selector-item" - @click="selectTask(child.id)" - > + <li v-for="child in taskChildren" :key="child.id"> + <button class="cw-element-selector-item" @click="selectTask(child.id)"> {{ child.attributes.title }} </button> </li> @@ -76,19 +75,21 @@ </fieldset> </form> <courseware-companion-box - v-else - mood="pointing" - :msgCompanion="$gettext('Bitte wählen Sie ein Lernmaterial aus.')" + v-else + mood="pointing" + :msgCompanion="$gettext('Bitte wählen Sie ein Lernmaterial aus.')" /> </template> <template v-slot:tasksettings> <form v-if="selectedTaskIsTask" class="default" @submit.prevent=""> <label> - <span>{{ $gettext('Aufgabentitel') }}</span><span aria-hidden="true" class="wizard-required">*</span> - <input type="text" v-model="taskTitle" required/> + <span>{{ $gettext('Aufgabentitel') }}</span> + <span aria-hidden="true" class="wizard-required">*</span> + <input type="text" v-model="taskTitle" required /> </label> <label> - <span>{{ $gettext('Abgabefrist') }}</span><span aria-hidden="true" class="wizard-required">*</span> + <span>{{ $gettext('Abgabefrist') }}</span> + <span aria-hidden="true" class="wizard-required">*</span> <input type="date" v-model="submissionDate" /> </label> <label> @@ -118,8 +119,12 @@ :key="'radio-' + unit.id" :aria-description="unit.element.attributes.title" /> - <label @click="selectedTargetUnit = unit" :key="'label-' + unit.id" :for="'cw-task-dist-target-unit' + unit.id"> - <div class="icon"><studip-icon shape="courseware" size="32"/></div> + <label + @click="selectedTargetUnit = unit" + :key="'label-' + unit.id" + :for="'cw-task-dist-target-unit' + unit.id" + > + <div class="icon"><studip-icon shape="courseware" size="32" /></div> <div class="text">{{ unit.element.attributes.title }}</div> <studip-icon shape="radiobutton-unchecked" size="24" class="unchecked" /> <studip-icon shape="check-circle" size="24" class="check" /> @@ -141,9 +146,14 @@ <template v-slot:targetelement> <form v-if="selectedTargetUnit && selectedTaskIsTask" class="default" @submit.prevent=""> <fieldset class="radiobutton-set"> - <input id="cw-task-dist-target-element" type="radio" checked :aria-description="selectedTargetElementTitle"/> - <label for="cw-task-dist-target-element" @click="e => e.preventDefault()"> - <div class="icon"><studip-icon shape="content2" size="32"/></div> + <input + id="cw-task-dist-target-element" + type="radio" + checked + :aria-description="selectedTargetElementTitle" + /> + <label for="cw-task-dist-target-element" @click="(e) => e.preventDefault()"> + <div class="icon"><studip-icon shape="content2" size="32" /></div> <div class="text">{{ selectedTargetElementTitle }}</div> <studip-icon shape="check-circle" size="24" class="check" /> </label> @@ -153,19 +163,13 @@ class="button" @click="selectTargetElement(selectedTargetElementParent.id)" > - {{ $gettext('zurück zur übergeordneten Seite') }} + {{ $gettext('zurück zur übergeordneten Seite') }} </button> <fieldset> <legend>{{ $gettext('Unterseiten') }}</legend> <ul class="cw-element-selector-list"> - <li - v-for="child in targetChildren" - :key="child.id" - > - <button - class="cw-element-selector-item" - @click="selectTargetElement(child.id)" - > + <li v-for="child in targetChildren" :key="child.id"> + <button class="cw-element-selector-item" @click="selectTargetElement(child.id)"> {{ child.attributes.title }} </button> </li> @@ -195,7 +199,7 @@ <option value="group">{{ $gettext('Gruppen') }}</option> </select> </label> - <template v-if="taskSolverType === 'autor'" > + <template v-if="taskSolverType === 'autor'"> <courseware-companion-box v-show="autor_members.length === 0" :msgCompanion="$gettext('Es wurden keine Studierenden in dieser Veranstaltung gefunden.')" @@ -204,13 +208,30 @@ <table v-show="autor_members.length > 0" class="default"> <thead> <tr> - <th><input type="checkbox" v-model="bulkSelectAutors"/></th> + <th> + <input + type="checkbox" + v-model="bulkSelectAutors" + :aria-label="$gettext('Alle Studierende auswählen')" + /> + </th> <th>{{ $gettext('Name') }}</th> </tr> </thead> <tbody> <tr v-for="user in autor_members" :key="user.user_id"> - <td><input type="checkbox" v-model="selectedAutors" :value="user.user_id" /></td> + <td> + <input + type="checkbox" + v-model="selectedAutors" + :value="user.user_id" + :aria-label=" + $gettextInterpolate($gettext('%{userName} auswählen'), { + userName: user.formattedname, + }) + " + /> + </td> <td>{{ user.formattedname }}</td> </tr> </tbody> @@ -225,13 +246,30 @@ <table v-show="groups.length > 0" class="default"> <thead> <tr> - <th><input type="checkbox" v-model="bulkSelectGroups"/></th> + <th> + <input + type="checkbox" + v-model="bulkSelectGroups" + :aria-label="$gettext('Alle Gruppen auswählen')" + /> + </th> <th>{{ $gettext('Gruppenname') }}</th> </tr> </thead> <tbody> <tr v-for="group in groups" :key="group.id"> - <td><input type="checkbox" v-model="selectedGroups" :value="group.id" /></td> + <td> + <input + type="checkbox" + v-model="selectedGroups" + :value="group.id" + :aria-label=" + $gettextInterpolate($gettext('%{groupName} auswählen'), { + groupName: group.name, + }) + " + /> + </td> <td>{{ group.name }}</td> </tr> </tbody> @@ -256,7 +294,7 @@ import CoursewareCompanionBox from './CoursewareCompanionBox.vue'; import StudipWizardDialog from './../StudipWizardDialog.vue'; -import { mapActions, mapGetters } from 'vuex' +import { mapActions, mapGetters } from 'vuex'; export default { name: 'courseware-tasks-dialog-distribute', @@ -267,18 +305,66 @@ export default { data() { return { wizardSlots: [ - { id: 1, valid: false, name: 'sourceunit', title: this.$gettext('Lernmaterial'), icon: 'courseware', - description: this.$gettext('Wählen Sie das Lernmaterial aus, in dem sich die Aufgabenvorlage befindet. Es sind nur Lernmaterialien aus Ihrem Arbeitsplatz aufgeführt.') }, - { id: 2, valid: false, name: 'task', title: this.$gettext('Aufgabenvorlage'), icon: 'category-task', - description: this.$gettext('Wählen Sie die zu verteilende Aufgabenvorlage aus. Vorausgewählt ist die oberste Seite des ausgewählten Lernmaterials. Unterseiten erreichen Sie über die Schaltflächen im Bereich "Unterseiten". Sie können über die "zurück zu" Schaltfläche das übergeordnete Element anwählen. Die ausgewählte Aufgabenvorlage ist mit einem Kontrollhaken markiert. Nur Seiten der Kategorie "Aufgabenvorlage" können verteilt werden.') }, - { id: 3, valid: false, name: 'tasksettings', title: this.$gettext('Aufgabeneinstellungen'), icon: 'settings', - description: this.$gettext('Wählen Sie hier die Einstellungen der Aufgabe. Es muss ein Aufgabentitel und eine Abgabenfrist gesetzt werden.') }, - { id: 4, valid: false, name: 'targetunit', title: this.$gettext('Ziel-Lernmaterial'), icon: 'courseware', - description: this.$gettext('Wählen Sie hier das Lernmaterial aus, in das die Aufgabe verteilt werden soll. Zum Bearbeiten der Aufgabe müssen Lernende Zugriff auf das Lernmaterial haben. Prüfen Sie gegebenenfalls die Leserechte und die Sichtbarkeit.') }, - { id: 5, valid: false, name: 'targetelement', title: this.$gettext('Zielseite'), icon: 'content2', - description: this.$gettext('Wählen Sie hier die Seite aus unterhalb der die Aufgabe verteilt werden soll. Zum bearbeiten der Aufgabe müssen Lernende Zugriff auf die Seite haben. Prüfen Sie ggf. die Leserechte und die Sichtbarkeit.') }, - { id: 6, valid: false, name: 'solver', title: this.$gettext('Aufgabe zuweisen'), icon: 'group3', - description: this.$gettext('Wählen Sie hier aus, an wen Sie die Aufgaben verteilen möchten. Aufgaben können entweder an Gruppen oder einzelne Teilnehmende verteilt werden. Über die Checkbox im Titel der Tabelle können Sie alles aus- bzw. abwählen.') }, + { + id: 1, + valid: false, + name: 'sourceunit', + title: this.$gettext('Lernmaterial'), + icon: 'courseware', + description: this.$gettext( + 'Wählen Sie das Lernmaterial aus, in dem sich die Aufgabenvorlage befindet. Es sind nur Lernmaterialien aus Ihrem Arbeitsplatz aufgeführt.' + ), + }, + { + id: 2, + valid: false, + name: 'task', + title: this.$gettext('Aufgabenvorlage'), + icon: 'category-task', + description: this.$gettext( + 'Wählen Sie die zu verteilende Aufgabenvorlage aus. Vorausgewählt ist die oberste Seite des ausgewählten Lernmaterials. Unterseiten erreichen Sie über die Schaltflächen im Bereich "Unterseiten". Sie können über die "zurück zu" Schaltfläche das übergeordnete Element anwählen. Die ausgewählte Aufgabenvorlage ist mit einem Kontrollhaken markiert. Nur Seiten der Kategorie "Aufgabenvorlage" können verteilt werden.' + ), + }, + { + id: 3, + valid: false, + name: 'tasksettings', + title: this.$gettext('Aufgabeneinstellungen'), + icon: 'settings', + description: this.$gettext( + 'Wählen Sie hier die Einstellungen der Aufgabe. Es muss ein Aufgabentitel und eine Abgabenfrist gesetzt werden.' + ), + }, + { + id: 4, + valid: false, + name: 'targetunit', + title: this.$gettext('Ziel-Lernmaterial'), + icon: 'courseware', + description: this.$gettext( + 'Wählen Sie hier das Lernmaterial aus, in das die Aufgabe verteilt werden soll. Zum Bearbeiten der Aufgabe müssen Lernende Zugriff auf das Lernmaterial haben. Prüfen Sie gegebenenfalls die Leserechte und die Sichtbarkeit.' + ), + }, + { + id: 5, + valid: false, + name: 'targetelement', + title: this.$gettext('Zielseite'), + icon: 'content2', + description: this.$gettext( + 'Wählen Sie hier die Seite aus unterhalb der die Aufgabe verteilt werden soll. Zum bearbeiten der Aufgabe müssen Lernende Zugriff auf die Seite haben. Prüfen Sie ggf. die Leserechte und die Sichtbarkeit.' + ), + }, + { + id: 6, + valid: false, + name: 'solver', + title: this.$gettext('Aufgabe zuweisen'), + icon: 'group3', + description: this.$gettext( + 'Wählen Sie hier aus, an wen Sie die Aufgaben verteilen möchten. Aufgaben können entweder an Gruppen oder einzelne Teilnehmende verteilt werden. Über die Checkbox im Titel der Tabelle können Sie alles aus- bzw. abwählen.' + ), + }, ], selectedSourceUnit: null, taskTitle: '', @@ -293,7 +379,7 @@ export default { selectedGroups: [], bulkSelectGroups: false, requirements: [], - } + }; }, computed: { ...mapGetters({ @@ -314,8 +400,8 @@ export default { return this.selectedSourceUnit?.relationships?.['structural-element']?.data?.id; }, sourceUnits() { - let units = this.coursewareUnits.filter(unit => unit.relationships.range.data.id === this.userId); - units.forEach(unit => { + let units = this.coursewareUnits.filter((unit) => unit.relationships.range.data.id === this.userId); + units.forEach((unit) => { unit.element = this.getUnitElement(unit); }); @@ -328,8 +414,8 @@ export default { return this.selectedTargetUnit?.relationships?.['structural-element']?.data?.id; }, targetUnits() { - let units = this.coursewareUnits.filter(unit => unit.relationships.range.data.id === this.context.id); - units.forEach(unit => { + let units = this.coursewareUnits.filter((unit) => unit.relationships.range.data.id === this.context.id); + units.forEach((unit) => { unit.element = this.getUnitElement(unit); }); @@ -343,8 +429,8 @@ export default { }, selectedTaskParent() { let parentData = this.selectedTask?.relationships?.parent?.data; - if (parentData){ - return this.structuralElementById({id: parentData.id}); + if (parentData) { + return this.structuralElementById({ id: parentData.id }); } return null; @@ -360,7 +446,7 @@ export default { let children = []; if (this.selectedTask) { children = this.structuralElements.filter( - element => element.relationships.parent?.data?.id === this.selectedTask.id + (element) => element.relationships.parent?.data?.id === this.selectedTask.id ); } @@ -371,8 +457,8 @@ export default { }, selectedTargetElementParent() { let parentData = this.selectedTargetElement?.relationships?.parent?.data; - if (parentData){ - return this.structuralElementById({id: parentData.id}); + if (parentData) { + return this.structuralElementById({ id: parentData.id }); } return null; @@ -388,7 +474,7 @@ export default { let children = []; if (this.selectedTargetElement) { children = this.structuralElements.filter( - element => element.relationships.parent?.data?.id === this.selectedTargetElement.id + (element) => element.relationships.parent?.data?.id === this.selectedTargetElement.id ); } @@ -444,7 +530,11 @@ export default { mounted() { this.initWizardData(); const parent = { type: 'courses', id: this.context.id }; - this.loadCourseMemberships({ parent, relationship: 'memberships', options: { include: 'user', 'page[offset]': 0, 'page[limit]': 10000, 'filter[permission]': 'autor' } }); + this.loadCourseMemberships({ + parent, + relationship: 'memberships', + options: { include: 'user', 'page[offset]': 0, 'page[limit]': 10000, 'filter[permission]': 'autor' }, + }); this.loadCourseStatusGroups({ parent, relationship: 'status-groups' }); }, methods: { @@ -467,15 +557,15 @@ export default { this.validate(); }, getUnitElement(unit) { - return this.structuralElementById({id: unit.relationships['structural-element'].data.id}); + return this.structuralElementById({ id: unit.relationships['structural-element'].data.id }); }, selectTask(id) { - this.selectedTask = this.structuralElementById({id: id}); - this.loadStructuralElement({id: id, options: {include: 'children'}}); + this.selectedTask = this.structuralElementById({ id: id }); + this.loadStructuralElement({ id: id, options: { include: 'children' } }); }, selectTargetElement(id) { - this.selectedTargetElement = this.structuralElementById({id: id}); - this.loadStructuralElement({id: id, options: {include: 'children'}}); + this.selectedTargetElement = this.structuralElementById({ id: id }); + this.loadStructuralElement({ id: id, options: { include: 'children' } }); }, async distributeTask() { this.setShowTasksDistributeDialog(false); @@ -515,7 +605,6 @@ export default { await this.createTaskGroup({ taskGroup }); this.companionSuccess({ info: this.$gettext('Aufgaben wurden verteilt.') }); - }, validateSolvers() { if ( @@ -558,15 +647,18 @@ export default { if (!this.validateSolvers()) { this.requirements.push({ slot: this.wizardSlots[5], text: this.$gettext('Aufgabe zuweisen') }); } - } + }, }, watch: { async selectedSourceUnit(newUnit) { this.validate(); if (newUnit !== null) { this.wizardSlots[0].valid = true; - await this.loadStructuralElement({id: this.selectedSourceUnitRootId, options: {include: 'children'}}); - this.selectedTask = this.structuralElementById({id: this.selectedSourceUnitRootId}); + await this.loadStructuralElement({ + id: this.selectedSourceUnitRootId, + options: { include: 'children' }, + }); + this.selectedTask = this.structuralElementById({ id: this.selectedSourceUnitRootId }); } else { this.wizardSlots[0].valid = false; } @@ -583,8 +675,11 @@ export default { this.validate(); if (newUnit !== null) { this.wizardSlots[3].valid = true; - await this.loadStructuralElement({id: this.selectedTargetUnitRootId, options: {include: 'children'}}); - this.selectedTargetElement = this.structuralElementById({id: this.selectedTargetUnitRootId}); + await this.loadStructuralElement({ + id: this.selectedTargetUnitRootId, + options: { include: 'children' }, + }); + this.selectedTargetElement = this.structuralElementById({ id: this.selectedTargetUnitRootId }); } else { this.wizardSlots[3].valid = false; } @@ -597,14 +692,12 @@ export default { this.wizardSlots[4].valid = false; } }, - taskTitle() { this.validate(); }, submissionDate() { this.validate(); }, - selectedAutors() { this.validate(); }, @@ -616,18 +709,18 @@ export default { }, bulkSelectAutors(newState) { if (newState) { - this.selectedAutors = this.autor_members.map( autor => autor.user_id); + this.selectedAutors = this.autor_members.map((autor) => autor.user_id); } else { this.selectedAutors = []; } }, bulkSelectGroups(newState) { if (newState) { - this.selectedGroups = this.groups.map( group => group.id); + this.selectedGroups = this.groups.map((group) => group.id); } else { this.selectedGroups = []; } - } - } -} + }, + }, +}; </script>