73 lines
2.6 KiB
JavaScript
73 lines
2.6 KiB
JavaScript
function createIssueCapture({ fetchJson, storage }) {
|
|
const storageKey = 'stackchain.issue-capture.v1';
|
|
let pending = null;
|
|
const safeLabelIds = value => Array.from(new Set(
|
|
(Array.isArray(value) ? value : []).filter(id => Number.isInteger(id) && id > 0)
|
|
)).slice(0, 20);
|
|
const emptyDraft = () => ({ repository: '', title: '', body: '', labelIds: [] });
|
|
|
|
function saveDraft(draft) {
|
|
const safe = {
|
|
repository: String(draft?.repository || ''),
|
|
title: String(draft?.title || ''),
|
|
body: String(draft?.body || ''),
|
|
labelIds: safeLabelIds(draft?.labelIds),
|
|
};
|
|
try { storage.setItem(storageKey, JSON.stringify(safe)); }
|
|
catch (_error) { /* Keep the form as the in-memory fallback. */ }
|
|
return safe;
|
|
}
|
|
|
|
function loadDraft() {
|
|
try {
|
|
const parsed = JSON.parse(storage.getItem(storageKey) || 'null');
|
|
return parsed && typeof parsed === 'object' ? {
|
|
repository: String(parsed.repository || ''),
|
|
title: String(parsed.title || ''),
|
|
body: String(parsed.body || ''),
|
|
labelIds: safeLabelIds(parsed.labelIds),
|
|
} : emptyDraft();
|
|
} catch (_error) {
|
|
return emptyDraft();
|
|
}
|
|
}
|
|
|
|
function clearDraft() {
|
|
try { storage.removeItem(storageKey); }
|
|
catch (_error) { /* Confirmed creation remains authoritative. */ }
|
|
}
|
|
|
|
function loadLabels(repository) {
|
|
const encoded = String(repository || '').split('/').map(encodeURIComponent).join('/');
|
|
const priorities = new Set(['p0', 'priority-high', 'critical']);
|
|
return fetchJson('api/v1/repos/' + encoded + '/labels').then(labels =>
|
|
(Array.isArray(labels) ? labels : []).slice().sort((left, right) => {
|
|
const leftPriority = priorities.has(String(left?.name || '').toLowerCase());
|
|
const rightPriority = priorities.has(String(right?.name || '').toLowerCase());
|
|
return Number(rightPriority) - Number(leftPriority);
|
|
})
|
|
);
|
|
}
|
|
|
|
function submit(draft) {
|
|
if (pending) return pending;
|
|
const saved = saveDraft(draft);
|
|
const repository = saved.repository.split('/').map(encodeURIComponent).join('/');
|
|
pending = fetchJson('api/v1/repos/' + repository + '/issues', {
|
|
method: 'POST',
|
|
headers: { Accept: 'application/json', 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({
|
|
title: saved.title, body: saved.body, label_ids: saved.labelIds,
|
|
}),
|
|
}).then(issue => {
|
|
clearDraft();
|
|
return issue;
|
|
}).finally(() => { pending = null; });
|
|
return pending;
|
|
}
|
|
|
|
return { saveDraft, loadDraft, loadLabels, submit };
|
|
}
|
|
|
|
if (typeof module !== 'undefined' && module.exports) module.exports = createIssueCapture;
|