feat: schedule assigned issues from mobile (#191)
This commit is contained in:
1 parent
5406ee2297
commit
c639b09aaf
11 files changed
+378
-6
No files matched your search
@@ -146,6 +146,10 @@ textarea { resize: vertical; min-height: 120px; }
|
||||
.issue-label-option { min-height:44px; max-width:100%; display:flex; align-items:center; gap:10px; padding:8px; border:1px solid #2a496e; border-radius:10px; overflow-wrap:anywhere; }
|
||||
.issue-label-option input { width:20px; height:20px; flex:0 0 auto; }
|
||||
.issue-label-editor button { min-height:44px; width:100%; margin-top:10px; }
|
||||
.issue-due-editor { display:grid; gap:8px; max-width:100%; margin:14px 0; padding:12px; border:1px solid #2a496e; border-radius:12px; }
|
||||
.issue-due-editor input { box-sizing:border-box; width:100%; max-width:100%; }
|
||||
.issue-due-actions { display:grid; grid-template-columns:1fr 1fr; gap:8px; }
|
||||
.issue-due-editor input, .issue-due-editor button { min-height:44px; }
|
||||
.issue-sheet-actions { position:sticky; bottom:0; z-index:3; display:grid; gap:8px; margin-top:14px; padding:10px 4px; padding-bottom:calc(10px + env(safe-area-inset-bottom)); background:rgba(11,21,38,.98); border-top:1px solid #2a496e; }
|
||||
.issue-sheet-actions button, .issue-sheet-actions a { min-height:44px; display:flex; align-items:center; justify-content:center; }
|
||||
.issue-sheet-actions a { border:1px solid #60a5fa; border-radius:10px; font-weight:700; }
|
||||
@@ -361,6 +365,16 @@ textarea { resize: vertical; min-height: 120px; }
|
||||
<div class="small" id="issue-label-status" aria-live="polite">Load an issue to edit labels.</div>
|
||||
<button id="save-issue-labels" type="button" disabled>Save labels</button>
|
||||
</fieldset>
|
||||
<fieldset class="issue-due-editor" aria-describedby="issue-due-status">
|
||||
<legend>Due date</legend>
|
||||
<label for="issue-due-date" class="small">Schedule this assigned issue</label>
|
||||
<input id="issue-due-date" type="date" disabled />
|
||||
<div class="issue-due-actions">
|
||||
<button id="save-issue-due-date" type="button" disabled>Save due date</button>
|
||||
<button id="clear-issue-due-date" type="button" disabled>Clear due date</button>
|
||||
</div>
|
||||
<div id="issue-due-status" class="small" aria-live="assertive">Load an issue to schedule it.</div>
|
||||
</fieldset>
|
||||
<p class="issue-sheet-content" id="issue-sheet-body"></p>
|
||||
<button id="edit-issue-content" type="button" disabled>Edit issue</button>
|
||||
<form class="issue-edit-form" id="issue-edit-form" hidden>
|
||||
@@ -934,6 +948,7 @@ textarea { resize: vertical; min-height: 120px; }
|
||||
'<span class="small">' + escapeHtml(item.key) + ' · ' + escapeHtml(item.kind === 'pull' ? 'PR' : (item.kind === 'update' ? 'Update' : 'Issue')) + '</span>' +
|
||||
'<span class="my-work-card-title">' + escapeHtml(item.title) + '</span>' +
|
||||
'<span class="pill">' + escapeHtml(item.reason) + '</span>' +
|
||||
(item.due_label ? ' <span class="pill due-badge">' + escapeHtml(item.due_label) + '</span>' : '') +
|
||||
(item.has_update ? ' <span class="pill">Unread update</span>' : '') +
|
||||
(item.updated_at ? '<span class="small"> · Updated ' + escapeHtml(fmt(item.updated_at)) + '</span>' : '');
|
||||
const markRead = item.has_update && Number.isInteger(item.notification_id) ?
|
||||
@@ -1088,6 +1103,11 @@ textarea { resize: vertical; min-height: 120px; }
|
||||
qs('#issue-label-list').textContent = '';
|
||||
qs('#issue-label-status').textContent = 'Loading labels…';
|
||||
qs('#save-issue-labels').disabled = true;
|
||||
qs('#issue-due-date').value = '';
|
||||
qs('#issue-due-date').disabled = true;
|
||||
qs('#save-issue-due-date').disabled = true;
|
||||
qs('#clear-issue-due-date').disabled = true;
|
||||
qs('#issue-due-status').textContent = 'Loading due date…';
|
||||
qs('#retry-issue-load').hidden = true;
|
||||
qs('#open-issue-gitea').href = item.url || '#';
|
||||
qs('#send-issue-comment').disabled = false;
|
||||
@@ -1113,6 +1133,13 @@ textarea { resize: vertical; min-height: 120px; }
|
||||
qs('#open-issue-gitea').href = detail.url || item.url || '#';
|
||||
qs('#issue-sheet-status').textContent = 'Issue ready · ' + (detail.state || 'open');
|
||||
qs('#edit-issue-content').disabled = false;
|
||||
const dueDraft = issueController.loadDueDateDraft(item);
|
||||
qs('#issue-due-date').value = String(dueDraft || detail.due_date || '').slice(0, 10);
|
||||
qs('#issue-due-date').disabled = false;
|
||||
qs('#save-issue-due-date').disabled = false;
|
||||
qs('#clear-issue-due-date').disabled = !detail.due_date;
|
||||
qs('#issue-due-status').textContent = detail.due_date ?
|
||||
'Due ' + new Date(detail.due_date).toLocaleDateString() : 'No due date set.';
|
||||
} catch (error) {
|
||||
if (selectedIssue !== item) return;
|
||||
qs('#issue-sheet-status').textContent = error.message + ' Retry here or open it in Gitea.';
|
||||
@@ -1853,6 +1880,45 @@ textarea { resize: vertical; min-height: 120px; }
|
||||
button.disabled = false;
|
||||
}
|
||||
});
|
||||
|
||||
async function saveSelectedIssueDueDate(dueDate) {
|
||||
if (!selectedIssue || !lastContextSnapshot) return;
|
||||
const editing = selectedIssue;
|
||||
const saveButton = qs('#save-issue-due-date');
|
||||
const clearButton = qs('#clear-issue-due-date');
|
||||
saveButton.disabled = true;
|
||||
clearButton.disabled = true;
|
||||
qs('#issue-due-status').textContent = dueDate ? 'Saving due date…' : 'Clearing due date…';
|
||||
try {
|
||||
const confirmed = await issueController.updateDueDate(editing, dueDate);
|
||||
lastContextSnapshot = buildMyWork.replaceIssueDueDate(
|
||||
lastContextSnapshot, editing.repository, editing.number, confirmed.due_date
|
||||
);
|
||||
selectedIssue = { ...editing, due_date: confirmed.due_date };
|
||||
selectedIssueDetail = { ...selectedIssueDetail, due_date: confirmed.due_date };
|
||||
qs('#issue-due-date').value = String(confirmed.due_date || '').slice(0, 10);
|
||||
paintMyWork(lastContextSnapshot);
|
||||
qs('#issue-due-status').textContent = confirmed.due_date ?
|
||||
'Due date saved. My Work reprioritized.' : 'Due date cleared.';
|
||||
} catch (error) {
|
||||
qs('#issue-due-status').textContent = error.message + ' Your selection is safe; retry.';
|
||||
qs('#issue-due-date').focus();
|
||||
} finally {
|
||||
saveButton.disabled = false;
|
||||
clearButton.disabled = !selectedIssueDetail?.due_date;
|
||||
}
|
||||
}
|
||||
|
||||
qs('#save-issue-due-date').addEventListener('click', () => {
|
||||
const value = qs('#issue-due-date').value;
|
||||
if (!value) {
|
||||
qs('#issue-due-status').textContent = 'Choose a date or use Clear due date.';
|
||||
qs('#issue-due-date').focus();
|
||||
return;
|
||||
}
|
||||
saveSelectedIssueDueDate(value + 'T23:59:59Z');
|
||||
});
|
||||
qs('#clear-issue-due-date').addEventListener('click', () => saveSelectedIssueDueDate(null));
|
||||
qs('#send-issue-comment').addEventListener('click', async () => {
|
||||
if (!selectedIssue) return;
|
||||
const body = qs('#issue-comment').value.trim();
|
||||
|
||||
Reference in new issue
Block a user