diff --git a/resources/vue/components/courseware/tasks/CoursewareDashboardStudents.vue b/resources/vue/components/courseware/tasks/CoursewareDashboardStudents.vue index 1bdbf3ce0e17b2e1b048207169eed4603a3219b3..455f7206c92292588a0bd0bb71c357da91340a5d 100644 --- a/resources/vue/components/courseware/tasks/CoursewareDashboardStudents.vue +++ b/resources/vue/components/courseware/tasks/CoursewareDashboardStudents.vue @@ -2,38 +2,47 @@ <div class="cw-dashboard-students-wrapper"> <table class="default" v-if="taskGroups.length"> <thead> - <tr> - <th>{{ $gettext('Status') }}</th> - <th>{{ $gettext('Titel') }}</th> - <th>{{ $gettext('Bearbeitungszeit') }}</th> + <tr class="sortable"> + <th> + {{ $gettext('Status') }} + </th> + <th :class="getSortClass('task-group-title')" @click="sort('task-group-title')"> + {{ $gettext('Titel') }} + </th> + <th :class="getSortClass('end-date')" @click="sort('end-date')"> + {{ $gettext('Bearbeitungszeit') }} + </th> </tr> </thead> <tbody> - <tr v-for="(taskGroup, index) in taskGroups"> - <td> - <StudipIcon - :shape="status(taskGroup).shape" - :role="status(taskGroup).role" - :title="status(taskGroup).description" - aria-hidden="true" + <tr v-for="(taskGroup, index) in sortedTaskGroups" :key="index"> + <td> + <StudipIcon + :shape="status(taskGroup).shape" + :role="status(taskGroup).role" + :title="status(taskGroup).description" + aria-hidden="true" /> - <span class="sr-only">{{ status(taskGroup).description }}</span> - </td> - <td> - <router-link :to="{ name: 'task-groups-show', params: { id: taskGroup.id } }">{{ taskGroup.attributes.title }}</router-link> - </td> - <td> - <StudipDate :date="new Date(taskGroup.attributes['start-date'])" />–<StudipDate :date="new Date(taskGroup.attributes['end-date'])" /> - </td> - </tr> + <span class="sr-only">{{ status(taskGroup).description }}</span> + </td> + <td> + <router-link :to="{ name: 'task-groups-show', params: { id: taskGroup.id } }">{{ + taskGroup.attributes.title + }}</router-link> + </td> + <td> + <StudipDate :date="new Date(taskGroup.attributes['start-date'])" />–<StudipDate + :date="new Date(taskGroup.attributes['end-date'])" + /> + </td> + </tr> </tbody> </table> - <CompanionBox v-else-if="!tasksLoading" - :msgCompanion="$gettext('Es wurden noch keine Aufgaben verteilt.')"> + <CompanionBox v-else-if="!tasksLoading" :msgCompanion="$gettext('Es wurden noch keine Aufgaben verteilt.')"> <template #companionActions> <button @click="setShowTasksDistributeDialog(true)" type="button" class="button"> - {{ $gettext("Aufgabe verteilen") }} + {{ $gettext('Aufgabe verteilen') }} </button> </template> </CompanionBox> @@ -59,6 +68,10 @@ export default { StudipDate, StudipIcon, }, + data: () => ({ + sortBy: 'end-date', + sortASC: false, + }), computed: { ...mapGetters({ context: 'context', @@ -66,10 +79,19 @@ export default { taskGroupsByCid: 'tasks/taskGroupsByCid', tasksLoading: 'courseware-tasks/isLoading', }), + sortedTaskGroups() { + const sorters = { + 'task-group-title': (taskGroup) => taskGroup.attributes.title, + 'end-date': (taskGroup) => new Date(taskGroup.attributes['end-date']), + }; + + return _.chain(this.taskGroups) + .sortBy([sorters[this.sortBy]]) + .thru((sorted) => (this.sortAsc ? sorted : _.reverse(sorted))) + .value(); + }, taskGroups() { - return _.sortBy(this.taskGroupsByCid(this.context.id), [ - (taskGroup) => -new Date(taskGroup.attributes['end-date']), - ]); + return this.taskGroupsByCid(this.context.id); }, }, methods: { @@ -77,7 +99,12 @@ export default { loadAllTasks: 'courseware-tasks/loadAll', setShowTasksDistributeDialog: 'tasks/setShowTasksDistributeDialog', }), - status: getStatus, + getSortClass(col) { + if (col === this.sortBy) { + return this.sortASC ? 'sortasc' : 'sortdesc'; + } + return ''; + }, reloadTasks() { this.loadAllTasks({ options: { @@ -86,6 +113,23 @@ export default { }, }); }, + sort(sortBy) { + if (this.sortBy === sortBy) { + this.sortASC = !this.sortASC; + } else { + this.sortBy = sortBy; + } + }, + status: getStatus, }, }; </script> + +<style scoped> +th { + cursor: pointer; +} +th:first-child { + cursor: not-allowed; +} +</style>