From 1511deb3d80804bd1567da0afdeb6dcc7bbbbbce Mon Sep 17 00:00:00 2001 From: Matthew Callens Date: Sun, 18 Jun 2023 12:48:14 -0400 Subject: [PATCH] add mark notifications as read mutation resolver (#4169) --- .../src/routes/graphql/clients/hasura.ts | 6 ++-- .../backpack-api/src/routes/graphql/index.ts | 2 ++ .../backpack-api/src/routes/graphql/nodes.ts | 7 ++--- .../graphql/resolvers/mutation/index.ts | 1 + .../resolvers/mutation/notifications.ts | 31 +++++++++++++++++++ .../backpack-api/src/routes/graphql/types.ts | 16 ++++++++++ .../native/backpack-api/src/schema.graphql | 10 ++++++ .../data-components/src/apollo/graphql.ts | 9 ++++++ 8 files changed, 75 insertions(+), 7 deletions(-) create mode 100644 backend/native/backpack-api/src/routes/graphql/resolvers/mutation/notifications.ts diff --git a/backend/native/backpack-api/src/routes/graphql/clients/hasura.ts b/backend/native/backpack-api/src/routes/graphql/clients/hasura.ts index fbbd1459b..448b9e7b5 100644 --- a/backend/native/backpack-api/src/routes/graphql/clients/hasura.ts +++ b/backend/native/backpack-api/src/routes/graphql/clients/hasura.ts @@ -82,8 +82,9 @@ export class Hasura { throw new GraphQLError("Failed to create new notification"); } - return NodeBuilder.notification(resp.insert_auth_notifications_one.id, { + return NodeBuilder.notification({ body: b, + dbId: resp.insert_auth_notifications_one.id, source, title, timestamp: timestamp.toISOString(), @@ -268,8 +269,9 @@ export class Hasura { // Create the list of notification type nodes for the connection const nodes = resp.auth_notifications.map((n) => - NodeBuilder.notification(n.id, { + NodeBuilder.notification({ body: n.body, + dbId: n.id, source: n.xnft_id, timestamp: new Date(n.timestamp as string).toISOString(), title: n.title, diff --git a/backend/native/backpack-api/src/routes/graphql/index.ts b/backend/native/backpack-api/src/routes/graphql/index.ts index d9b00e198..7d69ddcc2 100644 --- a/backend/native/backpack-api/src/routes/graphql/index.ts +++ b/backend/native/backpack-api/src/routes/graphql/index.ts @@ -10,6 +10,7 @@ import { friendshipTypeResolvers, importPublicKeyMutationResolver, jsonObjectScalar, + markNotificationsAsReadMutationResolver, notificationTypeResolvers, sendFriendRequestMutationResolver, tokenListQueryResolver, @@ -28,6 +29,7 @@ const mutationResolvers: MutationResolvers = { authenticate: authenticateMutationResolver, deauthenticate: deauthenticateMutationResolver, importPublicKey: importPublicKeyMutationResolver, + markNotificationsAsRead: markNotificationsAsReadMutationResolver, sendFriendRequest: sendFriendRequestMutationResolver, }; diff --git a/backend/native/backpack-api/src/routes/graphql/nodes.ts b/backend/native/backpack-api/src/routes/graphql/nodes.ts index 0c1041bfd..56a9cbbed 100644 --- a/backend/native/backpack-api/src/routes/graphql/nodes.ts +++ b/backend/native/backpack-api/src/routes/graphql/nodes.ts @@ -63,11 +63,8 @@ export abstract class NodeBuilder { ); } - static notification( - dbId: unknown, - data: Omit - ): Notification { - return this._createNode(`notification:${dbId}`, data); + static notification(data: Omit): Notification { + return this._createNode(`notification:${data.dbId}`, data); } static notificationAppData( diff --git a/backend/native/backpack-api/src/routes/graphql/resolvers/mutation/index.ts b/backend/native/backpack-api/src/routes/graphql/resolvers/mutation/index.ts index eca4939d9..ac20ca9d1 100644 --- a/backend/native/backpack-api/src/routes/graphql/resolvers/mutation/index.ts +++ b/backend/native/backpack-api/src/routes/graphql/resolvers/mutation/index.ts @@ -1,3 +1,4 @@ export * from "./authentication"; export * from "./friendship"; +export * from "./notifications"; export * from "./wallets"; diff --git a/backend/native/backpack-api/src/routes/graphql/resolvers/mutation/notifications.ts b/backend/native/backpack-api/src/routes/graphql/resolvers/mutation/notifications.ts new file mode 100644 index 000000000..ea350112c --- /dev/null +++ b/backend/native/backpack-api/src/routes/graphql/resolvers/mutation/notifications.ts @@ -0,0 +1,31 @@ +import type { GraphQLResolveInfo } from "graphql"; + +import { updateNotificationSeen } from "../../../../db/notifications"; +import type { ApiContext } from "../../context"; +import type { + MutationMarkNotificationsAsReadArgs, + MutationResolvers, +} from "../../types"; + +/** + * Handler for the mutation to mark a set of notifications as viewed. + * @param {{}} _parent + * @param {MutationMarkNotificationsAsReadArgs} args + * @param {ApiContext} ctx + * @param {GraphQLResolveInfo} _info + * @returns + */ +export const markNotificationsAsReadMutationResolver: MutationResolvers["markNotificationsAsRead"] = + async ( + _parent: {}, + args: MutationMarkNotificationsAsReadArgs, + ctx: ApiContext, + _info: GraphQLResolveInfo + ): Promise => { + // TODO: move implementation into contextual Hasura client + const res = await updateNotificationSeen({ + notificationIds: args.ids, + uuid: ctx.authorization.userId ?? "", + }); + return res.update_auth_notifications?.affected_rows ?? 0; + }; diff --git a/backend/native/backpack-api/src/routes/graphql/types.ts b/backend/native/backpack-api/src/routes/graphql/types.ts index a428d17ca..b043f9e08 100644 --- a/backend/native/backpack-api/src/routes/graphql/types.ts +++ b/backend/native/backpack-api/src/routes/graphql/types.ts @@ -162,6 +162,8 @@ export type Mutation = { deauthenticate: Scalars["String"]; /** Attempt to add a new wallet public key to the user account. */ importPublicKey?: Maybe; + /** Set the `viewed` status of the argued notification IDs are `true`. */ + markNotificationsAsRead: Scalars["Int"]; /** Allows users to send friend requests to another remote user. */ sendFriendRequest?: Maybe; }; @@ -181,6 +183,11 @@ export type MutationImportPublicKeyArgs = { signature: Scalars["String"]; }; +/** Root level mutation type. */ +export type MutationMarkNotificationsAsReadArgs = { + ids: Array; +}; + /** Root level mutation type. */ export type MutationSendFriendRequestArgs = { accept: Scalars["Boolean"]; @@ -258,6 +265,8 @@ export type Notification = Node & { app?: Maybe; /** Arbitrary body data of the notification parsed as an object. */ body: Scalars["JSONObject"]; + /** The database unique integer identifier. */ + dbId: Scalars["Int"]; /** Globally unique identifier for a specific notification. */ id: Scalars["ID"]; /** The emitting source of the notification. */ @@ -985,6 +994,12 @@ export type MutationResolvers< "address" | "providerId" | "signature" > >; + markNotificationsAsRead?: Resolver< + ResolversTypes["Int"], + ParentType, + ContextType, + RequireFields + >; sendFriendRequest?: Resolver< Maybe, ParentType, @@ -1092,6 +1107,7 @@ export type NotificationResolvers< ContextType >; body?: Resolver; + dbId?: Resolver; id?: Resolver; source?: Resolver; timestamp?: Resolver; diff --git a/backend/native/backpack-api/src/schema.graphql b/backend/native/backpack-api/src/schema.graphql index 3f8c68966..063a85c89 100644 --- a/backend/native/backpack-api/src/schema.graphql +++ b/backend/native/backpack-api/src/schema.graphql @@ -45,6 +45,11 @@ type Mutation { signature: String! ): Boolean + """ + Set the `viewed` status of the argued notification IDs are `true`. + """ + markNotificationsAsRead(ids: [Int!]!): Int! + """ Allows users to send friend requests to another remote user. """ @@ -562,6 +567,11 @@ type Notification implements Node { """ body: JSONObject! + """ + The database unique integer identifier. + """ + dbId: Int! + """ The emitting source of the notification. """ diff --git a/packages/data-components/src/apollo/graphql.ts b/packages/data-components/src/apollo/graphql.ts index 4f4b126cc..78f541709 100644 --- a/packages/data-components/src/apollo/graphql.ts +++ b/packages/data-components/src/apollo/graphql.ts @@ -156,6 +156,8 @@ export type Mutation = { deauthenticate: Scalars["String"]; /** Attempt to add a new wallet public key to the user account. */ importPublicKey?: Maybe; + /** Set the `viewed` status of the argued notification IDs are `true`. */ + markNotificationsAsRead: Scalars["Int"]; /** Allows users to send friend requests to another remote user. */ sendFriendRequest?: Maybe; }; @@ -175,6 +177,11 @@ export type MutationImportPublicKeyArgs = { signature: Scalars["String"]; }; +/** Root level mutation type. */ +export type MutationMarkNotificationsAsReadArgs = { + ids: Array; +}; + /** Root level mutation type. */ export type MutationSendFriendRequestArgs = { accept: Scalars["Boolean"]; @@ -252,6 +259,8 @@ export type Notification = Node & { app?: Maybe; /** Arbitrary body data of the notification parsed as an object. */ body: Scalars["JSONObject"]; + /** The database unique integer identifier. */ + dbId: Scalars["Int"]; /** Globally unique identifier for a specific notification. */ id: Scalars["ID"]; /** The emitting source of the notification. */