149 lines
3.5 KiB
Vue
149 lines
3.5 KiB
Vue
<template>
|
|
<div>
|
|
<div class="comment--header">
|
|
<NcAvatar :user="currentUser.uid" />
|
|
<span class="username">
|
|
{{ currentUser.displayName }}
|
|
</span>
|
|
</div>
|
|
|
|
<CommentItem v-if="replyTo"
|
|
:comment="replyTo"
|
|
:reply="true"
|
|
:preview="true"
|
|
@cancel="cancelReply" />
|
|
<CommentForm v-model="newComment" @submit="createComment" />
|
|
|
|
<ul v-if="getCommentsForCard(card.id).length > 0" id="commentsFeed">
|
|
<CommentItem v-for="comment in getCommentsForCard(card.id)"
|
|
:key="comment.id"
|
|
:comment="comment"
|
|
@doReload="loadComments" />
|
|
<InfiniteLoading :identifier="card.id" @infinite="infiniteHandler">
|
|
<div slot="spinner" class="icon-loading" />
|
|
<div slot="no-more" />
|
|
<div slot="no-results" />
|
|
</InfiniteLoading>
|
|
</ul>
|
|
<div v-else-if="isLoading" class="icon icon-loading" />
|
|
<div v-else class="emptycontent">
|
|
<div :class="{ 'icon-comment': !error, 'icon-error': error }" />
|
|
<p>{{ error || t('deck', 'No comments yet. Begin the discussion!') }}</p>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script>
|
|
import { mapState, mapGetters } from 'vuex'
|
|
import { NcAvatar } from '@nextcloud/vue'
|
|
import CommentItem from './CommentItem.vue'
|
|
import CommentForm from './CommentForm.vue'
|
|
import InfiniteLoading from 'vue-infinite-loading'
|
|
import { getCurrentUser } from '@nextcloud/auth'
|
|
|
|
export default {
|
|
name: 'CardSidebarTabComments',
|
|
components: {
|
|
NcAvatar,
|
|
CommentItem,
|
|
CommentForm,
|
|
InfiniteLoading,
|
|
},
|
|
props: {
|
|
card: {
|
|
type: Object,
|
|
default: undefined,
|
|
},
|
|
tabQuery: {
|
|
type: String,
|
|
required: false,
|
|
default: null,
|
|
},
|
|
},
|
|
data() {
|
|
return {
|
|
newComment: '',
|
|
isLoading: false,
|
|
currentUser: getCurrentUser(),
|
|
error: null,
|
|
}
|
|
},
|
|
computed: {
|
|
...mapState({
|
|
currentBoard: state => state.currentBoard,
|
|
replyTo: state => state.comment.replyTo,
|
|
}),
|
|
...mapGetters([
|
|
'getCommentsForCard',
|
|
'hasMoreComments',
|
|
]),
|
|
members() {
|
|
return this.currentBoard.users
|
|
},
|
|
},
|
|
watch: {
|
|
card: {
|
|
immediate: true,
|
|
handler() {
|
|
this.loadComments()
|
|
},
|
|
},
|
|
},
|
|
methods: {
|
|
async infiniteHandler($state) {
|
|
this.error = null
|
|
try {
|
|
await this.loadMore()
|
|
if (this.hasMoreComments(this.card.id)) {
|
|
$state.loaded()
|
|
} else {
|
|
$state.complete()
|
|
}
|
|
} catch (e) {
|
|
console.error('Failed to fetch more comments during infinite loading', e)
|
|
this.error = t('deck', 'Failed to load comments')
|
|
$state.complete()
|
|
}
|
|
},
|
|
async loadComments() {
|
|
this.$store.dispatch('setReplyTo', null)
|
|
this.error = null
|
|
this.isLoading = true
|
|
try {
|
|
await this.$store.dispatch('fetchComments', { cardId: this.card.id })
|
|
this.isLoading = false
|
|
if (this.card.commentsUnread > 0) {
|
|
await this.$store.dispatch('markCommentsAsRead', this.card.id)
|
|
}
|
|
} catch (e) {
|
|
this.isLoading = false
|
|
console.error('Failed to fetch more comments during infinite loading', e)
|
|
this.error = t('deck', 'Failed to load comments')
|
|
}
|
|
},
|
|
async createComment(content) {
|
|
const commentObj = {
|
|
cardId: this.card.id,
|
|
comment: content,
|
|
}
|
|
await this.$store.dispatch('createComment', commentObj)
|
|
this.$store.dispatch('setReplyTo', null)
|
|
this.newComment = ''
|
|
await this.loadComments()
|
|
},
|
|
async loadMore() {
|
|
this.isLoading = true
|
|
await this.$store.dispatch('fetchMore', { cardId: this.card.id })
|
|
this.isLoading = false
|
|
},
|
|
cancelReply() {
|
|
this.$store.dispatch('setReplyTo', null)
|
|
},
|
|
},
|
|
}
|
|
</script>
|
|
|
|
<style scoped lang="scss">
|
|
@import '../../css/comments';
|
|
</style>
|