Merge pull request #433 from shariquerik/notification-refactor

This commit is contained in:
Shariq Ansari 2024-10-31 12:49:37 +05:30 committed by GitHub
commit 0698fd6d78
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 43 additions and 54 deletions

View File

@ -18,15 +18,12 @@
> >
<template #right> <template #right>
<Badge <Badge
v-if=" v-if="!isSidebarCollapsed && unreadNotificationsCount"
!isSidebarCollapsed && :label="unreadNotificationsCount"
notificationsStore().unreadNotificationsCount
"
:label="notificationsStore().unreadNotificationsCount"
variant="subtle" variant="subtle"
/> />
<div <div
v-else-if="notificationsStore().unreadNotificationsCount" v-else-if="unreadNotificationsCount"
class="absolute -left-1.5 top-1 z-20 h-[5px] w-[5px] translate-x-6 translate-y-1 rounded-full bg-gray-800 ring-1 ring-white" class="absolute -left-1.5 top-1 z-20 h-[5px] w-[5px] translate-x-6 translate-y-1 rounded-full bg-gray-800 ring-1 ring-white"
/> />
</template> </template>
@ -112,7 +109,10 @@ import NotificationsIcon from '@/components/Icons/NotificationsIcon.vue'
import SidebarLink from '@/components/SidebarLink.vue' import SidebarLink from '@/components/SidebarLink.vue'
import Notifications from '@/components/Notifications.vue' import Notifications from '@/components/Notifications.vue'
import { viewsStore } from '@/stores/views' import { viewsStore } from '@/stores/views'
import { notificationsStore } from '@/stores/notifications' import {
unreadNotificationsCount,
notificationsStore,
} from '@/stores/notifications'
import { FeatherIcon } from 'frappe-ui' import { FeatherIcon } from 'frappe-ui'
import { useStorage } from '@vueuse/core' import { useStorage } from '@vueuse/core'
import { computed, h } from 'vue' import { computed, h } from 'vue'

View File

@ -25,8 +25,8 @@
> >
<template #right> <template #right>
<Badge <Badge
v-if="notificationsStore().unreadNotificationsCount" v-if="unreadNotificationsCount"
:label="notificationsStore().unreadNotificationsCount" :label="unreadNotificationsCount"
variant="subtle" variant="subtle"
/> />
</template> </template>
@ -101,7 +101,7 @@ import PhoneIcon from '@/components/Icons/PhoneIcon.vue'
import NotificationsIcon from '@/components/Icons/NotificationsIcon.vue' import NotificationsIcon from '@/components/Icons/NotificationsIcon.vue'
import SidebarLink from '@/components/SidebarLink.vue' import SidebarLink from '@/components/SidebarLink.vue'
import { viewsStore } from '@/stores/views' import { viewsStore } from '@/stores/views'
import { notificationsStore } from '@/stores/notifications' import { unreadNotificationsCount } from '@/stores/notifications'
import { computed, h } from 'vue' import { computed, h } from 'vue'
import { mobileSidebarOpened as sidebarOpened } from '@/composables/settings' import { mobileSidebarOpened as sidebarOpened } from '@/composables/settings'

View File

@ -1,6 +1,6 @@
<template> <template>
<div <div
v-if="notificationsStore().visible" v-if="visible"
ref="target" ref="target"
class="absolute z-20 h-screen bg-white transition-all duration-300 ease-in-out" class="absolute z-20 h-screen bg-white transition-all duration-300 ease-in-out"
:style="{ :style="{
@ -27,7 +27,7 @@
</Tooltip> </Tooltip>
<Tooltip :text="__('Close')"> <Tooltip :text="__('Close')">
<div> <div>
<Button variant="ghost" @click="() => toggleNotificationPanel()"> <Button variant="ghost" @click="() => toggle()">
<template #icon> <template #icon>
<FeatherIcon name="x" class="h-4 w-4" /> <FeatherIcon name="x" class="h-4 w-4" />
</template> </template>
@ -37,11 +37,11 @@
</div> </div>
</div> </div>
<div <div
v-if="notificationsStore().allNotifications?.length" v-if="notifications.data?.length"
class="divide-y overflow-auto text-base" class="divide-y overflow-auto text-base"
> >
<RouterLink <RouterLink
v-for="n in notificationsStore().allNotifications" v-for="n in notifications.data"
:key="n.comment" :key="n.comment"
:to="getRoute(n)" :to="getRoute(n)"
class="flex cursor-pointer items-start gap-2.5 px-4 py-2.5 hover:bg-gray-100" class="flex cursor-pointer items-start gap-2.5 px-4 py-2.5 hover:bg-gray-100"
@ -91,7 +91,11 @@ import WhatsAppIcon from '@/components/Icons/WhatsAppIcon.vue'
import MarkAsDoneIcon from '@/components/Icons/MarkAsDoneIcon.vue' import MarkAsDoneIcon from '@/components/Icons/MarkAsDoneIcon.vue'
import NotificationsIcon from '@/components/Icons/NotificationsIcon.vue' import NotificationsIcon from '@/components/Icons/NotificationsIcon.vue'
import UserAvatar from '@/components/UserAvatar.vue' import UserAvatar from '@/components/UserAvatar.vue'
import { notificationsStore } from '@/stores/notifications' import {
visible,
notifications,
notificationsStore,
} from '@/stores/notifications'
import { globalStore } from '@/stores/global' import { globalStore } from '@/stores/global'
import { timeAgo } from '@/utils' import { timeAgo } from '@/utils'
import { onClickOutside } from '@vueuse/core' import { onClickOutside } from '@vueuse/core'
@ -100,32 +104,27 @@ import { Tooltip } from 'frappe-ui'
import { ref, onMounted, onBeforeUnmount } from 'vue' import { ref, onMounted, onBeforeUnmount } from 'vue'
const { $socket } = globalStore() const { $socket } = globalStore()
const { mark_as_read, toggle, mark_doc_as_read } = notificationsStore()
const target = ref(null) const target = ref(null)
onClickOutside( onClickOutside(
target, target,
() => { () => {
if (notificationsStore().visible) { if (visible.value) toggle()
toggleNotificationPanel()
}
}, },
{ {
ignore: ['#notifications-btn'], ignore: ['#notifications-btn'],
}, },
) )
function toggleNotificationPanel() {
notificationsStore().toggle()
}
function markAsRead(doc) { function markAsRead(doc) {
capture('notification_mark_as_read') capture('notification_mark_as_read')
notificationsStore().mark_doc_as_read(doc) mark_doc_as_read(doc)
} }
function markAllAsRead() { function markAllAsRead() {
capture('notification_mark_all_as_read') capture('notification_mark_all_as_read')
notificationsStore().mark_as_read.reload() mark_as_read.reload()
} }
onBeforeUnmount(() => { onBeforeUnmount(() => {
@ -134,7 +133,7 @@ onBeforeUnmount(() => {
onMounted(() => { onMounted(() => {
$socket.on('crm_notification', () => { $socket.on('crm_notification', () => {
notificationsStore().notifications.reload() notifications.reload()
}) })
}) })
@ -154,6 +153,4 @@ function getRoute(notification) {
hash: notification.hash, hash: notification.hash,
} }
} }
onMounted(() => {})
</script> </script>

View File

@ -12,7 +12,7 @@
<div> <div>
<Button <Button
:label="__('Mark all as read')" :label="__('Mark all as read')"
@click="() => notificationsStore().mark_as_read.reload()" @click="() => mark_as_read.reload()"
> >
<template #prefix> <template #prefix>
<MarkAsDoneIcon class="h-4 w-4" /> <MarkAsDoneIcon class="h-4 w-4" />
@ -24,15 +24,15 @@
</LayoutHeader> </LayoutHeader>
<div class="flex flex-col overflow-hidden"> <div class="flex flex-col overflow-hidden">
<div <div
v-if="notificationsStore().allNotifications?.length" v-if="notifications.data?.length"
class="divide-y overflow-y-auto text-base" class="divide-y overflow-y-auto text-base"
> >
<RouterLink <RouterLink
v-for="n in notificationsStore().allNotifications" v-for="n in notifications.data"
:key="n.comment" :key="n.comment"
:to="getRoute(n)" :to="getRoute(n)"
class="flex cursor-pointer items-start gap-3 px-2.5 py-3 hover:bg-gray-100" class="flex cursor-pointer items-start gap-3 px-2.5 py-3 hover:bg-gray-100"
@click="mark_as_read(n.comment || n.notification_type_doc)" @click="mark_doc_as_read(n.comment || n.notification_type_doc)"
> >
<div class="mt-1 flex items-center gap-2.5"> <div class="mt-1 flex items-center gap-2.5">
<div <div
@ -75,17 +75,14 @@ import WhatsAppIcon from '@/components/Icons/WhatsAppIcon.vue'
import MarkAsDoneIcon from '@/components/Icons/MarkAsDoneIcon.vue' import MarkAsDoneIcon from '@/components/Icons/MarkAsDoneIcon.vue'
import NotificationsIcon from '@/components/Icons/NotificationsIcon.vue' import NotificationsIcon from '@/components/Icons/NotificationsIcon.vue'
import UserAvatar from '@/components/UserAvatar.vue' import UserAvatar from '@/components/UserAvatar.vue'
import { notificationsStore } from '@/stores/notifications' import { notifications, notificationsStore } from '@/stores/notifications'
import { globalStore } from '@/stores/global' import { globalStore } from '@/stores/global'
import { timeAgo } from '@/utils' import { timeAgo } from '@/utils'
import { Breadcrumbs, Tooltip } from 'frappe-ui' import { Breadcrumbs, Tooltip } from 'frappe-ui'
import { onMounted, onBeforeUnmount } from 'vue' import { onMounted, onBeforeUnmount } from 'vue'
const { $socket } = globalStore() const { $socket } = globalStore()
const { mark_as_read, mark_doc_as_read } = notificationsStore()
function mark_as_read(doc) {
notificationsStore().mark_doc_as_read(doc)
}
onBeforeUnmount(() => { onBeforeUnmount(() => {
$socket.off('crm_notification') $socket.off('crm_notification')
@ -93,7 +90,7 @@ onBeforeUnmount(() => {
onMounted(() => { onMounted(() => {
$socket.on('crm_notification', () => { $socket.on('crm_notification', () => {
notificationsStore().notifications.reload() notifications.reload()
}) })
}) })

View File

@ -2,18 +2,21 @@ import { defineStore } from 'pinia'
import { createResource } from 'frappe-ui' import { createResource } from 'frappe-ui'
import { computed, ref } from 'vue' import { computed, ref } from 'vue'
export const visible = ref(false)
export const notifications = createResource({
url: 'crm.api.notifications.get_notifications',
initialData: [],
auto: true,
})
export const unreadNotificationsCount = computed(
() => notifications.data?.filter((n) => !n.read).length || 0,
)
export const notificationsStore = defineStore('crm-notifications', () => { export const notificationsStore = defineStore('crm-notifications', () => {
let visible = ref(false)
const notifications = createResource({
url: 'crm.api.notifications.get_notifications',
initialData: [],
auto: true,
})
const mark_as_read = createResource({ const mark_as_read = createResource({
url: 'crm.api.notifications.mark_as_read', url: 'crm.api.notifications.mark_as_read',
auto: false,
onSuccess: () => { onSuccess: () => {
mark_as_read.params = {} mark_as_read.params = {}
notifications.reload() notifications.reload()
@ -24,11 +27,6 @@ export const notificationsStore = defineStore('crm-notifications', () => {
visible.value = !visible.value visible.value = !visible.value
} }
const allNotifications = computed(() => notifications.data || [])
const unreadNotificationsCount = computed(
() => notifications.data?.filter((n) => !n.read).length || 0
)
function mark_doc_as_read(doc) { function mark_doc_as_read(doc) {
mark_as_read.params = { doc: doc } mark_as_read.params = { doc: doc }
mark_as_read.reload() mark_as_read.reload()
@ -36,9 +34,6 @@ export const notificationsStore = defineStore('crm-notifications', () => {
} }
return { return {
notifications,
visible,
allNotifications,
unreadNotificationsCount, unreadNotificationsCount,
mark_as_read, mark_as_read,
mark_doc_as_read, mark_doc_as_read,