feat: preserve progressive My Work queue truth (Closes #1403)
This commit is contained in:
1 parent
024087d051
commit
c15f7768e4
3 files changed
+131
-11
No files matched your search
@@ -1,6 +1,7 @@
|
||||
(async function(){
|
||||
const workspaceLifecycle = await (window.stackchainWorkspaceLifecycle || loadWorkspace({ document, window }));
|
||||
await workspaceLifecycle.optionalReady;
|
||||
const progressiveWorkHandoff = window.stackchainProgressiveMyWork?.handoff?.();
|
||||
window.stackchainProgressiveMyWork?.stop();
|
||||
const qs = (s, el=document) => el.querySelector(s);
|
||||
const announceWork = message => qs('#my-work-action-status').textContent = message;
|
||||
@@ -322,15 +323,17 @@
|
||||
let offlineWorkMode = false;
|
||||
const WORK_FILTER_KEY = 'stackchain.my-work-filter.v1';
|
||||
const WORK_MILESTONE_KEY = 'stackchain.my-work-milestone.v1';
|
||||
let selectedWorkFilter = 'all';
|
||||
const WORK_FILTERS = ['all', 'today', 'agenda', 'attention', 'filed', 'authored', 'issue', 'pull', 'review', 'update', 'later', 'draft'];
|
||||
const hasProgressiveWorkFilter = WORK_FILTERS.includes(progressiveWorkHandoff?.selectedFilter);
|
||||
let selectedWorkFilter = hasProgressiveWorkFilter ? progressiveWorkHandoff.selectedFilter : 'all';
|
||||
let selectedFiledView = 'needs-review';
|
||||
let selectedWorkMilestone = 'all';
|
||||
let queueFindQuery = '';
|
||||
let savedWorkFilter = null;
|
||||
let launchFilterResolved = false;
|
||||
let launchFilterResolved = hasProgressiveWorkFilter;
|
||||
try {
|
||||
const savedFilter = sessionStorage.getItem(WORK_FILTER_KEY);
|
||||
if (['all', 'today', 'agenda', 'attention', 'filed', 'authored', 'issue', 'pull', 'review', 'update', 'later', 'draft'].includes(savedFilter)) {
|
||||
if (!hasProgressiveWorkFilter && ['all', 'today', 'agenda', 'attention', 'filed', 'authored', 'issue', 'pull', 'review', 'update', 'later', 'draft'].includes(savedFilter)) {
|
||||
selectedWorkFilter = savedFilter;
|
||||
savedWorkFilter = savedFilter;
|
||||
launchFilterResolved = true;
|
||||
|
||||
@@ -6,6 +6,10 @@ function createProgressiveMyWork({ document, fetchSnapshot }) {
|
||||
let items = [];
|
||||
let active = 'all';
|
||||
let stopped = false;
|
||||
let selectedByUser = false;
|
||||
const deferredQueues = {
|
||||
today:'Today', agenda:'Agenda', later:'Later', draft:'Drafts',
|
||||
};
|
||||
|
||||
const escapeHtml = value => String(value || '').replace(/[&<>"']/g, character => ({
|
||||
'&':'&', '<':'<', '>':'>', '"':'"', "'":''',
|
||||
@@ -16,15 +20,26 @@ function createProgressiveMyWork({ document, fetchSnapshot }) {
|
||||
return ['http:', 'https:'].includes(url.protocol) ? url.href : '';
|
||||
} catch (_error) { return ''; }
|
||||
};
|
||||
const visibleItems = () => active === 'all' ? items : items.filter(item =>
|
||||
active === 'review' ? item.is_review :
|
||||
active === 'update' ? item.has_update :
|
||||
active === 'attention' ? item.needs_attention : item.kind === active
|
||||
);
|
||||
const matches = (item, filter) =>
|
||||
filter === 'review' ? item.is_review :
|
||||
filter === 'update' ? item.has_update :
|
||||
filter === 'attention' ? item.needs_attention :
|
||||
filter === 'filed' ? item.is_filed :
|
||||
filter === 'authored' ? item.is_authored :
|
||||
filter === 'pull' ? item.kind === 'pull' && !item.is_review : item.kind === filter;
|
||||
const visibleItems = () => active === 'all' ? items : items.filter(item => matches(item, active));
|
||||
const updateCounts = () => {
|
||||
['all','attention','filed','authored','issue','pull','review','update'].forEach(filter => {
|
||||
const count = filter === 'all' ? items.length : items.filter(item => matches(item, filter)).length;
|
||||
const element = document.querySelector('[data-work-count="' + filter + '"]');
|
||||
if (element) element.textContent = String(count);
|
||||
});
|
||||
};
|
||||
const render = () => {
|
||||
if (stopped || !list) return;
|
||||
const visible = visibleItems();
|
||||
list.innerHTML = visible.length ? visible.map(item => {
|
||||
list.innerHTML = deferredQueues[active] ?
|
||||
'<div class="muted">' + deferredQueues[active] + ' is still loading…</div>' : visible.length ? visible.map(item => {
|
||||
const href = safeUrl(item.url);
|
||||
const title = escapeHtml(item.title || item.key || 'Untitled work');
|
||||
const context = escapeHtml(item.key || '');
|
||||
@@ -37,12 +52,15 @@ function createProgressiveMyWork({ document, fetchSnapshot }) {
|
||||
filters.forEach(button => button.setAttribute('aria-pressed', String(button.dataset.workFilter === active)));
|
||||
};
|
||||
filters.forEach(button => {
|
||||
const listener = () => { active = button.dataset.workFilter || 'all'; render(); };
|
||||
const listener = () => { active = button.dataset.workFilter || 'all'; selectedByUser = true; render(); };
|
||||
button.addEventListener('click', listener);
|
||||
listeners.push([button, listener]);
|
||||
});
|
||||
|
||||
return {
|
||||
handoff() {
|
||||
return { selectedFilter:selectedByUser ? active : null };
|
||||
},
|
||||
async start() {
|
||||
if (status) status.textContent = 'Loading assigned work…';
|
||||
try {
|
||||
@@ -50,6 +68,7 @@ function createProgressiveMyWork({ document, fetchSnapshot }) {
|
||||
if (stopped) return false;
|
||||
const context = snapshot?.context || snapshot || {};
|
||||
items = buildMyWork({ ...context, notifications:snapshot?.notifications || context.notifications || [] });
|
||||
updateCounts();
|
||||
render();
|
||||
const assigned = items.filter(item => item.is_assigned).length;
|
||||
if (status) status.textContent = assigned + ' assigned work item' + (assigned === 1 ? '' : 's') + ' ready.';
|
||||
|
||||
Reference in new issue
Block a user