feat(web): team list on the tracking dashboard

"¿Quién está con qué?" only listed people with open tickets. The tracking
page now shows the whole team: every member with their role and open
tickets (0 included), busiest first, plus former members who still have
tickets and the unassigned count. Each person links to the board filtered
by them: the board accepts ?assignee= like ?release=.

Role colours move to ui/copy.ts (shared with the members page). Docs and
Word/PDF updated.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-03 16:14:46 +02:00
parent 6c3550ae9d
commit 240ea9a539
8 changed files with 201 additions and 54 deletions

View File

@@ -74,7 +74,7 @@ const ALL = '';
class="ts-filter"
placeholder="Persona"
[options]="assigneeOptions()"
[(value)]="assignee"
[(value)]="assigneeFilter"
/>
<pi-select-field
class="ts-filter"
@@ -229,6 +229,8 @@ const ALL = '';
export class BoardPage {
/** `?release=` (from the releases page), bound by the router. */
readonly release = input<string | undefined>();
/** `?assignee=` (from the tracking page's team list), bound by the router. */
readonly assignee = input<string | undefined>();
protected readonly board = inject(BoardFacade);
protected readonly project = inject(ProjectFacade);
@@ -239,7 +241,7 @@ export class BoardPage {
viewChild.required<TemplateRef<unknown>>('reasonForm');
/* Filters */
protected readonly assignee = signal<string | null>(ALL);
protected readonly assigneeFilter = signal<string | null>(ALL);
protected readonly releaseFilter = signal<string | null>(ALL);
protected readonly area = signal<string | null>(ALL);
@@ -299,11 +301,15 @@ export class BoardPage {
const release = this.release();
if (release) untracked(() => this.releaseFilter.set(release));
});
effect(() => {
const assignee = this.assignee();
if (assignee) untracked(() => this.assigneeFilter.set(assignee));
});
// (Re)load whenever the project or a filter changes.
effect(() => {
const projectId = this.project.project()?.id;
const filter = {
assigneeId: this.assignee() || undefined,
assigneeId: this.assigneeFilter() || undefined,
releaseId: this.releaseFilter() || undefined,
area: (this.area() || undefined) as IssueArea | undefined,
};