Skip to content

feat: add subtask management features to view settings and API - #625

Merged
pikann merged 4 commits into
masterfrom
feature/add-subtask-management-features-to-view-setting
Oct 22, 2026
Merged

pikann merged 4 commits into
masterfrom
feature/add-subtask-management-features-to-view-setting

Conversation

@pikann

@pikann pikann commented Oct 22, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Shows subtasks hierarchically in the Table (product backlog, sprints) and Timeline views, as requested in #622. Parent rows get a chevron and a done/total progress chip; expanding a row loads its children on demand, indented under the parent, with the view's filters and sort applied. Board cards show the same chip but stay flat.

Closes #622

What changed

API (services/api)

  • Task list responses carry subtask_count and subtask_done_count (live direct children; children in a done-category status), computed in one batched query per page.
  • New exclude_subtasks=true list filter: omits tasks whose parent is a live non-Epic task, so a subtask is not shown both nested and as its own row. Tasks that only belong to an Epic stay in the list. It also applies to the count endpoint.
  • parent_task_id listing (already supported) keeps ignoring the sprint filter while status/assignee/sort filters apply; the web client relies on that.
  • New view config field subtask_mode (collapsed | expanded | hidden; empty means collapsed), included in the per-user override merge/diff logic.
  • docs/api/http-design.md updated.

Web (apps/web)

  • TaskRow gets the chevron, progress chip and indentation (capped at 3 levels, tighter on mobile); SubtaskRows lazily fetches children with loading, error/retry, load-more, "N of M match the current filters" and an inline "Add subtask" row.
  • The Timeline rows get the same chevron/chip and expand to their child tasks.
  • View settings (Table and Timeline only) gets a Subtasks option: Nested, collapsed (default), Nested, expanded, Hidden (flat list). It is saved with the view like other settings (only for me / for everyone). Rows opened or closed by hand are remembered per user and per view in localStorage.
  • Board cards show the progress chip inline with the other field chips.
  • Translations added in all 9 locales.

Behaviour to be aware of

  • While nesting is on, a child whose parent is hidden by a filter or sits in another group is not shown at the top level either (it appears when its parent does). Showing the parent as a dimmed context row is a possible follow-up.
  • New projects have no Subtask system type, so subtasks are ordinary tasks linked by parent_task_id; nesting works off that link.

Type of Change

  • Other (feature)

Testing

  • Go: new repository tests for the subtask counts and exclude_subtasks.
  • Web: subtask-rows.test.tsx, roadmap-nesting.test.tsx; full suite, tsc -b and biome pass.
  • e2e: new features/projects/subtask-hierarchy.feature and tests/projects/subtask-hierarchy.spec.ts (24 tests, passing on chromium and mobile-chrome against the e2e stack); the existing interaction-views, view-settings and timeline specs still pass.
  • Checked manually in the browser on the Backlog Table, Timeline and Board views.

Checklist

  • The change is focused and scoped.
  • Related documentation is updated.
  • New structure or direction is explained clearly.
  • I avoided unnecessary detail or premature abstraction.

🤖 Generated with Claude Code

- Introduced subtask mode options in the view settings panel for "Table" and "Roadmap" layouts, allowing users to choose between collapsed, expanded, or hidden views for subtasks.
- Updated internationalization files to include new translations for subtask-related labels and messages in English, Spanish, French, Japanese, Korean, Portuguese, Russian, Vietnamese, and Chinese.
- Enhanced the Task and ViewConfig interfaces to include subtask counts and modes, facilitating better task management and display.
- Implemented backend logic to support subtask counting and filtering, ensuring that subtasks can be excluded from task lists based on user preferences.
- Added tests to verify the correct functionality of subtask counting and filtering in the task repository.

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Important

The new subtask_mode setting cannot be saved back to "Nested, collapsed" as a personal override while the shared view is "Nested, expanded" — the choice is silently discarded. One other lower-severity concern inline, plus a cache-invalidation note below.

Reviewed changes

Reviewed the full PR (33 files, 1 commit) end to end.

  • API subtask counts and filter — ListTasks now attaches subtask_count / subtask_done_count per task through one batched query, and a new exclude_subtasks filter omits tasks whose live parent is a non-Epic task; applied to the list and count endpoints.
  • View config subtask_mode — new collapsed / expanded / hidden field threaded through the entity, DTOs, and the per-user override merge/diff.
  • Web nested rows — TaskRow gains a chevron, progress chip, and indentation; new SubtaskRows lazily fetches and recurses over children with the view's filters/sort and an inline "Add subtask"; the Timeline gets the same via RoadmapChildRows.
  • View settings and i18n — a Subtasks selector for Table/Roadmap views, translations in 9 locales, and per-user/per-view expansion remembered in localStorage.
  • Tests — Go repository tests for counts and exclude_subtasks, web unit tests, and a new e2e feature + spec.

ℹ️ Nested rows and the parent chip aren't refreshed by the task-detail modal

The new nested children query (childTasksInfiniteQueryOptions, key ["projects", id, "tasks", parentId, "children", filters]) is only invalidated through the broad ["projects", id, "tasks"] prefix from SubtaskRows.handleAdd, the list's field/status edits, and realtime. The task-detail modal's subtask callbacks still invalidate only the exact subtasksInfiniteQueryOptions(...).queryKey, so editing or adding a child there leaves the nested rows and the parent's done/total chip stale until a realtime task.* event (or the 15s staleTime) refetches them. If the acting client doesn't receive its own realtime event, this is user-visible.

Technical details
# Detail-modal subtask edits don't invalidate the nested child query

## Affected sites
- `apps/web/src/components/projects/interactions/task-detail/index.tsx:464-487` — `onSubtaskUpdate` / `onSubtaskCreate` invalidate the exact key `["projects", projectId, "tasks", task.id, "subtasks"]`.
- `apps/web/src/lib/interaction-api.ts:903-916` — the nested query uses the distinct key `[..., parentId, "children", filters]`, which the exact key does not match.
- `apps/web/src/components/projects/interactions/interaction-layout.tsx` — the parent's `subtask_count` / `subtask_done_count` chip lives on the top-level list (`allTasksQueryOptions`), also not matched by the exact key.

## Required outcome
A subtask change made from the detail modal should refresh both the nested rows and the parent's progress chip without relying on a realtime round-trip.

## Suggested approach
Change the two modal invalidations to the prefix `{ queryKey: ["projects", projectId, "tasks"] }`, matching the pattern already used by `SubtaskRows.handleAdd`.

Pullfrog  | Fix all ➔ | Fix 👍s ➔ | View workflow run | Using deepseek-v4.1-flash (free via Pullfrog for OSS) | 𝕏

Comment thread apps/web/src/components/projects/interactions/view-settings-panel.tsx Outdated
Comment thread services/api/internal/repository/postgres/task_repository.go

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ No new issues found.

Reviewed changes

Reviewed the delta from 24b1c1c to 8943b40; the prior review's three findings (one important, two informational) are all addressed, and no new issues were introduced.

  • Persisted an explicit "Nested, collapsed" personal override — a new pickSubtaskMode helper stores the literal "collapsed" when the shared view is "expanded"/"hidden" (and only leaves it unset when the shared default is already collapsed), fixing the silent discard, with unit tests in pick-subtask-mode.test.ts.
  • Scoped the new parent-based reads to the project — exclude_subtasks now requires sp.project_id = tasks.project_id, and attachSubtaskCounts joins the parent on a matching project_id; the repository tests add a cross-project child to cover both paths.
  • Widened the detail modal's subtask invalidation — onSubtaskUpdate / onSubtaskCreate now invalidate the ["projects", projectId, "tasks"] prefix, so the nested rows and the parent's progress chip refresh without waiting on a realtime round-trip.

Pullfrog  | View workflow run | Using deepseek-v4.1-flash (free via Pullfrog for OSS) | 𝕏

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Important

The new Epic exclusion in attachSubtaskCounts zeroes subtask_count for Epic parents, which is exactly the signal the Timeline (Roadmap) view reads to render the chevron/chip and to expand an Epic into its child tasks. Because the Timeline's default view lists Epics only, its nested-child feature is now unreachable — and the PR's own e2e scenario "An Epic shows its child count and expands to its tasks" would fail.

Reviewed changes

Reviewed the delta from 8943b40 to 3327b82 (Go repository/service/DTO/handler, the web subtask store and API, docs, and a migration). One must-address regression, flagged inline.

  • Sprint-scoped exclude_subtasks — the NOT EXISTS now requires the parent to share the child's sprint (sp.sprint_id IS NOT DISTINCT FROM tasks.sprint_id), so a child whose parent is in another sprint stays in the flat list.
  • Epics excluded from attachSubtaskCounts — the batched count query now skips Epic parents, and docs/api/http-design.md states Epics report no subtask_count.
  • View config normalization — normalizeViewConfig drops unknown subtask_mode values on create, update, and the per-user override path.
  • Filter/DB plumbing — exclude_subtasks is ignored when parent_task_id is set, a partial index on tasks(parent_task_id) is added, and the Go tests cover the new sprint scope and the Epic skip.
  • Web — the inline "Add subtask" now inherits the parent's sprint; the manual expand/collapse record drops an entry once it matches the view default.

Pullfrog  | Fix all ➔ | Fix 👍s ➔ | View workflow run | Using deepseek-v4.1-flash (free via Pullfrog for OSS) | 𝕏

Comment thread services/api/internal/repository/postgres/task_repository.go Outdated

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ No new issues found.

Reviewed changes

Reviewed the delta from 3327b82 to d331f33; the prior review's must-address regression is fixed and no new issues were introduced.

  • Restored Epic subtask_count on the server — the Epic predicate was removed from attachSubtaskCounts, so Epics again report their child counts and the Timeline's chevron/chip and child expansion keep working; the Go test now asserts an Epic count of 1.
  • Moved the double-display guard to the Table client — ListGroup.renderTaskRow zeroes the counts for a row whose type is the system Epic, since an Epic's children are already listed flat there, so the Table shows no chevron/chip for Epics without touching the server count the Timeline depends on.
  • Updated the API docs — docs/api/http-design.md no longer claims Epics report no subtask_count.

Pullfrog  | View workflow run | Using deepseek-v4.1-flash (free via Pullfrog for OSS) | 𝕏

@pikann
pikann merged commit e120af3 into master Oct 22, 2026
8 checks passed
@pikann
pikann deleted the feature/add-subtask-management-features-to-view-setting branch October 22, 2026 07:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature] Display subtasks hierarchically in the Backlog view

1 participant