fix(web): collection cards show real child-item progress; child-progress endpoint (BUG-1509)#710
Merged
Merged
Conversation
Backend: extract collectionChildrenProgress helper from handlePlansProgress
and expose it at GET /collections/{collSlug}/child-progress with identical
visibility/guest-grant filtering. handlePlansProgress refactored to delegate
to the shared helper (no duplication). Route registered in the existing
/{collSlug} subrouter alongside checkbox-progress.
Frontend: +page.svelte fetches child-progress + checkbox-progress in parallel
for non-plans collections; per-item merge prefers child-progress (label
"tasks") when total>0, falls back to checkbox counts (label "done"). ItemCard
extended to render progress.label when present. ChildItems.svelte render gate
fixed to include error state so a failed /children fetch surfaces instead of
silently vanishing.
Tests: TestCollectionChildProgress covers happy path (linked children counted
correctly), zero-children items (present with total=0), 404 for unknown
collection, and restricted-member visibility gate (empty response for hidden
collection, not a data leak).
…ex r2)
P1: GetAllItemProgress now accepts includeArchived bool; the parent-row
filter (AND p.deleted_at IS NULL) is conditioned on it, mirroring
CollectionCheckboxProgress. handleCollectionChildrenProgress reads
?include_archived=true and threads it through. handlePlansProgress
hardcodes false — no contract change there. collectionChildProgress()
client method gains opts?: { includeArchived? } with qs() serialisation.
Both call sites in +page.svelte (loadCollection and refreshProgress) now
pass includeArchived to the child-progress fetch.
P2: refreshProgress plans branch now sets progressLabel = 'tasks' so a
sync-triggered refresh after a failed initial plans load renders with the
correct label. progressLabel = 'done' moved inside the non-plans try block
(symmetric with plans) so a thrown fetch leaves the label in whatever
state the previous collection set, not silently desync'd.
Tests: TestCollectionChildProgress extended — archives parentA, confirms
it drops from default response and reappears with include_archived=true.
…(codex r3) GetAllItemProgress conditionally drops the p.deleted_at IS NULL parent filter when includeArchived=true, but the filter-discovery call at the top of the function — childrenDoneFiltersForCollection — still had the filter hardcoded. If a child collection's only parent links pointed to archived parents, that collection was absent from the done-semantics map, and those children fell back to default status terminals rather than the collection's configured done field — producing wrong done counts. Fix: childrenDoneFiltersForCollection gains an includeArchived bool param; the JOIN on items p conditions p.deleted_at IS NULL on it, exactly mirroring the main query. GetAllItemProgress passes includeArchived through. The only other caller of this helper (GetItemProgress via childrenDoneFiltersForParent) is unaffected — that path is a separate function and never surfaces archived parents. Test: TestCollectionChildProgress extended with a "Widgets" collection whose done field is `state` (terminal: "shipped") — not the default `status` field. An archived task parent links two widget children (one shipped, one open); no live task parent links into widgets, so the filter-discovery bug would drop the collection from the map and produce done=0. The test asserts done=1 and was verified to fail on the pre-fix code.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Non-plan collection cards showed markdown-checkbox counts (label "done") while the item page's Children section showed linked child items — two unrelated data sources, so a task could show "0/5" on its card with no visible subtasks on the item page (or the inverse). Fixes docapp BUG-1509, root cause documented in its comments.
Changes:
GET /workspaces/{ws}/collections/{collSlug}/child-progressendpoint generalizing the plans-progress logic (sharedcollectionChildrenProgresshelper;/plans-progressunchanged, now a thin wrapper).ChildItems.svelteerror state was unreachable behind theloading || children.length > 0gate — a failed/childrenfetch silently hid the section; nowerrorrenders.Plus (architectural decisions)
include_archivedquery param threaded end-to-end includingchildrenDoneFiltersForCollection's discovery query (codex r3 found the discovery/aggregation inconsistency; the regression test was proven load-bearing by reverting the fix).Known limitation
The restricted-visibility recompute path issues one
GetChildItemsquery per parent item (pre-existing trade-off from plans-progress, now generalized to potentially larger collections). Deferred; needs a bulk-join recompute.Test plan
go test ./...SQLitemake test-pgPostgresgolangci-lint run ./...0 issuesnpm run check0 errorsnpm run buildRefs
Fixes docapp BUG-1509. Review: 4 codex rounds (r1 CLEAN, r2 ×2 findings fixed, r3 ×1 finding fixed, r4 CLEAN — converged).