diff options
| author | Ron Lucke <lucke@elan-ev.de> | 2023-03-24 07:32:43 +0000 |
|---|---|---|
| committer | Jan-Hendrik Willms <tleilax+studip@gmail.com> | 2023-03-24 07:32:43 +0000 |
| commit | f3e00212fae3e46a08ae9fc447ba4426c0255682 (patch) | |
| tree | 35a892bfca87887045ea09499ae4fdda75654c6c /resources | |
| parent | 79e20d95a9e63e00f021cb04f2135705cbf32e48 (diff) | |
fix #2126
Closes #2126
Merge request studip/studip!1441
Diffstat (limited to 'resources')
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); |
