aboutsummaryrefslogtreecommitdiff
path: root/resources
diff options
context:
space:
mode:
authorRon Lucke <lucke@elan-ev.de>2023-03-24 07:32:43 +0000
committerJan-Hendrik Willms <tleilax+studip@gmail.com>2023-03-24 07:32:43 +0000
commitf3e00212fae3e46a08ae9fc447ba4426c0255682 (patch)
tree35a892bfca87887045ea09499ae4fdda75654c6c /resources
parent79e20d95a9e63e00f021cb04f2135705cbf32e48 (diff)
fix #2126
Closes #2126 Merge request studip/studip!1441
Diffstat (limited to 'resources')
-rw-r--r--resources/vue/components/courseware/CoursewareShelfDialogCopy.vue114
-rw-r--r--resources/vue/components/courseware/CoursewareStructuralElementDialogCopy.vue112
-rw-r--r--resources/vue/components/courseware/CoursewareStructuralElementDialogLink.vue3
-rw-r--r--resources/vue/components/courseware/CoursewareTasksDialogDistribute.vue1
-rw-r--r--resources/vue/store/courseware/courseware-shelf.module.js22
-rw-r--r--resources/vue/store/courseware/courseware.module.js22
6 files changed, 180 insertions, 94 deletions
diff --git a/resources/vue/components/courseware/CoursewareShelfDialogCopy.vue b/resources/vue/components/courseware/CoursewareShelfDialogCopy.vue
index 373fc41..9695df3 100644
--- a/resources/vue/components/courseware/CoursewareShelfDialogCopy.vue
+++ b/resources/vue/components/courseware/CoursewareShelfDialogCopy.vue
@@ -54,38 +54,50 @@
<studip-icon shape="check-circle" size="24" class="check" />
</label>
</fieldset>
- <label v-if="source === 'courses'">
- <span>{{ $gettext('Veranstaltung') }}</span><span aria-hidden="true" class="wizard-required">*</span>
- <studip-select
- v-if="courses.length !== 0 && !loadingCourses"
- :options="courses"
- label="title"
- :clearable="false"
- :reduce="option => option.id"
- v-model="selectedRange"
- >
- <template #open-indicator="selectAttributes">
- <span v-bind="selectAttributes"
- ><studip-icon shape="arr_1down" size="10"
- /></span>
- </template>
- <template #no-options="{}">
- {{ $gettext('Es steht keine Auswahl zur Verfügung.') }}
- </template>
- <template #selected-option="{ attributes }">
- <span>{{ attributes.title }}</span>
- </template>
- <template #option="{ attributes }">
- <span>{{ attributes.title }}</span>
- </template>
- </studip-select>
- <p v-if="loadingCourses">
- {{$gettext('Lade Veranstaltungen…')}}
- </p>
- <p v-if="courses.length === 0 && !loadingCourses">
- {{$gettext('Es wurden keine geeigneten Veranstaltungen gefunden.')}}
- </p>
- </label>
+ <template v-if="source === 'courses'">
+ <label>
+ <span>{{ $gettext('Semester') }}</span><span aria-hidden="true"></span>
+ <select v-model="selectedSemester">
+ <option value="all">{{ $gettext('Alle Semester') }}</option>
+ <option v-for="semester in semesterMap" :key="semester.id" :value="semester.id">
+ {{ semester.attributes.title }}
+ </option>
+ </select>
+ </label>
+ <label>
+ <span>{{ $gettext('Veranstaltung') }}</span><span aria-hidden="true" class="wizard-required">*</span>
+ <studip-select
+ v-if="filteredCourses.length !== 0 && !loadingCourses"
+ :options="filteredCourses"
+ label="title"
+ :clearable="false"
+ :reduce="option => option.id"
+ v-model="selectedRange"
+ >
+ <template #open-indicator="selectAttributes">
+ <span v-bind="selectAttributes"
+ ><studip-icon shape="arr_1down" size="10"
+ /></span>
+ </template>
+ <template #no-options="{}">
+ {{ $gettext('Es steht keine Auswahl zur Verfügung.') }}
+ </template>
+ <template #selected-option="{ attributes }">
+ <span>{{ attributes.title }}</span>
+ </template>
+ <template #option="{ attributes }">
+ <span>{{ attributes.title }}</span>
+ </template>
+ </studip-select>
+ <p v-if="loadingCourses">
+ {{$gettext('Lade Veranstaltungen…')}}
+ </p>
+ <p v-if="filteredCourses.length === 0 && !loadingCourses">
+ {{$gettext('Es wurden keine geeigneten Veranstaltungen gefunden.')}}
+ </p>
+ </label>
+ </template>
+
</form>
</template>
<template v-slot:unit>
@@ -192,6 +204,8 @@ export default {
source: '',
loadingCourses: false,
courses: [],
+ semesterMap: [],
+ selectedSemester: 'all',
selectedRange: '',
loadingUnits: false,
selectedUnit: null,
@@ -215,6 +229,7 @@ export default {
...mapGetters({
userId: 'userId',
coursewareUnits: 'courseware-units/all',
+ semesterById: 'semesters/byId',
structuralElementById: 'courseware-structural-elements/byId',
context: 'context'
}),
@@ -244,6 +259,16 @@ export default {
},
selectedUnitDescription() {
return this.selectedUnitElement.attributes.payload.description ?? '';
+ },
+ filteredCourses() {
+ const courses = this.courses.filter((course) => { return course.id !== this.context.id});
+ if (this.selectedSemester === 'all') {
+ return courses;
+ } else {
+ return courses.filter((course) => {
+ return course.relationships['start-semester'].data.id === this.selectedSemester;
+ });
+ }
}
},
async mounted() {
@@ -254,6 +279,7 @@ export default {
companionSuccess: 'companionSuccess',
loadCourseUnits: 'loadCourseUnits',
loadUsersCourses: 'loadUsersCourses',
+ loadSemester: 'semesters/loadById',
loadUserUnits: 'loadUserUnits',
setShowUnitCopyDialog: 'setShowUnitCopyDialog',
copyUnit: 'copyUnit',
@@ -286,8 +312,27 @@ export default {
async updateCourses() {
this.loadingCourses = true;
this.courses = await this.loadUsersCourses({ userId: this.userId, withCourseware: true });
+ this.loadSemesterMap();
this.loadingCourses = false;
},
+ loadSemesterMap() {
+ let view = this;
+ let semesters = [];
+ this.courses.every(course => {
+ let semId = course.relationships['start-semester'].data.id;
+ if(!semesters.includes(semId)) {
+ semesters.push(semId);
+ }
+ return true;
+ });
+ semesters.every(semester => {
+ view.loadSemester({id: semester}).then( () => {
+ view.semesterMap.push(view.semesterById({id: semester}));
+ view.semesterMap.sort((a, b) => a.attributes.start < b.attributes.start);
+ });
+ return true;
+ });
+ },
async updateCourseUnits(cid) {
this.loadingUnits = true;
await this.loadCourseUnits(cid);
@@ -356,7 +401,10 @@ export default {
this.selectedRange = this.userId;
break;
}
+ },
+ selectedSemester(newSemester) {
+ this.selectedRange = '';
}
}
}
-</script> \ No newline at end of file
+</script>
diff --git a/resources/vue/components/courseware/CoursewareStructuralElementDialogCopy.vue b/resources/vue/components/courseware/CoursewareStructuralElementDialogCopy.vue
index 215d866..8eda4d3 100644
--- a/resources/vue/components/courseware/CoursewareStructuralElementDialogCopy.vue
+++ b/resources/vue/components/courseware/CoursewareStructuralElementDialogCopy.vue
@@ -53,38 +53,50 @@
<studip-icon shape="check-circle" size="24" class="check" />
</label>
</fieldset>
- <label v-if="source === 'courses'">
- <span>{{ $gettext('Veranstaltung') }}</span><span aria-hidden="true" class="wizard-required">*</span>
- <studip-select
- v-if="courses.length !== 0 && !loadingCourses"
- :options="courses"
- label="title"
- :clearable="false"
- :reduce="option => option.id"
- v-model="selectedRange"
- >
- <template #open-indicator="selectAttributes">
- <span v-bind="selectAttributes"
- ><studip-icon shape="arr_1down" size="10"
- /></span>
- </template>
- <template #no-options="{}">
- {{ $gettext('Es steht keine Auswahl zur Verfügung.') }}
- </template>
- <template #selected-option="{ attributes }">
- <span>{{ attributes.title }}</span>
- </template>
- <template #option="{ attributes }">
- <span>{{ attributes.title }}</span>
- </template>
- </studip-select>
- <p v-if="loadingCourses">
- {{$gettext('Lade Veranstaltungen…')}}
- </p>
- <p v-if="courses.length === 0 && !loadingCourses">
- {{$gettext('Es wurden keine geeigneten Veranstaltungen gefunden.')}}
- </p>
- </label>
+ <template v-if="source === 'courses'">
+ <label>
+ <span>{{ $gettext('Semester') }}</span><span aria-hidden="true"></span>
+ <select v-model="selectedSemester">
+ <option value="all">{{ $gettext('Alle Semester') }}</option>
+ <option v-for="semester in semesterMap" :key="semester.id" :value="semester.id">
+ {{ semester.attributes.title }}
+ </option>
+ </select>
+ </label>
+ <label>
+ <span>{{ $gettext('Veranstaltung') }}</span><span aria-hidden="true" class="wizard-required">*</span>
+ <studip-select
+ v-if="filteredCourses.length !== 0 && !loadingCourses"
+ :options="filteredCourses"
+ label="title"
+ :clearable="false"
+ :reduce="option => option.id"
+ v-model="selectedRange"
+ >
+ <template #open-indicator="selectAttributes">
+ <span v-bind="selectAttributes"
+ ><studip-icon shape="arr_1down" size="10"
+ /></span>
+ </template>
+ <template #no-options="{}">
+ {{ $gettext('Es steht keine Auswahl zur Verfügung.') }}
+ </template>
+ <template #selected-option="{ attributes }">
+ <span>{{ attributes.title }}</span>
+ </template>
+ <template #option="{ attributes }">
+ <span>{{ attributes.title }}</span>
+ </template>
+ </studip-select>
+ <p v-if="loadingCourses">
+ {{$gettext('Lade Veranstaltungen…')}}
+ </p>
+ <p v-if="filteredCourses.length === 0 && !loadingCourses">
+ {{$gettext('Es wurden keine geeigneten Veranstaltungen gefunden.')}}
+ </p>
+ </label>
+ </template>
+
</form>
</template>
<template v-slot:unit>
@@ -239,6 +251,8 @@ export default {
source: '',
loadingCourses: false,
courses: [],
+ semesterMap: [],
+ selectedSemester: 'all',
selectedRange: '',
loadingUnits: false,
selectedUnit: null,
@@ -261,6 +275,7 @@ export default {
...mapGetters({
userId: 'userId',
coursewareUnits: 'courseware-units/all',
+ semesterById: 'semesters/byId',
structuralElementById: 'courseware-structural-elements/byId',
context: 'context',
childrenById: 'courseware-structure/children',
@@ -313,6 +328,16 @@ export default {
.map((id) => this.structuralElementById({ id }))
.filter(Boolean);
},
+ filteredCourses() {
+ const courses = this.courses.filter((course) => { return course.id !== this.context.id});
+ if (this.selectedSemester === 'all') {
+ return courses;
+ } else {
+ return courses.filter((course) => {
+ return course.relationships['start-semester'].data.id === this.selectedSemester;
+ });
+ }
+ }
},
mounted() {
this.initWizardData();
@@ -323,6 +348,7 @@ export default {
loadCourseUnits: 'loadCourseUnits',
loadUserUnits: 'loadUserUnits',
loadUsersCourses: 'loadUsersCourses',
+ loadSemester: 'semesters/loadById',
loadStructuralElement: 'courseware-structural-elements/loadById',
copyStructuralElement: 'copyStructuralElement',
companionError: 'companionError',
@@ -339,8 +365,27 @@ export default {
async updateCourses() {
this.loadingCourses = true;
this.courses = await this.loadUsersCourses({ userId: this.userId, withCourseware: true });
+ this.loadSemesterMap();
this.loadingCourses = false;
},
+ loadSemesterMap() {
+ let view = this;
+ let semesters = [];
+ this.courses.every(course => {
+ let semId = course.relationships['start-semester'].data.id;
+ if(!semesters.includes(semId)) {
+ semesters.push(semId);
+ }
+ return true;
+ });
+ semesters.every(semester => {
+ view.loadSemester({id: semester}).then( () => {
+ view.semesterMap.push(view.semesterById({id: semester}));
+ view.semesterMap.sort((a, b) => a.attributes.start < b.attributes.start);
+ });
+ return true;
+ });
+ },
async updateCourseUnits(cid) {
this.loadingUnits = true;
await this.loadCourseUnits(cid);
@@ -461,6 +506,9 @@ export default {
this.selectedRange = this.userId;
break;
}
+ },
+ selectedSemester(newSemester) {
+ this.selectedRange = '';
}
}
}
diff --git a/resources/vue/components/courseware/CoursewareStructuralElementDialogLink.vue b/resources/vue/components/courseware/CoursewareStructuralElementDialogLink.vue
index 4703858..38d3953 100644
--- a/resources/vue/components/courseware/CoursewareStructuralElementDialogLink.vue
+++ b/resources/vue/components/courseware/CoursewareStructuralElementDialogLink.vue
@@ -184,7 +184,6 @@ export default {
...mapActions({
showElementLinkDialog: 'showElementLinkDialog',
loadUserUnits: 'loadUserUnits',
- loadUsersCourses: 'loadUsersCourses',
loadStructuralElement: 'courseware-structural-elements/loadById',
linkStructuralElement: 'linkStructuralElement',
companionError: 'companionError',
@@ -261,4 +260,4 @@ export default {
},
}
}
-</script> \ No newline at end of file
+</script>
diff --git a/resources/vue/components/courseware/CoursewareTasksDialogDistribute.vue b/resources/vue/components/courseware/CoursewareTasksDialogDistribute.vue
index 36ad58b..b850558 100644
--- a/resources/vue/components/courseware/CoursewareTasksDialogDistribute.vue
+++ b/resources/vue/components/courseware/CoursewareTasksDialogDistribute.vue
@@ -542,7 +542,6 @@ export default {
setShowTasksDistributeDialog: 'setShowTasksDistributeDialog',
loadCourseUnits: 'loadCourseUnits',
loadUserUnits: 'loadUserUnits',
- loadUsersCourses: 'loadUsersCourses',
loadStructuralElement: 'courseware-structural-elements/loadById',
copyStructuralElement: 'copyStructuralElement',
companionError: 'companionError',
diff --git a/resources/vue/store/courseware/courseware-shelf.module.js b/resources/vue/store/courseware/courseware-shelf.module.js
index 1b91ff4..e1b0774 100644
--- a/resources/vue/store/courseware/courseware-shelf.module.js
+++ b/resources/vue/store/courseware/courseware-shelf.module.js
@@ -296,7 +296,7 @@ export const actions = {
});
const otherMemberships = memberships.filter(({ attributes, relationships }) => {
- return ['dozent', 'tutor'].includes(attributes.permission) && state.context.id !== relationships.course.data.id;
+ return ['dozent', 'tutor'].includes(attributes.permission);
});
if (!withCourseware) {
@@ -305,20 +305,16 @@ export const actions = {
});
}
- const items = await Promise.all(
- otherMemberships.map((membership) => {
- const course = getCourse(membership);
+ const items = otherMemberships.map((membership) => {
+ let course = getCourse(membership);
+ course['userPermission'] = membership.attributes.permission;
- return dispatch('loadRemoteCoursewareStructure', {
- rangeId: course.id,
- rangeType: course.type
- }).then((instance) => ({ instance, membership, course }));
- })
- )
+ return { membership, course };
+ });
- return items
- .filter(({ instance, membership }) => {
- return instance?.relationships?.root && (membership.attributes.permission === 'dozent' || instance.attributes['editing-permission-level'] === 'tutor');
+ return items
+ .filter(({ membership, course }) => {
+ return course.relationships.courseware;
})
.map(({ course }) => course);
diff --git a/resources/vue/store/courseware/courseware.module.js b/resources/vue/store/courseware/courseware.module.js
index 996cb37..7c1f2fe 100644
--- a/resources/vue/store/courseware/courseware.module.js
+++ b/resources/vue/store/courseware/courseware.module.js
@@ -1093,20 +1093,16 @@ export const actions = {
});
}
- const items = await Promise.all(
- otherMemberships.map((membership) => {
- const course = getCourse(membership);
-
- return dispatch('loadRemoteCoursewareStructure', {
- rangeId: course.id,
- rangeType: course.type
- }).then((instance) => ({ instance, membership, course }));
- })
- )
+ const items = otherMemberships.map((membership) => {
+ let course = getCourse(membership);
+ course['userPermission'] = membership.attributes.permission;
+
+ return { membership, course };
+ });
- return items
- .filter(({ instance, membership }) => {
- return instance?.relationships?.root && (membership.attributes.permission === 'dozent' || instance.attributes['editing-permission-level'] === 'tutor');
+ return items
+ .filter(({ membership, course }) => {
+ return course.relationships.courseware;
})
.map(({ course }) => course);