aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRon Lucke <lucke@elan-ev.de>2024-02-14 07:27:34 +0000
committerRon Lucke <lucke@elan-ev.de>2024-02-14 07:27:34 +0000
commit092e0659643e58d91086d2149a29b52648f38e85 (patch)
tree1fc9883db237ab7b2dfb61a9a695f97eb4726307
parentaa59e3ca07cf0cd9cb82e2cffa128d376f4a607c (diff)
fix #2768
Closes #2768 Merge request studip/studip!2465
-rw-r--r--resources/vue/components/StudipDialog.vue6
-rw-r--r--resources/vue/components/StudipWizardDialog.vue24
-rw-r--r--resources/vue/components/courseware/structural-element/CoursewareStructuralElementDialogAdd.vue23
-rw-r--r--resources/vue/components/courseware/structural-element/CoursewareStructuralElementDialogCopy.vue4
-rw-r--r--resources/vue/components/courseware/tasks/CoursewareTasksDialogDistribute.vue15
-rw-r--r--resources/vue/components/courseware/unit/CoursewareShelfDialogAdd.vue21
-rw-r--r--resources/vue/components/courseware/unit/CoursewareShelfDialogCopy.vue4
7 files changed, 58 insertions, 39 deletions
diff --git a/resources/vue/components/StudipDialog.vue b/resources/vue/components/StudipDialog.vue
index 8d88518..f14dd37 100644
--- a/resources/vue/components/StudipDialog.vue
+++ b/resources/vue/components/StudipDialog.vue
@@ -1,6 +1,6 @@
<template>
<MountingPortal mountTo="body" append>
- <focus-trap v-model="trap" :initial-focus="() => $refs.buttonB">
+ <focus-trap v-model="trap" :initial-focus="() => defaultFocus ? $refs.buttonB : null">
<div class="studip-dialog" @keydown.esc="closeDialog">
<transition name="dialog-fade">
<div class="studip-dialog-backdrop">
@@ -139,6 +139,10 @@ export default {
question: String,
alert: String,
message: String,
+ defaultFocus: {
+ type: Boolean,
+ default: true
+ }
},
data() {
const dialogId = uuid++;
diff --git a/resources/vue/components/StudipWizardDialog.vue b/resources/vue/components/StudipWizardDialog.vue
index 5f0339b..e75c1ca 100644
--- a/resources/vue/components/StudipWizardDialog.vue
+++ b/resources/vue/components/StudipWizardDialog.vue
@@ -8,6 +8,7 @@
:confirmDisabled="!showConfirm"
:closeText="closeText"
:closeClass="closeClass"
+ :defaultFocus="false"
@close="$emit('close')"
@confirm="confirm"
>
@@ -22,7 +23,7 @@
<span>{{ $gettext('Bitte geben Sie die folgenden Informationen an:') }}</span>
<ul>
<li v-for="(requirement, index) in requirements" :key="requirement.slot.name + '_' + index">
- <button @click="selectSlot(requirement.slot.id)">
+ <button @click="selectSlot(requirement.slot.id, requirement.target)">
<studip-icon
:shape="requirement.slot.icon"
:size="16"
@@ -54,7 +55,7 @@
:aria-selected="activeId === progress.id"
:aria-controls="progress.name"
:tabindex="0"
- @click="selectSlot(progress.id)"
+ @click="selectSlot(progress.id, progress.target)"
@keydown.right="nextContent"
@keydown.left="prevContent"
>
@@ -206,9 +207,7 @@ export default {
return;
} else {
this.activeId = this.activeId - 1;
- this.$nextTick(() => {
- this.$refs.tabs[this.activeId - 1].focus();
- });
+ this.selectSlot(this.activeId , this.activeSlot.target);
}
},
nextContent() {
@@ -216,13 +215,17 @@ export default {
return;
} else {
this.activeId = this.activeId + 1;
- this.$nextTick(() => {
- this.$refs.tabs[this.activeId - 1].focus();
- });
+ this.selectSlot(this.activeId , this.activeSlot.target);
}
},
- selectSlot(id) {
+ selectSlot(id, target = null) {
this.activeId = id;
+ if (target) {
+ this.$nextTick()
+ .then(() => {
+ document.getElementsByName(target)[0].focus();
+ });
+ }
},
isValid(id) {
const slot = this.slots.find( slot => slot.id === id);
@@ -243,6 +246,9 @@ export default {
this.$emit('confirm');
}
},
+ mounted() {
+ this.selectSlot(this.activeId , this.activeSlot.target);
+ },
watch: {
activeId(newVal) {
if (this.visitedIds.indexOf(newVal) === -1) {
diff --git a/resources/vue/components/courseware/structural-element/CoursewareStructuralElementDialogAdd.vue b/resources/vue/components/courseware/structural-element/CoursewareStructuralElementDialogAdd.vue
index 3d2e7e7..c34e45d 100644
--- a/resources/vue/components/courseware/structural-element/CoursewareStructuralElementDialogAdd.vue
+++ b/resources/vue/components/courseware/structural-element/CoursewareStructuralElementDialogAdd.vue
@@ -13,7 +13,7 @@
<form class="default" @submit.prevent="">
<label>
{{ $gettext('Position der neuen Seite') }}
- <select v-model="pageParent">
+ <select v-model="pageParent" name="relativePosition">
<option v-if="!isRoot && canEditParent" value="sibling">
{{ $gettext('Neben der aktuellen Seite') }}
</option>
@@ -23,11 +23,11 @@
<label>
<span>{{ text.title }}</span>
<span aria-hidden="true" class="wizard-required">*</span>
- <input type="text" v-model="title" required />
+ <input type="text" v-model="title" name="title" required />
</label>
<label>
<span>{{ $gettext('Beschreibung') }}</span>
- <textarea v-model="description" required />
+ <textarea v-model="description" name="description" required />
</label>
</form>
</template>
@@ -35,7 +35,7 @@
<form v-if="hasTemplates" class="default" @submit.prevent="">
<label>
{{ $gettext('Art der Vorlage') }}
- <select v-model="templatePurpose">
+ <select v-model="templatePurpose" name="templatePurpose">
<option value="content">{{ $gettext('Inhalt') }}</option>
<option value="oer">{{ $gettext('OER-Material') }}</option>
<option value="portfolio">{{ $gettext('ePortfolio') }}</option>
@@ -46,7 +46,7 @@
</label>
<label>
<span>{{ $gettext('Vorlage') }}</span>
- <select v-model="selectedTemplate">
+ <select v-model="selectedTemplate" name="template">
<option :value="null">{{ $gettext('ohne Vorlage') }}</option>
<option v-for="template in selectableTemplates" :key="template.id" :value="template">
{{ template.attributes.name }}
@@ -70,6 +70,7 @@
ref="upload_image"
type="file"
accept="image/*"
+ name="image"
@change="checkUploadFile"
/>
<courseware-companion-box
@@ -81,7 +82,7 @@
</label>
<label>
{{ $gettext('Farbe') }}
- <studip-select v-model="color" :options="colors" :reduce="(color) => color.class" label="class">
+ <studip-select v-model="color" :options="colors" :reduce="(color) => color.class" label="class" name="color">
<template #open-indicator="selectAttributes">
<span v-bind="selectAttributes"><studip-icon shape="arr_1down" :size="10" /></span>
</template>
@@ -104,7 +105,7 @@
<form class="default" @submit.prevent="">
<label>
{{ $gettext('Art des Lernmaterials') }}
- <select v-model="purpose">
+ <select v-model="purpose" name="purpose">
<option value="content">{{ $gettext('Inhalt') }}</option>
<option value="oer">{{ $gettext('OER-Material') }}</option>
<option value="portfolio">{{ $gettext('ePortfolio') }}</option>
@@ -177,6 +178,7 @@ export default {
name: 'basic',
title: this.$gettext('Grundeinstellungen'),
icon: 'courseware',
+ target: 'title',
description: this.$gettext(
'Wählen Sie einen kurzen, prägnanten Titel und beschreiben Sie in einigen Worten den Inhalt der Seite.'
),
@@ -187,6 +189,7 @@ export default {
name: 'template',
title: this.$gettext('Vorlage'),
icon: 'content2',
+ target: 'templatePurpose',
description: this.$gettext('Vorlagen enthalten Abschnitte und Blöcke, die bereits für bestimmte Zwecke angeordent sind. Beim anlegen der Seite, wird diese mit Abschnitten und Blöcken befüllt.'),
},
{
@@ -195,6 +198,7 @@ export default {
name: 'layout',
title: this.$gettext('Erscheinung'),
icon: 'picture',
+ target: 'image',
description: this.$gettext(
'Ein Vorschaubild motiviert Lernende die Seite zu erkunden. Die Kombination aus Bild und Farbe erleichtert das wiederfinden der Seite in einem Inhaltsverzeichnisblock.'
),
@@ -205,6 +209,7 @@ export default {
name: 'advanced',
title: this.$gettext('Zusatzangaben'),
icon: 'info-list',
+ target: 'purpose',
description: this.$gettext(
'Hier können Sie detaillierte Angaben zur Seite eintragen. Diese sind besonders interessant wenn die Seite als OER geteilt wird.'
),
@@ -278,7 +283,7 @@ export default {
this.difficulty_end = '';
this.templatePurpose = 'content';
this.selectedTemplate = null;
- this.requirements.push({ slot: this.wizardSlots[0], text: this.text.title });
+ this.requirements.push({ slot: this.wizardSlots[0], text: this.text.title, target: 'title' });
},
closeAddDialog() {
this.showElementAddDialog(false);
@@ -372,7 +377,7 @@ export default {
const slot = this.wizardSlots[0];
if (newTitle === '') {
slot.valid = false;
- this.requirements.push({ slot: slot, text: this.text.title });
+ this.requirements.push({ slot: slot, text: this.text.title, target: 'title' });
} else {
slot.valid = true;
}
diff --git a/resources/vue/components/courseware/structural-element/CoursewareStructuralElementDialogCopy.vue b/resources/vue/components/courseware/structural-element/CoursewareStructuralElementDialogCopy.vue
index 82539ec..8d0406c 100644
--- a/resources/vue/components/courseware/structural-element/CoursewareStructuralElementDialogCopy.vue
+++ b/resources/vue/components/courseware/structural-element/CoursewareStructuralElementDialogCopy.vue
@@ -137,7 +137,7 @@
<form v-if="selectedUnit" class="default" @submit.prevent="">
<label>
{{$gettext('Titel')}}
- <input type="text" v-model="modifiedTitle" required />
+ <input type="text" v-model="modifiedTitle" name="title" required />
</label>
<label>
{{$gettext('Farbe')}}
@@ -207,7 +207,7 @@ export default {
description: this.$gettext('Wählen Sie das Lernmaterial aus, in dem sich der zu kopierende Lerninhalt befindet.') },
{ id: 3, valid: false, name: 'element', title: this.$gettext('Seite'), icon: 'content2',
description: this.$gettext('Wählen Sie die zu kopierende Seite aus. Um Unterseiten anzuzeigen, klicken Sie auf den Seitennamen. Mit einem weiteren Klick werden die Unterseiten wieder zugeklappt.') },
- { id: 4, valid: true, name: 'edit', title: this.$gettext('Anpassen'), icon: 'edit',
+ { id: 4, valid: true, name: 'edit', title: this.$gettext('Anpassen'), icon: 'edit', target: 'title',
description: this.$gettext('Sie können hier die Daten der zu kopierenden Seite anpassen. Eine Anpassung ist optional, Sie können die Seite auch unverändert kopieren.') },
],
source: '',
diff --git a/resources/vue/components/courseware/tasks/CoursewareTasksDialogDistribute.vue b/resources/vue/components/courseware/tasks/CoursewareTasksDialogDistribute.vue
index e88bd04..1e076c7 100644
--- a/resources/vue/components/courseware/tasks/CoursewareTasksDialogDistribute.vue
+++ b/resources/vue/components/courseware/tasks/CoursewareTasksDialogDistribute.vue
@@ -60,7 +60,7 @@
<label>
<span>{{ $gettext('Aufgabentitel') }}</span>
<span aria-hidden="true" class="wizard-required">*</span>
- <input type="text" v-model="taskTitle" required />
+ <input type="text" v-model="taskTitle" name="taskTitle" required />
</label>
<label>
<span>{{ $gettext('Startdatum') }}</span>
@@ -70,7 +70,7 @@
<label>
<span>{{ $gettext('Abgabefrist') }}</span>
<span aria-hidden="true" class="wizard-required">*</span>
- <input type="date" v-model="endDate" :min="startDate" required />
+ <input type="date" v-model="endDate" name="endDate" :min="startDate" required />
</label>
<label>
{{ $gettext('Inhalte ergänzen') }}
@@ -287,6 +287,7 @@ export default {
name: 'tasksettings',
title: this.$gettext('Aufgabeneinstellungen'),
icon: 'settings',
+ target: 'taskTitle',
description: this.$gettext(
'Wählen Sie hier die Einstellungen der Aufgabe. Es muss ein Aufgabentitel und eine Abgabenfrist gesetzt werden.'
),
@@ -600,8 +601,6 @@ export default {
} else {
this.wizardSlots[2].valid = false;
}
-
- return this.wizardSlots[2].valid;
},
validate() {
this.requirements = [];
@@ -611,9 +610,13 @@ export default {
if (!this.selectedTaskIsTask) {
this.requirements.push({ slot: this.wizardSlots[1], text: this.$gettext('Aufgabenvorlage') });
}
- if (!this.validateTaskSettings()) {
- this.requirements.push({ slot: this.wizardSlots[2], text: this.$gettext('Aufgabeneinstellungen') });
+ if (this.taskTitle === '') {
+ this.requirements.push({ slot: this.wizardSlots[2], text: this.$gettext('Aufgabentitel'), target: 'taskTitle' });
+ }
+ if (this.endDate === '') {
+ this.requirements.push({ slot: this.wizardSlots[2], text: this.$gettext('Abgabefrist'), target: 'endDate' });
}
+ this.validateTaskSettings();
if (this.selectedTargetUnit === null) {
this.requirements.push({ slot: this.wizardSlots[3], text: this.$gettext(' Ziel-Lernmaterial') });
}
diff --git a/resources/vue/components/courseware/unit/CoursewareShelfDialogAdd.vue b/resources/vue/components/courseware/unit/CoursewareShelfDialogAdd.vue
index 43163ec..a55d1e0 100644
--- a/resources/vue/components/courseware/unit/CoursewareShelfDialogAdd.vue
+++ b/resources/vue/components/courseware/unit/CoursewareShelfDialogAdd.vue
@@ -13,11 +13,11 @@
<form class="default" @submit.prevent="">
<label>
<span>{{ text.title }}</span><span aria-hidden="true" class="wizard-required">*</span>
- <input type="text" v-model="addWizardData.title" required/>
+ <input type="text" v-model="addWizardData.title" name="title" required/>
</label>
<label>
<span>{{ text.description }}</span><span aria-hidden="true" class="wizard-required">*</span>
- <textarea v-model="addWizardData.description" required/>
+ <textarea v-model="addWizardData.description" name="description" required/>
</label>
</form>
</template>
@@ -26,7 +26,7 @@
<label>
{{ $gettext('Bild hochladen') }}
<br>
- <input class="cw-file-input" ref="upload_image" type="file" accept="image/*" @change="checkUploadFile"/>
+ <input class="cw-file-input" ref="upload_image" type="file" accept="image/*" name="image" @change="checkUploadFile"/>
<CoursewareCompanionBox
v-if="uploadFileError"
:msgCompanion="uploadFileError"
@@ -57,6 +57,7 @@
:options="colors"
:reduce="(color) => color.class"
label="class"
+ name="color"
>
<template #open-indicator="selectAttributes">
<span v-bind="selectAttributes"
@@ -78,7 +79,7 @@
</label>
<label>
<span>{{ $gettext('Titelseite') }}</span>
- <select v-model="addWizardData.rootLayout">
+ <select v-model="addWizardData.rootLayout" name="layout">
<option value="default">{{ $gettext('Automatisch') }}</option>
<option value="toc">{{ $gettext('Automatisch mit Inhaltsverzeichnis') }}</option>
<option value="classic">{{ $gettext('Frei bearbeitbar') }}</option>
@@ -91,7 +92,7 @@
<form class="default" @submit.prevent="">
<label>
{{ $gettext('Art des Lernmaterials') }}
- <select v-model="addWizardData.purpose">
+ <select v-model="addWizardData.purpose" name="purpose">
<option value="content">{{ $gettext('Inhalt') }}</option>
<option value="oer">{{ $gettext('OER-Material') }}</option>
<option value="portfolio">{{ $gettext('ePortfolio') }}</option>
@@ -164,11 +165,11 @@ export default {
data() {
return {
wizardSlots: [
- { id: 1, valid: false, name: 'basic', title: this.$gettext('Grundeinstellungen'), icon: 'courseware',
+ { id: 1, valid: false, name: 'basic', title: this.$gettext('Grundeinstellungen'), icon: 'courseware', target: 'title',
description: this.$gettext('Wählen Sie einen kurzen, prägnanten Titel und beschreiben Sie in einigen Worten den Inhalt des Lernmaterials. Eine Beschreibung erleichtert Lernenden die Auswahl des Lernmaterials.') },
- { id: 2, valid: true, name: 'layout', title: this.$gettext('Darstellung'), icon: 'picture',
+ { id: 2, valid: true, name: 'layout', title: this.$gettext('Darstellung'), icon: 'picture', target: 'image',
description: this.$gettext('Ein Vorschaubild motiviert Lernende das Lernmaterial zu erkunden. Die Kombination aus Bild und Farbe erleichtert das wiederfinden des Lernmaterials in der Übersicht.') },
- { id: 3, valid: true, name: 'advanced', title: this.$gettext('Zusatzangaben'), icon: 'info-list',
+ { id: 3, valid: true, name: 'advanced', title: this.$gettext('Zusatzangaben'), icon: 'info-list', target: 'purpose',
description: this.$gettext('Hier können Sie detaillierte Angaben zum Lernmaterial eintragen. Diese sind besonders interessant wenn das Lernmaterial als OER geteilt wird.') }
],
text: {
@@ -321,11 +322,11 @@ export default {
}
if (newData.title === '' ) {
slot.valid = false;
- this.requirements.push({slot: slot, text: this.text.title });
+ this.requirements.push({slot: slot, text: this.text.title, target: 'title' });
}
if (newData.description === '') {
slot.valid = false;
- this.requirements.push({slot: slot, text: this.text.description });
+ this.requirements.push({slot: slot, text: this.text.description, target: 'description' });
}
},
deep: true
diff --git a/resources/vue/components/courseware/unit/CoursewareShelfDialogCopy.vue b/resources/vue/components/courseware/unit/CoursewareShelfDialogCopy.vue
index a2d1dec..ea475e7 100644
--- a/resources/vue/components/courseware/unit/CoursewareShelfDialogCopy.vue
+++ b/resources/vue/components/courseware/unit/CoursewareShelfDialogCopy.vue
@@ -123,7 +123,7 @@
<form v-if="selectedUnit" class="default" @submit.prevent="">
<label>
<span>{{$gettext('Titel')}}</span><span aria-hidden="true" class="wizard-required">*</span>
- <input type="text" v-model="modifiedTitle" :placeholder="selectedUnitTitle" required />
+ <input type="text" v-model="modifiedTitle" :placeholder="selectedUnitTitle" name="title" required />
</label>
<label>
{{$gettext('Farbe')}}
@@ -189,7 +189,7 @@ export default {
description: this.$gettext('Wählen Sie hier den Ort in Stud.IP aus, an dem sich das zu kopierende Lernmaterial befindet.') },
{ id: 2, valid: false, name: 'unit', title: this.$gettext('Lernmaterial'), icon: 'courseware',
description: this.$gettext('Wählen Sie hier das gewünschte Lernmaterial aus der Liste aus. Eine Auswahl wird durch einen grauen Hintergrund und einen Kontrollhaken angezeigt.') },
- { id: 3, valid: true, name: 'edit', title: this.$gettext('Anpassen'), icon: 'edit',
+ { id: 3, valid: true, name: 'edit', title: this.$gettext('Anpassen'), icon: 'edit', target: 'title',
description: this.$gettext('Sie können hier die Daten des zu kopierenden Lernmaterials anpassen. Eine Anpassung ist optional, Sie können das Lernmaterial auch unverändert kopieren.') },
],
source: '',