mirror of
https://github.com/Ocelot-Social-Community/Ocelot-Social.git
synced 2025-12-13 07:46:06 +00:00
- still working on getting the counter to be reactive when markAsRead, subscribeToMore are triggered
145 lines
3.8 KiB
Vue
145 lines
3.8 KiB
Vue
<template>
|
|
<nuxt-link v-if="!notificationsCount" class="notifications-menu" :to="{ name: 'notifications' }">
|
|
<base-button icon="bell" ghost circle />
|
|
</nuxt-link>
|
|
<dropdown v-else class="notifications-menu" offset="8" :placement="placement">
|
|
<template #default="{ toggleMenu }">
|
|
<base-button @click="toggleMenu" ghost circle>
|
|
<counter-icon icon="bell" :count="notificationsCount" danger />
|
|
</base-button>
|
|
</template>
|
|
<template slot="popover">
|
|
<div class="notifications-menu-popover">
|
|
<notification-list :notifications="unreadNotifications" @markAsRead="markAsRead" />
|
|
</div>
|
|
<div class="notifications-link-container">
|
|
<nuxt-link :to="{ name: 'notifications' }">
|
|
{{
|
|
notificationsCount > 25
|
|
? $t('notifications.manyNotifications', { notificationsCount })
|
|
: $t('notifications.pageLink')
|
|
}}
|
|
</nuxt-link>
|
|
</div>
|
|
</template>
|
|
</dropdown>
|
|
</template>
|
|
|
|
<script>
|
|
import { mapGetters } from 'vuex'
|
|
import unionBy from 'lodash/unionBy'
|
|
import { notificationQuery, markAsReadMutation, notificationAdded } from '~/graphql/User'
|
|
import CounterIcon from '~/components/_new/generic/CounterIcon/CounterIcon'
|
|
import Dropdown from '~/components/Dropdown'
|
|
import NotificationList from '../NotificationList/NotificationList'
|
|
|
|
export default {
|
|
name: 'NotificationMenu',
|
|
components: {
|
|
CounterIcon,
|
|
Dropdown,
|
|
NotificationList,
|
|
},
|
|
data() {
|
|
return {
|
|
unreadNotifications: [],
|
|
notificationsCount: null,
|
|
}
|
|
},
|
|
props: {
|
|
placement: { type: String },
|
|
},
|
|
methods: {
|
|
async markAsRead(notificationSourceId) {
|
|
const variables = { id: notificationSourceId }
|
|
try {
|
|
await this.$apollo.mutate({
|
|
mutation: markAsReadMutation(this.$i18n),
|
|
variables,
|
|
update: () => {
|
|
this.notificationsCount--
|
|
},
|
|
})
|
|
} catch (err) {
|
|
this.$toast.error(err.message)
|
|
}
|
|
},
|
|
},
|
|
computed: {
|
|
...mapGetters({
|
|
user: 'auth/user',
|
|
}),
|
|
},
|
|
apollo: {
|
|
notifications: {
|
|
query() {
|
|
return notificationQuery(this.$i18n)
|
|
},
|
|
variables() {
|
|
return {
|
|
read: false,
|
|
orderBy: 'updatedAt_desc',
|
|
first: 25,
|
|
}
|
|
},
|
|
update({ notifications }) {
|
|
this.unreadNotifications = notifications.notifications
|
|
this.notificationsCount = notifications.notificationsCount
|
|
},
|
|
subscribeToMore: {
|
|
document: notificationAdded(),
|
|
variables() {
|
|
return {
|
|
userId: this.user.id,
|
|
}
|
|
},
|
|
updateQuery: (previousResult, { subscriptionData }) => {
|
|
const {
|
|
data: { notificationAdded: newNotification },
|
|
} = subscriptionData
|
|
return {
|
|
notificationsCount:
|
|
previousResult.notificationsCount - newNotification.notificationsCount,
|
|
unreadNotifications: unionBy(
|
|
[newNotification.notifications],
|
|
previousResult.notifications.notifications,
|
|
(notification) => notification.id,
|
|
).sort((a, b) => new Date(b.updatedAt) - new Date(a.updatedAt)),
|
|
}
|
|
},
|
|
},
|
|
error(error) {
|
|
this.$toast.error(error.message)
|
|
},
|
|
},
|
|
},
|
|
}
|
|
</script>
|
|
|
|
<style lang="scss">
|
|
.notifications-menu {
|
|
flex-shrink: 0;
|
|
display: flex;
|
|
align-items: center;
|
|
|
|
.base-button {
|
|
overflow: visible;
|
|
}
|
|
}
|
|
|
|
.notifications-menu-popover {
|
|
max-width: 500px;
|
|
margin-bottom: $size-height-base;
|
|
}
|
|
.notifications-link-container {
|
|
background-color: $background-color-softer-active;
|
|
text-align: center;
|
|
position: fixed;
|
|
bottom: 0;
|
|
left: 0;
|
|
right: 0;
|
|
height: $size-height-base;
|
|
padding: $space-x-small;
|
|
}
|
|
</style>
|