mirror of
https://github.com/Ocelot-Social-Community/Ocelot-Social.git
synced 2025-12-13 07:46:06 +00:00
- We want to publish when a notification occurs for a specific user, not have the client poll the backend for ever user every minute. - Co-authored-by: @Tirokk <wolle.huss@pjannto.com>
118 lines
4.0 KiB
JavaScript
118 lines
4.0 KiB
JavaScript
import log from './helpers/databaseLogger'
|
|
import { PubSub } from 'apollo-server'
|
|
import { withFilter } from 'graphql-subscriptions'
|
|
|
|
export const pubsub = new PubSub()
|
|
export const NOTIFICATION_ADDED = 'NOTIFICATION_ADDED'
|
|
export const transformReturnType = record => {
|
|
return {
|
|
...record.get('notification').properties,
|
|
from: {
|
|
__typename: record.get('type'),
|
|
...record.get('resource').properties,
|
|
},
|
|
to: {
|
|
...record.get('user').properties,
|
|
},
|
|
}
|
|
}
|
|
|
|
export default {
|
|
Subscription: {
|
|
notificationAdded: {
|
|
subscribe: withFilter(
|
|
() => pubsub.asyncIterator(NOTIFICATION_ADDED),
|
|
(payload, variables) => {
|
|
return payload.notificationAdded.to.id === variables.userId
|
|
},
|
|
),
|
|
},
|
|
},
|
|
Query: {
|
|
notifications: async (_parent, args, context, _resolveInfo) => {
|
|
const { user: currentUser } = context
|
|
const session = context.driver.session()
|
|
let whereClause, orderByClause
|
|
|
|
switch (args.read) {
|
|
case true:
|
|
whereClause = 'WHERE notification.read = TRUE'
|
|
break
|
|
case false:
|
|
whereClause = 'WHERE notification.read = FALSE'
|
|
break
|
|
default:
|
|
whereClause = ''
|
|
}
|
|
switch (args.orderBy) {
|
|
case 'updatedAt_asc':
|
|
orderByClause = 'ORDER BY notification.updatedAt ASC'
|
|
break
|
|
case 'updatedAt_desc':
|
|
orderByClause = 'ORDER BY notification.updatedAt DESC'
|
|
break
|
|
default:
|
|
orderByClause = ''
|
|
}
|
|
const offset = args.offset && typeof args.offset === 'number' ? `SKIP ${args.offset}` : ''
|
|
const limit = args.first && typeof args.first === 'number' ? `LIMIT ${args.first}` : ''
|
|
|
|
const readTxResultPromise = session.readTransaction(async transaction => {
|
|
const notificationsTransactionResponse = await transaction.run(
|
|
`
|
|
MATCH (resource {deleted: false, disabled: false})-[notification:NOTIFIED]->(user:User {id:$id})
|
|
${whereClause}
|
|
WITH user, notification, resource,
|
|
[(resource)<-[:WROTE]-(author:User) | author {.*}] as authors,
|
|
[(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}
|
|
${offset} ${limit}
|
|
`,
|
|
{ id: currentUser.id },
|
|
)
|
|
log(notificationsTransactionResponse)
|
|
return notificationsTransactionResponse.records.map(record => record.get('notification'))
|
|
})
|
|
try {
|
|
const notifications = await readTxResultPromise
|
|
return notifications
|
|
} finally {
|
|
session.close()
|
|
}
|
|
},
|
|
},
|
|
Mutation: {
|
|
markAsRead: async (parent, args, context, resolveInfo) => {
|
|
const { user: currentUser } = context
|
|
const session = context.driver.session()
|
|
const writeTxResultPromise = session.writeTransaction(async transaction => {
|
|
const markNotificationAsReadTransactionResponse = await transaction.run(
|
|
`
|
|
MATCH (resource {id: $resourceId})-[notification:NOTIFIED {read: FALSE}]->(user:User {id:$id})
|
|
SET notification.read = TRUE
|
|
RETURN resource, notification, user, labels(resource)[0] AS type
|
|
`,
|
|
{ resourceId: args.id, id: currentUser.id },
|
|
)
|
|
log(markNotificationAsReadTransactionResponse)
|
|
return markNotificationAsReadTransactionResponse.records.map(transformReturnType)
|
|
})
|
|
try {
|
|
const [notifications] = await writeTxResultPromise
|
|
return notifications
|
|
} finally {
|
|
session.close()
|
|
}
|
|
},
|
|
},
|
|
NOTIFIED: {
|
|
id: async parent => {
|
|
// serialize an ID to help the client update the cache
|
|
return `${parent.reason}/${parent.from.id}/${parent.to.id}`
|
|
},
|
|
},
|
|
}
|