86 lines
3.0 KiB
JavaScript
86 lines
3.0 KiB
JavaScript
function createNotificationUndo({ restore, onItems, onStatus, onOffer = () => {}, onClear = () => {} }) {
|
|
let offered = null;
|
|
let pending = false;
|
|
|
|
return {
|
|
offer(item, items) {
|
|
if (!item || !Number.isInteger(item.notification_id)) return false;
|
|
offered = { item, items: Array.isArray(items) ? [...items] : [] };
|
|
const label = item.key || 'Update';
|
|
onStatus(label + ' marked read. Undo?');
|
|
onOffer(item);
|
|
return true;
|
|
},
|
|
async run() {
|
|
if (!offered || pending) return false;
|
|
const current = offered;
|
|
const label = current.item.key || 'Update';
|
|
pending = true;
|
|
onStatus('Restoring ' + label + '…');
|
|
try {
|
|
await restore(current.item.notification_id);
|
|
if (offered !== current) return false;
|
|
const restored = [current.item].concat(current.items.filter(
|
|
item => item?.notification_id !== current.item.notification_id
|
|
));
|
|
offered = null;
|
|
onItems(restored, current.item);
|
|
onStatus(label + ' is unread again.');
|
|
onClear();
|
|
return true;
|
|
} catch (_error) {
|
|
onStatus('Could not restore ' + label + '. Retry Undo.');
|
|
return false;
|
|
} finally {
|
|
pending = false;
|
|
}
|
|
},
|
|
clear() {
|
|
offered = null;
|
|
onClear();
|
|
},
|
|
};
|
|
}
|
|
|
|
async function requestNotificationUnread(notificationId) {
|
|
const response = await fetch('api/v1/notifications/' + encodeURIComponent(notificationId) + '/unread', {
|
|
method: 'PATCH', headers: { Accept: 'application/json' },
|
|
});
|
|
const payload = await response.json().catch(() => ({}));
|
|
if (!response.ok) throw new Error(payload.error || 'Restore unread failed.');
|
|
return payload;
|
|
}
|
|
|
|
function createDashboardNotificationUndo({ restore, getItems, setItems, getNotifications, setNotifications, refresh, select }) {
|
|
let timer = null;
|
|
const controller = createNotificationUndo({
|
|
restore,
|
|
onItems: (items, restored) => {
|
|
setItems(items);
|
|
const notifications = getNotifications();
|
|
if (!notifications.some(item => item.id === restored.notification_id)) {
|
|
setNotifications([{ id:restored.notification_id }].concat(notifications));
|
|
}
|
|
refresh();
|
|
},
|
|
onStatus: message => {
|
|
select('#notification-undo-status').textContent = message;
|
|
select('#my-work-action-status').textContent = message;
|
|
},
|
|
onOffer: item => {
|
|
clearTimeout(timer);
|
|
select('#notification-undo').hidden = false;
|
|
select('#undo-notification').disabled = false;
|
|
select('#undo-notification').setAttribute('aria-label', 'Undo marking ' + (item.key || 'update') + ' read');
|
|
timer = setTimeout(() => controller.clear(), 10000);
|
|
},
|
|
onClear: () => { select('#notification-undo').hidden = true; },
|
|
});
|
|
return controller;
|
|
}
|
|
|
|
if (typeof module !== 'undefined' && module.exports) {
|
|
module.exports = createNotificationUndo;
|
|
module.exports.createDashboardNotificationUndo = createDashboardNotificationUndo;
|
|
}
|