feat: open delegated filings read-only (Closes #872)
CI / lint (pull_request) Successful in 1m53s
CI / build-release (pull_request) Successful in 5s
CI / browser-journey (pull_request) Successful in 57s
CI / release-candidate (pull_request) Has been skipped

This commit is contained in:
timmy committed 2026-08-15 05:43:28 +00:00
1 parent efafaaddd2
commit 0bb76bdc8b
11 files changed
+238 -18

No files matched your search

+9
View File
@@ -521,6 +521,15 @@ textarea { resize: vertical; min-height: 120px; }
.issue-milestone-editor { display:grid; gap:8px; max-width:100%; margin:14px 0; padding:12px; border:1px solid #2a496e; border-radius:12px; }
.issue-milestone-editor select { width:100%; padding:8px; border-radius:8px; border:1px solid #1f3a5f; background:#0b1526; color:var(--text); }
.work-milestone-filter, .issue-milestone-editor select, .issue-milestone-editor button { min-height:44px; }
#issue-sheet.read-only .issue-comment-composer,
#issue-sheet.read-only #issue-planning,
#issue-sheet.read-only #issue-handoff,
#issue-sheet.read-only #release-issue,
#issue-sheet.read-only #close-issue,
#issue-sheet.read-only .detail-defer,
#issue-sheet.read-only #issue-blockers,
#issue-sheet.read-only #load-older-issue-comments,
#issue-sheet.read-only #retry-issue-comment-actions { display:none; }
.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; }
+14 -4
View File
@@ -1269,7 +1269,7 @@
closeOpenWorkSheets();
if (item.kind === 'update') notificationReader.open(item, lastMyWork);
else if (item.kind === 'review') openReviewSheet(item, reviewTrigger);
else if (item.kind === 'issue') openIssueSheet(item, issueTrigger);
else if (item.kind === 'issue' || item.kind === 'filed') openIssueSheet(item, issueTrigger);
else if (item.kind === 'pull') openPullSheet(item, pullTrigger);
},
onQueue: openWorkQueueRoute,
@@ -3294,6 +3294,8 @@
async function openIssueSheet(item, trigger, offlineDetail = null) {
if (!item) return;
const readOnly = issueController.readOnly(item);
qs('#issue-sheet').classList.toggle('read-only', readOnly);
issueDetailPosition.open(workDetailIdentity('issue', item));
qs('#issue-planning').inert = false;
qs('#issue-handoff').inert = false;
@@ -3362,9 +3364,12 @@
).join(' ');
qs('#issue-assignees').textContent = (detail.assignees || []).length ?
'Assigned to ' + detail.assignees.join(', ') : 'No assignee reported';
renderIssueConversation(issueConversation.snapshot());
if (readOnly) paintIssueConversation(issueConversation.snapshot(), null);
else renderIssueConversation(issueConversation.snapshot());
if (readOnly) qs('#load-older-issue-comments').hidden = true;
qs('#open-issue-gitea').href = detail.url || item.url || '#';
qs('#issue-sheet-status').textContent = 'Issue ready · ' + (detail.state || 'open');
qs('#issue-sheet-status').textContent = readOnly ? 'Filed issue ready · read-only' :
'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);
@@ -3978,7 +3983,12 @@
qs('#new-issue').click();
},
onFileAnother:() => qs('#new-issue').click(),
onViewFiled:issue => { selectMobileQueue('filed'); openRoutedWork({...issue, kind:'issue'}); },
onViewFiled:issue => {
selectMobileQueue('filed');
openRoutedWork({
...issue, kind:'issue', is_filed:true, is_assigned:(issue.assignees || []).includes(confirmedOwnerLogin),
});
},
});
function closeCreateIssueSheet(navigate = true, preserveDraft = true) {
if (navigate && taskOverlayHistory.current() === 'new') {
+5 -1
View File
@@ -38,8 +38,12 @@ function createIssueSheet({ fetchJson, storage, createConversationPager = global
const milestoneDraftKey = item => 'stackchain.issue-milestone.v1:' + item.repository + '#' + item.number;
return {
readOnly(item) {
return Boolean(item?.is_filed && !item?.is_assigned);
},
load(item) {
return fetchJson(issuePath(item) + '/detail', {
const access = this.readOnly(item) ? '?access=filed' : '';
return fetchJson(issuePath(item) + '/detail' + access, {
headers: { Accept: 'application/json' },
});
},
+7 -5
View File
@@ -6,7 +6,7 @@
'use strict';
const repositoryPart = /^[A-Za-z0-9_.-]+$/;
const queueFilters = ['today', 'agenda', 'attention', 'update', 'later', 'draft'];
const queueFilters = ['today', 'agenda', 'attention', 'filed', 'update', 'later', 'draft'];
function positiveInteger(value) {
const number = Number(value);
@@ -27,7 +27,7 @@
const notificationId = positiveInteger(parts[3]);
return notificationId ? { kind: 'update', notification_id: notificationId } : null;
}
if (!['issue', 'pull', 'review'].includes(parts[2]) || parts.length !== 6) return null;
if (!['issue', 'filed', 'pull', 'review'].includes(parts[2]) || parts.length !== 6) return null;
if (!repositoryPart.test(parts[3]) || !repositoryPart.test(parts[4])) return null;
const number = positiveInteger(parts[5]);
return number ? { kind: parts[2], repository: parts[3] + '/' + parts[4], number } : null;
@@ -38,11 +38,12 @@
const notificationId = positiveInteger(item.notification_id);
return notificationId ? '#/my-work/update/' + notificationId : '';
}
if (!['issue', 'pull', 'review'].includes(item?.kind)) return '';
const kind = item?.is_filed && !item?.is_assigned ? 'filed' : item?.kind;
if (!['issue', 'filed', 'pull', 'review'].includes(kind)) return '';
const repository = String(item.repository || '').split('/');
const number = positiveInteger(item.number);
if (repository.length !== 2 || !repository.every(part => repositoryPart.test(part)) || !number) return '';
return '#/my-work/' + item.kind + '/' + repository.join('/') + '/' + number;
return '#/my-work/' + kind + '/' + repository.join('/') + '/' + number;
}
function sameRoute(item, route) {
@@ -50,7 +51,8 @@
if (route.kind === 'update') {
return Number(item.notification_id) === route.notification_id;
}
const itemKind = item.is_review ? 'review' : item.kind;
const itemKind = item.is_review ? 'review' :
(item.is_filed && !item.is_assigned ? 'filed' : item.kind);
return itemKind === route.kind && item.repository === route.repository &&
Number(item.number) === route.number;
}