Skip to content
Snippets Groups Projects
Select Git revision
  • 7fef0df3ae2d94272081600d3c3500fa2580039a
  • main default protected
  • step-3263
  • feature/plugins-cli
  • feature/vite
  • step-2484-peerreview
  • biest/issue-5051
  • tests/simplify-jsonapi-tests
  • fix/typo-in-1a70031
  • feature/broadcasting
  • database-seeders-and-factories
  • feature/peer-review-2
  • feature-feedback-jsonapi
  • feature/peerreview
  • feature/balloon-plus
  • feature/stock-images-unsplash
  • tic-2588
  • 5.0
  • 5.2
  • biest/unlock-blocks
  • biest-1514
21 results

StructuralElement.php

Blame
  • 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>