feat: acknowledge unread updates with reactions (Closes #539)
This commit is contained in:
1 parent
fb34b5ffda
commit
d7e2813700
10 files changed
+332
No files matched your search
@@ -265,6 +265,7 @@ textarea { resize: vertical; min-height: 120px; }
|
||||
.update-ownership-actions { display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:8px; }
|
||||
.update-ownership-actions button { min-width:0; width:100%; }
|
||||
.update-sheet-actions button, .update-sheet-actions a { min-height:44px; display:flex; align-items:center; justify-content:center; }
|
||||
.update-sheet-actions #acknowledge-update-next { min-height:44px; width:100%; }
|
||||
.update-sheet-actions a { border:1px solid #60a5fa; border-radius:10px; font-weight:700; }
|
||||
.update-retry { min-height:44px; width:100%; margin-top:10px; }
|
||||
.issue-sheet { position:fixed; inset:0; z-index:56; display:none; justify-content:flex-end; background:rgba(5,12,21,.72); backdrop-filter:blur(4px); }
|
||||
|
||||
@@ -508,6 +508,14 @@
|
||||
return payload;
|
||||
}
|
||||
|
||||
async function acknowledgeNotification(notificationId) {
|
||||
const response = await fetch('api/v1/notifications/' + encodeURIComponent(notificationId) +
|
||||
'/acknowledge', { method: 'POST', headers: { Accept: 'application/json' } });
|
||||
const payload = await response.json().catch(() => ({}));
|
||||
if (!response.ok) throw new Error(payload.error || 'Acknowledging the update failed.');
|
||||
return payload;
|
||||
}
|
||||
|
||||
async function markNotificationsRead(ids) {
|
||||
const response = await fetch('api/v1/notifications/read', {
|
||||
method: 'PATCH',
|
||||
@@ -674,6 +682,7 @@
|
||||
load: fetchNotificationDetail,
|
||||
loadConversation: fetchNotificationConversation,
|
||||
markRead: markNotificationRead,
|
||||
acknowledge: acknowledgeNotification,
|
||||
queueRead: notificationId => notificationReadOutbox.enqueueDurably(notificationId),
|
||||
loadSaved: item => offlineWorkStore.loadDetail(confirmedOwnerLogin, item),
|
||||
onOpen: item => {
|
||||
@@ -696,6 +705,7 @@
|
||||
qs('#update-reply-status').textContent = '';
|
||||
qs('#send-update-reply').disabled = false;
|
||||
qs('#send-update-reply-read-next').disabled = false;
|
||||
qs('#acknowledge-update-next').hidden = true;
|
||||
qs('#update-ownership-action').hidden = true;
|
||||
qs('#update-ownership-start').hidden = true;
|
||||
qs('#retry-update-load').hidden = true;
|
||||
@@ -708,6 +718,7 @@
|
||||
qs('#update-subject-state').textContent = detail.state || '';
|
||||
qs('#update-subject-body').innerHTML = renderMarkdown(detail.subject_body || 'No subject context was provided.');
|
||||
qs('#open-update-gitea').href = detail.url || selectedUpdate?.url || '#';
|
||||
qs('#acknowledge-update-next').hidden = !detail.acknowledge_supported;
|
||||
if (offlineWorkMode) {
|
||||
setOfflineUpdateControls(true);
|
||||
} else {
|
||||
@@ -1676,6 +1687,7 @@
|
||||
function setOfflineUpdateControls(offline) {
|
||||
qs('#mark-update-read-next').disabled = false;
|
||||
qs('#mark-update-read-next').textContent = offline ? 'Queue read & next' : 'Mark read & next';
|
||||
qs('#acknowledge-update-next').disabled = offline;
|
||||
qs('#update-ownership-action').disabled = offline;
|
||||
qs('#update-ownership-start').disabled = offline;
|
||||
qs('#load-older-update-comments').disabled = offline;
|
||||
@@ -4696,6 +4708,16 @@
|
||||
qs('#mark-update-read-next').disabled = false;
|
||||
}
|
||||
});
|
||||
qs('#acknowledge-update-next').addEventListener('click', async () => {
|
||||
const button = qs('#acknowledge-update-next');
|
||||
button.disabled = true;
|
||||
try {
|
||||
const result = await notificationReader.acknowledgeAndNext(lastMyWork);
|
||||
if (result) qs('#my-work-action-status').textContent = 'Update acknowledged with 👍.';
|
||||
} finally {
|
||||
button.disabled = offlineWorkMode;
|
||||
}
|
||||
});
|
||||
qs('#close-review-sheet').addEventListener('click', closeReviewSheet);
|
||||
qs('#retry-review-load').addEventListener('click', () => {
|
||||
if (selectedReview) openReviewSheet(selectedReview, reviewTrigger);
|
||||
|
||||
@@ -548,6 +548,7 @@
|
||||
<button id="update-ownership-start" type="button" hidden aria-describedby="update-sheet-status">Take ownership & start</button>
|
||||
</div>
|
||||
<button class="share-work-route" type="button">Share</button>
|
||||
<button id="acknowledge-update-next" type="button" hidden aria-label="Acknowledge and open next update">👍 Acknowledge & next</button>
|
||||
<button id="mark-update-read-next" type="button">Mark read & next</button>
|
||||
<a id="open-update-gitea" href="#" target="_blank" rel="noopener noreferrer">Open in Gitea</a>
|
||||
<details class="detail-defer"><summary>Defer</summary><div class="detail-defer-options"><button type="button" data-detail-defer-preset="today" disabled data-planning-disabled>Later today</button><button type="button" data-detail-defer-preset="tomorrow" disabled data-planning-disabled>Tomorrow</button><button type="button" data-detail-defer-custom disabled data-planning-disabled>Choose date & time</button><button type="button" data-detail-defer-cancel>Cancel</button></div></details>
|
||||
|
||||
@@ -280,6 +280,7 @@ function createWorkPager({ load, onItems, onPagination, onStatus }) {
|
||||
|
||||
function createNotificationReader({
|
||||
load, markRead, onOpen, onDetail, onItems, onStatus, onClose,
|
||||
acknowledge = null,
|
||||
queueRead = null,
|
||||
loadSaved = () => null,
|
||||
loadConversation = null,
|
||||
@@ -382,6 +383,21 @@ function createNotificationReader({
|
||||
marking = false;
|
||||
}
|
||||
},
|
||||
async acknowledgeAndNext(items) {
|
||||
if (!selected || marking || offlineHydrated || !acknowledge) return false;
|
||||
const current = selected;
|
||||
marking = true;
|
||||
onStatus('Adding reaction and marking read…');
|
||||
try {
|
||||
await acknowledge(current.notification_id);
|
||||
return await advanceAfterRead(items, current);
|
||||
} catch (_error) {
|
||||
onStatus('Could not acknowledge update. Retry.');
|
||||
return false;
|
||||
} finally {
|
||||
marking = false;
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user