feat: plan Following changes and continue review (Closes #1326)
CI / lint (pull_request) Successful in 3m25s
CI / build-release (pull_request) Successful in 6s
CI / browser-journey (pull_request) Successful in 5m46s
CI / release-candidate (pull_request) Has been skipped

This commit is contained in:
timmy committed 2026-08-23 23:33:36 +00:00
1 parent 0f36d3077b
commit 07836f7176
6 files changed
+107 -7

No files matched your search

+2
View File
@@ -1056,8 +1056,10 @@ textarea { resize: vertical; min-height: 120px; }
#keep-following-status { display:block; min-height:20px; overflow-wrap:anywhere; }
.search-preview-actions button, .search-preview-actions a { min-height:44px; box-sizing:border-box; display:flex; align-items:center; justify-content:center; }
.search-preview-primary-actions { display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:8px; }
.search-preview-primary-actions.following-disposition-mode { grid-template-columns:repeat(3,minmax(0,1fr)); }
@media (max-width:420px) {
.search-preview-primary-actions { grid-template-columns:1fr; }
.search-preview-primary-actions.following-disposition-mode { grid-template-columns:1fr; }
}
@media (max-width:600px) {
.search-preview-panel { width:100%; border-left:0; padding:14px; padding-top:max(12px,env(safe-area-inset-top)); }
+3 -1
View File
@@ -5716,6 +5716,7 @@
const detail = state.detail;
if (!detail) return;
searchPreviewDetail = detail;
shareButton.disabled = state.status === 'sharing';
qs('#search-preview-key').textContent = detail.repository + ' #' + detail.number;
qs('#search-preview-title').textContent = detail.title || 'Untitled work item';
@@ -5747,6 +5748,7 @@
(detail.assigned_to_me ? 'Start in Today' : 'Assign & start');
startButton.disabled = state.status === 'claiming' || state.status === 'reopening';
renderSearchPreviewWatch(detail, state, watchButton);
followingQueue.preview(state);
const shareStatus = {
sharing:'Opening share options…', shared:'Search result shared.', copied:'Search result link copied.',
'share-canceled':'Share canceled.', 'share-error':'Could not share this result. Try again.',
@@ -5817,7 +5819,7 @@
createSearchWeekPlanUI({planner:searchWeekPlan,document,window,escapeHtml,escapeAttribute:escAttr,
getDetail:()=>searchPreviewDetail,
announce:message=>{qs('#search-preview-status').textContent=message;},
onPlanned:item=>{searchPreviewDetail={...item,assigned_to_me:true,claimable:false};},
onPlanned:item=>(searchPreviewDetail=item,item.following&&next()),
});
searchBatchPlanning = mountSearchBatchPlanning(
document, createBatchFindWork, todayWork, ()=>planningOwnerLogin, fetchReviewJson,
+25 -2
View File
@@ -3,11 +3,33 @@
if (typeof module === 'object' && module.exports) {
module.exports = exports.createFollowing;
module.exports.attachFollowing = exports.attachFollowing;
module.exports.planningDisposition = exports.planningDisposition;
} else {
root.createFollowing = exports.createFollowing;
root.attachFollowing = exports.attachFollowing;
root.followingPlanningDisposition = exports.planningDisposition;
}
})(typeof self !== 'undefined' ? self : this, function () {
function planningDisposition(detail, controls) {
const active = detail?.following === true && detail.kind === 'issue' && detail.state === 'open' &&
Boolean(detail.claimable || detail.assigned_to_me);
const result = active ? {active:true,today:'Add to Today & next',later:'Later & next',week:'Week Ahead & next'} : {active:false};
if (!controls && globalThis.document) {
const query = selector => globalThis.document.querySelector(selector);
controls = {root:query('.search-preview-primary-actions'),claim:query('#claim-search-result'),
today:query('#queue-search-result'),later:query('#defer-search-result'),week:query('#plan-search-result'),
start:query('#start-search-result'),watch:query('#watch-search-result')};
}
controls?.root?.classList.toggle('following-disposition-mode', active);
if (active && controls) {
controls.claim.hidden = controls.start.hidden = controls.watch.hidden = true;
controls.today.textContent = result.today;
controls.later.textContent = result.later;
controls.week.textContent = result.week;
}
return result;
}
function createFollowing(options) {
let generation = 0;
let snapshot = {revision:0, items:[]};
@@ -248,7 +270,8 @@
keepForLater:feature.keepForLater,
retire:feature.retire,
preview(state) {
keepButton.hidden = state?.item?.following !== true;
const disposition = planningDisposition(state?.detail || state?.item);
keepButton.hidden = state?.item?.following !== true || disposition.active;
keepButton.disabled = false;
if (keepButton.hidden || state.status === 'loading') query('#keep-following-status').textContent = '';
},
@@ -265,5 +288,5 @@
};
}
return {createFollowing, attachFollowing};
return {createFollowing, attachFollowing, planningDisposition};
});
+3 -3
View File
@@ -42,7 +42,7 @@ function createSearchWeekPlan({week,claim,accept=item=>item,identity,maxItems=5}
await week.flush();
return {status:'planned',date:options.date,estimate,item};
} catch(_error) {
return {status:'planned-pending',date:options.date,estimate};
return {status:'planned-pending',date:options.date,estimate,item};
}
};
running=perform().finally(()=>{running=null;});
@@ -99,8 +99,8 @@ function createSearchWeekPlanUI({planner,document,window,getDetail,onPlanned=()=
else if(outcome.status==='day-full')status.textContent='That day already has '+outcome.limit+' items. Choose another day.';
else if(outcome.status==='already-planned')status.textContent='Already planned for '+outcome.date+'. Choose Move to change the day.';
else if(outcome.status==='assigned-not-planned')status.textContent='Assigned, not planned. Find it in My Work and retry.';
else if(outcome.status==='planned-pending'){announce('Planned for '+date+' · sync pending.');onPlanned(detail,true);close(true);}
else if(outcome.status==='planned'){announce('Planned for '+date+'.');onPlanned(detail,false);close(true);}
else if(outcome.status==='planned-pending'){announce('Planned for '+date+' · sync pending.');await onPlanned(outcome.item||detail,true,outcome);close(true);}
else if(outcome.status==='planned'){announce('Planned for '+date+'.');await onPlanned(outcome.item||detail,false,outcome);close(true);}
else status.textContent='Could not plan this issue. Retry.';
button.disabled=false;
}