mirror of
https://github.com/Ocelot-Social-Community/Ocelot-Social.git
synced 2025-12-13 07:46:06 +00:00
196 lines
5.1 KiB
Vue
196 lines
5.1 KiB
Vue
<template>
|
|
<base-card v-if="isUnavailable" class="comment-card">
|
|
<p>
|
|
<base-icon name="ban" />
|
|
{{ this.$t('comment.content.unavailable-placeholder') }}
|
|
</p>
|
|
</base-card>
|
|
<base-card v-else :class="commentClass" :id="anchor">
|
|
<header class="header">
|
|
<user-teaser :user="comment.author" :date-time="comment.createdAt">
|
|
<template v-if="wasEdited" v-slot:dateTime>
|
|
<span>({{ $t('comment.edited') }})</span>
|
|
</template>
|
|
</user-teaser>
|
|
<client-only>
|
|
<content-menu
|
|
v-show="!editingComment"
|
|
placement="bottom-end"
|
|
resource-type="comment"
|
|
:resource="comment"
|
|
:modalsData="menuModalsData"
|
|
:is-owner="user.id === comment.author.id"
|
|
@editComment="editComment(true)"
|
|
/>
|
|
</client-only>
|
|
</header>
|
|
<hc-comment-form
|
|
v-if="editingComment"
|
|
:update="true"
|
|
:postId="postId"
|
|
:comment="comment"
|
|
@finishEditing="editComment(false)"
|
|
@updateComment="updateComment"
|
|
@collapse="isCollapsed = true"
|
|
/>
|
|
<template v-else>
|
|
<content-viewer :content="commentContent" class="content" />
|
|
<base-button v-if="hasLongContent" size="small" ghost @click="isCollapsed = !isCollapsed">
|
|
{{ isCollapsed ? $t('comment.show.more') : $t('comment.show.less') }}
|
|
</base-button>
|
|
</template>
|
|
</base-card>
|
|
</template>
|
|
|
|
<script>
|
|
import { mapGetters } from 'vuex'
|
|
import { COMMENT_MAX_UNTRUNCATED_LENGTH, COMMENT_TRUNCATE_TO_LENGTH } from '~/constants/comment'
|
|
import UserTeaser from '~/components/UserTeaser/UserTeaser'
|
|
import ContentMenu from '~/components/ContentMenu/ContentMenu'
|
|
import ContentViewer from '~/components/Editor/ContentViewer'
|
|
import HcCommentForm from '~/components/CommentForm/CommentForm'
|
|
import CommentMutations from '~/graphql/CommentMutations'
|
|
import scrollToAnchor from '~/mixins/scrollToAnchor.js'
|
|
|
|
export default {
|
|
components: {
|
|
UserTeaser,
|
|
ContentMenu,
|
|
ContentViewer,
|
|
HcCommentForm,
|
|
},
|
|
mixins: [scrollToAnchor],
|
|
data() {
|
|
const anchor = `commentId-${this.comment.id}`
|
|
const isTarget = this.$route.hash === `#${anchor}`
|
|
|
|
return {
|
|
anchor,
|
|
isTarget,
|
|
isCollapsed: !isTarget,
|
|
editingComment: false,
|
|
}
|
|
},
|
|
props: {
|
|
comment: {
|
|
type: Object,
|
|
required: true,
|
|
},
|
|
postId: {
|
|
type: String,
|
|
required: true,
|
|
},
|
|
},
|
|
computed: {
|
|
...mapGetters({
|
|
user: 'auth/user',
|
|
isModerator: 'auth/isModerator',
|
|
}),
|
|
hasLongContent() {
|
|
return this.$filters.removeHtml(this.comment.content).length > COMMENT_MAX_UNTRUNCATED_LENGTH
|
|
},
|
|
isUnavailable() {
|
|
return (this.comment.deleted || this.comment.disabled) && !this.isModerator
|
|
},
|
|
wasEdited() {
|
|
return this.comment.createdAt !== this.comment.updatedAt
|
|
},
|
|
commentClass() {
|
|
let commentClass = 'comment-card'
|
|
|
|
if (this.comment.deleted || this.comment.disabled) commentClass += ' disabled-content'
|
|
if (this.isTarget) commentClass += ' --target'
|
|
|
|
return commentClass
|
|
},
|
|
commentContent() {
|
|
if (this.hasLongContent && this.isCollapsed) {
|
|
return this.$filters.truncate(this.comment.content, COMMENT_TRUNCATE_TO_LENGTH)
|
|
}
|
|
|
|
return this.comment.content
|
|
},
|
|
menuModalsData() {
|
|
return {
|
|
delete: {
|
|
titleIdent: 'delete.comment.title',
|
|
messageIdent: 'delete.comment.message',
|
|
messageParams: {
|
|
name: this.$filters.truncate(this.comment.contentExcerpt, 30),
|
|
},
|
|
buttons: {
|
|
confirm: {
|
|
danger: true,
|
|
icon: 'trash',
|
|
textIdent: 'delete.submit',
|
|
callback: this.deleteCommentCallback,
|
|
},
|
|
cancel: {
|
|
icon: 'close',
|
|
textIdent: 'delete.cancel',
|
|
callback: () => {},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
},
|
|
},
|
|
methods: {
|
|
checkAnchor(anchor) {
|
|
return `#${this.anchor}` === anchor
|
|
},
|
|
editComment(editing) {
|
|
this.editingComment = editing
|
|
this.$emit('toggleNewCommentForm', !editing)
|
|
},
|
|
updateComment(comment) {
|
|
this.$emit('updateComment', comment)
|
|
},
|
|
async deleteCommentCallback() {
|
|
try {
|
|
const {
|
|
data: { DeleteComment },
|
|
} = await this.$apollo.mutate({
|
|
mutation: CommentMutations(this.$i18n).DeleteComment,
|
|
variables: { id: this.comment.id },
|
|
})
|
|
this.$toast.success(this.$t(`delete.comment.success`))
|
|
this.$emit('deleteComment', DeleteComment)
|
|
} catch (err) {
|
|
this.$toast.error(err.message)
|
|
}
|
|
},
|
|
},
|
|
}
|
|
</script>
|
|
<style lang="scss">
|
|
.comment-card {
|
|
display: flex;
|
|
flex-direction: column;
|
|
margin-bottom: $space-small;
|
|
|
|
&.--target {
|
|
animation: highlight 4s ease;
|
|
}
|
|
|
|
> .header {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
margin-bottom: $space-small;
|
|
}
|
|
|
|
> .base-button {
|
|
align-self: flex-end;
|
|
}
|
|
}
|
|
|
|
@keyframes highlight {
|
|
0% {
|
|
border: $border-size-base solid $color-primary;
|
|
}
|
|
100% {
|
|
border: $border-size-base solid transparent;
|
|
}
|
|
}
|
|
</style>
|