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
|
<template>
<SidebarWidget :title="$gettext('Konversationen')" @scroll="handleScroll">
<template #content>
<div class="scrollable_area blubber_thread_widget" :class="{ scrolled }" ref="scrollableArea">
<ol>
<li
v-for="thread in sortedThreads"
:key="thread.id"
:data-thread_id="thread.id"
:class="threadClasses(thread)"
:data-unseen_comments="thread.unseenComments"
@click.prevent="changeActiveThread(thread.id)"
>
<a :href="link(thread.id)">
<div class="avatar" :style="{ backgroundImage: 'url(' + thread.avatar + ')' }"></div>
<div class="info">
<div class="title">
<span class="thread-name">{{ thread.name }}</span>
<span v-if="thread.unseenComments > 0" class="unseen-comments-counter">{{ thread.unseenComments }}</span>
</div>
<studip-date-time
:timestamp="threadLatestActivity(thread)"
:relative="true"
></studip-date-time>
</div>
</a>
</li>
<li class="more" v-if="hasMoreThreads" key="more" ref="more">
<studip-asset-img file="loading-indicator.svg" width="20"></studip-asset-img>
</li>
</ol>
</div>
</template>
<template #actions>
<a :href="urlCompose" data-dialog="width=600;height=300">
<studip-icon shape="add" />
</a>
</template>
</SidebarWidget>
</template>
<script>
import SidebarWidget from '../SidebarWidget.vue';
export default {
emits: ['load-more-threads', 'select-thread'],
props: {
hasMoreThreads: {
type: Boolean,
default: false,
},
threadId: {
type: String,
default: null,
},
threads: {
type: Array,
default: () => [],
},
},
data: () => ({
scrolled: false,
}),
components: {
SidebarWidget,
},
computed: {
sortedThreads() {
const sorted = [...this.threads].sort((a, b) => {
return (
new Date(b['latest-activity']) - new Date(a['latest-activity'])
|| new Date(b['mkdate']) - new Date(a['mkdate'])
|| b.name.localeCompare(a.name)
);
});
return sorted;
},
urlCompose() {
return STUDIP.URLHelper.getURL('dispatch.php/blubber/compose');
},
},
methods: {
changeActiveThread(threadId) {
this.$emit('select-thread', threadId);
},
handleScroll({ element }) {
this.scrolled = element.scrollTop > 0;
if (
this.hasMoreThreads
&& element.scrollTop >= element.scrollHeight - this.$refs.more.clientHeight - element.clientHeight
) {
this.$emit('load-more-threads');
}
},
link(thread_id) {
return STUDIP.URLHelper.getURL(`dispatch.php/blubber/index/${thread_id}`);
},
threadClasses(thread) {
return {
active: thread.id === this.threadId,
unseen: thread.unseenComments > 0,
};
},
threadLatestActivity(thread) {
return new Date(thread['latest-activity']) / 1000;
},
},
};
</script>
|