Compare commits
No commits in common. "7a09452bef57705e32f1e3d4da1b05ac021b7230" and "977493907e18ce5f6e6efaae77bde7e5c0d65630" have entirely different histories.
7a09452bef
...
977493907e
|
|
@ -123,14 +123,12 @@
|
||||||
queueCounts.followingUnavailable = false;
|
queueCounts.followingUnavailable = false;
|
||||||
preparationItems.following = items.filter(item => item.has_unseen_change === true);
|
preparationItems.following = items.filter(item => item.has_unseen_change === true);
|
||||||
renderMobileQueuePresentation();
|
renderMobileQueuePresentation();
|
||||||
mobileTaskDock.updateQueues(queueCounts);
|
|
||||||
mobileStartDay.render();
|
mobileStartDay.render();
|
||||||
},
|
},
|
||||||
onStatus:status => {
|
onStatus:status => {
|
||||||
if (status === 'loading') return;
|
if (status === 'loading') return;
|
||||||
queueCounts.followingUnavailable = status === 'error';
|
queueCounts.followingUnavailable = status === 'error';
|
||||||
renderMobileQueuePresentation();
|
renderMobileQueuePresentation();
|
||||||
mobileTaskDock.updateQueues(queueCounts);
|
|
||||||
mobileStartDay.render();
|
mobileStartDay.render();
|
||||||
},
|
},
|
||||||
onReviewComplete:() => mobileStartDay.completePhase('following'),
|
onReviewComplete:() => mobileStartDay.completePhase('following'),
|
||||||
|
|
@ -3549,12 +3547,9 @@
|
||||||
counts.delivery = draftInbox.partition(lastDrafts).actionable;
|
counts.delivery = draftInbox.partition(lastDrafts).actionable;
|
||||||
counts.gate = queueCounts.gate;
|
counts.gate = queueCounts.gate;
|
||||||
counts.gateUnavailable = queueCounts.gateUnavailable;
|
counts.gateUnavailable = queueCounts.gateUnavailable;
|
||||||
counts.following = queueCounts.following;
|
|
||||||
counts.followingUnavailable = queueCounts.followingUnavailable;
|
|
||||||
preparationItems = {
|
preparationItems = {
|
||||||
delivery:draftInbox.partition(lastDrafts).deliveries,
|
delivery:draftInbox.partition(lastDrafts).deliveries,
|
||||||
gate:preparationItems.gate || [],
|
gate:preparationItems.gate || [],
|
||||||
following:preparationItems.following || [],
|
|
||||||
agenda:agendaMyWork(activeMyWork),
|
agenda:agendaMyWork(activeMyWork),
|
||||||
attention:activeMyWork.filter(item => item.needs_attention),
|
attention:activeMyWork.filter(item => item.needs_attention),
|
||||||
update:activeMyWork.filter(item => item.has_update),
|
update:activeMyWork.filter(item => item.has_update),
|
||||||
|
|
|
||||||
|
|
@ -97,9 +97,9 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateQueues(counts) {
|
function updateQueues(counts) {
|
||||||
const names = 'today agenda delivery gate attention update following filed authored later draft'.split(' ');
|
const names = 'today agenda delivery gate attention update filed later draft'.split(' ');
|
||||||
const normalized = Object.fromEntries(names.map(name => [name, Math.max(0, Number(counts?.[name]) || 0)]));
|
const normalized = Object.fromEntries(names.map(name => [name, Math.max(0, Number(counts?.[name]) || 0)]));
|
||||||
const actionableNames = ['today', 'delivery', 'gate', 'attention', 'update', 'following', 'filed', 'authored', 'later', 'draft'];
|
const actionableNames = ['today', 'delivery', 'gate', 'attention', 'update', 'filed', 'later', 'draft'];
|
||||||
const active = actionableNames.reduce((total, name) => total + (normalized[name] > 0 ? 1 : 0), 0);
|
const active = actionableNames.reduce((total, name) => total + (normalized[name] > 0 ? 1 : 0), 0);
|
||||||
Object.entries(options.queueCounts || {}).forEach(([name, element]) => {
|
Object.entries(options.queueCounts || {}).forEach(([name, element]) => {
|
||||||
element.textContent = String(normalized[name] || 0);
|
element.textContent = String(normalized[name] || 0);
|
||||||
|
|
@ -107,9 +107,6 @@
|
||||||
options.queueRows?.update?.setAttribute(
|
options.queueRows?.update?.setAttribute(
|
||||||
'aria-label', 'Updates, ' + normalized.update + ' unread conversations'
|
'aria-label', 'Updates, ' + normalized.update + ' unread conversations'
|
||||||
);
|
);
|
||||||
options.queueRows?.following?.setAttribute(
|
|
||||||
'aria-label', 'Following, ' + normalized.following + ' unseen changes'
|
|
||||||
);
|
|
||||||
if (options.queueBadge) {
|
if (options.queueBadge) {
|
||||||
options.queueBadge.textContent = active + ' active';
|
options.queueBadge.textContent = active + ' active';
|
||||||
options.queueBadge.hidden = active === 0;
|
options.queueBadge.hidden = active === 0;
|
||||||
|
|
@ -130,9 +127,7 @@
|
||||||
+ ', Human Gates ' + normalized.gate
|
+ ', Human Gates ' + normalized.gate
|
||||||
+ ', Attention ' + normalized.attention
|
+ ', Attention ' + normalized.attention
|
||||||
+ ', Updates ' + normalized.update
|
+ ', Updates ' + normalized.update
|
||||||
+ ', Following ' + normalized.following
|
|
||||||
+ ', Filed ' + normalized.filed
|
+ ', Filed ' + normalized.filed
|
||||||
+ ', My PRs ' + normalized.authored
|
|
||||||
+ ', Later ' + normalized.later
|
+ ', Later ' + normalized.later
|
||||||
+ ', Drafts ' + normalized.draft
|
+ ', Drafts ' + normalized.draft
|
||||||
+ '; ' + active + ' active ' + (active === 1 ? 'queue' : 'queues');
|
+ '; ' + active + ' active ' + (active === 1 ? 'queue' : 'queues');
|
||||||
|
|
|
||||||
|
|
@ -300,33 +300,6 @@ async def test_mobile_queue_sheet_prioritizes_next_active_and_planning_without_d
|
||||||
assert html.count(f'<button data-mobile-queue="{name}"') == 1
|
assert html.count(f'<button data-mobile-queue="{name}"') == 1
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.anyio
|
|
||||||
async def test_following_hydration_refreshes_the_persistent_mobile_queue_census():
|
|
||||||
html = await dashboard()
|
|
||||||
|
|
||||||
assert (
|
|
||||||
"preparationItems.following = items.filter(item => item.has_unseen_change === true);\n"
|
|
||||||
" renderMobileQueuePresentation();\n"
|
|
||||||
" mobileTaskDock.updateQueues(queueCounts);\n"
|
|
||||||
" mobileStartDay.render();"
|
|
||||||
) in html
|
|
||||||
assert (
|
|
||||||
"queueCounts.followingUnavailable = status === 'error';\n"
|
|
||||||
" renderMobileQueuePresentation();\n"
|
|
||||||
" mobileTaskDock.updateQueues(queueCounts);\n"
|
|
||||||
" mobileStartDay.render();"
|
|
||||||
) in html
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.anyio
|
|
||||||
async def test_my_work_refresh_preserves_the_hydrated_following_queue():
|
|
||||||
html = await dashboard()
|
|
||||||
|
|
||||||
assert "counts.following = queueCounts.following;" in html
|
|
||||||
assert "counts.followingUnavailable = queueCounts.followingUnavailable;" in html
|
|
||||||
assert "following:preparationItems.following || []," in html
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.anyio
|
@pytest.mark.anyio
|
||||||
async def test_find_and_queue_detours_are_visible_and_wired_to_today_timing():
|
async def test_find_and_queue_detours_are_visible_and_wired_to_today_timing():
|
||||||
html = await dashboard()
|
html = await dashboard()
|
||||||
|
|
@ -575,7 +548,7 @@ process.stdout.write(JSON.stringify({{
|
||||||
"populated": {
|
"populated": {
|
||||||
"badge": "8 active",
|
"badge": "8 active",
|
||||||
"badgeHidden": False,
|
"badgeHidden": False,
|
||||||
"badgeLabel": "Queues: Today 2, Agenda 5 due, Delivery 1, Human Gates 2, Attention 1, Updates 5, Following 0, Filed 2, My PRs 0, Later 3, Drafts 4; 8 active queues",
|
"badgeLabel": "Queues: Today 2, Agenda 5 due, Delivery 1, Human Gates 2, Attention 1, Updates 5, Filed 2, Later 3, Drafts 4; 8 active queues",
|
||||||
"deadline": "5 due",
|
"deadline": "5 due",
|
||||||
"deadlineHidden": False,
|
"deadlineHidden": False,
|
||||||
"agendaDue": "true",
|
"agendaDue": "true",
|
||||||
|
|
@ -584,7 +557,7 @@ process.stdout.write(JSON.stringify({{
|
||||||
"badge": "1 active",
|
"badge": "1 active",
|
||||||
"badgeHidden": False,
|
"badgeHidden": False,
|
||||||
"deadlineHidden": True,
|
"deadlineHidden": True,
|
||||||
"badgeLabel": "Queues: Today 0, Agenda 0 due, Delivery 0, Human Gates 0, Attention 0, Updates 7, Following 0, Filed 0, My PRs 0, Later 0, Drafts 0; 1 active queue",
|
"badgeLabel": "Queues: Today 0, Agenda 0 due, Delivery 0, Human Gates 0, Attention 0, Updates 7, Filed 0, Later 0, Drafts 0; 1 active queue",
|
||||||
},
|
},
|
||||||
"clearedBadgeHidden": True,
|
"clearedBadgeHidden": True,
|
||||||
"clearedDeadlineHidden": True,
|
"clearedDeadlineHidden": True,
|
||||||
|
|
@ -597,59 +570,6 @@ process.stdout.write(JSON.stringify({{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def test_mobile_task_dock_counts_following_and_authored_work_truthfully():
|
|
||||||
script = f"""
|
|
||||||
const createDock = require({json.dumps(str(DOCK))});
|
|
||||||
const node = () => ({{
|
|
||||||
textContent:'', hidden:false, attributes:{{}},
|
|
||||||
setAttribute(name, value) {{ this.attributes[name] = value; }},
|
|
||||||
removeAttribute(name) {{ delete this.attributes[name]; }},
|
|
||||||
}});
|
|
||||||
const queues = node();
|
|
||||||
const badge = node();
|
|
||||||
const deadline = node();
|
|
||||||
const following = node();
|
|
||||||
const authored = node();
|
|
||||||
const dock = createDock({{
|
|
||||||
nav:node(), buttons:{{queues}}, queueBadge:badge, deadlineBadge:deadline,
|
|
||||||
queueRows:{{following, authored}},
|
|
||||||
queueCounts:{{following:node(), authored:node()}},
|
|
||||||
}});
|
|
||||||
dock.updateQueues({{following:3, authored:2}});
|
|
||||||
const active = {{
|
|
||||||
badge:badge.textContent,
|
|
||||||
badgeHidden:badge.hidden,
|
|
||||||
summary:queues.attributes['aria-label'],
|
|
||||||
followingCount:dock ? following.attributes['aria-label'] : null,
|
|
||||||
}};
|
|
||||||
dock.updateQueues({{following:0, authored:0}});
|
|
||||||
process.stdout.write(JSON.stringify({{
|
|
||||||
active,
|
|
||||||
cleared:{{
|
|
||||||
badgeHidden:badge.hidden,
|
|
||||||
summary:queues.attributes['aria-label'],
|
|
||||||
followingLabel:following.attributes['aria-label'],
|
|
||||||
}},
|
|
||||||
}}));
|
|
||||||
"""
|
|
||||||
result = subprocess.run(["node", "-e", script], capture_output=True, text=True)
|
|
||||||
|
|
||||||
assert result.returncode == 0, result.stderr
|
|
||||||
assert json.loads(result.stdout) == {
|
|
||||||
"active": {
|
|
||||||
"badge": "2 active",
|
|
||||||
"badgeHidden": False,
|
|
||||||
"summary": "Queues: Today 0, Agenda 0 due, Delivery 0, Human Gates 0, Attention 0, Updates 0, Following 3, Filed 0, My PRs 2, Later 0, Drafts 0; 2 active queues",
|
|
||||||
"followingCount": "Following, 3 unseen changes",
|
|
||||||
},
|
|
||||||
"cleared": {
|
|
||||||
"badgeHidden": True,
|
|
||||||
"summary": "Queues: no active queues; no upcoming deadlines",
|
|
||||||
"followingLabel": "Following, 0 unseen changes",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
def test_mobile_queue_launcher_opens_first_actionable_item_after_selecting_queue():
|
def test_mobile_queue_launcher_opens_first_actionable_item_after_selecting_queue():
|
||||||
script = f"""
|
script = f"""
|
||||||
const createLauncher = require({json.dumps(str(QUEUE_LAUNCHER))});
|
const createLauncher = require({json.dumps(str(QUEUE_LAUNCHER))});
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user