Allow enabling/disabling individual SMS template types from dashboard with sync to notification settings

This commit is contained in:
2026-08-21 11:04:26 +03:30
parent 091e519280
commit 3c6eb278b0
4 changed files with 104 additions and 7 deletions
+56 -6
View File
@@ -49,13 +49,19 @@ const resolveTemplateId = (entry, def) => {
return envFallbackFor(def);
};
const toPublicTemplates = (storedMap) => {
const toPublicTemplates = (storedMap, notificationMap = {}) => {
return SMS_TEMPLATE_DEFS.map((def) => {
const entry = normalizeStoredEntry(storedMap[def.key], def);
const variables = resolveVariablesList(def, entry.variables);
const notifyAction = notificationMap[def.key];
const isEnabled = notifyAction && notifyAction.sms !== undefined
? Boolean(notifyAction.sms)
: entry.enabled;
return {
key: def.key,
label: def.label,
enabled: isEnabled,
templateId: resolveTemplateId(entry, def),
availableSlots: (def.slots || []).map((slot) => ({
slot: slot.key,
@@ -98,8 +104,9 @@ const getSettings = async () => {
}
const storedMap = readStoredMap(doc);
const notificationMap = readNotificationStoredMap(doc);
return {
smsTemplates: toPublicTemplates(storedMap),
smsTemplates: toPublicTemplates(storedMap, notificationMap),
messaging: getPublicMessaging(doc),
notificationSettings: await getPublicNotificationSettings(doc)
};
@@ -108,11 +115,18 @@ const getSettings = async () => {
const getSmsTemplate = async (key) => {
const def = SMS_TEMPLATE_DEFS.find((item) => item.key === key);
if (!def) {
return { templateId: '', variables: [] };
return { templateId: '', variables: [], enabled: true };
}
const doc = await Setting.findOne({ key: SETTINGS_KEY }).lean();
const entry = normalizeStoredEntry(readStoredMap(doc)[key], def);
const notificationStored = readNotificationStoredMap(doc);
const notifyAction = notificationStored[key];
const isEnabled = notifyAction && notifyAction.sms !== undefined
? Boolean(notifyAction.sms)
: entry.enabled;
return {
enabled: isEnabled,
templateId: resolveTemplateId(entry, def),
variables: resolveVariablesList(def, entry.variables)
};
@@ -126,10 +140,11 @@ const getSmsTemplateId = async (key) => {
const parseIncomingEntry = (raw) => {
if (raw == null) return null;
if (typeof raw === 'string' || typeof raw === 'number') {
return { templateId: raw, variables: undefined };
return { templateId: raw, variables: undefined, enabled: undefined };
}
if (typeof raw !== 'object') return null;
return {
enabled: raw.enabled !== undefined ? Boolean(raw.enabled) : undefined,
templateId: raw.templateId,
variables: raw.variables
};
@@ -172,6 +187,23 @@ const saveSettings = async (body = {}) => {
doc.set('smsTemplates', JSON.parse(JSON.stringify(nextMap)));
doc.markModified('smsTemplates');
// Synchronize smsEnabled to notificationSettings
const storedNotificationMap = existing
? readNotificationStoredMap(existing.toObject ? existing.toObject() : existing)
: emptyNotificationSettingsMap();
const updatedNotificationMap = { ...storedNotificationMap };
for (const def of SMS_TEMPLATE_DEFS) {
if (nextMap[def.key] && nextMap[def.key].enabled !== undefined) {
const currentAction = updatedNotificationMap[def.key] || { sms: true, email: false, bot: false };
updatedNotificationMap[def.key] = {
...currentAction,
sms: Boolean(nextMap[def.key].enabled)
};
}
}
doc.set('notificationSettings', JSON.parse(JSON.stringify(mergeNotificationSettings(updatedNotificationMap))));
doc.markModified('notificationSettings');
} else if (!existing) {
doc.set('smsTemplates', emptyTemplateMap());
}
@@ -191,7 +223,24 @@ const saveSettings = async (body = {}) => {
const nextNotificationMap = mergeNotificationSettings(storedNotificationMap, incomingNotificationSettings);
doc.set('notificationSettings', JSON.parse(JSON.stringify(nextNotificationMap)));
doc.markModified('notificationSettings');
} else if (!existing) {
// Synchronize enabled flag in smsTemplates
const storedSmsMap = existing
? readStoredMap(existing.toObject ? existing.toObject() : existing)
: emptyTemplateMap();
const updatedSmsMap = { ...storedSmsMap };
for (const def of SMS_TEMPLATE_DEFS) {
if (nextNotificationMap[def.key] && nextNotificationMap[def.key].sms !== undefined) {
const currentTemplate = normalizeStoredEntry(updatedSmsMap[def.key], def);
updatedSmsMap[def.key] = {
...currentTemplate,
enabled: Boolean(nextNotificationMap[def.key].sms)
};
}
}
doc.set('smsTemplates', JSON.parse(JSON.stringify(updatedSmsMap)));
doc.markModified('smsTemplates');
} else if (!existing && !hasTemplatePayload) {
doc.set('notificationSettings', emptyNotificationSettingsMap());
}
@@ -200,8 +249,9 @@ const saveSettings = async (body = {}) => {
invalidateNotificationSettingsCache();
const saved = await Setting.findOne({ key: SETTINGS_KEY }).lean();
const finalNotificationMap = readNotificationStoredMap(saved);
return {
smsTemplates: toPublicTemplates(readStoredMap(saved)),
smsTemplates: toPublicTemplates(readStoredMap(saved), finalNotificationMap),
messaging: getPublicMessaging(saved),
notificationSettings: await getPublicNotificationSettings(saved)
};