Skip to content

Add tune set grouping to the repertoire grid#593

Open
sboagy wants to merge 21 commits intomainfrom
sets-in-grid
Open

Add tune set grouping to the repertoire grid#593
sboagy wants to merge 21 commits intomainfrom
sets-in-grid

Conversation

@sboagy
Copy link
Copy Markdown
Owner

@sboagy sboagy commented May 7, 2026

Summary

  • add reusable mixed tune/set hierarchy helpers for grid rows so tune-set grouping lives at the TunesGrid layer instead of only in the repertoire route
  • render repertoire tunes as expandable set containers in both grid and list views, including visible set-row styling
  • fix bulk-selection semantics by using flattened selected rows so tunes that already appear inside a set can still be saved into another set

What changed

  • added grouped-grid-rows.ts to build mixed tune/set rows, row ids, subrow access, and row-selection rules for hierarchical tune grids
  • extended TunesGrid with reusable hierarchy support: expandable rows, row id/subrow hooks, auto-expanded parents, hierarchy-aware list data, and set-row styling
  • updated TuneStackedList to support hierarchical rows in list mode so the Display Options toggle works again for repertoire
  • updated TunesGridRepertoire to fetch visible tune sets and tune-set items, then build mixed tune/set rows for the repertoire tab
  • updated repertoire selection consumers to use getSelectedRowModel().flatRows and dedupe on tune_id ?? id
  • updated bulk goal apply in the repertoire route to use flattened selected rows as well
  • added focused unit coverage for the mixed row builder search and grouping behavior

User-visible behavior

  • tunes that belong to visible sets now appear under expandable set rows in the repertoire tab
  • list view and grid view both preserve the hierarchy
  • set rows are visually distinct from regular tune rows
  • selecting a tune from within an existing set no longer prevents saving that tune to another set

Validation

  • npx vitest run tests/components/grids/grouped-grid-rows.test.ts
  • npx tsc -p tsconfig.app.json --noEmit
  • user-confirmed broader validation later in session: npm run lint && npm run check && npm run typecheck && npm run test:unit

Notes

@sboagy sboagy self-assigned this May 7, 2026
@sboagy sboagy requested a review from Copilot May 7, 2026 02:54
@sboagy sboagy temporarily deployed to tunetrees_ci_env May 7, 2026 02:55 — with GitHub Actions Inactive
@sboagy sboagy temporarily deployed to tunetrees_ci_env May 7, 2026 02:55 — with GitHub Actions Inactive
@sboagy sboagy temporarily deployed to tunetrees_ci_env May 7, 2026 02:55 — with GitHub Actions Inactive
@sboagy sboagy temporarily deployed to tunetrees_ci_env May 7, 2026 02:55 — with GitHub Actions Inactive
@sboagy sboagy had a problem deploying to tunetrees_ci_env May 7, 2026 02:55 — with GitHub Actions Error
@sboagy sboagy temporarily deployed to tunetrees_ci_env May 7, 2026 02:55 — with GitHub Actions Inactive
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds hierarchical Tune Set grouping to the Repertoire tunes grid/list by introducing a mixed tune + tune-set row model (expandable parents with subrows), updating selection semantics to work with duplicated tunes, and wiring the repertoire tab to fetch visible sets + items.

Changes:

  • Added grouped-grid-rows.ts helpers to build mixed tune/tune-set rows (row ids, subrows, selection rules, auto-expand IDs).
  • Extended TunesGrid + TuneStackedList to render expandable hierarchical rows in both grid and list modes, with set-row styling.
  • Updated repertoire selection consumers to use getSelectedRowModel().flatRows and dedupe tune IDs for bulk actions.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
tests/components/grids/grouped-grid-rows.test.ts Adds unit tests for mixed row building / grouping / search behavior.
src/routes/repertoire.tsx Switches bulk selection semantics to flattened selected rows.
src/components/repertoire/RepertoireToolbar.tsx Uses flattened selected rows and deduped tune IDs for toolbar actions.
src/components/grids/TuneStackedList.tsx Adds list-mode hierarchy rendering (indentation + expand/collapse UI) and selection gating.
src/components/grids/TunesGridRepertoire.tsx Fetches visible tune sets + items and builds mixed hierarchical rows for the repertoire tab.
src/components/grids/TunesGrid.tsx Adds TanStack expanding/subrows support, hierarchy cell rendering, list-mode expansion wiring, and set-row styling.
src/components/grids/grouped-grid-rows.ts Implements the reusable mixed tune/tune-set row builder and helper accessors.
Comments suppressed due to low confidence (1)

src/components/grids/TunesGrid.tsx:642

  • In list mode, row-selection state is keyed by TanStack row IDs (including compound IDs for subrows), but this handler uses String(row.id) which is the tune/set id from the original data. For hierarchical rows this will (a) fail to toggle selection for subrows and (b) collide when the same tune appears under multiple sets. Use row.stacked_row_id (added in stackedListData) as the selection key (fallback to row.id only if needed).
  const handleStackedRowSelectionChange = (
    row: IStackedListRow,
    checked: boolean
  ) => {
    const rowId = String(row.id);

Comment thread src/components/grids/grouped-grid-rows.ts
Comment thread tests/components/grids/grouped-grid-rows.test.ts Outdated
Comment thread src/components/grids/TunesGridRepertoire.tsx Outdated
Comment thread src/components/grids/TunesGrid.tsx
Comment thread src/components/grids/TuneStackedList.tsx
Comment thread src/components/grids/TunesGrid.tsx Outdated
sboagy and others added 5 commits May 6, 2026 23:39
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
…e grid

Adds getBatchedTuneSetItemRefs to tune-sets.ts which fetches tuneSetRef,
tuneRef and position for all visible set IDs in a single SQL query. This
eliminates the previous N+1 pattern in TunesGridRepertoire where each set
triggered getTuneSetAccessForUser + item fetch + per-item getTuneRow.
Access control is satisfied by the prior getVisibleTuneSets call so no
per-set access re-check is needed; no tune-row hydration is performed since
the hierarchy builder only needs tuneRef and position.

Also adds unit coverage for getBatchedTuneSetItemRefs in the existing
groups-and-tune-sets test file (empty-input shortcut, multi-set fetch,
position ordering, deleted-item exclusion).

Agent-Logs-Url: https://github.com/sboagy/tunetrees/sessions/c942beb5-37c0-4606-9645-7836f577652b

Co-authored-by: sboagy <136380088+sboagy@users.noreply.github.com>
Copilot finished work on behalf of sboagy May 7, 2026 03:48
@sboagy sboagy had a problem deploying to tunetrees_ci_env May 7, 2026 04:08 — with GitHub Actions Error
@sboagy sboagy temporarily deployed to tunetrees_ci_env May 7, 2026 04:08 — with GitHub Actions Inactive
@sboagy sboagy temporarily deployed to tunetrees_ci_env May 8, 2026 01:01 — with GitHub Actions Inactive
@sboagy sboagy temporarily deployed to tunetrees_ci_env May 8, 2026 01:01 — with GitHub Actions Inactive
@sboagy sboagy temporarily deployed to tunetrees_ci_env May 8, 2026 01:01 — with GitHub Actions Inactive
@sboagy sboagy temporarily deployed to tunetrees_ci_env May 8, 2026 01:01 — with GitHub Actions Inactive
@sboagy sboagy temporarily deployed to tunetrees_ci_env May 8, 2026 01:01 — with GitHub Actions Inactive
@sboagy sboagy temporarily deployed to tunetrees_ci_env May 8, 2026 01:01 — with GitHub Actions Inactive
@sboagy sboagy had a problem deploying to tunetrees_ci_env May 8, 2026 02:18 — with GitHub Actions Error
@sboagy sboagy had a problem deploying to tunetrees_ci_env May 8, 2026 02:18 — with GitHub Actions Error
@sboagy sboagy temporarily deployed to tunetrees_ci_env May 8, 2026 02:18 — with GitHub Actions Inactive
@sboagy sboagy had a problem deploying to tunetrees_ci_env May 8, 2026 02:18 — with GitHub Actions Error
@sboagy sboagy had a problem deploying to tunetrees_ci_env May 8, 2026 02:18 — with GitHub Actions Error
@sboagy sboagy temporarily deployed to tunetrees_ci_env May 8, 2026 02:18 — with GitHub Actions Inactive
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 14 out of 14 changed files in this pull request and generated 2 comments.

Comment thread src/routes/repertoire.tsx Outdated
Comment on lines +347 to +351
return getTuneIdsForTuneSets(
params.db,
visibleSets.map((set) => set.id),
params.userId
);
Comment on lines 294 to +299
<For each={props.data}>
{(item) => {
const itemId = item.tune_id ?? item.id;
const rowId = String(item.id);
const rowId = String(item.stacked_row_id ?? item.id);
const checkboxIdentifier = String(item.id);
const rowDepth = item.stacked_depth ?? 0;
@sboagy
Copy link
Copy Markdown
Owner Author

sboagy commented May 8, 2026

@copilot apply changes based on the comments in this thread

… for stacked-item testid

repertoire.tsx:
- Both selectedTuneSetTuneIds and anyTuneSetTuneIds resources now use
  getBatchedTuneSetItemRefs instead of getTuneIdsForTuneSets. This avoids
  the per-set getTuneSetAccessForUser + item fetch + per-item getTuneRow
  round trips that getTuneIdsForTuneSets performs. Unique tune IDs are
  collected client-side with new Set().

TuneStackedList.tsx:
- data-testid for the <li> element now uses rowId (TanStack row ID, e.g.
  set-{setId}-tune-{tuneId}) instead of itemId (tune_id ?? id). When the
  same tune appears in multiple sets itemId is identical for both rows, so
  using it as a DOM identifier produces non-unique testids and makes
  test/automation selectors ambiguous. rowId is always unique. The
  isSelected() comparison continues to use itemId since current-tune
  selection is by tune identity, not by position in the hierarchy.

Agent-Logs-Url: https://github.com/sboagy/tunetrees/sessions/247b26ed-76bc-481a-81f9-9d11e8547307

Co-authored-by: sboagy <136380088+sboagy@users.noreply.github.com>
Copy link
Copy Markdown
Contributor

Copilot AI commented May 8, 2026

@copilot apply changes based on the comments in this thread

Done in commit 7bac9db.

repertoire.tsx N+1 fix — both selectedTuneSetTuneIds and anyTuneSetTuneIds resources now use getBatchedTuneSetItemRefs instead of getTuneIdsForTuneSets. This replaces the per-set getTuneSetAccessForUser + item fetch + per-item getTuneRow chain with a single SELECT tuneSetRef, tuneRef, position ... WHERE tuneSetRef IN (...) query; unique tune IDs are then collected client-side with new Set().

TuneStackedList.tsx non-unique DOM ID fixdata-testid on the <li> element now uses rowId (the TanStack row ID, e.g. set-{setId}-tune-{tuneId}) instead of itemId (tune_id ?? id). When the same tune appears in multiple sets, itemId was identical for both rows making the testid non-unique. rowId is always unique. isSelected() continues using itemId since current-tune selection is by tune identity.

Copilot finished work on behalf of sboagy May 8, 2026 03:13
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.

3 participants