all repos — caroster @ e2d79baf7de5a761181c256ba3ce651181e4af84

[Octree] Group carpool to your event https://caroster.io

feat: :sparkles: Add notification model in Strapi
Tim Izzo tim@octree.ch
Tue, 23 Jan 2024 09:03:47 +0000
commit

e2d79baf7de5a761181c256ba3ce651181e4af84

parent

5543c4ec6a234b0844c86b19f3953fc1e189943c

A backend/src/api/notification/content-types/notification/schema.json

@@ -0,0 +1,39 @@

+{ + "kind": "collectionType", + "collectionName": "notifications", + "info": { + "singularName": "notification", + "pluralName": "notifications", + "displayName": "Notification" + }, + "options": { + "draftAndPublish": false + }, + "pluginOptions": {}, + "attributes": { + "type": { + "type": "enumeration", + "enum": [ + "NewPassengerInYourTrip", + "NewTrip" + ], + "required": true + }, + "user": { + "type": "relation", + "relation": "manyToOne", + "target": "plugin::users-permissions.user", + "inversedBy": "notifications" + }, + "event": { + "type": "relation", + "relation": "oneToOne", + "target": "api::event.event" + }, + "read": { + "type": "boolean", + "default": false, + "required": false + } + } +}
A backend/src/api/notification/controllers/notification.ts

@@ -0,0 +1,7 @@

+/** + * notification controller + */ + +import { factories } from '@strapi/strapi' + +export default factories.createCoreController('api::notification.notification');
A backend/src/api/notification/routes/notification.ts

@@ -0,0 +1,7 @@

+/** + * notification router + */ + +import { factories } from '@strapi/strapi'; + +export default factories.createCoreRouter('api::notification.notification');
A backend/src/api/notification/services/notification.ts

@@ -0,0 +1,7 @@

+/** + * notification service + */ + +import { factories } from '@strapi/strapi'; + +export default factories.createCoreService('api::notification.notification');
M backend/src/extensions/users-permissions/content-types/user/schema.jsonbackend/src/extensions/users-permissions/content-types/user/schema.json

@@ -109,6 +109,12 @@ },

"newsletterConsent": { "type": "boolean", "default": true + }, + "notifications": { + "type": "relation", + "relation": "oneToMany", + "target": "api::notification.notification", + "mappedBy": "user" } } }
M backend/src/graphql/index.tsbackend/src/graphql/index.ts

@@ -4,6 +4,7 @@ import userExtensions from "./user";

import travelExtensions from "./travel"; import vehicleExtensions from "./vehicle"; import passengerExtensions from "./passenger"; +import notificationExtensions from "./notification"; export default ({ strapi }) => { const extService = strapi.plugin("graphql").service("extension");

@@ -13,6 +14,7 @@ userExtensions.forEach(extService.use);

travelExtensions.forEach(extService.use); vehicleExtensions.forEach(extService.use); passengerExtensions.forEach(extService.use); + notificationExtensions.forEach(extService.use); // Disable shadow CRUD /// Fields
A backend/src/graphql/notification/index.ts

@@ -0,0 +1,63 @@

+import pMap from "p-map"; + +export default [ + ({ nexus, strapi }) => ({ + types: [ + nexus.mutationField("readNotifications", { + type: "NotificationEntityResponseCollection", + args: { + id: "ID", + }, + }), + ], + resolvers: { + Mutation: { + readNotifications: { + async resolve(_root, args, context) { + const user = context.state.user; + const { id } = args; + + const { toEntityResponseCollection } = strapi + .plugin("graphql") + .service("format").returnTypes; + + let idFilter = {}; + if (id) idFilter = { id }; + + const userNotifications = await strapi.entityService.findMany( + "api::notification.notification", + { + filters: { + user: { id: user.id }, + read: false, + ...idFilter, + }, + } + ); + const updatedNotifications = await pMap( + userNotifications, + (notification: { id: "string" }) => + strapi.entityService.update( + "api::notification.notification", + notification.id, + { data: { read: true } } + ) + ); + return toEntityResponseCollection(updatedNotifications, { + resourceUID: "api::notification.notification", + }); + }, + id: { + description: + "Notification ID to read. If no ID is provided, all user's notifications are set as read.", + }, + }, + }, + }, + resolversConfig: { + "Mutation.readNotifications": { + auth: true, + }, + }, + }), +];
M backend/src/graphql/user/index.tsbackend/src/graphql/user/index.ts

@@ -87,5 +87,12 @@ },

}, }, }, + resolversConfig: { + "UsersPermissionsUser.notifications": { + auth: { + scope: ["plugin::users-permissions.user.me"], + }, + }, + }, }), ];
M backend/types/generated/contentTypes.d.tsbackend/types/generated/contentTypes.d.ts

@@ -773,6 +773,11 @@ onboardingUser: Attribute.Boolean & Attribute.DefaultTo<false>;

onboardingCreator: Attribute.Boolean & Attribute.DefaultTo<false>; lang: Attribute.Enumeration<['fr', 'en']> & Attribute.DefaultTo<'fr'>; newsletterConsent: Attribute.Boolean & Attribute.DefaultTo<true>; + notifications: Attribute.Relation< + 'plugin::users-permissions.user', + 'oneToMany', + 'api::notification.notification' + >; createdAt: Attribute.DateTime; updatedAt: Attribute.DateTime; createdBy: Attribute.Relation<

@@ -892,6 +897,47 @@ > &

Attribute.Private; updatedBy: Attribute.Relation< 'api::event.event', + 'oneToOne', + 'admin::user' + > & + Attribute.Private; + }; +} + +export interface ApiNotificationNotification extends Schema.CollectionType { + collectionName: 'notifications'; + info: { + singularName: 'notification'; + pluralName: 'notifications'; + displayName: 'Notification'; + }; + options: { + draftAndPublish: false; + }; + attributes: { + type: Attribute.Enumeration<['NewPassengerInYourTrip', 'NewTrip']> & + Attribute.Required; + user: Attribute.Relation< + 'api::notification.notification', + 'manyToOne', + 'plugin::users-permissions.user' + >; + event: Attribute.Relation< + 'api::notification.notification', + 'oneToOne', + 'api::event.event' + >; + read: Attribute.Boolean & Attribute.DefaultTo<false>; + createdAt: Attribute.DateTime; + updatedAt: Attribute.DateTime; + createdBy: Attribute.Relation< + 'api::notification.notification', + 'oneToOne', + 'admin::user' + > & + Attribute.Private; + updatedBy: Attribute.Relation< + 'api::notification.notification', 'oneToOne', 'admin::user' > &

@@ -1174,6 +1220,7 @@ 'plugin::users-permissions.role': PluginUsersPermissionsRole;

'plugin::users-permissions.user': PluginUsersPermissionsUser; 'plugin::email-designer.email-template': PluginEmailDesignerEmailTemplate; 'api::event.event': ApiEventEvent; + 'api::notification.notification': ApiNotificationNotification; 'api::page.page': ApiPagePage; 'api::passenger.passenger': ApiPassengerPassenger; 'api::setting.setting': ApiSettingSetting;