Start subscriptions for notifications

This commit is contained in:
mattwr18 2020-01-24 18:23:59 +01:00
parent 3be5dee08b
commit a28eb8c91f
9 changed files with 80 additions and 22 deletions

View File

@ -1,5 +1,9 @@
import extractMentionedUsers from './mentions/extractMentionedUsers' import extractMentionedUsers from './mentions/extractMentionedUsers'
import { validateNotifyUsers } from '../validation/validationMiddleware' import { validateNotifyUsers } from '../validation/validationMiddleware'
import { PubSub } from 'apollo-server'
const pubsub = new PubSub()
const NOTIFICATION_ADDED = 'NOTIFICATION_ADDED'
const handleContentDataOfPost = async (resolve, root, args, context, resolveInfo) => { const handleContentDataOfPost = async (resolve, root, args, context, resolveInfo) => {
const idsOfUsers = extractMentionedUsers(args.content) const idsOfUsers = extractMentionedUsers(args.content)
@ -74,12 +78,18 @@ const notifyUsersOfMention = async (label, id, idsOfUsers, reason, context) => {
WHEN notification.createdAt IS NULL WHEN notification.createdAt IS NULL
THEN notification END ).createdAt = toString(datetime()) THEN notification END ).createdAt = toString(datetime())
SET notification.updatedAt = toString(datetime()) SET notification.updatedAt = toString(datetime())
RETURN notification
` `
const session = context.driver.session() const session = context.driver.session()
const writeTxResultPromise = session.writeTransaction(async transaction => {
const notificationTransactionResponse = await transaction.run(mentionedCypher, { id, idsOfUsers, reason })
return notificationTransactionResponse.records.map(record => record.get('notification').properties)
})
try { try {
await session.writeTransaction(transaction => { const [notification] = await writeTxResultPromise
return transaction.run(mentionedCypher, { id, idsOfUsers, reason }) return pubsub.publish(NOTIFICATION_ADDED, { notificationAdded: notification })
}) } catch (error) {
throw new Error(error)
} finally { } finally {
session.close() session.close()
} }

View File

@ -1,4 +1,8 @@
import log from './helpers/databaseLogger' import log from './helpers/databaseLogger'
import { PubSub } from 'apollo-server'
const pubsub = new PubSub()
const NOTIFICATION_ADDED = 'NOTIFICATION_ADDED'
const resourceTypes = ['Post', 'Comment'] const resourceTypes = ['Post', 'Comment']
@ -16,6 +20,11 @@ const transformReturnType = record => {
} }
export default { export default {
Subscription: {
notificationAdded: {
subscribe: () => pubsub.asyncIterator([NOTIFICATION_ADDED]),
},
},
Query: { Query: {
notifications: async (_parent, args, context, _resolveInfo) => { notifications: async (_parent, args, context, _resolveInfo) => {
const { user: currentUser } = context const { user: currentUser } = context

View File

@ -7,8 +7,8 @@ import Resolver from './helpers/Resolver'
import { filterForMutedUsers } from './helpers/filterForMutedUsers' import { filterForMutedUsers } from './helpers/filterForMutedUsers'
import { PubSub } from 'apollo-server' import { PubSub } from 'apollo-server'
const pubsub = new PubSub(); const pubsub = new PubSub()
const POST_ADDED = 'POST_ADDED'; const POST_ADDED = 'POST_ADDED'
const maintainPinnedPosts = params => { const maintainPinnedPosts = params => {
@ -113,7 +113,7 @@ export default {
}) })
try { try {
const [post] = await writeTxResultPromise const [post] = await writeTxResultPromise
pubsub.publish(POST_ADDED, { postAdded: post }); pubsub.publish(POST_ADDED, { postAdded: post })
return post return post
} catch (e) { } catch (e) {
if (e.code === 'Neo.ClientError.Schema.ConstraintValidationFailed') if (e.code === 'Neo.ClientError.Schema.ConstraintValidationFailed')

View File

@ -1,7 +1,3 @@
type Subscription {
postAdded: Post
}
type Mutation { type Mutation {
# Get a JWT Token for the given Email and password # Get a JWT Token for the given Email and password
login(email: String!, password: String!): String! login(email: String!, password: String!): String!

View File

@ -0,0 +1,4 @@
type Subscription {
postAdded: Post
notificationAdded: NOTIFIED
}

View File

@ -42,7 +42,6 @@ const createServer = options => {
schema: middleware(schema), schema: middleware(schema),
subscriptions: { subscriptions: {
onConnect: (connectionParams, webSocket) => { onConnect: (connectionParams, webSocket) => {
console.log('connectionParams', connectionParams)
return getContext(connectionParams) return getContext(connectionParams)
}, },
}, },

View File

@ -22,13 +22,13 @@
</template> </template>
<script> <script>
import unionBy from 'lodash/unionBy'
import { NOTIFICATIONS_POLL_INTERVAL } from '~/constants/notifications' import { NOTIFICATIONS_POLL_INTERVAL } from '~/constants/notifications'
import { notificationQuery, markAsReadMutation } from '~/graphql/User' import { notificationQuery, markAsReadMutation } from '~/graphql/User'
import unionBy from 'lodash/unionBy'
import CounterIcon from '~/components/_new/generic/CounterIcon/CounterIcon' import CounterIcon from '~/components/_new/generic/CounterIcon/CounterIcon'
import Dropdown from '~/components/Dropdown' import Dropdown from '~/components/Dropdown'
import NotificationList from '../NotificationList/NotificationList' import NotificationList from '../NotificationList/NotificationList'
import { notificationAdded } from '~/graphql/User'
export default { export default {
name: 'NotificationMenu', name: 'NotificationMenu',
@ -77,11 +77,18 @@ export default {
orderBy: 'updatedAt_desc', orderBy: 'updatedAt_desc',
} }
}, },
pollInterval: NOTIFICATIONS_POLL_INTERVAL, // pollInterval: NOTIFICATIONS_POLL_INTERVAL,
update({ notifications }) { // update({ notifications }) {
return unionBy(notifications, this.notifications, notification => notification.id).sort( // return unionBy(notifications, this.notifications, notification => notification.id).sort(
(a, b) => new Date(b.createdAt) - new Date(a.createdAt), // (a, b) => new Date(b.createdAt) - new Date(a.createdAt),
) // )
// },
subscribeToMore: {
document: notificationAdded(),
updateQuery: (previousResult, { subscriptionData }) => {
const { data: { notificationAdded: newNotification } } = subscriptionData
return { notifications: [newNotification, ...previousResult.notifications] }
},
}, },
error(error) { error(error) {
this.$toast.error(error.message) this.$toast.error(error.message)

View File

@ -130,6 +130,43 @@ export const markAsReadMutation = i18n => {
` `
} }
export const notificationAdded = () => {
return gql`
${userFragment}
${commentFragment}
${postFragment}
subscription notifications {
notificationAdded {
id
read
reason
createdAt
from {
__typename
... on Post {
...post
author {
...user
}
}
... on Comment {
...comment
author {
...user
}
post {
...post
author {
...user
}
}
}
}
}
}
`
}
export const followUserMutation = i18n => { export const followUserMutation = i18n => {
return gql` return gql`
${userFragment} ${userFragment}

View File

@ -244,13 +244,9 @@ export default {
} }
} }
}`, }`,
// Mutate the previous result
updateQuery: (previousResult, { subscriptionData }) => { updateQuery: (previousResult, { subscriptionData }) => {
console.log('previousResult', previousResult)
console.log('subscriptionData', subscriptionData)
const { data: { postAdded: newPost } } = subscriptionData const { data: { postAdded: newPost } } = subscriptionData
return { Post: [newPost, ...previousResult.Post] } return { Post: [newPost, ...previousResult.Post] }
// Here, return the new result from the previous with the new data
}, },
} }
}, },