notifications: add context field

This commit is contained in:
Girish Ramakrishnan
2024-12-11 22:29:00 +01:00
parent 701c25d07a
commit d0d0913c70
4 changed files with 23 additions and 13 deletions

View File

@@ -0,0 +1,9 @@
'use strict';
exports.up = async function (db) {
await db.runSql('ALTER TABLE notifications ADD COLUMN context VARCHAR(128) DEFAULT ""');
};
exports.down = async function (db) {
await db.runSql('ALTER TABLE notifications DROP COLUMN context');
};

View File

@@ -272,6 +272,7 @@ CREATE TABLE IF NOT EXISTS notifications(
message TEXT,
acknowledged BOOLEAN DEFAULT false,
creationTime TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
context VARCHAR(128) DEFAULT "", // used along with "type" to create uniqueness
INDEX creationTime_index (creationTime),
FOREIGN KEY(eventId) REFERENCES eventlog(id),

View File

@@ -48,7 +48,7 @@ const assert = require('assert'),
mailer = require('./mailer.js'),
users = require('./users.js');
const NOTIFICATION_FIELDS = [ 'id', 'eventId', 'type', 'title', 'message', 'creationTime', 'acknowledged' ];
const NOTIFICATION_FIELDS = [ 'id', 'eventId', 'type', 'title', 'message', 'creationTime', 'acknowledged', 'context' ];
function postProcess(result) {
assert.strictEqual(typeof result, 'object');
@@ -63,8 +63,8 @@ async function add(type, title, message, data) {
assert.strictEqual(typeof message, 'string');
assert.strictEqual(typeof data, 'object');
const query = 'INSERT INTO notifications (type, title, message, acknowledged, eventId) VALUES (?, ?, ?, ?, ?)';
const args = [ type, title, message, false, data?.eventId || null ];
const query = 'INSERT INTO notifications (type, title, message, acknowledged, eventId, context) VALUES (?, ?, ?, ?, ?, ?)';
const args = [ type, title, message, false, data?.eventId || null, data.context || '' ];
const result = await database.query(query, args);
return String(result.insertId);
@@ -79,10 +79,11 @@ async function get(id) {
return postProcess(result[0]);
}
async function getByType(type) {
async function getByType(type, context) {
assert.strictEqual(typeof type, 'string');
assert.strictEqual(typeof context, 'string');
const results = await database.query(`SELECT ${NOTIFICATION_FIELDS} from notifications WHERE type = ? ORDER BY creationTime LIMIT 1`, [ type ]);
const results = await database.query(`SELECT ${NOTIFICATION_FIELDS} from notifications WHERE type = ? AND context = ? ORDER BY creationTime LIMIT 1`, [ type, context || '']);
if (results.length === 0) return null;
return postProcess(results[0]);
@@ -280,16 +281,14 @@ async function pin(type, title, message, options) {
return null;
}
const isUpdateType = type === exports.TYPE_BOX_UPDATE || type === exports.TYPE_MANUAL_APP_UPDATE_NEEDED;
if (options.context) type = `${type}-${options.context}`; // create a unique type for this context
const result = await getByType(type);
if (!result) return await add(type, title, message, { eventId: null });
const result = await getByType(type, options.context || '');
if (!result) return await add(type, title, message, { eventId: null, context: options.context || '' });
// do not reset the ack state if user has already seen the update notification
const isUpdateType = type === exports.TYPE_BOX_UPDATE || type === exports.TYPE_MANUAL_APP_UPDATE_NEEDED;
const acknowledged = (isUpdateType && result.message === message) ? result.acknowledged : false;
await update(result, { id: result.id, title, message, acknowledged, creationTime: new Date() });
await update(result, { title, message, acknowledged, creationTime: new Date() });
return result.id;
}
@@ -297,8 +296,7 @@ async function unpin(type, options) {
assert.strictEqual(typeof type, 'string'); // TYPE_
assert.strictEqual(typeof options, 'object');
if (options.context) type = `${type}-${options.context}`; // create a unique type for this context
await database.query('UPDATE notifications SET acknowledged=1 WHERE type = ?', [ type ]);
await database.query('UPDATE notifications SET acknowledged=1 WHERE type = ? AND context = ?', [ type, options.context || '' ]);
}
async function onEvent(id, action, source, data) {

View File

@@ -132,6 +132,8 @@ describe('Notifications', function () {
it('can add pin', async function () {
pinId = await notifications.pin(notifications.TYPE_REBOOT, 'Reboot required', 'Do it now', {});
console.log(pinId);
const result = await notifications.get(pinId);
expect(result.title).to.be('Reboot required');
expect(result.message).to.be('Do it now');