stackchain-dashboard/frontend/pull-sheet.js
timmy 745c3779c2
All checks were successful
CI / lint (pull_request) Successful in 13s
CI / build-frontend (pull_request) Successful in 4s
feat: complete assigned pull requests from mobile (#161)
2026-08-07 03:30:21 +00:00

64 lines
2.6 KiB
JavaScript

function mergeEligibility(detail) {
if (!detail || detail.state !== 'open' || detail.merged) {
return { allowed: false, reason: 'Pull request is not open' };
}
if (detail.draft) return { allowed: false, reason: 'Draft pull requests cannot be merged' };
if (!detail.mergeable) return { allowed: false, reason: 'Resolve conflicts before merging' };
if (detail.ci_state !== 'success') {
return { allowed: false, reason: 'CI must succeed before merging' };
}
if (!detail.head_sha) return { allowed: false, reason: 'Current head is unavailable' };
return { allowed: true, reason: 'Ready to merge' };
}
function createPullSheet({ fetchJson, storage }) {
let commentRequest = null;
let mergeRequest = null;
const pathFor = item => 'api/v1/repos/' + String(item.repository || '').split('/')
.map(encodeURIComponent).join('/') + '/pulls/' + encodeURIComponent(item.number);
const draftKey = item => 'stackchain.pull-comment.v1:' + item.repository + '#' + item.number;
return {
load(item) {
return fetchJson(pathFor(item) + '/detail', { headers: { Accept: 'application/json' } });
},
loadDraft(item) {
try { return storage?.getItem(draftKey(item)) || ''; }
catch (_error) { return ''; }
},
saveDraft(item, body) {
try { storage?.setItem(draftKey(item), body); }
catch (_error) { /* The textarea remains the fallback. */ }
},
comment(item, body) {
if (commentRequest) return commentRequest;
this.saveDraft(item, body);
commentRequest = fetchJson(pathFor(item) + '/comments', {
method: 'POST',
headers: { Accept: 'application/json', 'Content-Type': 'application/json' },
body: JSON.stringify({ body }),
}).then(result => {
try { storage?.removeItem(draftKey(item)); }
catch (_error) { /* The upstream comment is authoritative. */ }
return result;
}).finally(() => { commentRequest = null; });
return commentRequest;
},
merge(item, expectedHeadSha) {
if (mergeRequest) return mergeRequest;
mergeRequest = fetchJson(pathFor(item) + '/merge', {
method: 'POST',
headers: { Accept: 'application/json', 'Content-Type': 'application/json' },
body: JSON.stringify({ expected_head_sha: expectedHeadSha }),
}).then(result => {
if (!result?.merged) throw new Error('Pull request merge was not confirmed.');
return result;
}).finally(() => { mergeRequest = null; });
return mergeRequest;
},
};
}
createPullSheet.mergeEligibility = mergeEligibility;
if (typeof module !== 'undefined' && module.exports) module.exports = createPullSheet;