feat: send mobile deadline reminders (Closes #709)
This commit is contained in:
1 parent
4209834d6d
commit
5e6328a8d0
12 files changed
+540
-5
No files matched your search
@@ -6044,6 +6044,8 @@
|
||||
const controller = createPushNotifications({
|
||||
control:qs('#push-updates'),
|
||||
status:qs('#push-update-status'),
|
||||
deadlineControl:qs('#push-deadlines'),
|
||||
deadlineStatus:qs('#push-deadline-status'),
|
||||
notification:window.Notification,
|
||||
serviceWorker:navigator.serviceWorker,
|
||||
fetchJson:fetchReviewJson,
|
||||
|
||||
@@ -129,6 +129,8 @@
|
||||
<label for="delivery-receipts"><input id="delivery-receipts" type="checkbox" /> Notify me when queued work finishes</label>
|
||||
<label class="push-update-control" for="push-updates"><input id="push-updates" type="checkbox" /> Notify me about new updates</label>
|
||||
<span class="small" id="push-update-status" role="status" aria-live="polite"></span>
|
||||
<label class="push-update-control" for="push-deadlines"><input id="push-deadlines" type="checkbox" /> Notify me about deadlines</label>
|
||||
<span class="small" id="push-deadline-status" role="status" aria-live="polite"></span>
|
||||
<button id="clear-offline-work" type="button">Clear offline work data</button>
|
||||
<button id="retry-offline-storage" type="button" hidden>Retry offline saving</button>
|
||||
<span class="small" id="offline-work-status" role="status" aria-live="polite"></span>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
if (typeof module === 'object' && module.exports) module.exports = factory;
|
||||
else root.createPushNotifications = factory;
|
||||
})(typeof self !== 'undefined' ? self : this, function createPushNotifications({
|
||||
control, status, notification, serviceWorker, fetchJson,
|
||||
control, status, deadlineControl, deadlineStatus, notification, serviceWorker, fetchJson,
|
||||
}) {
|
||||
let configuration = null;
|
||||
|
||||
@@ -20,7 +20,9 @@
|
||||
await fetchJson('api/v1/push-subscription', {method:'DELETE'});
|
||||
await subscription?.unsubscribe?.();
|
||||
control.checked = false;
|
||||
if (deadlineControl) deadlineControl.checked = false;
|
||||
status.textContent = 'New update notifications are off for this device.';
|
||||
if (deadlineStatus) deadlineStatus.textContent = 'Deadline reminders are off for this device.';
|
||||
}
|
||||
|
||||
async function enable() {
|
||||
@@ -60,20 +62,53 @@
|
||||
}
|
||||
}
|
||||
|
||||
async function changeDeadline() {
|
||||
deadlineControl.disabled = true;
|
||||
try {
|
||||
const registration = await serviceWorker.ready;
|
||||
const subscription = await registration.pushManager.getSubscription();
|
||||
if (deadlineControl.checked && !subscription) {
|
||||
deadlineControl.checked = false;
|
||||
deadlineStatus.textContent = 'Enable new update notifications first.';
|
||||
return;
|
||||
}
|
||||
const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone || 'UTC';
|
||||
await fetchJson('api/v1/push-subscription/deadlines', {
|
||||
method:'PUT',
|
||||
headers:{'Content-Type':'application/json'},
|
||||
body:JSON.stringify({enabled:deadlineControl.checked, timezone, reminder_hour:9}),
|
||||
});
|
||||
deadlineStatus.textContent = deadlineControl.checked
|
||||
? 'Deadline reminders enabled for 9:00 local time.'
|
||||
: 'Deadline reminders are off for this device.';
|
||||
} catch (error) {
|
||||
deadlineControl.checked = !deadlineControl.checked;
|
||||
deadlineStatus.textContent = 'Could not change deadline reminders. Check your connection and try again.';
|
||||
} finally {
|
||||
deadlineControl.disabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
async function init() {
|
||||
if (!control || !notification || !serviceWorker) return;
|
||||
control.addEventListener('change', change);
|
||||
deadlineControl?.addEventListener('change', changeDeadline);
|
||||
configuration = await fetchJson('api/v1/push-subscription');
|
||||
if (!configuration.available) {
|
||||
control.disabled = true;
|
||||
if (deadlineControl) deadlineControl.disabled = true;
|
||||
status.textContent = 'New update notifications are not available on this server.';
|
||||
return;
|
||||
}
|
||||
control.checked = Boolean(configuration.subscribed);
|
||||
if (deadlineControl) deadlineControl.checked = Boolean(configuration.deadline_enabled);
|
||||
status.textContent = configuration.subscribed
|
||||
? 'New update notifications enabled for this device.'
|
||||
: 'New update notifications are off for this device.';
|
||||
if (deadlineStatus) deadlineStatus.textContent = configuration.deadline_enabled
|
||||
? `Deadline reminders enabled for ${configuration.reminder_hour}:00 local time.`
|
||||
: 'Deadline reminders are off for this device.';
|
||||
}
|
||||
|
||||
return {init, change};
|
||||
return {init, change, changeDeadline};
|
||||
});
|
||||
@@ -316,6 +316,24 @@ self.addEventListener('push', event => {
|
||||
const tag = String(payload.tag || '');
|
||||
const notificationId = Number(payload.notification_id);
|
||||
const updateCount = Number(payload.update_count);
|
||||
const deadlineCount = Number(payload.deadline_count);
|
||||
if (
|
||||
route === '#/my-work/agenda'
|
||||
&& /^stackchain-deadline-digest-\d{4}-\d{2}-\d{2}$/.test(tag)
|
||||
&& Number.isSafeInteger(deadlineCount)
|
||||
&& deadlineCount > 0
|
||||
&& deadlineCount <= 50
|
||||
) {
|
||||
event.waitUntil(self.registration.showNotification(
|
||||
deadlineCount + ' deadline' + (deadlineCount === 1 ? '' : 's') + ' need' + (deadlineCount === 1 ? 's' : '') + ' attention',
|
||||
{
|
||||
body: 'Open Agenda to review or replan ' + (deadlineCount === 1 ? 'it.' : 'them.'),
|
||||
tag,
|
||||
data: {route},
|
||||
}
|
||||
));
|
||||
return;
|
||||
}
|
||||
if (
|
||||
route === '#/my-work/updates'
|
||||
&& tag === 'stackchain-update-digest'
|
||||
|
||||
Reference in new issue
Block a user