diff --git a/libs/web/tracker/presenters/src/lib/pages/board.page.ts b/libs/web/tracker/presenters/src/lib/pages/board.page.ts
index d5eb07f..405bd77 100644
--- a/libs/web/tracker/presenters/src/lib/pages/board.page.ts
+++ b/libs/web/tracker/presenters/src/lib/pages/board.page.ts
@@ -1,9 +1,4 @@
-import {
- CdkDrag,
- CdkDragDrop,
- CdkDropList,
- CdkDropListGroup,
-} from '@angular/cdk/drag-drop';
+import { CdkDrag, CdkDragDrop, CdkDropList } from '@angular/cdk/drag-drop';
import {
ChangeDetectionStrategy,
Component,
@@ -90,7 +85,6 @@ const NOBODY = '__nobody__';
selector: 'ts-board-page',
changeDetection: ChangeDetectionStrategy.OnPush,
imports: [
- CdkDropListGroup,
CdkDropList,
CdkDrag,
FormField,
@@ -218,7 +212,7 @@ const NOBODY = '__nobody__';
} @else {
@if (laneMode() === 'none') {
-
+
@for (column of board.columns(); track column.status) {
{{ lane.count }}
-
+
@for (column of lane.columns; track column.status) {
statusLook(this.project.workflow(), status).tone;
+ /**
+ * The ids of each row's column lists, by row ('' without swimlanes): a card
+ * moves between the columns of its own row. Connected by id because the
+ * lists are stamped from a template, and a template only sees the drop
+ * groups around where it is declared, not where it is placed.
+ */
+ protected readonly rowLists = computed(() => {
+ const statuses = this.board.columns().map((c) => c.status);
+ const rows =
+ this.laneMode() === 'none' ? [''] : this.lanes().map((l) => l.key);
+ return Object.fromEntries(
+ rows.map((row) => [row, statuses.map((status) => `${row}|${status}`)]),
+ );
+ });
+
/** Columns a dragged ticket can enter: its allowed transitions. */
protected readonly canEnter = (
drag: CdkDrag,