feat: make Week Ahead review readable and editable (Closes #1190)
This commit is contained in:
1 parent
356f11b9c1
commit
9f40a4c5ac
6 files changed
+135
-11
No files matched your search
@@ -44,7 +44,11 @@ def test_release_artifact_plans_seven_touch_safe_mobile_dates(
|
||||
}))
|
||||
return
|
||||
route.fulfill(status=200, content_type="application/json", body=json.dumps({
|
||||
"revision": 0, "timezone": None, "days": [],
|
||||
"revision": 0, "timezone": None, "days": [{
|
||||
"plan_date": (date.today() + timedelta(days=1)).isoformat(),
|
||||
"ids": ["issue:acme/mobile:41:"], "capacity_minutes": 60,
|
||||
"estimates": {"issue:acme/mobile:41:": 30},
|
||||
}],
|
||||
}))
|
||||
|
||||
page.route("**/api/v1/week", week_route)
|
||||
@@ -67,18 +71,32 @@ def test_release_artifact_plans_seven_touch_safe_mobile_dates(
|
||||
assert bounds and bounds["height"] >= 44
|
||||
dates.nth(2).click()
|
||||
expect(dates.nth(2)).to_have_attribute("aria-current", "date")
|
||||
expect(page.locator("#week-plan-progress")).to_have_text("Day 3 of 7 · 0 planned")
|
||||
expect(page.locator("#week-plan-progress")).to_have_text("Day 3 of 7 · 1 planned")
|
||||
expect(page.locator("#save-today-plan")).to_have_text("Save & next")
|
||||
page.locator("#save-today-plan").click()
|
||||
expect(page.locator("#plan-today-sheet")).to_be_visible()
|
||||
expect(dates.nth(3)).to_have_attribute("aria-current", "date")
|
||||
expect(page.locator("#week-plan-progress")).to_have_text("Day 4 of 7 · 0 planned")
|
||||
expect(page.locator("#week-plan-progress")).to_have_text("Day 4 of 7 · 1 planned")
|
||||
dates.nth(6).click()
|
||||
expect(page.locator("#save-today-plan")).to_have_text("Save week")
|
||||
page.locator("#save-today-plan").click()
|
||||
expect(page.locator("#plan-today-sheet")).to_be_visible()
|
||||
expect(page.locator("#week-review")).to_be_visible()
|
||||
expect(page.locator("#week-review-days .week-review-day")).to_have_count(7)
|
||||
first_day = page.locator("#week-review-days .week-review-day").first
|
||||
expect(first_day).to_contain_text("Ship mobile capture")
|
||||
expect(first_day).to_contain_text("acme/mobile #41 · Issue · 30 min")
|
||||
expect(first_day.locator("code")).to_have_count(0)
|
||||
edit = first_day.locator("[data-week-edit-day]")
|
||||
bounds = edit.bounding_box()
|
||||
assert bounds and bounds["height"] >= 44
|
||||
edit.click()
|
||||
expect(page.locator("#week-review")).to_be_hidden()
|
||||
expect(page.locator("#back-to-week-review")).to_be_visible()
|
||||
expect(page.locator("#save-today-plan")).to_have_text("Save & review")
|
||||
page.locator("#back-to-week-review").click()
|
||||
expect(page.locator("#week-review")).to_be_visible()
|
||||
expect(first_day).to_contain_text("Ship mobile capture")
|
||||
page.wait_for_function("() => !document.querySelector('#confirm-week-plan').disabled")
|
||||
confirm = page.locator("#confirm-week-plan")
|
||||
bounds = confirm.bounding_box()
|
||||
@@ -86,7 +104,7 @@ def test_release_artifact_plans_seven_touch_safe_mobile_dates(
|
||||
confirm.click()
|
||||
expect(page.locator("#plan-today-sheet")).to_be_hidden()
|
||||
page.wait_for_function("() => document.querySelector('#mobile-week-summary').textContent !== 'Loading Week Ahead…'")
|
||||
assert saved and len(saved[-1]["days"]) == 2
|
||||
assert saved and len(saved[-1]["days"]) == 3
|
||||
assert [day["plan_date"] for day in saved[-1]["days"]] == sorted(
|
||||
day["plan_date"] for day in saved[-1]["days"]
|
||||
)
|
||||
|
||||
@@ -173,6 +173,70 @@ console.log(JSON.stringify({advanced,reviewing:workflow.reviewing(),reviewMode,
|
||||
assert "shared" in result["duplicates"]
|
||||
|
||||
|
||||
def test_week_review_names_work_and_can_edit_a_day_then_return_to_review():
|
||||
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:'',dataset:{},listeners:{},
|
||||
addEventListener(name,listener){this.listeners[name]=listener;},focus(){this.focused=true;},
|
||||
querySelectorAll:()=>[],querySelector:()=>null,scrollIntoView:()=>{}});
|
||||
const dateRoot=makeElement();
|
||||
Object.defineProperty(dateRoot,'innerHTML',{set(value){this.value=value;this.buttons=[...value.matchAll(/data-week-plan-date=\"([^\"]+)/g)].map(match=>({
|
||||
dataset:{weekPlanDate:match[1]},addEventListener:()=>{},scrollIntoView:()=>{},focus:()=>{}
|
||||
}));},get(){return this.value||'';}});
|
||||
dateRoot.querySelectorAll=()=>dateRoot.buttons||[];
|
||||
dateRoot.querySelector=selector=>(dateRoot.buttons||[]).find(button=>selector.includes(button.dataset.weekPlanDate))||null;
|
||||
elements.set('#week-plan-dates',dateRoot);
|
||||
const reviewDays=makeElement();
|
||||
Object.defineProperty(reviewDays,'innerHTML',{set(value){
|
||||
this.value=value;this.editButtons=[...value.matchAll(/data-week-edit-day=\"([^\"]+)/g)].map(match=>{
|
||||
const button=makeElement();button.dataset.weekEditDay=match[1];return button;
|
||||
});
|
||||
},get(){return this.value||'';}});
|
||||
reviewDays.querySelectorAll=selector=>selector==='[data-week-edit-day]'?reviewDays.editButtons||[]:[];
|
||||
reviewDays.querySelector=selector=>(reviewDays.editButtons||[]).find(button=>selector.includes(button.dataset.weekEditDay))||null;
|
||||
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']) {
|
||||
if(!elements.has(selector))elements.set(selector,makeElement());
|
||||
}
|
||||
let reviewMode=false;
|
||||
const review={days:dates.map((date,index)=>({plan_date:date,label:'Day '+(index+1),
|
||||
ids:index===0?['issue:stackchain/dashboard:42:']:[],capacity_minutes:60,
|
||||
estimates:index===0?{'issue:stackchain/dashboard:42:':30}:{},planned_minutes:index===0?30:0,overloaded:false})),
|
||||
duplicates:[],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()=>({})};
|
||||
const workflow=createWorkflow({controller,qs:selector=>elements.get(selector),getLogin:()=> 'timmy',
|
||||
getItem:id=>id==='issue:stackchain/dashboard:42:'?{kind:'issue',title:'Fix mobile sign in',repository:'stackchain/dashboard',number:42}:null,
|
||||
openPlanner:()=>{},setReviewMode:value=>{reviewMode=value;},escapeHtml:value=>value,escapeAttribute:value=>value,
|
||||
todayWork:{replace:()=>{},replacePlanning:()=>{}},refresh:()=>{},warm:()=>{}});
|
||||
await workflow.open({disabled:false});
|
||||
for(let index=0;index<7;index++)workflow.advance();
|
||||
const markup=reviewDays.innerHTML;
|
||||
const edit=reviewDays.editButtons[0];edit.listeners.click();
|
||||
const whileEditing={selected:workflow.selectedDate(),reviewing:workflow.reviewing(),reviewMode,
|
||||
reviewHidden:elements.get('#week-review').hidden,backHidden:elements.get('#back-to-week-review').hidden};
|
||||
elements.get('#back-to-week-review').listeners.click();
|
||||
console.log(JSON.stringify({markup,whileEditing,after:{selected:workflow.selectedDate(),reviewing:workflow.reviewing(),reviewMode,
|
||||
reviewHidden:elements.get('#week-review').hidden,editFocused:reviewDays.editButtons[0].focused}}));
|
||||
""")
|
||||
|
||||
assert "Fix mobile sign in" in result["markup"]
|
||||
assert "stackchain/dashboard #42 · Issue · 30 min" in result["markup"]
|
||||
assert "<code>issue:stackchain/dashboard:42:</code>" not in result["markup"]
|
||||
assert result["whileEditing"] == {
|
||||
"selected": "2026-08-21", "reviewing": False, "reviewMode": False,
|
||||
"reviewHidden": True, "backHidden": False,
|
||||
}
|
||||
assert result["after"] == {
|
||||
"selected": None, "reviewing": True, "reviewMode": True,
|
||||
"reviewHidden": False, "editFocused": True,
|
||||
}
|
||||
|
||||
|
||||
def test_week_controller_preserves_both_versions_when_another_device_changes_the_week():
|
||||
result = run_controller("""
|
||||
let calls=0;
|
||||
|
||||
Reference in new issue
Block a user