feat: add read-first Week Ahead overview (Closes #1216)
This commit is contained in:
parent
45e2798d37
commit
42e97b4a79
|
|
@ -167,6 +167,9 @@ storage before closing on a phone. The Queues summary marks it **sync pending**
|
|||
foreground, and midnight lifecycle checks share one delivery flight. A successful account receipt removes
|
||||
the pending copy, while a revision conflict preserves both the phone plan and fresh server snapshot for
|
||||
review. Unsynced Tomorrow work is never promoted into Today.
|
||||
**Week Ahead** opens as a read-first seven-day mobile overview, so operators can inspect the next planned day,
|
||||
work titles and references, load versus capacity, overloads, and pending sync without staging a change. **Edit day**
|
||||
enters one date and returns to the refreshed overview; **Edit week** starts the continuous planning pass.
|
||||
**Plan Week Ahead** continues through seven local dates and now finishes on a mobile review step instead of
|
||||
closing after the seventh save. The review shows planned minutes against each day’s capacity, marks overloads,
|
||||
and flags work assigned to more than one date. Operators can move an item to another date without copying it;
|
||||
|
|
|
|||
|
|
@ -321,6 +321,8 @@ textarea { resize: vertical; min-height: 120px; }
|
|||
.week-review-days { display:grid; gap:12px; }
|
||||
.week-review-day { padding:12px; border:1px solid #31577f; border-radius:12px; background:#10233a; }
|
||||
.week-review-day.is-overloaded { border-color:#f59e0b; background:#2a1c12; }
|
||||
.week-review-day.is-next-up { border-color:#60a5fa; box-shadow:0 0 0 1px #60a5fa inset; }
|
||||
.week-next-up { display:inline-block; margin-left:6px; padding:2px 7px; border-radius:999px; background:#1d4f7a; color:#dbeafe; font-size:11px; vertical-align:middle; }
|
||||
.week-review-day header { display:flex; align-items:center; justify-content:space-between; gap:8px; }
|
||||
.week-review-day header button { flex:0 0 auto; min-height:44px; }
|
||||
.week-review-day h3, .week-review-day p { margin:0 0 8px; }
|
||||
|
|
@ -337,6 +339,7 @@ textarea { resize: vertical; min-height: 120px; }
|
|||
.week-review-duplicates { margin:12px 0; padding:12px; border:1px solid #f59e0b; border-radius:10px; background:#2a1c12; }
|
||||
.week-review-status { min-height:1.4em; margin:10px 0; }
|
||||
#confirm-week-plan { width:100%; min-height:48px; position:sticky; bottom:0; }
|
||||
#edit-week-plan { width:100%; min-height:48px; position:sticky; bottom:0; }
|
||||
#open-week-capacity-import { width:100%; min-height:44px; margin:8px 0 12px; }
|
||||
.week-capacity-import { position:fixed; z-index:121; inset:0; box-sizing:border-box; width:100%; max-width:560px; margin-inline:auto; padding:18px; padding-bottom:calc(18px + env(safe-area-inset-bottom)); background:#0b1526; overflow:auto; overflow-x:hidden; }
|
||||
.week-capacity-import[hidden] { display:none; }
|
||||
|
|
|
|||
|
|
@ -506,13 +506,14 @@
|
|||
<div class="small week-conflict-status" id="week-conflict-status" role="status" aria-live="assertive"></div>
|
||||
</section>
|
||||
<section class="week-review" id="week-review" aria-labelledby="week-review-title" hidden>
|
||||
<div class="small">Final planning step</div>
|
||||
<h2 id="week-review-title">Review & rebalance Week Ahead</h2>
|
||||
<p class="small muted">Check each day’s load. Move work instead of copying it, then confirm one executable week.</p>
|
||||
<div class="small">Seven-day overview</div>
|
||||
<h2 id="week-review-title">Week Ahead</h2>
|
||||
<p class="small muted">See what is next and check each day’s load. Edit only when you are ready.</p>
|
||||
<button id="open-week-capacity-import" type="button">Set capacity from calendar</button>
|
||||
<div class="week-review-duplicates" id="week-review-duplicates" role="alert" hidden></div>
|
||||
<div class="week-review-days" id="week-review-days"></div>
|
||||
<div class="small week-review-status" id="week-review-status" role="status" aria-live="polite"></div>
|
||||
<button id="edit-week-plan" type="button" hidden>Edit week</button>
|
||||
<button id="confirm-week-plan" type="button">Confirm Week Ahead</button>
|
||||
</section>
|
||||
<section class="week-capacity-import" id="week-capacity-import" aria-labelledby="week-capacity-title" hidden>
|
||||
|
|
|
|||
|
|
@ -348,6 +348,7 @@ function createWeekPlanWorkflow({controller,qs,getLogin,getItem=()=>null,openPla
|
|||
todayWork,refresh,warm}={}) {
|
||||
let selectedDate=null;
|
||||
let reviewing=false;
|
||||
let overviewing=false;
|
||||
let editingFromReview=false;
|
||||
let blockedReviewOpen=false;
|
||||
let reconciliation=null;
|
||||
|
|
@ -419,6 +420,7 @@ function createWeekPlanWorkflow({controller,qs,getLogin,getItem=()=>null,openPla
|
|||
}
|
||||
function renderReview() {
|
||||
const value=controller.review(),root=qs('#week-review-days'),duplicates=qs('#week-review-duplicates');
|
||||
const nextUp=overviewing?value.days.find(day=>day.ids.length):null;
|
||||
const destinations=value.days.map(day=>'<option value="'+escapeAttribute(day.plan_date)+'">'+escapeHtml(day.label)+'</option>').join('');
|
||||
const itemMarkup=(id,day)=>{
|
||||
const item=getItem(id),estimate=Number(day.estimates?.[id])||0;
|
||||
|
|
@ -430,10 +432,11 @@ function createWeekPlanWorkflow({controller,qs,getLogin,getItem=()=>null,openPla
|
|||
root.innerHTML=value.days.map(day=>{
|
||||
const capacity=Number(day.capacity_minutes)||0;
|
||||
const load=day.planned_minutes+(capacity?' of '+capacity:'')+' min'+(day.overloaded?' · over capacity':'');
|
||||
const items=day.ids.length?'<ul>'+day.ids.map(id=>'<li>'+itemMarkup(id,day)+'<div class="week-review-move"><label>Move to <select data-week-move-destination="'+
|
||||
escapeAttribute(id)+'">'+destinations+'</select></label><button type="button" data-week-move="'+escapeAttribute(id)+'">Move</button></div></li>').join('')+'</ul>':
|
||||
const move=id=>overviewing?'':'<div class="week-review-move"><label>Move to <select data-week-move-destination="'+escapeAttribute(id)+'">'+destinations+
|
||||
'</select></label><button type="button" data-week-move="'+escapeAttribute(id)+'">Move</button></div>';
|
||||
const items=day.ids.length?'<ul>'+day.ids.map(id=>'<li>'+itemMarkup(id,day)+move(id)+'</li>').join('')+'</ul>':
|
||||
'<p class="small muted">Nothing planned.</p>';
|
||||
return '<article class="week-review-day'+(day.overloaded?' is-overloaded':'')+'"><header><h3>'+escapeHtml(day.label)+'</h3><button type="button" data-week-edit-day="'+
|
||||
return '<article class="week-review-day'+(day.overloaded?' is-overloaded':'')+(day===nextUp?' is-next-up':'')+'"><header><h3>'+escapeHtml(day.label)+(day===nextUp?' <span class="week-next-up">Next up</span>':'')+'</h3><button type="button" data-week-edit-day="'+
|
||||
escapeAttribute(day.plan_date)+'" aria-label="Edit '+escapeAttribute(day.label)+'">Edit day</button></header><p class="week-review-load">'+
|
||||
escapeHtml(load)+'</p>'+items+'</article>';
|
||||
}).join('');
|
||||
|
|
@ -444,12 +447,14 @@ function createWeekPlanWorkflow({controller,qs,getLogin,getItem=()=>null,openPla
|
|||
const pending=Boolean(controller.pending?.());
|
||||
confirm.disabled=!value.can_confirm||pending;
|
||||
const blocker=value.blockers?.[0];
|
||||
qs('#week-review-status').textContent=value.duplicates.length?'Duplicate work must be moved to one date.':
|
||||
qs('#week-review-status').textContent=overviewing?'Week Ahead overview · '+(pending?'sync pending.':'no changes made.'):(value.duplicates.length?'Duplicate work must be moved to one date.':
|
||||
(pending?'Saving the latest week to your account…':blocker?(
|
||||
blocker.type==='over-capacity'?blocker.plan_date+' is '+blocker.minutes+' min over capacity. Edit that day before confirming.':
|
||||
blocker.type==='missing-estimate'?'Add an estimate for work on '+blocker.plan_date+' before confirming.':
|
||||
'Add capacity for '+blocker.plan_date+' before confirming.'
|
||||
):'Week Ahead is balanced and ready.');
|
||||
):'Week Ahead is balanced and ready.'));
|
||||
confirm.hidden=overviewing;
|
||||
const editWeek=qs('#edit-week-plan');if(editWeek){editWeek.hidden=!overviewing;editWeek.textContent=nextUp?'Edit week':'Plan Week Ahead';}
|
||||
root.querySelectorAll('[data-week-move]').forEach(button=>button.addEventListener('click',()=>{
|
||||
const selector=root.querySelector(`[data-week-move-destination="${button.dataset.weekMove}"]`);
|
||||
if(!controller.move(button.dataset.weekMove,selector?.value))return;
|
||||
|
|
@ -469,6 +474,12 @@ function createWeekPlanWorkflow({controller,qs,getLogin,getItem=()=>null,openPla
|
|||
qs('#week-plan-progress')?.focus?.();
|
||||
return true;
|
||||
}
|
||||
function editWeek() {
|
||||
overviewing=false;reviewing=false;selectedDate=controller.dates()[0].date;setReviewMode(false);
|
||||
qs('#week-review').hidden=true;qs('#confirm-week-plan').hidden=false;
|
||||
const edit=qs('#edit-week-plan');if(edit)edit.hidden=true;
|
||||
renderDates();openPlanner(null,false);qs('#week-plan-progress')?.focus?.();return true;
|
||||
}
|
||||
function returnToReview() {
|
||||
if(!editingFromReview)return false;
|
||||
const editedDate=selectedDate;
|
||||
|
|
@ -480,11 +491,12 @@ function createWeekPlanWorkflow({controller,qs,getLogin,getItem=()=>null,openPla
|
|||
return true;
|
||||
}
|
||||
async function open(trigger) {
|
||||
trigger.disabled=true;reviewing=false;editingFromReview=false;setReviewMode(false);const reviewRoot=qs('#week-review');if(reviewRoot)reviewRoot.hidden=true;
|
||||
trigger.disabled=true;reviewing=false;overviewing=false;editingFromReview=false;setReviewMode(false);const reviewRoot=qs('#week-review');if(reviewRoot)reviewRoot.hidden=true;
|
||||
const back=qs('#back-to-week-review');if(back)back.hidden=true;
|
||||
selectedDate=controller.dates()[0].date;renderDates();openPlanner(trigger);
|
||||
selectedDate=null;renderDates();openPlanner(trigger);
|
||||
qs('#mobile-week-summary').textContent='Loading Week Ahead…';
|
||||
try{await controller.load();qs('#mobile-week-summary').textContent=controller.summary();renderDates();openPlanner(null,false);return true;}
|
||||
try{await controller.load();qs('#mobile-week-summary').textContent=controller.summary();overviewing=true;reviewing=true;
|
||||
setReviewMode(true);reviewRoot.hidden=false;renderDates();renderReview();openPlanner(null,false);return true;}
|
||||
catch(error){qs('#mobile-week-summary').textContent='Unavailable · tap to retry';qs('#my-work-action-status').textContent=(error.message||'Week Ahead is unavailable.')+' Retry when connected.';return false;}
|
||||
finally{trigger.disabled=false;}
|
||||
}
|
||||
|
|
@ -534,8 +546,9 @@ function createWeekPlanWorkflow({controller,qs,getLogin,getItem=()=>null,openPla
|
|||
if(!reviewing||!value.can_confirm||controller.pending()) return false;
|
||||
return true;
|
||||
}
|
||||
function finish(){reviewing=false;setReviewMode(false);qs('#week-review').hidden=true;return true;}
|
||||
function finish(){reviewing=false;overviewing=false;setReviewMode(false);qs('#week-review').hidden=true;return true;}
|
||||
qs('#back-to-week-review')?.addEventListener('click',returnToReview);
|
||||
qs('#edit-week-plan')?.addEventListener('click',editWeek);
|
||||
async function promote(plan){
|
||||
try{await controller.load();const promoted=await controller.promote(plan.revision);if(!promoted)return false;blockedReviewOpen=false;todayWork.replace(promoted.ids);todayWork.replacePlanning({capacity_minutes:promoted.capacity_minutes??null,estimates:promoted.estimates||{}});refresh();warm();qs('#mobile-week-summary').textContent=controller.summary();qs('#my-work-action-status').textContent='Your saved Week Ahead plan is now Today.';return true;}
|
||||
catch(error){
|
||||
|
|
@ -549,12 +562,13 @@ function createWeekPlanWorkflow({controller,qs,getLogin,getItem=()=>null,openPla
|
|||
qs('#my-work-action-status').textContent=(error.message||'Week Ahead needs review before promotion.')+' Open Week Ahead to review.';return false;
|
||||
}
|
||||
}
|
||||
const workflow={open,save,advance,confirm,finish,promote,renderDates,renderReview,renderConflict,active:()=>Boolean(selectedDate)||reviewing||Boolean(reconciliation),
|
||||
reviewing:()=>reviewing,selectedDate:()=>selectedDate,
|
||||
const workflow={open,save,advance,confirm,finish,promote,editWeek,renderDates,renderReview,renderConflict,active:()=>Boolean(selectedDate)||reviewing||Boolean(reconciliation),
|
||||
reviewing:()=>reviewing,overviewing:()=>overviewing,selectedDate:()=>selectedDate,
|
||||
day:()=>reconciliationDay()||(selectedDate?controller.day(selectedDate):null),
|
||||
copy:()=>reconciliation?{title:"Start today's plan",heading:'Unfinished Today + due Week Ahead',available:'Available today',build:'Build combined Today'}:
|
||||
(selectedDate?{title:'Plan Week Ahead',heading:selectedDate+', in order',available:'Available this day',build:'Build this day'}:null),
|
||||
clear(){selectedDate=null;reviewing=false;editingFromReview=false;reconciliation=null;setReviewMode(false);qs('#week-review').hidden=true;
|
||||
(overviewing?{title:'Week Ahead',heading:'Seven-day overview',available:'Planned work',build:'Edit week'}:
|
||||
(selectedDate?{title:'Plan Week Ahead',heading:selectedDate+', in order',available:'Available this day',build:'Build this day'}:null)),
|
||||
clear(){selectedDate=null;reviewing=false;overviewing=false;editingFromReview=false;reconciliation=null;setReviewMode(false);qs('#week-review').hidden=true;
|
||||
const back=qs('#back-to-week-review');if(back)back.hidden=true;renderDates();}};
|
||||
if(typeof weekCalendarImport!=='undefined')weekCalendarImport.mount(controller,workflow,qs);
|
||||
return workflow;
|
||||
|
|
|
|||
|
|
@ -62,6 +62,26 @@ def test_release_artifact_plans_seven_touch_safe_mobile_dates(
|
|||
page.wait_for_timeout(100)
|
||||
|
||||
assert not page_errors, f"Week Ahead launch raised: {page_errors}"
|
||||
expect(page.locator("#plan-today-title")).to_have_text("Week Ahead")
|
||||
overview = page.locator("#week-review")
|
||||
expect(overview).to_be_visible()
|
||||
cards = page.locator("#week-review-days .week-review-day")
|
||||
expect(cards).to_have_count(7)
|
||||
expect(cards.first).to_contain_text("Next up")
|
||||
expect(cards.first).to_contain_text("Ship mobile capture")
|
||||
expect(page.locator("#week-review-status")).to_have_text(
|
||||
"Week Ahead overview · no changes made."
|
||||
)
|
||||
expect(page.locator("#confirm-week-plan")).to_be_hidden()
|
||||
edit_week = page.locator("#edit-week-plan")
|
||||
expect(edit_week).to_be_visible()
|
||||
assert saved == [], "opening and inspecting Week Ahead must not write"
|
||||
for control in (cards.first.locator("[data-week-edit-day]"), edit_week):
|
||||
bounds = control.bounding_box()
|
||||
assert bounds and bounds["height"] >= 44
|
||||
assert page.evaluate("document.documentElement.scrollWidth <= window.innerWidth")
|
||||
edit_week.click()
|
||||
expect(overview).to_be_hidden()
|
||||
expect(page.locator("#plan-today-title")).to_have_text("Plan Week Ahead")
|
||||
dates = page.locator("#week-plan-dates button")
|
||||
expect(dates).to_have_count(7)
|
||||
|
|
@ -243,6 +263,7 @@ def test_release_artifact_reconciles_only_the_week_day_changed_on_both_devices(
|
|||
page.wait_for_url(origin + "/", wait_until="networkidle")
|
||||
page.locator('[data-mobile-task="queues"]').click()
|
||||
page.locator('[data-mobile-queue="week"]').click()
|
||||
page.locator("#edit-week-plan").click()
|
||||
page.locator("#plan-today-available").fill("60")
|
||||
page.locator("#save-today-plan").click()
|
||||
page.wait_for_function("() => document.querySelector('#mobile-week-summary').textContent.includes('Conflict')")
|
||||
|
|
|
|||
|
|
@ -179,15 +179,18 @@ Object.defineProperty(root,'innerHTML',{set(value){this.value=value;this.buttons
|
|||
root.querySelectorAll=()=>root.buttons||[];
|
||||
root.querySelector=selector=>(root.buttons||[]).find(button=>selector.includes(button.dataset.weekPlanDate))||null;
|
||||
elements.set('#week-plan-dates',root);
|
||||
for(const selector of ['#mobile-week-summary','#my-work-action-status','#week-plan-progress','#save-today-plan']) elements.set(selector,makeElement());
|
||||
for(const selector of ['#mobile-week-summary','#my-work-action-status','#week-plan-progress','#save-today-plan',
|
||||
'#week-review','#week-review-days','#week-review-duplicates','#confirm-week-plan','#week-review-status','#edit-week-plan']) elements.set(selector,makeElement());
|
||||
let opened=0,staged=[];
|
||||
const controller={dates:()=>dates.map((date,index)=>({date,label:'Day '+(index+1)})),day:date=>({plan_date:date,ids:[]}),
|
||||
pass:date=>{const index=dates.indexOf(date);return {position:index+1,total:7,planned:staged.length,next_date:dates[index+1]||null,last:index===6};},
|
||||
load:async()=>({}),summary:()=> 'Nothing planned',stageDay:(date,plan)=>{staged.push({date,plan});return true;},flush:async()=>({})};
|
||||
load:async()=>({}),summary:()=> 'Nothing planned',review:()=>({days:dates.map(date=>({plan_date:date,label:date,ids:[],capacity_minutes:null,estimates:{},planned_minutes:0,overloaded:false})),duplicates:[],blockers:[],can_confirm:true}),pending:()=>false,
|
||||
stageDay:(date,plan)=>{staged.push({date,plan});return true;},flush:async()=>({})};
|
||||
const workflow=createWorkflow({controller,qs:selector=>elements.get(selector),getLogin:()=> 'timmy',
|
||||
openPlanner:()=>{opened+=1;},escapeHtml:value=>value,escapeAttribute:value=>value,
|
||||
todayWork:{replace:()=>{},replacePlanning:()=>{}},refresh:()=>{},warm:()=>{}});
|
||||
await workflow.open({disabled:false});
|
||||
workflow.editWeek();
|
||||
workflow.save({ids:['issue:r:1:'],capacity_minutes:60,estimates:{'issue:r:1:':30}});
|
||||
const continued=workflow.advance();
|
||||
console.log(JSON.stringify({continued,selected:workflow.selectedDate(),opened,staged,
|
||||
|
|
@ -196,12 +199,67 @@ console.log(JSON.stringify({continued,selected:workflow.selectedDate(),opened,st
|
|||
|
||||
assert result["continued"] is True
|
||||
assert result["selected"] == "2026-08-22"
|
||||
assert result["opened"] == 3
|
||||
assert result["opened"] == 4
|
||||
assert result["staged"][0]["date"] == "2026-08-21"
|
||||
assert result["progress"] == "Day 2 of 7 · 1 planned"
|
||||
assert result["label"] == "Save & next"
|
||||
|
||||
|
||||
def test_week_workflow_opens_a_read_only_overview_with_next_up_work():
|
||||
result = run_controller("""
|
||||
const createWorkflow=createWeekPlan.Workflow;
|
||||
const dates=['2026-08-21','2026-08-22','2026-08-23','2026-08-24','2026-08-25','2026-08-26','2026-08-27'];
|
||||
const elements=new Map();
|
||||
const makeElement=()=>({hidden:false,textContent:'',disabled:false,innerHTML:'',addEventListener:()=>{},focus:()=>{},
|
||||
querySelectorAll:()=>[],querySelector:()=>null,scrollIntoView:()=>{}});
|
||||
const dateRoot=makeElement();
|
||||
Object.defineProperty(dateRoot,'innerHTML',{set(value){this.value=value;this.buttons=[];},get(){return this.value||'';}});
|
||||
elements.set('#week-plan-dates',dateRoot);
|
||||
const reviewDays=makeElement();
|
||||
Object.defineProperty(reviewDays,'innerHTML',{set(value){this.value=value;},get(){return this.value||'';}});
|
||||
elements.set('#week-review-days',reviewDays);
|
||||
for(const selector of ['#mobile-week-summary','#my-work-action-status','#week-plan-progress','#save-today-plan',
|
||||
'#week-review','#week-review-duplicates','#confirm-week-plan','#week-review-status','#back-to-week-review',
|
||||
'#edit-week-plan']) if(!elements.has(selector))elements.set(selector,makeElement());
|
||||
let writes=0,opened=0,reviewMode=false;
|
||||
const review={days:dates.map((date,index)=>({plan_date:date,label:'Day '+(index+1),
|
||||
ids:index===2?['issue:stackchain/dashboard:42:']:[],capacity_minutes:60,
|
||||
estimates:index===2?{'issue:stackchain/dashboard:42:':30}:{},planned_minutes:index===2?30:0,overloaded:false})),
|
||||
duplicates:[],blockers:[],can_confirm:true};
|
||||
const controller={dates:()=>dates.map((date,index)=>({date,label:'Day '+(index+1)})),day:date=>review.days.find(day=>day.plan_date===date),
|
||||
pass:date=>{const index=dates.indexOf(date);return {position:index+1,total:7,planned:1,next_date:dates[index+1]||null,last:index===6};},
|
||||
load:async()=>({}),summary:()=> '1 item across 1 day',review:()=>review,pending:()=>false,
|
||||
move:()=>true,flush:async()=>{writes+=1;}};
|
||||
const workflow=createWorkflow({controller,qs:selector=>elements.get(selector),getLogin:()=> 'timmy',
|
||||
getItem:id=>id.includes(':42:')?{kind:'issue',title:'Ship mobile overview',repository:'stackchain/dashboard',number:42}:null,
|
||||
openPlanner:()=>{opened+=1;},setReviewMode:value=>{reviewMode=value;},escapeHtml:value=>value,escapeAttribute:value=>value,
|
||||
todayWork:{replace:()=>{},replacePlanning:()=>{}},refresh:()=>{},warm:()=>{}});
|
||||
await workflow.open({disabled:false});
|
||||
console.log(JSON.stringify({reviewing:workflow.reviewing(),reviewMode,writes,opened,copy:workflow.copy(),
|
||||
reviewHidden:elements.get('#week-review').hidden,datesHidden:elements.get('#week-plan-dates').hidden,
|
||||
markup:reviewDays.innerHTML,status:elements.get('#week-review-status').textContent,
|
||||
confirmHidden:elements.get('#confirm-week-plan').hidden,editWeekHidden:elements.get('#edit-week-plan').hidden,
|
||||
editWeekLabel:elements.get('#edit-week-plan').textContent}));
|
||||
""")
|
||||
|
||||
assert result["reviewing"] is True
|
||||
assert result["reviewMode"] is True
|
||||
assert result["writes"] == 0
|
||||
assert result["copy"] == {
|
||||
"title": "Week Ahead", "heading": "Seven-day overview",
|
||||
"available": "Planned work", "build": "Edit week",
|
||||
}
|
||||
assert result["reviewHidden"] is False
|
||||
assert result["datesHidden"] is True
|
||||
assert "Ship mobile overview" in result["markup"]
|
||||
assert "Next up" in result["markup"]
|
||||
assert "data-week-move" not in result["markup"]
|
||||
assert result["status"] == "Week Ahead overview · no changes made."
|
||||
assert result["confirmHidden"] is True
|
||||
assert result["editWeekHidden"] is False
|
||||
assert result["editWeekLabel"] == "Edit week"
|
||||
|
||||
|
||||
def test_week_workflow_opens_review_after_day_seven_and_blocks_duplicate_confirmation():
|
||||
result = run_controller("""
|
||||
const createWorkflow=createWeekPlan.Workflow;
|
||||
|
|
@ -213,7 +271,7 @@ const root=makeElement();
|
|||
Object.defineProperty(root,'innerHTML',{set(value){this.value=value;this.buttons=[];},get(){return this.value||'';}});
|
||||
elements.set('#week-plan-dates',root);
|
||||
for(const selector of ['#mobile-week-summary','#my-work-action-status','#week-plan-progress','#save-today-plan',
|
||||
'#week-review','#week-review-days','#week-review-duplicates','#confirm-week-plan','#week-review-status']) elements.set(selector,makeElement());
|
||||
'#week-review','#week-review-days','#week-review-duplicates','#confirm-week-plan','#week-review-status','#edit-week-plan']) elements.set(selector,makeElement());
|
||||
let reviewMode=false;
|
||||
const review={days:dates.map((date,index)=>({plan_date:date,label:'Day '+(index+1),ids:index<2?['shared']:[],
|
||||
capacity_minutes:index===0?30:60,planned_minutes:index===0?45:15,overloaded:index===0})),
|
||||
|
|
@ -225,6 +283,7 @@ const workflow=createWorkflow({controller,qs:selector=>elements.get(selector),ge
|
|||
openPlanner:()=>{},setReviewMode:value=>{reviewMode=value;},escapeHtml:value=>value,escapeAttribute:value=>value,
|
||||
todayWork:{replace:()=>{},replacePlanning:()=>{}},refresh:()=>{},warm:()=>{}});
|
||||
await workflow.open({disabled:false});
|
||||
workflow.editWeek();
|
||||
for(let index=0;index<6;index++) workflow.advance();
|
||||
const advanced=workflow.advance();
|
||||
console.log(JSON.stringify({advanced,reviewing:workflow.reviewing(),reviewMode,
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user