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>
This commit is contained in:
58
libs/web/tracker/domain/src/lib/models/home.ts
Normal file
58
libs/web/tracker/domain/src/lib/models/home.ts
Normal file
@@ -0,0 +1,58 @@
|
||||
import { SprintPulse } from './insights';
|
||||
import { Activity, UserRef } from './models';
|
||||
|
||||
/** Something on a day of my coming week. */
|
||||
export interface AgendaItem {
|
||||
/** `YYYY-MM-DD`. */
|
||||
day: string;
|
||||
kind: 'ISSUE' | 'SPRINT_END' | 'RELEASE';
|
||||
projectKey: string;
|
||||
title: string;
|
||||
issueKey: string | null;
|
||||
}
|
||||
|
||||
/** What a project's card shows besides its name. */
|
||||
export interface HomeProject {
|
||||
projectId: string;
|
||||
open: number;
|
||||
overdue: number;
|
||||
/** Activity per day, the last 14, oldest first. */
|
||||
activity: number[];
|
||||
sprint: { name: string; percent: number; behind: boolean } | null;
|
||||
}
|
||||
|
||||
/** Something worth doing when nothing is mine. */
|
||||
export interface Suggestion {
|
||||
kind: 'UNASSIGNED' | 'PROPOSALS' | 'QA_WAITING';
|
||||
projectKey: string;
|
||||
count: number;
|
||||
}
|
||||
|
||||
/** Someone of my projects on a ticket right now. */
|
||||
export interface Online {
|
||||
user: UserRef;
|
||||
projectKey: string;
|
||||
issueKey: string | null;
|
||||
issueTitle: string | null;
|
||||
editing: boolean;
|
||||
at: string;
|
||||
}
|
||||
|
||||
/** The home page beyond «my work». */
|
||||
export interface Home {
|
||||
agenda: AgendaItem[];
|
||||
/** Newest first, across my projects. */
|
||||
activity: Activity[];
|
||||
team: { perDay: number[]; thisWeek: number; lastWeek: number };
|
||||
me: { thisWeek: number; lastWeek: number; streak: number };
|
||||
sprints: { projectKey: string; projectName: string; sprint: SprintPulse }[];
|
||||
projects: HomeProject[];
|
||||
suggestions: Suggestion[];
|
||||
firstSteps: {
|
||||
project: boolean;
|
||||
invited: boolean;
|
||||
ticket: boolean;
|
||||
calendar: boolean;
|
||||
};
|
||||
online: Online[];
|
||||
}
|
||||
@@ -378,6 +378,8 @@ export interface Release {
|
||||
export interface Activity {
|
||||
id: string;
|
||||
type: string;
|
||||
/** Absent in activity read before it carried the project. */
|
||||
projectId?: string;
|
||||
issueId: string | null;
|
||||
issueKey: string | null;
|
||||
actor: UserRef;
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { Home } from '../models/home';
|
||||
import { PortfolioProject, ProjectInsights } from '../models/insights';
|
||||
import { Observable } from 'rxjs';
|
||||
import {
|
||||
@@ -69,6 +70,8 @@ export abstract class ProjectsGateway {
|
||||
abstract stats(projectId: string): Observable<ProjectStats>;
|
||||
/** My active projects at a glance. */
|
||||
abstract portfolio(): Observable<PortfolioProject[]>;
|
||||
/** The home page beyond «my work». */
|
||||
abstract myHome(): Observable<Home>;
|
||||
/** The dashboard; with `since`, also what changed after it. */
|
||||
abstract insights(
|
||||
projectId: string,
|
||||
|
||||
Reference in New Issue
Block a user