aboutsummaryrefslogtreecommitdiff
path: root/resources/vue/components/courseware/CoursewareStructuralElementCommentsOverview.vue
blob: e0b264c211baa4d9bc26f03d475107905f262321 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
<template>
    <div class="cw-structural-element-comments-overview-wrapper">
        <table class="default">
            <caption>
                {{ $gettext('Seiten') }}
            </caption>
            <colgroup>
                <col style="width: 16em">
                <col style="width: 16em">
                <col style="width: 8em">
                <col class="responsive-hidden" style="width: 8em">
                <col class="responsive-hidden" style="width: 8em">
                <col style="width: 2em">
            </colgroup>
            <thead>
                <tr class="sortable">
                    <th :class="getSortClass('units')" @click="sort('units')">
                        <a href="#">{{ $gettext('Lernmaterial') }}</a>
                    </th>
                    <th :class="getSortClass('structural-elements')" @click="sort('structural-elements')">
                        <a href="#">{{ $gettext('Seite') }}</a>
                    </th>
                    <th></th>
                    <th class="responsive-hidden" :class="getSortClass('comments')" @click="sort('comments')">
                        <a href="#">{{ $gettext('Kommentare') }}</a>
                    </th>
                    <th class="responsive-hidden" :class="getSortClass('feedback')" @click="sort('feedback')">
                        <a href="#">{{ $gettext('Anmerkungen') }}</a>
                    </th>
                    <th class="actions">
                        {{ $gettext('Aktionen') }}
                    </th>
                </tr>
            </thead>
            <tbody v-if="filteredElements.length > 0">
                <tr v-for="element in filteredElements" :key="element.id">
                    <td>{{ element.unitName }}</td>
                    <td>
                        <a :href="element.url">
                            {{ element.attributes.title }}
                        </a>
                    </td>
                    <td></td>
                    <td class="responsive-hidden">
                        <a
                            href="#"
                            :title="$gettext('Kommentare anzeigen')"
                            @click.prevent="enableCommentsDialog(element)"
                        >
                            {{ $ngettext(
                                '%{length} Kommentar',
                                '%{length} Kommentare',
                                element.comments.length,
                                { length: element.comments.length }
                            ) }}
                        </a>
                    </td>
                    <td class="responsive-hidden">
                        <a
                            v-if="element.attributes['can-edit'] && element.feedbacks.length > 0"
                            href="#"
                            :title="$gettext('Anmerkungen anzeigen')"
                            @click.prevent="enableFeedbackDialog(element)"
                        >
                            {{ $ngettext(
                                '%{length} Anmerkung',
                                '%{length} Anmerkungen',
                                element.feedbacks.length,
                                {length: element.feedbacks.length}
                            ) }}
                        </a>
                        <template v-else>
                            -
                        </template>
                    </td>
                    <td class="actions">
                        <studip-action-menu
                            :items="getMenuItems(element)"
                            :context="$gettext('Seiten')"
                            @showComments="enableCommentsDialog(element)"
                            @showFeedback="enableFeedbackDialog(element)"
                        />
                    </td>
                </tr>
            </tbody>
            <tbody v-else>
                <tr class="empty">
                    <td colspan="6">
                        {{ $gettext('Es wurden keine Kommentare oder Anmerkungen gefunden') }}
                    </td>
                </tr>
            </tbody>
        </table>
        <courseware-comments-overview-dialog
            v-if="showCommentsDialog"
            item-type="structuralElement"
            com-type="comment"
            :item="currentDialogElement"
            @close="closeCommentsDialog"
        />
        <courseware-comments-overview-dialog
            v-if="showFeedbackDialog"
            item-type="structuralElement"
            com-type="feedback"
            :item="currentDialogElement"
            @close="closeFeedbackDialog"
        />
    </div>
</template>

<script>
import CoursewareCommentsOverviewDialog from './CoursewareCommentsOverviewDialog.vue';
import commentsOverviewMixin from '@/vue/mixins/courseware/comments-overview-helper.js';
import { mapGetters } from 'vuex';

export default {
    name: 'courseware-structural-element-comments-overview',
    components: {
        CoursewareCommentsOverviewDialog
    },
    mixins: [commentsOverviewMixin],
    data() {
        return {
            elementsWithRelations: [],
            currentDialogElement: null,
            showCommentsDialog: false,
            showFeedbackDialog: false,
            sortBy: 'units',
            sortASC: true,
        }
    },
    computed: {
        ...mapGetters({
            units: 'courseware-units/all',
            elements: 'courseware-structural-elements/all',
            elementComments: 'courseware-structural-element-comments/all',
            elementFeedbacks: 'courseware-structural-element-feedback/all',
            elementById: 'courseware-structural-elements/byId',
            unitById: 'courseware-units/byId',
            context: 'context',
            createdFilter: 'createdFilter',
            unitFilter: 'unitFilter'
        }),
        filteredElements() {
            let filteredElements = this.elementsWithRelations;
            if (this.unitFilter !== 'all') {
                filteredElements = filteredElements.filter(block => block.unit.id === this.unitFilter);
            }
            return this.sortElements(filteredElements);
        }
    },
    methods: {
        collectElementRelations() {
            this.elementsWithRelations = _.cloneDeep(this.elements);
            this.elementsWithRelations.forEach(element => {
                element.comments = this.elementComments.filter(comment => comment.relationships['structural-element'].data.id === element.id);
                element.comments.oneDay = 0;
                element.comments.oneWeek = 0;
                element.comments.forEach(comment => {
                    comment.created = this.calcCreated(comment.attributes.mkdate);
                    if (comment.created.oneDay) {
                        element.comments.oneDay++;
                    }
                    if (comment.created.oneWeek) {
                        element.comments.oneWeek++;
                    }
                });
                element.feedbacks = this.elementFeedbacks.filter(feedback => feedback.relationships['structural-element'].data.id === element.id);
                element.feedbacks.forEach(feedback => {
                    feedback.created = this.calcCreated(feedback.attributes.mkdate);
                });
                if (element.comments.length === 0 && element.feedbacks.length === 0) {
                    element.empty = true;
                } else {
                    element.unit = this.unitById({ id: element.relationships.unit.data.id });
                    const unitRoot = this.elementById({ id: element.unit.relationships['structural-element'].data.id});
                    element.unitName = unitRoot.attributes.title;
                    element.url = STUDIP.URLHelper.getURL(`dispatch.php/course/courseware/courseware/${element.unit.id}?cid=${this.context.id}#/structural_element/${element.id}`);
                }
            });
            this.elementsWithRelations = this.elementsWithRelations.filter(element => !element.empty);
        },
        enableCommentsDialog(element) {
            this.currentDialogElement = element;
            this.showCommentsDialog = true;
        },
        closeCommentsDialog() {
            this.showCommentsDialog = false;
            this.currentDialogElement = null;
            this.collectElementRelations();
        },
        enableFeedbackDialog(element) {
            this.currentDialogElement = element;
            this.showFeedbackDialog = true;
        },
        closeFeedbackDialog() {
            this.showFeedbackDialog = false;
            this.currentDialogElement = null;
            this.collectElementRelations();
        },
        getMenuItems(element) {
            let menuItems = [];
            menuItems.push({ id: 1, label: this.$gettext('Kommentare anzeigen'), icon: 'comment2', emit: 'showComments' });
            if (element.attributes['can-edit']) {
                menuItems.push({ id: 2, label: this.$gettext('Anmerkungen anzeigen'), icon: 'comment2', emit: 'showFeedback' });
            }

            return menuItems;
        },
        sort(sortBy) {
            if (this.sortBy === sortBy) {
                this.sortASC = !this.sortASC;
            } else {
                this.sortBy = sortBy;
            }
        },
        getSortClass(col) {
            if (col === this.sortBy) {
                return this.sortASC ? 'sortasc' : 'sortdesc';
            }
        },
        sortElements(elements) {
            switch (this.sortBy) {
                case 'units':
                    elements = elements.sort((a, b) => {
                        if (this.sortASC) {
                            return a.unitName < b.unitName ? -1 : 1;
                        } else {
                            return a.unitName > b.unitName ? -1 : 1;
                        }
                    });
                    break;
                case 'structural-elements':
                    elements = elements.sort((a, b) => {
                        if (this.sortASC) {
                            return a.attributes.title < b.attributes.title ? -1 : 1;
                        } else {
                            return a.attributes.title > b.attributes.title ? -1 : 1;
                        }
                    });
                    break;
                case 'comments':
                    elements = elements.sort((a, b) => {
                        if (this.sortASC) {
                            return a.comments.length - b.comments.length;
                        } else {
                            return  b.comments.length - a.comments.length;
                        }
                    });
                    break;
                case 'feedback':
                    elements = elements.sort((a, b) => {
                            if (this.sortASC) {
                                return a.feedbacks.length - b.feedbacks.length;
                            } else {
                                return  b.feedbacks.length - a.feedbacks.length;
                            }
                        });
                    break;
            }

            return elements;
        }
    },
    mounted() {
        this.$nextTick(() => {
            this.collectElementRelations();
        });
    }
}
</script>