feat: saved board views and richer board filters

The board now filters by text, type, priority and unassigned tickets as
well. Any combination can be saved as a named view, private or shared with
the project, and opened again with one click.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-08 14:14:38 +02:00
parent 0606f53026
commit 298383f19f
46 changed files with 2922 additions and 26 deletions

View File

@@ -52,6 +52,13 @@ export class GraphqlIssuesGateway extends IssuesGateway {
releaseId: filter.releaseId ?? null,
assigneeId: filter.assigneeId ?? null,
area: filter.area ?? null,
types: filter.types?.length ? filter.types : null,
priorities: filter.priorities?.length
? (filter.priorities as never)
: null,
labels: filter.labels?.length ? filter.labels : null,
search: filter.search?.trim() || null,
unassigned: filter.unassigned ?? null,
})
.pipe(
map((d) =>

View File

@@ -0,0 +1,41 @@
import { inject, Injectable } from '@angular/core';
import {
SavedFilter,
SavedFilterCriteria,
SavedFiltersGateway,
} from '@task-stream/web/tracker/domain';
import { map, Observable } from 'rxjs';
import {
DeleteSavedFilterDocument,
SavedFiltersDocument,
SaveFilterDocument,
} from '../graphql/generated';
import { GraphqlOperations } from './graphql-operations';
@Injectable()
export class GraphqlSavedFiltersGateway extends SavedFiltersGateway {
private readonly gql = inject(GraphqlOperations);
list(projectId: string): Observable<SavedFilter[]> {
return this.gql
.query(SavedFiltersDocument, { projectId })
.pipe(map((d) => d.savedFilters as SavedFilter[]));
}
save(input: {
projectId: string;
name: string;
shared: boolean;
criteria: SavedFilterCriteria;
}): Observable<string> {
return this.gql
.mutate(SaveFilterDocument, { input: input as never })
.pipe(map((d) => d.saveFilter));
}
remove(id: string): Observable<void> {
return this.gql
.mutate(DeleteSavedFilterDocument, { id })
.pipe(map(() => undefined));
}
}