feature/IO-3096-GlobalNotifications - Checkpoint, Ratify notifications tb table.
This commit is contained in:
@@ -4893,46 +4893,78 @@
|
||||
- name: job
|
||||
using:
|
||||
foreign_key_constraint_on: jobid
|
||||
insert_permissions:
|
||||
- role: user
|
||||
permission:
|
||||
check:
|
||||
job:
|
||||
bodyshop:
|
||||
associations:
|
||||
_and:
|
||||
- user:
|
||||
authid:
|
||||
_eq: X-Hasura-User-Id
|
||||
- active:
|
||||
_eq: true
|
||||
columns:
|
||||
- scenario_meta
|
||||
- scenario_text
|
||||
- fcm_text
|
||||
- created_at
|
||||
- read
|
||||
- updated_at
|
||||
- associationid
|
||||
- id
|
||||
- jobid
|
||||
comment: ""
|
||||
select_permissions:
|
||||
- role: user
|
||||
permission:
|
||||
columns:
|
||||
- associationid
|
||||
- scenario_meta
|
||||
- scenario_text
|
||||
- fcm_text
|
||||
- created_at
|
||||
- fcm_data
|
||||
- fcm_message
|
||||
- fcm_title
|
||||
- read
|
||||
- updated_at
|
||||
- associationid
|
||||
- id
|
||||
- jobid
|
||||
- meta
|
||||
- read
|
||||
- ui_translation_meta
|
||||
- ui_translation_string
|
||||
- updated_at
|
||||
filter:
|
||||
association:
|
||||
_and:
|
||||
- active:
|
||||
_eq: true
|
||||
- user:
|
||||
authid:
|
||||
_eq: X-Hasura-User-Id
|
||||
job:
|
||||
bodyshop:
|
||||
associations:
|
||||
_and:
|
||||
- user:
|
||||
authid:
|
||||
_eq: X-Hasura-User-Id
|
||||
- active:
|
||||
_eq: true
|
||||
comment: ""
|
||||
update_permissions:
|
||||
- role: user
|
||||
permission:
|
||||
columns:
|
||||
- meta
|
||||
- scenario_meta
|
||||
- scenario_text
|
||||
- fcm_text
|
||||
- created_at
|
||||
- read
|
||||
filter:
|
||||
association:
|
||||
_and:
|
||||
- active:
|
||||
_eq: true
|
||||
- user:
|
||||
authid:
|
||||
_eq: X-Hasura-User-Id
|
||||
check: null
|
||||
- updated_at
|
||||
- associationid
|
||||
- id
|
||||
- jobid
|
||||
filter: {}
|
||||
check:
|
||||
job:
|
||||
bodyshop:
|
||||
associations:
|
||||
_and:
|
||||
- user:
|
||||
authid:
|
||||
_eq: X-Hasura-User-Id
|
||||
- active:
|
||||
_eq: true
|
||||
comment: ""
|
||||
- table:
|
||||
name: owners
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
comment on column "public"."notifications"."html_body" is E'Real Time Notifications System';
|
||||
alter table "public"."notifications" alter column "html_body" drop not null;
|
||||
alter table "public"."notifications" add column "html_body" text;
|
||||
@@ -0,0 +1 @@
|
||||
alter table "public"."notifications" drop column "html_body" cascade;
|
||||
@@ -0,0 +1,4 @@
|
||||
comment on column "public"."notifications"."fcm_data" is E'Real Time Notifications System';
|
||||
alter table "public"."notifications" alter column "fcm_data" set default jsonb_build_object();
|
||||
alter table "public"."notifications" alter column "fcm_data" drop not null;
|
||||
alter table "public"."notifications" add column "fcm_data" jsonb;
|
||||
@@ -0,0 +1 @@
|
||||
alter table "public"."notifications" drop column "fcm_data" cascade;
|
||||
@@ -0,0 +1,3 @@
|
||||
comment on column "public"."notifications"."fcm_message" is E'Real Time Notifications System';
|
||||
alter table "public"."notifications" alter column "fcm_message" drop not null;
|
||||
alter table "public"."notifications" add column "fcm_message" text;
|
||||
@@ -0,0 +1 @@
|
||||
alter table "public"."notifications" drop column "fcm_message" cascade;
|
||||
@@ -0,0 +1,3 @@
|
||||
comment on column "public"."notifications"."ui_translation_string" is E'Real Time Notifications System';
|
||||
alter table "public"."notifications" alter column "ui_translation_string" drop not null;
|
||||
alter table "public"."notifications" add column "ui_translation_string" text;
|
||||
@@ -0,0 +1 @@
|
||||
alter table "public"."notifications" drop column "ui_translation_string" cascade;
|
||||
@@ -0,0 +1 @@
|
||||
alter table "public"."notifications" rename column "fcm_text" to "fcm_title";
|
||||
@@ -0,0 +1 @@
|
||||
alter table "public"."notifications" rename column "fcm_title" to "fcm_text";
|
||||
@@ -0,0 +1 @@
|
||||
alter table "public"."notifications" rename column "scenario_text" to "ui_translation_meta";
|
||||
@@ -0,0 +1 @@
|
||||
alter table "public"."notifications" rename column "ui_translation_meta" to "scenario_text";
|
||||
@@ -0,0 +1 @@
|
||||
alter table "public"."notifications" rename column "scenario_meta" to "meta";
|
||||
@@ -0,0 +1 @@
|
||||
alter table "public"."notifications" rename column "meta" to "scenario_meta";
|
||||
@@ -20,7 +20,7 @@ const RATE_LIMITER_DURATION = APP_CONSOLIDATION_DELAY * 0.1; // 6 seconds (tenth
|
||||
let addQueue;
|
||||
let consolidateQueue;
|
||||
|
||||
// GraphQL mutation to insert notifications
|
||||
// Updated GraphQL mutation to insert notifications with the new schema
|
||||
const INSERT_NOTIFICATIONS_MUTATION = `
|
||||
mutation INSERT_NOTIFICATIONS($objects: [notifications_insert_input!]!) {
|
||||
insert_notifications(objects: $objects) {
|
||||
@@ -29,61 +29,34 @@ const INSERT_NOTIFICATIONS_MUTATION = `
|
||||
id
|
||||
jobid
|
||||
associationid
|
||||
ui_translation_string
|
||||
ui_translation_meta
|
||||
html_body
|
||||
scenario_text
|
||||
fcm_text
|
||||
scenario_meta
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
/**
|
||||
* Builds an HTML unordered list from an array of notification bodies.
|
||||
* Builds the scenario_text, fcm_text, and scenario_meta for a batch of notifications.
|
||||
*
|
||||
* @param {Array<Object>} notifications - Array of notification objects with a 'body' field.
|
||||
* @returns {string} HTML string representing an unordered list of bodies.
|
||||
* @param {Array<Object>} notifications - Array of notification objects with 'body' and 'variables'.
|
||||
* @returns {Object} An object with 'scenario_text', 'fcm_text', and 'scenario_meta'.
|
||||
*/
|
||||
const buildHtmlBody = (notifications) => {
|
||||
const listItems = notifications.map((n) => `<li>${n.body}</li>`).join("");
|
||||
return `<ul>${listItems}</ul>`;
|
||||
};
|
||||
const buildNotificationContent = (notifications) => {
|
||||
const scenarioText = notifications.map((n) => n.body); // Array of text entries
|
||||
const fcmText = scenarioText.join(". "); // Concatenated text with period separator
|
||||
const scenarioMeta = notifications.map((n) => n.variables || {}); // Array of metadata objects
|
||||
|
||||
/**
|
||||
* Determines the key and variables for a batch of notifications.
|
||||
*
|
||||
* @param {Array<Object>} notifications - Array of notification objects with 'key' and 'variables'.
|
||||
* @returns {Object} An object with 'key' and 'variables' properties.
|
||||
*/
|
||||
const determineKeyAndVariables = (notifications) => {
|
||||
if (notifications.length === 1) {
|
||||
// Single notification: use the original key and variables
|
||||
return {
|
||||
key: notifications[0].key,
|
||||
variables: notifications[0].variables
|
||||
};
|
||||
} else {
|
||||
// Multiple notifications: use a generic key and consolidate variables with their original keys
|
||||
return {
|
||||
key: "notifications.job.multipleChanges",
|
||||
variables: {
|
||||
variables: notifications.map((n) => ({
|
||||
key: n.key, // Include the original key in each variables object
|
||||
...n.variables
|
||||
}))
|
||||
}
|
||||
};
|
||||
}
|
||||
return {
|
||||
scenario_text: scenarioText,
|
||||
fcm_text: fcmText ? `${fcmText}.` : null, // Add trailing period if non-empty, otherwise null
|
||||
scenario_meta: scenarioMeta
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Initializes the notification queues and workers for adding and consolidating notifications.
|
||||
*
|
||||
* @param {Object} options - Configuration options for queue initialization.
|
||||
* @param {Object} options.pubClient - Redis client instance for queue communication.
|
||||
* @param {Object} options.logger - Logger instance for logging events and debugging.
|
||||
* @param {Object} options.redisHelpers - Utility functions for Redis operations.
|
||||
* @param {Object} options.ioRedis - Socket.io Redis adapter for real-time event emission.
|
||||
* @returns {Queue} The initialized `addQueue` instance for dispatching notifications.
|
||||
*/
|
||||
const loadAppQueue = async ({ pubClient, logger, redisHelpers, ioRedis }) => {
|
||||
if (!addQueue || !consolidateQueue) {
|
||||
@@ -195,14 +168,13 @@ const loadAppQueue = async ({ pubClient, logger, redisHelpers, ioRedis }) => {
|
||||
const employeeId = userRecipients[0]?.employeeId;
|
||||
|
||||
for (const [bodyShopId, notifications] of Object.entries(bodyShopData)) {
|
||||
const { key, variables } = determineKeyAndVariables(notifications);
|
||||
const htmlBody = buildHtmlBody(notifications);
|
||||
const { scenario_text, fcm_text, scenario_meta } = buildNotificationContent(notifications);
|
||||
notificationInserts.push({
|
||||
jobid: jobId,
|
||||
associationid: employeeId || null,
|
||||
ui_translation_string: key,
|
||||
ui_translation_meta: JSON.stringify(variables),
|
||||
html_body: htmlBody
|
||||
scenario_text: JSON.stringify(scenario_text), // JSONB requires stringified input
|
||||
fcm_text: fcm_text,
|
||||
scenario_meta: JSON.stringify(scenario_meta) // JSONB requires stringified input
|
||||
});
|
||||
notificationIdMap.set(`${user}:${bodyShopId}`, null);
|
||||
}
|
||||
@@ -301,9 +273,6 @@ const loadAppQueue = async ({ pubClient, logger, redisHelpers, ioRedis }) => {
|
||||
|
||||
/**
|
||||
* Retrieves the initialized `addQueue` instance.
|
||||
*
|
||||
* @returns {Queue} The `addQueue` instance for adding notifications.
|
||||
* @throws {Error} If `addQueue` is not initialized (i.e., `loadAppQueue` wasn’t called).
|
||||
*/
|
||||
const getQueue = () => {
|
||||
if (!addQueue) throw new Error("Add queue not initialized. Ensure loadAppQueue is called during bootstrap.");
|
||||
@@ -312,11 +281,6 @@ const getQueue = () => {
|
||||
|
||||
/**
|
||||
* Dispatches notifications to the `addQueue` for processing.
|
||||
*
|
||||
* @param {Object} options - Options for dispatching notifications.
|
||||
* @param {Array} options.appsToDispatch - Array of notification objects to dispatch.
|
||||
* @param {Object} options.logger - Logger instance for logging dispatch events.
|
||||
* @returns {Promise<void>} Resolves when all notifications are added to the queue.
|
||||
*/
|
||||
const dispatchAppsToQueue = async ({ appsToDispatch, logger }) => {
|
||||
const appQueue = getQueue();
|
||||
|
||||
Reference in New Issue
Block a user