Files
wekan/models/lib/webhookActivityPicker.js
Lauri Ojansivu c3321926ab Webhooks: pick which activities a webhook is sent.
An outgoing webhook was sent every activity, or whatever its activities
list said with no way to change it in the interface. Its form now has
"Send this webhook:" with "Every activity" and a tick per kind of
activity - the same groups a member mutes notifications by (#572):
labels, members, assignees, comments, moves, dates, checklists,
attachments, custom field values, archive and created. Ticks are saved as
the act-<type> descriptions the activity hook matches webhooks by;
nothing ticked, or Every activity, stays "all", the default.

models/lib/webhookActivityPicker.js maps both ways;
tests/webhookActivityPicker.test.cjs checks that a picked group selects
exactly its activities through webhookActivitySelection, the form state,
and that a webhook never silently gets nothing. Part of #2026 and #1377,
with the activity feed and browser push. The new strings are English
placeholders until the next translation pass.

Thanks to xet7 !
2026-10-14 15:37:16 +03:00

33 lines
1.5 KiB
JavaScript

'use strict';
// #2026 / #1377: which activities an outgoing webhook is sent, picked in its
// form by the same groups a member mutes notifications by (#572,
// models/lib/notificationActivityGroups.js) instead of only "all". A webhook
// matches an activity by its description, `act-<activityType>`
// (server/models/activities.js), so a group is the descriptions of its
// types. "Every activity" stays `all`, the default, which also gets
// activities no group lists. Pure: tests/webhookActivityPicker.test.cjs.
const { NOTIFICATION_ACTIVITY_GROUPS, GROUP_KEYS } = require('./notificationActivityGroups');
function groupDescriptions(key) {
return (NOTIFICATION_ACTIVITY_GROUPS[key] || []).map(type => `act-${type}`);
}
// What the form shows for a webhook's stored activities.
function pickerState(activities) {
const list = Array.isArray(activities) ? activities : ['all'];
if (list.includes('all')) return { all: true, groups: [] };
return { all: false, groups: GROUP_KEYS.filter(key => groupDescriptions(key).every(d => list.includes(d))) };
}
// The activities to store for what was ticked. Nothing ticked is "all":
// a webhook that receives nothing is switched off with its own toggle.
function activitiesFor({ all, groups } = {}) {
const chosen = GROUP_KEYS.filter(key => Array.isArray(groups) && groups.includes(key));
if (all || chosen.length === 0) return ['all'];
return [...new Set(chosen.flatMap(groupDescriptions))];
}
module.exports = { groupDescriptions, pickerState, activitiesFor };