Files
task-stream/libs/web/tracker/infrastructure/src/lib/adapters/graphql-projects.gateway.ts
Josep Piguillem 0946e9517d feat: a home page with life
Greeting and summary of the day, the coming week, the latest across my
projects, who is online now, the week in numbers (mine and the team's,
with a streak), sprints under way, «Retomar», project cards with their
activity, what to pick up when nothing is mine and first steps for
newcomers. REST (GET /api/me/home), GraphQL (myHome) and MCP
(get_my_week).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 19:20:41 +02:00

167 lines
4.7 KiB
TypeScript

import { inject, Injectable } from '@angular/core';
import {
CommandResult,
CreateProjectInput,
MemberInput,
Project,
ProjectAnalytics,
ProjectInsights,
PortfolioProject,
Home,
ProjectSettings,
ProjectsGateway,
ProjectStats,
UpdateProjectInput,
} from '@task-stream/web/tracker/domain';
import { map, Observable } from 'rxjs';
import {
AddProjectMemberDocument,
ChangeProjectMemberRoleDocument,
CreateProjectDocument,
DeleteProjectDocument,
ArchiveProjectDocument,
UnarchiveProjectDocument,
MyProjectsDocument,
ProjectAnalyticsDocument,
ProjectInsightsDocument,
PortfolioDocument,
MyHomeDocument,
ProjectDocument,
ProjectStatsDocument,
PublicProjectsDocument,
RemoveProjectMemberDocument,
UpdateProjectDocument,
UpdateProjectSettingsDocument,
} from '../graphql/generated';
import { GraphqlOperations } from './graphql-operations';
import {
toCommandResult,
toIssueSummary,
toProject,
toSettingsInput,
toStats,
} from './mappers';
@Injectable()
export class GraphqlProjectsGateway extends ProjectsGateway {
private readonly gql = inject(GraphqlOperations);
myProjects(): Observable<Project[]> {
return this.gql
.query(MyProjectsDocument)
.pipe(map((d) => d.myProjects.map(toProject)));
}
publicProjects(): Observable<Project[]> {
return this.gql
.query(PublicProjectsDocument)
.pipe(map((d) => d.publicProjects.map(toProject)));
}
project(idOrKey: string): Observable<Project> {
return this.gql
.query(ProjectDocument, { idOrKey })
.pipe(map((d) => toProject(d.project)));
}
stats(projectId: string): Observable<ProjectStats> {
return this.gql
.query(ProjectStatsDocument, { idOrKey: projectId })
.pipe(map((d) => toStats(d.project.stats)));
}
myHome(): Observable<Home> {
return this.gql
.query(MyHomeDocument, {})
.pipe(map((d) => d.myHome as Home));
}
portfolio(): Observable<PortfolioProject[]> {
return this.gql.query(PortfolioDocument, {}).pipe(
map((d) =>
d.portfolio.map((p) => ({
...(p as unknown as PortfolioProject),
epics: p.epics.map((e) => ({
issue: toIssueSummary(e.issue),
progress: { ...e.progress },
links: [],
})),
})),
),
);
}
insights(
projectId: string,
since: string | null,
): Observable<ProjectInsights> {
return this.gql
.query(ProjectInsightsDocument, { idOrKey: projectId, since })
.pipe(map((d) => d.project.insights as ProjectInsights));
}
analytics(projectId: string, days: number): Observable<ProjectAnalytics> {
return this.gql
.query(ProjectAnalyticsDocument, { idOrKey: projectId, days })
.pipe(map((d) => d.project.analytics));
}
updateSettings(
projectId: string,
settings: ProjectSettings,
): Observable<CommandResult> {
return this.gql
.mutate(UpdateProjectSettingsDocument, {
projectId,
settings: toSettingsInput(settings),
})
.pipe(map((d) => toCommandResult(d.updateProjectSettings)));
}
create(input: CreateProjectInput): Observable<CommandResult> {
return this.gql
.mutate(CreateProjectDocument, { input })
.pipe(map((d) => toCommandResult(d.createProject)));
}
update(input: UpdateProjectInput): Observable<CommandResult> {
return this.gql
.mutate(UpdateProjectDocument, { input })
.pipe(map((d) => toCommandResult(d.updateProject)));
}
setArchived(projectId: string, archived: boolean): Observable<CommandResult> {
return archived
? this.gql
.mutate(ArchiveProjectDocument, { projectId })
.pipe(map((d) => toCommandResult(d.archiveProject)))
: this.gql
.mutate(UnarchiveProjectDocument, { projectId })
.pipe(map((d) => toCommandResult(d.unarchiveProject)));
}
delete(projectId: string, confirmKey: string): Observable<CommandResult> {
return this.gql
.mutate(DeleteProjectDocument, { projectId, confirmKey })
.pipe(map((d) => toCommandResult(d.deleteProject)));
}
addMember(input: MemberInput): Observable<CommandResult> {
return this.gql
.mutate(AddProjectMemberDocument, { input: input as never })
.pipe(map((d) => toCommandResult(d.addProjectMember)));
}
changeMemberRole(input: MemberInput): Observable<CommandResult> {
return this.gql
.mutate(ChangeProjectMemberRoleDocument, { input: input as never })
.pipe(map((d) => toCommandResult(d.changeProjectMemberRole)));
}
removeMember(projectId: string, userId: string): Observable<CommandResult> {
return this.gql
.mutate(RemoveProjectMemberDocument, { projectId, userId })
.pipe(map((d) => toCommandResult(d.removeProjectMember)));
}
}