refactor: update notifications to return count

- still working on getting the counter to be reactive when markAsRead,
  subscribeToMore are triggered
This commit is contained in:
mattwr18 2020-04-20 15:05:06 +02:00
parent 58bc9aa414
commit 3f30d93726
7 changed files with 83 additions and 106 deletions

View File

@ -90,7 +90,7 @@ const notifyUsersOfMention = async (label, id, idsOfUsers, reason, context) => {
SET notification.read = FALSE
SET notification.createdAt = COALESCE(notification.createdAt, toString(datetime()))
SET notification.updatedAt = toString(datetime())
RETURN notification {.*, from: finalResource, to: properties(user)}
RETURN { notificationsCount: toString(size(collect(notification))), notifications: collect(notification {.*, from: finalResource, to: properties(user)}) } as noticationsResult
`
const session = context.driver.session()
const writeTxResultPromise = session.writeTransaction(async (transaction) => {
@ -99,10 +99,10 @@ const notifyUsersOfMention = async (label, id, idsOfUsers, reason, context) => {
idsOfUsers,
reason,
})
return notificationTransactionResponse.records.map((record) => record.get('notification'))
return notificationTransactionResponse.records.map((record) => record.get('noticationsResult'))
})
try {
const notifications = await writeTxResultPromise
const [notifications] = await writeTxResultPromise
return notifications
} catch (error) {
throw new Error(error)
@ -126,14 +126,14 @@ const notifyUsersOfComment = async (label, commentId, postAuthorId, reason, cont
SET notification.updatedAt = toString(datetime())
WITH notification, postAuthor, post,
comment {.*, __typename: labels(comment)[0], author: properties(commenter), post: post {.*, author: properties(postAuthor) } } AS finalResource
RETURN notification {.*, from: finalResource, to: properties(postAuthor)}
RETURN { notificationsCount: toString(size(collect(notification))), notifications: collect(notification {.*, from: finalResource, to: properties(postAuthor)}) } as noticationsResult
`,
{ commentId, postAuthorId, reason },
)
return notificationTransactionResponse.records.map((record) => record.get('notification'))
return notificationTransactionResponse.records.map((record) => record.get('noticationsResult'))
})
try {
const notifications = await writeTxResultPromise
const [notifications] = await writeTxResultPromise
return notifications
} finally {
session.close()

View File

@ -104,7 +104,6 @@ export default shield(
mutedUsers: isAuthenticated,
blockedUsers: isAuthenticated,
notifications: isAuthenticated,
unreadNotificationsCount: isAuthenticated,
Donations: isAuthenticated,
},
Mutation: {

View File

@ -8,7 +8,9 @@ export default {
subscribe: withFilter(
() => pubsub.asyncIterator(NOTIFICATION_ADDED),
(payload, variables) => {
return payload.notificationAdded.to.id === variables.userId
const { notifications } = payload.notificationAdded
const [currentUser] = notifications
return currentUser.to.id === variables.userId
},
),
},
@ -50,46 +52,24 @@ export default {
[(resource)-[:COMMENTS]->(post:Post)<-[:WROTE]-(author:User) | post{.*, author: properties(author)} ] AS posts
WITH resource, user, notification, authors, posts,
resource {.*, __typename: labels(resource)[0], author: authors[0], post: posts[0]} AS finalResource
RETURN notification {.*, from: finalResource, to: properties(user)}
${orderByClause}
RETURN { notificationsCount: toString(size(collect(notification))), notifications: collect(notification {.*, from: finalResource, to: properties(user)})} as noticationsResult
${offset} ${limit}
`,
{ id: currentUser.id },
)
log(notificationsTransactionResponse)
return notificationsTransactionResponse.records.map((record) => record.get('notification'))
return notificationsTransactionResponse.records.map((record) =>
record.get('noticationsResult'),
)
})
try {
const notifications = await readTxResultPromise
const [notifications] = await readTxResultPromise
return notifications
} finally {
session.close()
}
},
unreadNotificationsCount: async (_parent, _args, context, _resolveInfo) => {
const { user: currentUser, driver } = context
const session = driver.session()
const readTxResultPromise = session.readTransaction(async (transaction) => {
const unreadNotificationsCountTransactionResponse = await transaction.run(
`
MATCH (resource {deleted: false, disabled: false})-[notification:NOTIFIED {read: false}]->(user:User {id:$id})
RETURN count(notification) as unreadNotificationsCount
`,
{ id: currentUser.id },
)
log(unreadNotificationsCountTransactionResponse)
return unreadNotificationsCountTransactionResponse.records.map(
(record) => record.get('unreadNotificationsCount').low,
)
})
try {
const [unreadNotificationsCount] = await readTxResultPromise
return unreadNotificationsCount
} finally {
session.close()
}
},
},
Mutation: {
markAsRead: async (parent, args, context, resolveInfo) => {

View File

@ -8,6 +8,11 @@ type NOTIFIED {
reason: NotificationReason
}
type notificationsResult {
notificationsCount: Int!
notifications: [NOTIFIED]
}
union NotificationSource = Post | Comment
enum NotificationOrdering {
@ -24,8 +29,7 @@ enum NotificationReason {
}
type Query {
notifications(read: Boolean, orderBy: NotificationOrdering, first: Int, offset: Int): [NOTIFIED]
unreadNotificationsCount: Int!
notifications(read: Boolean, orderBy: NotificationOrdering, first: Int, offset: Int): notificationsResult!
}
type Mutation {
@ -33,5 +37,5 @@ type Mutation {
}
type Subscription {
notificationAdded(userId: ID!): NOTIFIED
notificationAdded(userId: ID!): notificationsResult
}

View File

@ -1,26 +1,22 @@
<template>
<nuxt-link
v-if="!unreadNotificationsCount"
class="notifications-menu"
:to="{ name: 'notifications' }"
>
<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="unreadNotificationsCount" danger />
<counter-icon icon="bell" :count="notificationsCount" danger />
</base-button>
</template>
<template slot="popover">
<div class="notifications-menu-popover">
<notification-list :notifications="notifications" @markAsRead="markAsRead" />
<notification-list :notifications="unreadNotifications" @markAsRead="markAsRead" />
</div>
<div class="notifications-link-container">
<nuxt-link :to="{ name: 'notifications' }">
{{
unreadNotificationsCount > 25
? $t('notifications.manyNotifications', { unreadNotificationsCount })
notificationsCount > 25
? $t('notifications.manyNotifications', { notificationsCount })
: $t('notifications.pageLink')
}}
</nuxt-link>
@ -32,12 +28,7 @@
<script>
import { mapGetters } from 'vuex'
import unionBy from 'lodash/unionBy'
import {
notificationQuery,
markAsReadMutation,
notificationAdded,
unreadNotificationsCountQuery,
} from '~/graphql/User'
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'
@ -51,7 +42,8 @@ export default {
},
data() {
return {
notifications: [],
unreadNotifications: [],
notificationsCount: null,
}
},
props: {
@ -65,7 +57,7 @@ export default {
mutation: markAsReadMutation(this.$i18n),
variables,
update: () => {
this.unreadNotificationsCount--
this.notificationsCount--
},
})
} catch (err) {
@ -90,6 +82,10 @@ export default {
first: 25,
}
},
update({ notifications }) {
this.unreadNotifications = notifications.notifications
this.notificationsCount = notifications.notificationsCount
},
subscribeToMore: {
document: notificationAdded(),
variables() {
@ -102,9 +98,11 @@ export default {
data: { notificationAdded: newNotification },
} = subscriptionData
return {
notifications: unionBy(
[newNotification],
previousResult.notifications,
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)),
}
@ -114,9 +112,6 @@ export default {
this.$toast.error(error.message)
},
},
unreadNotificationsCount: {
query: unreadNotificationsCountQuery,
},
},
}
</script>

View File

@ -69,30 +69,32 @@ export const notificationQuery = (i18n) => {
query($read: Boolean, $orderBy: NotificationOrdering, $first: Int, $offset: Int) {
notifications(read: $read, orderBy: $orderBy, first: $first, offset: $offset) {
id
read
reason
createdAt
updatedAt
from {
__typename
... on Post {
...post
author {
...user
}
}
... on Comment {
...comment
author {
...user
}
post {
notificationsCount
notifications {
id
read
reason
createdAt
updatedAt
from {
... on Post {
...post
author {
...user
}
}
... on Comment {
...comment
author {
...user
}
post {
...post
author {
...user
}
}
}
}
}
}
@ -144,30 +146,33 @@ export const notificationAdded = () => {
subscription notifications($userId: ID!) {
notificationAdded(userId: $userId) {
id
read
reason
createdAt
updatedAt
from {
__typename
... on Post {
...post
author {
...user
}
}
... on Comment {
...comment
author {
...user
}
post {
notificationsCount
notifications {
id
read
reason
createdAt
updatedAt
from {
__typename
... on Post {
...post
author {
...user
}
}
... on Comment {
...comment
author {
...user
}
post {
...post
author {
...user
}
}
}
}
}
}
@ -175,12 +180,6 @@ export const notificationAdded = () => {
`
}
export const unreadNotificationsCountQuery = gql`
query {
unreadNotificationsCount
}
`
export const followUserMutation = (i18n) => {
return gql`
${userFragment}

View File

@ -450,7 +450,7 @@
"read": "Read",
"unread": "Unread"
},
"manyNotifications": "See all {unreadNotificationsCount} notifications",
"manyNotifications": "See all {notificationsCount} notifications",
"pageLink": "All notifications",
"post": "Post",
"reason": {