Select Git revision
StructuralElement.php
Forked from
Stud.IP / Stud.IP
Source project has a limited visibility.
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
CoursewareDashboardStudents.vue 16.50 KiB
<template>
<div class="cw-dashboard-students-wrapper">
<table v-if="tasks.length > 0" class="default">
<colgroup>
<col />
</colgroup>
<thead>
<tr>
<th><translate>Status</translate></th>
<th><translate>Aufgabentitel</translate></th>
<th><translate>Teilnehmende/Gruppen</translate></th>
<th><translate class="responsive-hidden">Seite</translate></th>
<th><translate>bearbeitet</translate></th>
<th><translate>Abgabefrist</translate></th>
<th><translate>Abgabe</translate></th>
<th class="responsive-hidden renewal"><translate>Verlängerungsanfrage</translate></th>
<th class="responsive-hidden feedback"><translate>Feedback</translate></th>
</tr>
</thead>
<tbody>
<tr v-for="{ task, taskGroup, status, element, user, group, feedback } in tasks" :key="task.id">
<td>
<studip-icon
v-if="status.shape !== undefined"
:shape="status.shape"
:role="status.role"
:title="status.description"
aria-hidden="true"
/>
<span class="sr-only">{{ status.description }}</span>
</td>
<td>
{{ taskGroup && taskGroup.attributes.title }}
</td>
<td>
<span v-if="user">
<studip-icon
shape="person2"
role="info"
aria-hidden="true"
:title="$gettext('Teilnehmende Person')"
/>
<span class="sr-only">{{ $gettext('Teilnehmende Person') }}</span>
{{ user.attributes['formatted-name'] }}
</span>
<span v-if="group">
<studip-icon
shape="group2"
role="info"
aria-hidden="true"
:title="$gettext('Gruppe')"
/>
<span class="sr-only">{{ $gettext('Gruppe') }}</span>
{{ group.attributes['name'] }}
</span>
</td>
<td class="responsive-hidden">
<a v-if="task.attributes.submitted" :href="getLinkToElement(element)">
{{ element.attributes.title }}
</a>
<span v-else>{{ element.attributes.title }}</span>
</td>
<td>{{ task.attributes?.progress?.toFixed(2) || '-.--' }}%</td>
<td>{{ getReadableDate(task.attributes['submission-date']) }}</td>
<td>
<studip-icon v-if="task.attributes.submitted" shape="accept" role="status-green" />
</td>
<td class="responsive-hidden">
<button
v-show="task.attributes.renewal === 'pending'"
class="button"
@click="solveRenewalRequest(task)"
>
<translate>Anfrage bearbeiten</translate>
</button>
<span v-show="task.attributes.renewal === 'declined'">
<studip-icon shape="decline" role="status-red" />
<translate>Anfrage abgelehnt</translate>
</span>
<span v-show="task.attributes.renewal === 'granted'">
<translate>verlängert bis</translate>:
{{ getReadableDate(task.attributes['renewal-date']) }}
</span>
<studip-icon
v-if="task.attributes.renewal === 'declined' || task.attributes.renewal === 'granted'"
:title="$gettext('Anfrage bearbeiten')"
class="edit"
shape="edit"
role="clickable"
@click="solveRenewalRequest(task)"
/>
</td>
<td class="responsive-hidden">
<span
v-if="feedback"
:title="
$gettext('Feedback geschrieben am:') +
' ' +
getReadableDate(feedback.attributes['chdate'])
"
>
<studip-icon shape="accept" role="status-green" />
<translate>Feedback gegeben</translate>
<studip-icon
:title="$gettext('Feedback bearbeiten')"
class="edit"
shape="edit"
role="clickable"
@click="editFeedback(feedback)"
/>
</span>
<button
v-show="!feedback && task.attributes.submitted"
class="button"
@click="addFeedback(task)"
>
<translate>Feedback geben</translate>
</button>
</td>
</tr>
</tbody>
</table>
<div v-else>
<courseware-companion-box
mood="pointing"
:msgCompanion="$gettext('Es wurden bisher keine Aufgaben gestellt.')"
>
</courseware-companion-box>
</div>
<studip-dialog
v-if="showRenewalDialog"
:title="text.renewalDialog.title"
:confirmText="text.renewalDialog.confirm"
confirmClass="accept"
:closeText="text.renewalDialog.close"
closeClass="cancel"
height="350"
@close="
showRenewalDialog = false;
currentDialogTask = {};
"
@confirm="updateRenewal"
>
<template v-slot:dialogContent>
<form class="default" @submit.prevent="">
<label>
<translate>Fristverlängerung</translate>
<select v-model="currentDialogTask.attributes.renewal">
<option value="declined">
<translate>ablehnen</translate>
</option>
<option value="granted">
<translate>gewähren</translate>
</option>
</select>
</label>
<label v-if="currentDialogTask.attributes.renewal === 'granted'">
<translate>neue Frist</translate>
<courseware-date-input v-model="currentDialogTask.attributes['renewal-date']" class="size-l" />
</label>
</form>
</template>
</studip-dialog>
<studip-dialog
v-if="showEditFeedbackDialog"
:title="text.editFeedbackDialog.title"
:confirmText="text.editFeedbackDialog.confirm"
confirmClass="accept"
:closeText="text.editFeedbackDialog.close"
closeClass="cancel"
height="420"
@close="
showEditFeedbackDialog = false;
currentDialogFeedback = {};
"
@confirm="updateFeedback"
>
<template v-slot:dialogContent>
<courseware-companion-box
v-if="currentDialogFeedback.attributes.content === ''"
mood="pointing"
:msgCompanion="
$gettext('Sie haben kein Feedback geschrieben, beim Speichern wird dieses Feedback gelöscht!')
"
/>
<form class="default" @submit.prevent="">
<label>
<translate>Feedback</translate>
<textarea v-model="currentDialogFeedback.attributes.content" />
</label>
</form>
</template>
</studip-dialog>
<studip-dialog
v-if="showAddFeedbackDialog"
:title="text.addFeedbackDialog.title"
:confirmText="text.addFeedbackDialog.confirm"
confirmClass="accept"
:closeText="text.addFeedbackDialog.close"
closeClass="cancel"
@close="
showAddFeedbackDialog = false;
currentDialogFeedback = {};
"
@confirm="createFeedback"
>
<template v-slot:dialogContent>
<form class="default" @submit.prevent="">
<label>
<translate>Feedback</translate>
<textarea v-model="currentDialogFeedback.attributes.content" />
</label>
</form>
</template>
</studip-dialog>
<courseware-tasks-dialog-distribute v-if="showTasksDistributeDialog"/>
</div>
</template>
<script>
import StudipIcon from './../StudipIcon.vue';
import StudipDialog from './../StudipDialog.vue';
import CoursewareCompanionBox from './CoursewareCompanionBox.vue';
import CoursewareDateInput from './CoursewareDateInput.vue';
import CoursewareTasksDialogDistribute from './CoursewareTasksDialogDistribute.vue';
import taskHelperMixin from '../../mixins/courseware/task-helper.js';
import { mapActions, mapGetters } from 'vuex';
export default {
name: 'courseware-dashboard-students',
mixins: [taskHelperMixin],
components: {
CoursewareCompanionBox,
CoursewareDateInput,
StudipIcon,
StudipDialog,
CoursewareTasksDialogDistribute,
},
data() {
return {
showRenewalDialog: false,
showAddFeedbackDialog: false,
showEditFeedbackDialog: false,
currentDialogTask: {},
currentDialogFeedback: {},
text: {
renewalDialog: {
title: this.$gettext('Verlängerungsanfrage bearbeiten'),
confirm: this.$gettext('Speichern'),
close: this.$gettext('Schließen'),
},
editFeedbackDialog: {
title: this.$gettext('Feedback zur Aufgabe ändern'),
confirm: this.$gettext('Speichern'),
close: this.$gettext('Schließen'),
},
addFeedbackDialog: {
title: this.$gettext('Feedback zur Aufgabe geben'),
confirm: this.$gettext('Speichern'),
close: this.$gettext('Schließen'),
},
},
};
},
computed: {
...mapGetters({
context: 'context',
allTasks: 'courseware-tasks/all',
userById: 'users/byId',
statusGroupById: 'status-groups/byId',
getElementById: 'courseware-structural-elements/byId',
getFeedbackById: 'courseware-task-feedback/byId',
relatedTaskGroups: 'courseware-task-groups/related',
showTasksDistributeDialog: 'showTasksDistributeDialog'
}),
tasks() {
return this.allTasks.map((task) => {
const result = {
task,
taskGroup: this.relatedTaskGroups({ parent: task, relationship: 'task-group' }),
status: this.getStatus(task),
element: this.getElementById({ id: task.relationships['structural-element'].data.id }),
user: null,
group: null,
feedback: null,
};
let solver = task.relationships.solver.data;
if (solver.type === 'users') {
result.user = this.userById({ id: solver.id });
}
if (solver.type === 'status-groups') {
result.group = this.statusGroupById({ id: solver.id });
}
const feedbackId = task.relationships['task-feedback'].data?.id;
if (feedbackId) {
result.feedback = this.getFeedbackById({ id: feedbackId });
}
return result;
});
},
managerUrl() {
return STUDIP.URLHelper.getURL('dispatch.php/course/courseware/manager', {cid: this.context.id});
}
},
methods: {
...mapActions({
updateTask: 'updateTask',
createTaskFeedback: 'createTaskFeedback',
updateTaskFeedback: 'updateTaskFeedback',
deleteTaskFeedback: 'deleteTaskFeedback',
loadRemoteCoursewareStructure: 'loadRemoteCoursewareStructure',
copyStructuralElement: 'copyStructuralElement',
companionSuccess: 'companionSuccess',
companionError: 'companionError',
}),
addFeedback(task) {
this.currentDialogFeedback.attributes = {};
this.currentDialogFeedback.attributes.content = '';
this.currentDialogFeedback.relationships = {};
this.currentDialogFeedback.relationships.task = {};
this.currentDialogFeedback.relationships.task.data = {};
this.currentDialogFeedback.relationships.task.data.id = task.id;
this.currentDialogFeedback.relationships.task.data.type = task.type;
this.showAddFeedbackDialog = true;
},
createFeedback() {
if (this.currentDialogFeedback.attributes.content === '') {
this.companionError({
info: this.$gettext('Bitte schreiben Sie ein Feedback.'),
});
return false;
}
this.showAddFeedbackDialog = false;
this.createTaskFeedback({
taskFeedback: this.currentDialogFeedback,
});
this.currentDialogFeedback = {};
},
editFeedback(feedback) {
this.currentDialogFeedback = _.cloneDeep(feedback);
this.showEditFeedbackDialog = true;
},
async updateFeedback() {
this.showEditFeedbackDialog = false;
let attributes = {};
attributes.content = this.currentDialogFeedback.attributes.content;
if (attributes.content === '') {
await this.deleteTaskFeedback({
taskFeedbackId: this.currentDialogFeedback.id,
});
this.companionSuccess({
info: this.$gettext('Feedback wurde gelöscht.'),
});
} else {
await this.updateTaskFeedback({
attributes: attributes,
taskFeedbackId: this.currentDialogFeedback.id,
});
this.companionSuccess({
info: this.$gettext('Feedback wurde gespeichert.'),
});
}
this.currentDialogFeedback = {};
},
solveRenewalRequest(task) {
this.currentDialogTask = _.cloneDeep(task);
this.currentDialogTask.attributes['renewal-date'] = new Date().toISOString();
this.showRenewalDialog = true;
},
updateRenewal() {
this.showRenewalDialog = false;
let attributes = {};
attributes.renewal = this.currentDialogTask.attributes.renewal;
if (attributes.renewal === 'granted') {
attributes['renewal-date'] = new Date(this.currentDialogTask.attributes['renewal-date'] || Date.now()).toISOString();
}
this.updateTask({
attributes: attributes,
taskId: this.currentDialogTask.id,
});
this.currentDialogTask = {};
},
},
};
</script>