@mj-biz-apps/tasks-server 0.0.1 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Initializes the global event subscription for task notifications.
3
+ * Call once at server startup from {@link LoadBizAppsTasksServer}.
4
+ */
5
+ export declare function InitTaskNotificationHandler(): void;
6
+ //# sourceMappingURL=TaskNotificationHandler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TaskNotificationHandler.d.ts","sourceRoot":"","sources":["../../src/event-handlers/TaskNotificationHandler.ts"],"names":[],"mappings":"AA6BA;;;GAGG;AACH,wBAAgB,2BAA2B,IAAI,IAAI,CAuBlD"}
@@ -0,0 +1,363 @@
1
+ /**
2
+ * BizAppsTasks Notification Handler
3
+ *
4
+ * Subscribes to MJGlobal entity events and creates in-app notifications
5
+ * (MJ: User Notifications) for key task events:
6
+ *
7
+ * - Task assigned → notify the assignee
8
+ * - Task completed → notify all assignees
9
+ * - Task status changed to Blocked → notify all assignees
10
+ * - Task comment created → notify all assignees except the commenter
11
+ * - TaskType action hooks → invoke linked MJ Actions (OnAssign, OnComplete, OnOverdue, OnPercentChange)
12
+ */
13
+ import { BaseEntity, LogError, LogStatus, Metadata, RunView, } from '@memberjunction/core';
14
+ import { MJEventType, MJGlobal } from '@memberjunction/global';
15
+ /** Entity names we listen for */
16
+ const TASKS_ENTITY = 'MJ_BizApps_Tasks: Tasks';
17
+ const TASK_ASSIGNMENTS_ENTITY = 'MJ_BizApps_Tasks: Task Assignments';
18
+ const TASK_COMMENTS_ENTITY = 'MJ_BizApps_Tasks: Task Comments';
19
+ /**
20
+ * Initializes the global event subscription for task notifications.
21
+ * Call once at server startup from {@link LoadBizAppsTasksServer}.
22
+ */
23
+ export function InitTaskNotificationHandler() {
24
+ const storeKey = '___BizAppsTasks___NotificationHandler___Subscription';
25
+ const store = MJGlobal.Instance.GetGlobalObjectStore();
26
+ // Guard against double-subscription (bundler duplication / hot-reload)
27
+ if (store[storeKey]) {
28
+ return;
29
+ }
30
+ const subscription = MJGlobal.Instance.GetEventListener(true).subscribe((event) => {
31
+ if (event.event === MJEventType.ComponentEvent &&
32
+ event.eventCode === BaseEntity.BaseEventCode) {
33
+ const entityEvent = event.args;
34
+ handleEntityEvent(entityEvent);
35
+ }
36
+ });
37
+ store[storeKey] = subscription;
38
+ LogStatus('[BizAppsTasks] Notification handler initialized');
39
+ }
40
+ // ---------------------------------------------------------------------------
41
+ // Event Router
42
+ // ---------------------------------------------------------------------------
43
+ function handleEntityEvent(event) {
44
+ if (event.type !== 'save' || !event.baseEntity) {
45
+ return;
46
+ }
47
+ const entityName = event.baseEntity.EntityInfo.Name;
48
+ switch (entityName) {
49
+ case TASKS_ENTITY:
50
+ handleTaskSave(event).catch(logHandlerError('TaskSave'));
51
+ break;
52
+ case TASK_ASSIGNMENTS_ENTITY:
53
+ handleAssignmentSave(event).catch(logHandlerError('AssignmentSave'));
54
+ break;
55
+ case TASK_COMMENTS_ENTITY:
56
+ handleCommentSave(event).catch(logHandlerError('CommentSave'));
57
+ break;
58
+ }
59
+ }
60
+ function logHandlerError(handler) {
61
+ return (err) => {
62
+ const msg = err instanceof Error ? err.message : String(err);
63
+ LogError(`[BizAppsTasks] ${handler} notification error: ${msg}`);
64
+ };
65
+ }
66
+ // ---------------------------------------------------------------------------
67
+ // Task Notifications (status changes)
68
+ // ---------------------------------------------------------------------------
69
+ /**
70
+ * When a task is saved:
71
+ * - If completed → notify all assignees: "Task completed: {name}"
72
+ * - If blocked → notify all assignees: "Task blocked: {name}"
73
+ * - If newly created → no notification (assignment creation handles that)
74
+ *
75
+ * Also invokes TaskType action hooks if configured (OnComplete, OnOverdue, OnPercentChange).
76
+ */
77
+ async function handleTaskSave(event) {
78
+ const task = event.baseEntity;
79
+ const contextUser = task.ContextCurrentUser;
80
+ if (!contextUser)
81
+ return;
82
+ const taskID = task.Get('ID');
83
+ const taskName = task.Get('Name');
84
+ const status = task.Get('Status');
85
+ // Only notify on specific status values, and only on update (not create)
86
+ if (event.saveSubType === 'create') {
87
+ return;
88
+ }
89
+ if (status === 'Completed') {
90
+ const userIDs = await getTaskAssigneeUserIDs(taskID, contextUser);
91
+ if (userIDs.length > 0) {
92
+ await createNotificationsForUsers(userIDs, `Task Completed: ${taskName}`, `"${taskName}" has been marked as completed.`, contextUser);
93
+ LogStatus(`[BizAppsTasks] Sent completion notification for "${taskName}" to ${userIDs.length} assignee(s)`);
94
+ }
95
+ // Invoke OnComplete action if configured on TaskType
96
+ await invokeTaskTypeAction(task, 'OnCompleteActionID', contextUser);
97
+ }
98
+ if (status === 'Blocked') {
99
+ const blockedReason = task.Get('BlockedReason');
100
+ const userIDs = await getTaskAssigneeUserIDs(taskID, contextUser);
101
+ if (userIDs.length > 0) {
102
+ const reasonStr = blockedReason ? ` Reason: ${blockedReason}` : '';
103
+ await createNotificationsForUsers(userIDs, `Task Blocked: ${taskName}`, `"${taskName}" has been blocked.${reasonStr}`, contextUser);
104
+ LogStatus(`[BizAppsTasks] Sent blocked notification for "${taskName}" to ${userIDs.length} assignee(s)`);
105
+ }
106
+ }
107
+ }
108
+ // ---------------------------------------------------------------------------
109
+ // Assignment Notifications
110
+ // ---------------------------------------------------------------------------
111
+ /**
112
+ * When a NEW task assignment is created, notify the assignee:
113
+ * "You've been assigned: {task name}"
114
+ *
115
+ * Also invokes OnAssign action if configured on the task's TaskType.
116
+ */
117
+ async function handleAssignmentSave(event) {
118
+ if (event.saveSubType !== 'create') {
119
+ return;
120
+ }
121
+ const assignment = event.baseEntity;
122
+ const contextUser = assignment.ContextCurrentUser;
123
+ if (!contextUser)
124
+ return;
125
+ const assigneeRecordID = assignment.Get('AssigneeRecordID');
126
+ const taskID = assignment.Get('TaskID');
127
+ // Resolve the assignee's linked MJ UserID
128
+ const userID = await getPersonLinkedUserID(assigneeRecordID, contextUser);
129
+ if (!userID)
130
+ return;
131
+ // Load the task to get its name and details
132
+ const rv = new RunView();
133
+ const taskResult = await rv.RunView({
134
+ EntityName: TASKS_ENTITY,
135
+ ExtraFilter: `ID='${taskID}'`,
136
+ ResultType: 'simple',
137
+ MaxRows: 1,
138
+ }, contextUser);
139
+ const task = taskResult?.Results?.[0];
140
+ if (!task)
141
+ return;
142
+ const taskName = task.Name;
143
+ const priority = task.Priority;
144
+ const dueAt = task.DueAt ? formatDate(new Date(task.DueAt)) : null;
145
+ const dueStr = dueAt ? ` Due: ${dueAt}.` : '';
146
+ // Resolve role name if present
147
+ const roleID = assignment.Get('RoleID');
148
+ let roleStr = '';
149
+ if (roleID) {
150
+ const roleResult = await new RunView().RunView({
151
+ EntityName: 'MJ_BizApps_Tasks: Task Roles',
152
+ ExtraFilter: `ID='${roleID}'`,
153
+ ResultType: 'simple',
154
+ MaxRows: 1,
155
+ }, contextUser);
156
+ const roleName = roleResult?.Results?.[0]?.Name;
157
+ if (roleName)
158
+ roleStr = ` Role: ${roleName}.`;
159
+ }
160
+ await createNotificationsForUsers([userID], `Task Assigned: ${taskName}`, `You've been assigned to "${taskName}". Priority: ${priority}.${roleStr}${dueStr}`, contextUser);
161
+ LogStatus(`[BizAppsTasks] Sent assignment notification for "${taskName}"`);
162
+ // Invoke OnAssign action if configured on the task's TaskType
163
+ await invokeTaskTypeActionByTaskID(taskID, 'OnAssignActionID', contextUser);
164
+ }
165
+ // ---------------------------------------------------------------------------
166
+ // Comment Notifications
167
+ // ---------------------------------------------------------------------------
168
+ /**
169
+ * When a NEW comment is created on a task, notify all assignees
170
+ * except the comment author.
171
+ */
172
+ async function handleCommentSave(event) {
173
+ if (event.saveSubType !== 'create') {
174
+ return;
175
+ }
176
+ const comment = event.baseEntity;
177
+ const contextUser = comment.ContextCurrentUser;
178
+ if (!contextUser)
179
+ return;
180
+ const taskID = comment.Get('TaskID');
181
+ const authorPersonID = comment.Get('PersonID');
182
+ const content = comment.Get('Content');
183
+ const preview = content.length > 100 ? content.substring(0, 100) + '...' : content;
184
+ // Get task name
185
+ const rv = new RunView();
186
+ const taskResult = await rv.RunView({
187
+ EntityName: TASKS_ENTITY,
188
+ ExtraFilter: `ID='${taskID}'`,
189
+ ResultType: 'simple',
190
+ MaxRows: 1,
191
+ }, contextUser);
192
+ const taskName = taskResult?.Results?.[0]?.Name ?? 'a task';
193
+ // Get author name
194
+ const authorName = await getPersonName(authorPersonID, contextUser) ?? 'Someone';
195
+ // Get all assignee UserIDs except the author
196
+ const allUserIDs = await getTaskAssigneeUserIDs(taskID, contextUser);
197
+ const authorUserID = await getPersonLinkedUserID(authorPersonID, contextUser);
198
+ const notifyUserIDs = allUserIDs.filter(id => id !== authorUserID);
199
+ if (notifyUserIDs.length === 0)
200
+ return;
201
+ await createNotificationsForUsers(notifyUserIDs, `Comment on: ${taskName}`, `${authorName} commented: "${preview}"`, contextUser);
202
+ LogStatus(`[BizAppsTasks] Sent comment notification for "${taskName}" to ${notifyUserIDs.length} assignee(s)`);
203
+ }
204
+ // ---------------------------------------------------------------------------
205
+ // TaskType Action Invocation
206
+ // ---------------------------------------------------------------------------
207
+ /**
208
+ * Looks up the TaskType for a task entity and invokes the specified action
209
+ * FK column if it has a value.
210
+ */
211
+ async function invokeTaskTypeAction(task, actionColumn, contextUser) {
212
+ const typeID = task.Get('TypeID');
213
+ if (!typeID)
214
+ return;
215
+ const rv = new RunView();
216
+ const typeResult = await rv.RunView({
217
+ EntityName: 'MJ_BizApps_Tasks: Task Types',
218
+ ExtraFilter: `ID='${typeID}'`,
219
+ ResultType: 'simple',
220
+ MaxRows: 1,
221
+ }, contextUser);
222
+ const taskType = typeResult?.Results?.[0];
223
+ if (!taskType)
224
+ return;
225
+ const actionID = taskType[actionColumn];
226
+ if (!actionID)
227
+ return;
228
+ try {
229
+ // Dynamic import to avoid hard dependency on @memberjunction/actions
230
+ const { ActionEngineServer } = await import('@memberjunction/actions');
231
+ await ActionEngineServer.Instance.Config(false, contextUser);
232
+ const action = ActionEngineServer.Instance.Actions.find((a) => a.ID === actionID);
233
+ if (!action) {
234
+ LogError(`[BizAppsTasks] Action ${actionID} not found for TaskType ${actionColumn}`);
235
+ return;
236
+ }
237
+ await ActionEngineServer.Instance.RunAction({
238
+ Action: action,
239
+ ContextUser: contextUser,
240
+ Params: [
241
+ { Name: 'TaskID', Value: task.Get('ID'), Type: 'Input' },
242
+ { Name: 'TaskName', Value: task.Get('Name'), Type: 'Input' },
243
+ { Name: 'Status', Value: task.Get('Status'), Type: 'Input' },
244
+ ],
245
+ Filters: [],
246
+ });
247
+ LogStatus(`[BizAppsTasks] Invoked ${actionColumn} action for task "${task.Get('Name')}"`);
248
+ }
249
+ catch (err) {
250
+ const msg = err instanceof Error ? err.message : String(err);
251
+ LogError(`[BizAppsTasks] Failed to invoke ${actionColumn}: ${msg}`);
252
+ }
253
+ }
254
+ /**
255
+ * Convenience wrapper: loads a task by ID, then invokes a TaskType action.
256
+ */
257
+ async function invokeTaskTypeActionByTaskID(taskID, actionColumn, contextUser) {
258
+ const rv = new RunView();
259
+ const result = await rv.RunView({
260
+ EntityName: TASKS_ENTITY,
261
+ ExtraFilter: `ID='${taskID}'`,
262
+ ResultType: 'entity_object',
263
+ MaxRows: 1,
264
+ }, contextUser);
265
+ const task = result?.Results?.[0];
266
+ if (task) {
267
+ await invokeTaskTypeAction(task, actionColumn, contextUser);
268
+ }
269
+ }
270
+ // ---------------------------------------------------------------------------
271
+ // Helpers
272
+ // ---------------------------------------------------------------------------
273
+ /**
274
+ * Returns MJ UserIDs for all people assigned to a task.
275
+ * Two-step: TaskAssignment → Person → LinkedUserID.
276
+ */
277
+ async function getTaskAssigneeUserIDs(taskID, contextUser) {
278
+ const rv = new RunView();
279
+ const assignments = await rv.RunView({
280
+ EntityName: TASK_ASSIGNMENTS_ENTITY,
281
+ ExtraFilter: `TaskID='${taskID}'`,
282
+ ResultType: 'simple',
283
+ }, contextUser);
284
+ if (!assignments?.Success || assignments.Results.length === 0) {
285
+ return [];
286
+ }
287
+ const personIDs = assignments.Results.map((a) => a.AssigneeRecordID);
288
+ const inClause = personIDs.map((id) => `'${id}'`).join(',');
289
+ const people = await rv.RunView({
290
+ EntityName: 'MJ_BizApps_Common: People',
291
+ ExtraFilter: `ID IN (${inClause}) AND LinkedUserID IS NOT NULL`,
292
+ Fields: ['ID', 'LinkedUserID'],
293
+ ResultType: 'simple',
294
+ }, contextUser);
295
+ if (!people?.Success) {
296
+ return [];
297
+ }
298
+ return people.Results
299
+ .map((p) => p.LinkedUserID)
300
+ .filter((id) => id != null);
301
+ }
302
+ /**
303
+ * Resolves a PersonID to their linked MJ UserID (if any).
304
+ */
305
+ async function getPersonLinkedUserID(personID, contextUser) {
306
+ const rv = new RunView();
307
+ const result = await rv.RunView({
308
+ EntityName: 'MJ_BizApps_Common: People',
309
+ ExtraFilter: `ID='${personID}'`,
310
+ Fields: ['ID', 'LinkedUserID'],
311
+ ResultType: 'simple',
312
+ MaxRows: 1,
313
+ }, contextUser);
314
+ return result?.Results?.[0]?.LinkedUserID ?? null;
315
+ }
316
+ /**
317
+ * Resolves a PersonID to their display name.
318
+ */
319
+ async function getPersonName(personID, contextUser) {
320
+ const rv = new RunView();
321
+ const result = await rv.RunView({
322
+ EntityName: 'MJ_BizApps_Common: People',
323
+ ExtraFilter: `ID='${personID}'`,
324
+ Fields: ['ID', 'FirstName', 'LastName'],
325
+ ResultType: 'simple',
326
+ MaxRows: 1,
327
+ }, contextUser);
328
+ const p = result?.Results?.[0];
329
+ return p ? `${p.FirstName} ${p.LastName}` : null;
330
+ }
331
+ /**
332
+ * Creates an in-app notification for each UserID in the list.
333
+ */
334
+ async function createNotificationsForUsers(userIDs, title, message, contextUser) {
335
+ const md = new Metadata();
336
+ const saves = userIDs.map(async (userID) => {
337
+ const notification = await md.GetEntityObject('MJ: User Notifications', contextUser);
338
+ notification.NewRecord();
339
+ notification.Set('UserID', userID);
340
+ notification.Set('Title', title);
341
+ notification.Set('Message', message);
342
+ notification.Set('Unread', true);
343
+ const saved = await notification.Save();
344
+ if (!saved) {
345
+ LogError(`[BizAppsTasks] Failed to save notification for user ${userID}`);
346
+ }
347
+ });
348
+ await Promise.all(saves);
349
+ }
350
+ /**
351
+ * Formats a Date to a readable string like "Mar 12, 2026"
352
+ */
353
+ function formatDate(date) {
354
+ if (!(date instanceof Date) || isNaN(date.getTime())) {
355
+ return 'TBD';
356
+ }
357
+ return date.toLocaleDateString('en-US', {
358
+ month: 'short',
359
+ day: 'numeric',
360
+ year: 'numeric',
361
+ });
362
+ }
363
+ //# sourceMappingURL=TaskNotificationHandler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TaskNotificationHandler.js","sourceRoot":"","sources":["../../src/event-handlers/TaskNotificationHandler.ts"],"names":[],"mappings":"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"}