@burdenoff/microfe-planmagnet 2026.928.7 → 2026.928.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/planmagnet/PlanMagnetRoutes.d.ts.map +1 -1
- package/dist/planmagnet/PlanMagnetRoutes.js +18 -14
- package/dist/planmagnet/PlanMagnetRoutes.js.map +1 -1
- package/dist/planmagnet/automation/AutomationRuleFields.d.ts.map +1 -1
- package/dist/planmagnet/automation/AutomationRuleFields.js +13 -12
- package/dist/planmagnet/automation/AutomationRuleFields.js.map +1 -1
- package/dist/planmagnet/controls/WorkItemControls.d.ts +21 -0
- package/dist/planmagnet/controls/WorkItemControls.d.ts.map +1 -1
- package/dist/planmagnet/controls/WorkItemControls.js +34 -15
- package/dist/planmagnet/controls/WorkItemControls.js.map +1 -1
- package/dist/planmagnet/pages/ProjectsCriticalPathPagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/ProjectsCriticalPathPagePage.js +153 -63
- package/dist/planmagnet/pages/ProjectsCriticalPathPagePage.js.map +1 -1
- package/dist/planmagnet/pages/ReportsReportsPagePage.d.ts +0 -7
- package/dist/planmagnet/pages/ReportsReportsPagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/ReportsReportsPagePage.js +517 -39
- package/dist/planmagnet/pages/ReportsReportsPagePage.js.map +1 -1
- package/dist/planmagnet/pages/TasksMyWorkPagePage.d.ts +2 -0
- package/dist/planmagnet/pages/TasksMyWorkPagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/TasksMyWorkPagePage.js +257 -0
- package/dist/planmagnet/pages/TasksMyWorkPagePage.js.map +1 -0
- package/dist/planmagnet/pages/TemplatesTemplatesPagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/TemplatesTemplatesPagePage.js +77 -70
- package/dist/planmagnet/pages/TemplatesTemplatesPagePage.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,49 +1,527 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
1
|
+
import { usePlanMagnet as e } from "../providers/PlanMagnetProvider.js";
|
|
2
|
+
import { Legend as t } from "../../node_modules/recharts/es6/component/Legend.js";
|
|
3
|
+
import { Tooltip as n } from "../../node_modules/recharts/es6/component/Tooltip.js";
|
|
4
|
+
import { ResponsiveContainer as r } from "../../node_modules/recharts/es6/component/ResponsiveContainer.js";
|
|
5
|
+
import { Bar as i } from "../../node_modules/recharts/es6/cartesian/Bar.js";
|
|
6
|
+
import { ReferenceLine as a } from "../../node_modules/recharts/es6/cartesian/ReferenceLine.js";
|
|
7
|
+
import { CartesianGrid as o } from "../../node_modules/recharts/es6/cartesian/CartesianGrid.js";
|
|
8
|
+
import { XAxis as s } from "../../node_modules/recharts/es6/cartesian/XAxis.js";
|
|
9
|
+
import { YAxis as c } from "../../node_modules/recharts/es6/cartesian/YAxis.js";
|
|
10
|
+
import { BarChart as l } from "../../node_modules/recharts/es6/chart/BarChart.js";
|
|
11
|
+
import { CycleTimeCard as u } from "./analytics/DeliveryHealthCards.js";
|
|
12
|
+
import { useState as d } from "react";
|
|
13
|
+
import { BarChart3 as f, ShieldCheck as p, TrendingUp as m, Users as h } from "lucide-react";
|
|
14
|
+
import { gql as g } from "@apollo/client";
|
|
15
|
+
import { useQuery as _ } from "@apollo/client/react";
|
|
16
|
+
import { Fragment as v, jsx as y, jsxs as b } from "react/jsx-runtime";
|
|
17
|
+
import { useI18n as x } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
|
|
18
|
+
import { Badge as S, Card as C, CardContent as w, CardHeader as T, CardTitle as E, Select as D, SelectContent as O, SelectItem as k, SelectTrigger as A, SelectValue as j, Tabs as M, TabsContent as N, TabsList as P, TabsTrigger as F } from "@burdenoff/fe-libs/ui";
|
|
5
19
|
//#region src/planmagnet/pages/ReportsReportsPagePage.tsx
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
20
|
+
var I = g`
|
|
21
|
+
query GetReportsProjects($workspaceId: ID!) {
|
|
22
|
+
planmagnetProjects(workspaceId: $workspaceId, pagination: { first: 100 }) {
|
|
23
|
+
items {
|
|
24
|
+
id
|
|
25
|
+
name
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
`, L = g`
|
|
30
|
+
query GetReportsVelocity($workspaceId: ID!, $projectId: ID!, $trailingSprintCount: Int) {
|
|
31
|
+
planmagnetVelocity(
|
|
32
|
+
workspaceId: $workspaceId
|
|
33
|
+
projectId: $projectId
|
|
34
|
+
trailingSprintCount: $trailingSprintCount
|
|
35
|
+
) {
|
|
36
|
+
projectId
|
|
37
|
+
averageVelocity
|
|
38
|
+
forecastNextSprintPoints
|
|
39
|
+
sprints {
|
|
40
|
+
sprintId
|
|
41
|
+
sprintName
|
|
42
|
+
sequenceNumber
|
|
43
|
+
completedPoints
|
|
44
|
+
completedCount
|
|
45
|
+
plannedPoints
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
`, R = g`
|
|
50
|
+
query GetReportsThroughput(
|
|
51
|
+
$workspaceId: ID!
|
|
52
|
+
$projectId: ID!
|
|
53
|
+
$bucket: PlanmagnetThroughputBucket
|
|
54
|
+
) {
|
|
55
|
+
planmagnetThroughput(workspaceId: $workspaceId, projectId: $projectId, bucket: $bucket) {
|
|
56
|
+
projectId
|
|
57
|
+
bucket
|
|
58
|
+
startDate
|
|
59
|
+
endDate
|
|
60
|
+
points {
|
|
61
|
+
periodStart
|
|
62
|
+
completedCount
|
|
63
|
+
completedPoints
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
`, z = g`
|
|
68
|
+
query GetReportsTeams($workspaceId: ID!) {
|
|
69
|
+
planmagnetTeams(workspaceId: $workspaceId, pagination: { first: 100 }) {
|
|
70
|
+
items {
|
|
71
|
+
id
|
|
72
|
+
name
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
`, B = g`
|
|
77
|
+
query GetReportsTeamVelocity($workspaceId: ID!, $teamId: ID!, $trailingSprintCount: Int) {
|
|
78
|
+
planmagnetTeamVelocity(
|
|
79
|
+
workspaceId: $workspaceId
|
|
80
|
+
teamId: $teamId
|
|
81
|
+
trailingSprintCount: $trailingSprintCount
|
|
82
|
+
) {
|
|
83
|
+
teamId
|
|
84
|
+
averageVelocity
|
|
85
|
+
forecastNextSprintPoints
|
|
86
|
+
sprints {
|
|
87
|
+
sprintId
|
|
88
|
+
sprintName
|
|
89
|
+
sequenceNumber
|
|
90
|
+
completedCount
|
|
91
|
+
completedPoints
|
|
92
|
+
plannedPoints
|
|
93
|
+
byProject {
|
|
94
|
+
projectId
|
|
95
|
+
projectName
|
|
96
|
+
count
|
|
97
|
+
points
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
`, V = g`
|
|
103
|
+
query GetReportsReleases($workspaceId: ID!, $projectId: String) {
|
|
104
|
+
planmagnetReleases(
|
|
105
|
+
workspaceId: $workspaceId
|
|
106
|
+
filter: { projectId: $projectId }
|
|
107
|
+
pagination: { first: 50 }
|
|
108
|
+
) {
|
|
109
|
+
items {
|
|
110
|
+
id
|
|
111
|
+
name
|
|
112
|
+
status
|
|
113
|
+
plannedDate
|
|
114
|
+
}
|
|
115
|
+
totalCount
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
`, H = g`
|
|
119
|
+
query GetReportsReleaseReadiness($releaseId: ID!) {
|
|
120
|
+
planmagnetReleaseReadiness(releaseId: $releaseId) {
|
|
121
|
+
releaseId
|
|
122
|
+
doneItems
|
|
123
|
+
totalItems
|
|
124
|
+
blockers {
|
|
125
|
+
workItem {
|
|
126
|
+
id
|
|
127
|
+
key
|
|
128
|
+
title
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
`, U = new Set([
|
|
134
|
+
"DRAFT",
|
|
135
|
+
"PLANNING",
|
|
136
|
+
"IN_PROGRESS",
|
|
137
|
+
"STAGING",
|
|
138
|
+
"READY"
|
|
139
|
+
]);
|
|
140
|
+
function W(e) {
|
|
141
|
+
let t = new Date(e);
|
|
142
|
+
return `${t.getUTCMonth() + 1}/${t.getUTCDate()}`;
|
|
143
|
+
}
|
|
144
|
+
function G({ release: e }) {
|
|
145
|
+
let { t } = x(), { data: n, loading: r, error: i } = _(H, { variables: { releaseId: e.id } }), a = n?.planmagnetReleaseReadiness, o = a && a.totalItems > 0 ? Math.round(a.doneItems / a.totalItems * 100) : null, s = a ? a.doneItems >= a.totalItems && a.blockers.length === 0 : null;
|
|
146
|
+
return /* @__PURE__ */ b(C, {
|
|
147
|
+
"data-testid": `release-readiness-${e.id}`,
|
|
148
|
+
children: [/* @__PURE__ */ y(T, { children: /* @__PURE__ */ b(E, {
|
|
149
|
+
className: "flex items-center justify-between text-sm",
|
|
150
|
+
children: [/* @__PURE__ */ y("span", { children: e.name }), /* @__PURE__ */ y(S, {
|
|
151
|
+
variant: "outline",
|
|
152
|
+
children: K(e.status)
|
|
153
|
+
})]
|
|
154
|
+
}) }), /* @__PURE__ */ y(w, {
|
|
155
|
+
className: "space-y-2",
|
|
156
|
+
children: r ? /* @__PURE__ */ y("p", {
|
|
157
|
+
className: "text-sm text-muted-foreground",
|
|
158
|
+
children: t("planmagnet.reports.loading", "Loading…")
|
|
159
|
+
}) : i ? /* @__PURE__ */ y("p", {
|
|
160
|
+
className: "text-sm text-destructive",
|
|
161
|
+
children: t("planmagnet.reports.readiness.error", "Readiness could not be loaded")
|
|
162
|
+
}) : a ? /* @__PURE__ */ b(v, { children: [
|
|
163
|
+
/* @__PURE__ */ b("p", {
|
|
164
|
+
className: "text-sm",
|
|
165
|
+
children: [
|
|
166
|
+
/* @__PURE__ */ y("span", {
|
|
167
|
+
className: "font-semibold",
|
|
168
|
+
children: a.doneItems
|
|
169
|
+
}),
|
|
170
|
+
" /",
|
|
171
|
+
" ",
|
|
172
|
+
/* @__PURE__ */ y("span", {
|
|
173
|
+
className: "text-muted-foreground",
|
|
174
|
+
children: a.totalItems
|
|
175
|
+
}),
|
|
176
|
+
" ",
|
|
177
|
+
t("planmagnet.reports.readiness.itemsDone", "items done"),
|
|
178
|
+
o !== null && /* @__PURE__ */ b("span", {
|
|
179
|
+
className: "text-muted-foreground",
|
|
180
|
+
children: [
|
|
181
|
+
" (",
|
|
182
|
+
o,
|
|
183
|
+
"%)"
|
|
184
|
+
]
|
|
185
|
+
})
|
|
186
|
+
]
|
|
187
|
+
}),
|
|
188
|
+
/* @__PURE__ */ y(S, {
|
|
189
|
+
variant: s ? "success" : "warning",
|
|
190
|
+
children: s ? t("planmagnet.reports.readiness.ready", "Ready") : t("planmagnet.reports.readiness.notReady", "Not ready")
|
|
191
|
+
}),
|
|
192
|
+
a.blockers.length > 0 && /* @__PURE__ */ y("p", {
|
|
193
|
+
className: "text-xs text-muted-foreground",
|
|
194
|
+
children: t("planmagnet.reports.readiness.blockers", "{{count}} blocker(s)", { count: a.blockers.length })
|
|
195
|
+
})
|
|
196
|
+
] }) : null
|
|
197
|
+
})]
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
function K(e) {
|
|
201
|
+
let t = e.toLowerCase().replace(/_/g, " ");
|
|
202
|
+
return t.charAt(0).toUpperCase() + t.slice(1);
|
|
203
|
+
}
|
|
204
|
+
function q({ workspaceId: e, projectId: d }) {
|
|
205
|
+
let { t: h } = x(), { data: g, loading: v } = _(L, {
|
|
206
|
+
variables: {
|
|
207
|
+
workspaceId: e,
|
|
208
|
+
projectId: d,
|
|
209
|
+
trailingSprintCount: 10
|
|
210
|
+
},
|
|
211
|
+
skip: !e || !d
|
|
212
|
+
}), { data: S, loading: D, error: O } = _(R, {
|
|
213
|
+
variables: {
|
|
214
|
+
workspaceId: e,
|
|
215
|
+
projectId: d,
|
|
216
|
+
bucket: "WEEK"
|
|
217
|
+
},
|
|
218
|
+
skip: !e || !d
|
|
219
|
+
}), { data: k } = _(V, {
|
|
220
|
+
variables: {
|
|
221
|
+
workspaceId: e,
|
|
222
|
+
projectId: d
|
|
223
|
+
},
|
|
224
|
+
skip: !e || !d
|
|
225
|
+
}), A = g?.planmagnetVelocity, j = A?.sprints.map((e) => ({
|
|
226
|
+
name: e.sprintName,
|
|
227
|
+
completed: e.completedPoints,
|
|
228
|
+
planned: e.plannedPoints ?? void 0
|
|
229
|
+
})) ?? [], M = A ? Math.round(A.averageVelocity) : 0, N = S?.planmagnetThroughput.points.map((e) => ({
|
|
230
|
+
period: W(e.periodStart),
|
|
231
|
+
count: e.completedCount,
|
|
232
|
+
points: e.completedPoints
|
|
233
|
+
})) ?? [], P = (k?.planmagnetReleases.items ?? []).filter((e) => U.has(e.status));
|
|
234
|
+
return /* @__PURE__ */ b("div", {
|
|
235
|
+
className: "space-y-6",
|
|
236
|
+
children: [
|
|
237
|
+
/* @__PURE__ */ b("div", {
|
|
238
|
+
className: "grid grid-cols-1 lg:grid-cols-2 gap-6",
|
|
239
|
+
children: [/* @__PURE__ */ b(C, { children: [/* @__PURE__ */ y(T, { children: /* @__PURE__ */ b(E, {
|
|
240
|
+
className: "flex items-center gap-2",
|
|
241
|
+
children: [
|
|
242
|
+
/* @__PURE__ */ y(m, { className: "h-4 w-4" }),
|
|
243
|
+
h("planmagnet.reports.velocity.title", "Sprint Velocity"),
|
|
244
|
+
" (",
|
|
245
|
+
j.length,
|
|
246
|
+
" ",
|
|
247
|
+
h("planmagnet.reports.velocity.sprints", "sprints"),
|
|
248
|
+
")"
|
|
249
|
+
]
|
|
250
|
+
}) }), /* @__PURE__ */ y(w, { children: v ? /* @__PURE__ */ y("div", {
|
|
251
|
+
className: "flex justify-center py-12",
|
|
252
|
+
children: /* @__PURE__ */ y("div", { className: "animate-spin h-6 w-6 border-2 border-primary border-t-transparent rounded-full" })
|
|
253
|
+
}) : j.length > 0 ? /* @__PURE__ */ y(r, {
|
|
254
|
+
width: "100%",
|
|
255
|
+
height: 220,
|
|
256
|
+
children: /* @__PURE__ */ b(l, {
|
|
257
|
+
data: j,
|
|
258
|
+
children: [
|
|
259
|
+
/* @__PURE__ */ y(o, {
|
|
260
|
+
strokeDasharray: "3 3",
|
|
261
|
+
opacity: .2
|
|
262
|
+
}),
|
|
263
|
+
/* @__PURE__ */ y(s, {
|
|
264
|
+
dataKey: "name",
|
|
265
|
+
tick: { fontSize: 11 }
|
|
266
|
+
}),
|
|
267
|
+
/* @__PURE__ */ y(c, {
|
|
268
|
+
tick: { fontSize: 11 },
|
|
269
|
+
allowDecimals: !1
|
|
270
|
+
}),
|
|
271
|
+
/* @__PURE__ */ y(n, {}),
|
|
272
|
+
/* @__PURE__ */ y(t, { wrapperStyle: { fontSize: 12 } }),
|
|
273
|
+
/* @__PURE__ */ y(i, {
|
|
274
|
+
dataKey: "planned",
|
|
275
|
+
name: h("planmagnet.reports.velocity.planned", "Planned"),
|
|
276
|
+
fill: "#cbd5e1"
|
|
277
|
+
}),
|
|
278
|
+
/* @__PURE__ */ y(i, {
|
|
279
|
+
dataKey: "completed",
|
|
280
|
+
name: h("planmagnet.reports.velocity.completed", "Completed"),
|
|
281
|
+
fill: "#6366f1"
|
|
282
|
+
}),
|
|
283
|
+
/* @__PURE__ */ y(a, {
|
|
284
|
+
y: M,
|
|
285
|
+
stroke: "#22c55e",
|
|
286
|
+
strokeDasharray: "4 4"
|
|
287
|
+
})
|
|
288
|
+
]
|
|
289
|
+
})
|
|
290
|
+
}) : /* @__PURE__ */ y("p", {
|
|
291
|
+
className: "text-sm text-muted-foreground py-8 text-center",
|
|
292
|
+
children: h("planmagnet.reports.velocity.empty", "No completed sprints yet for this project")
|
|
293
|
+
}) })] }), /* @__PURE__ */ b(C, { children: [/* @__PURE__ */ b(T, { children: [/* @__PURE__ */ b(E, {
|
|
294
|
+
className: "flex items-center gap-2",
|
|
295
|
+
children: [/* @__PURE__ */ y(f, { className: "h-4 w-4" }), h("planmagnet.reports.throughput.title", "Throughput")]
|
|
296
|
+
}), /* @__PURE__ */ y("p", {
|
|
297
|
+
className: "text-xs text-muted-foreground",
|
|
298
|
+
children: h("planmagnet.reports.throughput.subtitle", "Work items completed per week, trailing 12 weeks.")
|
|
299
|
+
})] }), /* @__PURE__ */ y(w, { children: D ? /* @__PURE__ */ y("div", {
|
|
300
|
+
className: "flex justify-center py-12",
|
|
301
|
+
children: /* @__PURE__ */ y("div", { className: "animate-spin h-6 w-6 border-2 border-primary border-t-transparent rounded-full" })
|
|
302
|
+
}) : O ? /* @__PURE__ */ y("p", {
|
|
303
|
+
className: "text-sm text-muted-foreground py-8 text-center",
|
|
304
|
+
children: h("planmagnet.reports.throughput.unavailable", "Throughput is not available yet for this workspace.")
|
|
305
|
+
}) : N.length > 0 ? /* @__PURE__ */ y(r, {
|
|
306
|
+
width: "100%",
|
|
307
|
+
height: 220,
|
|
308
|
+
children: /* @__PURE__ */ b(l, {
|
|
309
|
+
data: N,
|
|
310
|
+
children: [
|
|
311
|
+
/* @__PURE__ */ y(o, {
|
|
312
|
+
strokeDasharray: "3 3",
|
|
313
|
+
opacity: .2
|
|
314
|
+
}),
|
|
315
|
+
/* @__PURE__ */ y(s, {
|
|
316
|
+
dataKey: "period",
|
|
317
|
+
tick: { fontSize: 11 }
|
|
318
|
+
}),
|
|
319
|
+
/* @__PURE__ */ y(c, {
|
|
320
|
+
tick: { fontSize: 11 },
|
|
321
|
+
allowDecimals: !1
|
|
322
|
+
}),
|
|
323
|
+
/* @__PURE__ */ y(n, {}),
|
|
324
|
+
/* @__PURE__ */ y(t, { wrapperStyle: { fontSize: 12 } }),
|
|
325
|
+
/* @__PURE__ */ y(i, {
|
|
326
|
+
dataKey: "count",
|
|
327
|
+
name: h("planmagnet.reports.throughput.items", "Items done"),
|
|
328
|
+
fill: "#0ea5e9"
|
|
329
|
+
}),
|
|
330
|
+
/* @__PURE__ */ y(i, {
|
|
331
|
+
dataKey: "points",
|
|
332
|
+
name: h("planmagnet.reports.throughput.points", "Points done"),
|
|
333
|
+
fill: "#a855f7"
|
|
334
|
+
})
|
|
335
|
+
]
|
|
336
|
+
})
|
|
337
|
+
}) : /* @__PURE__ */ y("p", {
|
|
338
|
+
className: "text-sm text-muted-foreground py-8 text-center",
|
|
339
|
+
children: h("planmagnet.reports.throughput.empty", "No work completed in this project yet")
|
|
340
|
+
}) })] })]
|
|
341
|
+
}),
|
|
342
|
+
/* @__PURE__ */ y(u, {
|
|
343
|
+
workspaceId: e,
|
|
344
|
+
projectId: d
|
|
345
|
+
}),
|
|
346
|
+
/* @__PURE__ */ b(C, { children: [/* @__PURE__ */ b(T, { children: [/* @__PURE__ */ b(E, {
|
|
347
|
+
className: "flex items-center gap-2",
|
|
348
|
+
children: [/* @__PURE__ */ y(p, { className: "h-4 w-4" }), h("planmagnet.reports.readiness.title", "Release readiness")]
|
|
349
|
+
}), /* @__PURE__ */ y("p", {
|
|
350
|
+
className: "text-xs text-muted-foreground",
|
|
351
|
+
children: h("planmagnet.reports.readiness.subtitle", "Open releases for this project, and what still blocks each.")
|
|
352
|
+
})] }), /* @__PURE__ */ y(w, { children: P.length === 0 ? /* @__PURE__ */ y("p", {
|
|
353
|
+
className: "text-sm text-muted-foreground py-4 text-center",
|
|
354
|
+
children: h("planmagnet.reports.readiness.empty", "No open releases for this project")
|
|
355
|
+
}) : /* @__PURE__ */ y("div", {
|
|
356
|
+
className: "grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-3",
|
|
357
|
+
children: P.map((e) => /* @__PURE__ */ y(G, { release: e }, e.id))
|
|
358
|
+
}) })] })
|
|
359
|
+
]
|
|
360
|
+
});
|
|
361
|
+
}
|
|
362
|
+
function J({ workspaceId: e }) {
|
|
363
|
+
let { t: a } = x(), [u, f] = d(""), { data: p } = _(z, {
|
|
364
|
+
variables: { workspaceId: e },
|
|
365
|
+
skip: !e
|
|
366
|
+
}), m = p?.planmagnetTeams.items ?? [], g = u || m[0]?.id || "", { data: v, loading: S } = _(B, {
|
|
367
|
+
variables: {
|
|
368
|
+
workspaceId: e,
|
|
369
|
+
teamId: g,
|
|
370
|
+
trailingSprintCount: 10
|
|
371
|
+
},
|
|
372
|
+
skip: !e || !g
|
|
373
|
+
}), M = (v?.planmagnetTeamVelocity)?.sprints.map((e) => ({
|
|
374
|
+
name: e.sprintName,
|
|
375
|
+
completed: e.completedPoints,
|
|
376
|
+
planned: e.plannedPoints ?? void 0
|
|
377
|
+
})) ?? [];
|
|
378
|
+
return m.length === 0 ? /* @__PURE__ */ y("p", {
|
|
379
|
+
className: "text-sm text-muted-foreground py-8 text-center",
|
|
380
|
+
children: a("planmagnet.reports.team.empty", "No teams in this workspace yet — create one under Teams.")
|
|
381
|
+
}) : /* @__PURE__ */ b("div", {
|
|
382
|
+
className: "space-y-4",
|
|
383
|
+
children: [/* @__PURE__ */ b(D, {
|
|
384
|
+
value: g,
|
|
385
|
+
onValueChange: f,
|
|
386
|
+
children: [/* @__PURE__ */ y(A, {
|
|
387
|
+
className: "h-8 w-56",
|
|
388
|
+
children: /* @__PURE__ */ y(j, { placeholder: a("planmagnet.reports.team.pick", "Select team") })
|
|
389
|
+
}), /* @__PURE__ */ y(O, { children: m.map((e) => /* @__PURE__ */ y(k, {
|
|
390
|
+
value: e.id,
|
|
391
|
+
children: e.name
|
|
392
|
+
}, e.id)) })]
|
|
393
|
+
}), /* @__PURE__ */ b(C, { children: [/* @__PURE__ */ b(T, { children: [/* @__PURE__ */ b(E, {
|
|
394
|
+
className: "flex items-center gap-2",
|
|
395
|
+
children: [
|
|
396
|
+
/* @__PURE__ */ y(h, { className: "h-4 w-4" }),
|
|
397
|
+
a("planmagnet.reports.team.velocityTitle", "Team velocity"),
|
|
398
|
+
" (",
|
|
399
|
+
M.length,
|
|
400
|
+
" ",
|
|
401
|
+
a("planmagnet.reports.velocity.sprints", "sprints"),
|
|
402
|
+
")"
|
|
403
|
+
]
|
|
404
|
+
}), /* @__PURE__ */ y("p", {
|
|
405
|
+
className: "text-xs text-muted-foreground",
|
|
406
|
+
children: a("planmagnet.reports.team.velocitySubtitle", "Whole-team completed points across the trailing 10 completed team sprints (BOFF-8044 per-project split, no double counting).")
|
|
407
|
+
})] }), /* @__PURE__ */ y(w, { children: S ? /* @__PURE__ */ y("div", {
|
|
408
|
+
className: "flex justify-center py-12",
|
|
409
|
+
children: /* @__PURE__ */ y("div", { className: "animate-spin h-6 w-6 border-2 border-primary border-t-transparent rounded-full" })
|
|
410
|
+
}) : M.length > 0 ? /* @__PURE__ */ y(r, {
|
|
411
|
+
width: "100%",
|
|
412
|
+
height: 220,
|
|
413
|
+
children: /* @__PURE__ */ b(l, {
|
|
414
|
+
data: M,
|
|
415
|
+
children: [
|
|
416
|
+
/* @__PURE__ */ y(o, {
|
|
417
|
+
strokeDasharray: "3 3",
|
|
418
|
+
opacity: .2
|
|
419
|
+
}),
|
|
420
|
+
/* @__PURE__ */ y(s, {
|
|
421
|
+
dataKey: "name",
|
|
422
|
+
tick: { fontSize: 11 }
|
|
423
|
+
}),
|
|
424
|
+
/* @__PURE__ */ y(c, {
|
|
425
|
+
tick: { fontSize: 11 },
|
|
426
|
+
allowDecimals: !1
|
|
427
|
+
}),
|
|
428
|
+
/* @__PURE__ */ y(n, {}),
|
|
429
|
+
/* @__PURE__ */ y(t, { wrapperStyle: { fontSize: 12 } }),
|
|
430
|
+
/* @__PURE__ */ y(i, {
|
|
431
|
+
dataKey: "planned",
|
|
432
|
+
name: a("planmagnet.reports.velocity.planned", "Planned"),
|
|
433
|
+
fill: "#cbd5e1"
|
|
434
|
+
}),
|
|
435
|
+
/* @__PURE__ */ y(i, {
|
|
436
|
+
dataKey: "completed",
|
|
437
|
+
name: a("planmagnet.reports.velocity.completed", "Completed"),
|
|
438
|
+
fill: "#6366f1"
|
|
439
|
+
})
|
|
440
|
+
]
|
|
441
|
+
})
|
|
442
|
+
}) : /* @__PURE__ */ y("p", {
|
|
443
|
+
className: "text-sm text-muted-foreground py-8 text-center",
|
|
444
|
+
children: a("planmagnet.reports.team.velocityEmpty", "No completed team sprints yet")
|
|
445
|
+
}) })] })]
|
|
446
|
+
});
|
|
447
|
+
}
|
|
448
|
+
function Y() {
|
|
449
|
+
let { workspaceId: t } = e(), { t: n } = x(), [r, i] = d(""), { data: a, loading: o, error: s } = _(I, {
|
|
450
|
+
variables: { workspaceId: t },
|
|
451
|
+
skip: !t
|
|
452
|
+
}), c = a?.planmagnetProjects.items ?? [], l = r || c[0]?.id || "", u = c.find((e) => e.id === l)?.name ?? "";
|
|
453
|
+
return o && !a ? /* @__PURE__ */ y("div", {
|
|
454
|
+
className: "flex items-center justify-center p-12",
|
|
455
|
+
children: /* @__PURE__ */ y("div", { className: "animate-spin h-8 w-8 border-2 border-primary border-t-transparent rounded-full" })
|
|
456
|
+
}) : s ? /* @__PURE__ */ b("div", {
|
|
457
|
+
className: "p-6 text-destructive",
|
|
458
|
+
children: [
|
|
459
|
+
n("planmagnet.reports.errorLoading", "Reports could not be loaded"),
|
|
460
|
+
": ",
|
|
461
|
+
s.message
|
|
462
|
+
]
|
|
463
|
+
}) : /* @__PURE__ */ b("div", {
|
|
9
464
|
className: "space-y-6 p-6",
|
|
10
|
-
children: [/* @__PURE__ */
|
|
465
|
+
children: [/* @__PURE__ */ b("div", { children: [/* @__PURE__ */ b("h1", {
|
|
11
466
|
className: "text-2xl font-semibold flex items-center gap-2",
|
|
12
|
-
children: [/* @__PURE__ */
|
|
13
|
-
}), /* @__PURE__ */
|
|
467
|
+
children: [/* @__PURE__ */ y(f, { className: "h-6 w-6" }), n("planmagnet.reports.title", "Reports")]
|
|
468
|
+
}), /* @__PURE__ */ y("p", {
|
|
14
469
|
className: "text-sm text-muted-foreground",
|
|
15
|
-
children: "
|
|
16
|
-
})] }), /* @__PURE__ */
|
|
17
|
-
className: "
|
|
18
|
-
children:
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
470
|
+
children: n("planmagnet.reports.subtitle", "Delivery numbers computed on the server — velocity, cycle time, throughput and release readiness.")
|
|
471
|
+
})] }), c.length === 0 ? /* @__PURE__ */ y(C, { children: /* @__PURE__ */ y(w, {
|
|
472
|
+
className: "py-12 text-center text-sm text-muted-foreground",
|
|
473
|
+
children: n("planmagnet.reports.noProjects", "No projects in this workspace yet.")
|
|
474
|
+
}) }) : /* @__PURE__ */ b(M, {
|
|
475
|
+
defaultValue: "project",
|
|
476
|
+
children: [
|
|
477
|
+
/* @__PURE__ */ b("div", {
|
|
478
|
+
className: "flex flex-col sm:flex-row gap-3 items-start sm:items-center sm:justify-between",
|
|
479
|
+
children: [/* @__PURE__ */ b(P, { children: [/* @__PURE__ */ y(F, {
|
|
480
|
+
value: "project",
|
|
481
|
+
"data-testid": "reports-tab-project",
|
|
482
|
+
children: n("planmagnet.reports.tabs.project", "Project")
|
|
483
|
+
}), /* @__PURE__ */ y(F, {
|
|
484
|
+
value: "team",
|
|
485
|
+
"data-testid": "reports-tab-team",
|
|
486
|
+
children: n("planmagnet.reports.tabs.team", "Team")
|
|
487
|
+
})] }), /* @__PURE__ */ b(D, {
|
|
488
|
+
value: l,
|
|
489
|
+
onValueChange: i,
|
|
490
|
+
children: [/* @__PURE__ */ y(A, {
|
|
491
|
+
className: "h-8 w-56",
|
|
492
|
+
"data-testid": "reports-project-select",
|
|
493
|
+
children: /* @__PURE__ */ y(j, { placeholder: n("planmagnet.reports.pickProject", "Select project") })
|
|
494
|
+
}), /* @__PURE__ */ y(O, { children: c.map((e) => /* @__PURE__ */ y(k, {
|
|
495
|
+
value: e.id,
|
|
496
|
+
children: e.name
|
|
497
|
+
}, e.id)) })]
|
|
498
|
+
})]
|
|
499
|
+
}),
|
|
500
|
+
/* @__PURE__ */ b(N, {
|
|
501
|
+
value: "project",
|
|
502
|
+
className: "mt-4",
|
|
503
|
+
children: [l ? /* @__PURE__ */ y(q, {
|
|
504
|
+
workspaceId: t,
|
|
505
|
+
projectId: l
|
|
506
|
+
}) : /* @__PURE__ */ y("p", {
|
|
507
|
+
className: "text-sm text-muted-foreground py-8 text-center",
|
|
508
|
+
children: n("planmagnet.reports.pickProjectHint", "Select a project to see its report.")
|
|
509
|
+
}), u && /* @__PURE__ */ y("p", {
|
|
510
|
+
className: "sr-only",
|
|
511
|
+
"data-testid": "reports-current-project",
|
|
512
|
+
children: u
|
|
513
|
+
})]
|
|
514
|
+
}),
|
|
515
|
+
/* @__PURE__ */ y(N, {
|
|
516
|
+
value: "team",
|
|
517
|
+
className: "mt-4",
|
|
518
|
+
children: /* @__PURE__ */ y(J, { workspaceId: t })
|
|
519
|
+
})
|
|
520
|
+
]
|
|
43
521
|
})]
|
|
44
522
|
});
|
|
45
523
|
}
|
|
46
524
|
//#endregion
|
|
47
|
-
export {
|
|
525
|
+
export { Y as ReportsReportsPagePage };
|
|
48
526
|
|
|
49
527
|
//# sourceMappingURL=ReportsReportsPagePage.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ReportsReportsPagePage.js","names":[],"sources":["../../../src/planmagnet/pages/ReportsReportsPagePage.tsx"],"sourcesContent":["import { Card, CardContent, CardHeader, CardTitle, Button } from '@burdenoff/fe-libs/ui';\nimport { BarChart3, FileSpreadsheet, LineChart } from 'lucide-react';\nimport { usePlanMagnetNavigate } from '../providers/PlanMagnetProvider';\n\n/**\n * Reports (BOFF-7967). There is no saved-report model and no report runner yet, so there are no reports to list.\n * This page used to invent them — one \"Velocity Report\" per completed sprint, one \"Burndown\" per active sprint, one\n * \"Status Report\" per active project — with made-up schedules, \"Run Today\" counts for reports that never ran, and\n * the viewer named as their creator. It now says so, and points to where the same analysis lives, computed on the\n * server from real data.\n */\nexport function ReportsReportsPagePage() {\n const navigate = usePlanMagnetNavigate();\n const places = [\n {\n title: 'Analytics',\n body: 'Sprint burndown, velocity, cumulative flow, cycle time and delivery health for any project.',\n icon: LineChart,\n to: '/analytics/analytics-page',\n },\n {\n title: 'Task Board export',\n body: 'Download every work item that matches the board’s filters as CSV.',\n icon: FileSpreadsheet,\n to: '/tasks/tasks-page',\n },\n ];\n return (\n <div className=\"space-y-6 p-6\">\n <div>\n <h1 className=\"text-2xl font-semibold flex items-center gap-2\">\n <BarChart3 className=\"h-6 w-6\" />\n Reports\n </h1>\n <p className=\"text-sm text-muted-foreground\">\n Saved and scheduled reports are not available yet — there are none to show.\n </p>\n </div>\n <div className=\"grid gap-4 md:grid-cols-2\">\n {places.map((p) => (\n <Card key={p.title}>\n <CardHeader>\n <CardTitle className=\"flex items-center gap-2 text-base\">\n <p.icon className=\"h-5 w-5 text-primary\" />\n {p.title}\n </CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n <p className=\"text-sm text-muted-foreground\">{p.body}</p>\n <Button size=\"sm\" variant=\"outline\" onClick={() => navigate(p.to)}>\n Open {p.title}\n </Button>\n </CardContent>\n </Card>\n ))}\n </div>\n </div>\n );\n}\n"],"mappings":";;;;;AAWA,SAAgB,IAAyB;CACvC,IAAM,IAAW,GAAuB;AAexC,QACE,kBAAC,OAAD;EAAK,WAAU;YAAf,CACE,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,MAAD;GAAI,WAAU;aAAd,CACE,kBAAC,GAAD,EAAW,WAAU,WAAY,CAAA,EAAA,UAE9B;MACL,kBAAC,KAAD;GAAG,WAAU;aAAgC;GAEzC,CAAA,CACA,EAAA,CAAA,EACN,kBAAC,OAAD;GAAK,WAAU;aAzBJ,CACb;IACE,OAAO;IACP,MAAM;IACN,MAAM;IACN,IAAI;IACL,EACD;IACE,OAAO;IACP,MAAM;IACN,MAAM;IACN,IAAI;IACL,CACF,CAaa,KAAK,MACX,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD;IAAW,WAAU;cAArB,CACE,kBAAC,EAAE,MAAH,EAAQ,WAAU,wBAAyB,CAAA,EAC1C,EAAE,MACO;OACD,CAAA,EACb,kBAAC,GAAD;IAAa,WAAU;cAAvB,CACE,kBAAC,KAAD;KAAG,WAAU;eAAiC,EAAE;KAAS,CAAA,EACzD,kBAAC,GAAD;KAAQ,MAAK;KAAK,SAAQ;KAAU,eAAe,EAAS,EAAE,GAAG;eAAjE,CAAmE,SAC3D,EAAE,MACD;OACG;MACT,EAAA,EAbI,EAAE,MAaN,CACP;GACE,CAAA,CACF"}
|
|
1
|
+
{"version":3,"file":"ReportsReportsPagePage.js","names":[],"sources":["../../../src/planmagnet/pages/ReportsReportsPagePage.tsx"],"sourcesContent":["import { useState } from 'react';\nimport { gql } from '@apollo/client';\nimport { useQuery } from '@apollo/client/react';\nimport {\n Badge,\n Card,\n CardContent,\n CardHeader,\n CardTitle,\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n Tabs,\n TabsContent,\n TabsList,\n TabsTrigger,\n} from '@burdenoff/fe-libs/ui';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { BarChart3, ShieldCheck, TrendingUp, Users } from 'lucide-react';\nimport {\n Bar,\n BarChart,\n CartesianGrid,\n Legend,\n ReferenceLine,\n ResponsiveContainer,\n Tooltip,\n XAxis,\n YAxis,\n} from 'recharts';\nimport { usePlanMagnet } from '../providers/PlanMagnetProvider';\nimport { CycleTimeCard } from './analytics/DeliveryHealthCards';\n\n/**\n * Reports (BOFF-8048). Until this ticket, Reports had no saved-report model and no report runner, so the page said\n * so and pointed at Analytics instead (BOFF-7967). Every panel here is query-driven — it reads numbers the server\n * already computes (velocity, cycle time, throughput, release readiness) — with ZERO client-side row fabrication.\n * That property is the entire point: this page previously invented rows (\"Velocity Report\", \"Burndown\", …) with\n * made-up schedules and run counts, which is exactly what must never come back (see git history / BOFF-7967).\n *\n * `planmagnetThroughput` ships with the BOFF-8048 backend PR — until it deploys and the schema is re-pulled,\n * `bun run validate:schema` fails on the Throughput panel's query below (expected; not a regression in the other\n * three panels, which reuse queries that already exist and are already validated: planmagnetVelocity,\n * planmagnetCycleTime — via <CycleTimeCard>, planmagnetTeamVelocity and planmagnetReleaseReadiness).\n */\n\nconst GET_REPORTS_PROJECTS = gql`\n query GetReportsProjects($workspaceId: ID!) {\n planmagnetProjects(workspaceId: $workspaceId, pagination: { first: 100 }) {\n items {\n id\n name\n }\n }\n }\n`;\n\nconst GET_REPORTS_VELOCITY = gql`\n query GetReportsVelocity($workspaceId: ID!, $projectId: ID!, $trailingSprintCount: Int) {\n planmagnetVelocity(\n workspaceId: $workspaceId\n projectId: $projectId\n trailingSprintCount: $trailingSprintCount\n ) {\n projectId\n averageVelocity\n forecastNextSprintPoints\n sprints {\n sprintId\n sprintName\n sequenceNumber\n completedPoints\n completedCount\n plannedPoints\n }\n }\n }\n`;\n\n// New with BOFF-8048 — see the file-header note on schema-drift.\nconst GET_REPORTS_THROUGHPUT = gql`\n query GetReportsThroughput(\n $workspaceId: ID!\n $projectId: ID!\n $bucket: PlanmagnetThroughputBucket\n ) {\n planmagnetThroughput(workspaceId: $workspaceId, projectId: $projectId, bucket: $bucket) {\n projectId\n bucket\n startDate\n endDate\n points {\n periodStart\n completedCount\n completedPoints\n }\n }\n }\n`;\n\nconst GET_REPORTS_TEAMS = gql`\n query GetReportsTeams($workspaceId: ID!) {\n planmagnetTeams(workspaceId: $workspaceId, pagination: { first: 100 }) {\n items {\n id\n name\n }\n }\n }\n`;\n\nconst GET_REPORTS_TEAM_VELOCITY = gql`\n query GetReportsTeamVelocity($workspaceId: ID!, $teamId: ID!, $trailingSprintCount: Int) {\n planmagnetTeamVelocity(\n workspaceId: $workspaceId\n teamId: $teamId\n trailingSprintCount: $trailingSprintCount\n ) {\n teamId\n averageVelocity\n forecastNextSprintPoints\n sprints {\n sprintId\n sprintName\n sequenceNumber\n completedCount\n completedPoints\n plannedPoints\n byProject {\n projectId\n projectName\n count\n points\n }\n }\n }\n }\n`;\n\nconst GET_REPORTS_RELEASES = gql`\n query GetReportsReleases($workspaceId: ID!, $projectId: String) {\n planmagnetReleases(\n workspaceId: $workspaceId\n filter: { projectId: $projectId }\n pagination: { first: 50 }\n ) {\n items {\n id\n name\n status\n plannedDate\n }\n totalCount\n }\n }\n`;\n\nconst GET_RELEASE_READINESS = gql`\n query GetReportsReleaseReadiness($releaseId: ID!) {\n planmagnetReleaseReadiness(releaseId: $releaseId) {\n releaseId\n doneItems\n totalItems\n blockers {\n workItem {\n id\n key\n title\n }\n }\n }\n }\n`;\n\n// Non-terminal: still worth watching for readiness. RELEASED/ROLLED_BACK/CANCELLED are done stories, not upcoming.\nconst OPEN_RELEASE_STATUSES = new Set(['DRAFT', 'PLANNING', 'IN_PROGRESS', 'STAGING', 'READY']);\n\ninterface ProjectNode {\n id: string;\n name: string;\n}\n\ninterface VelocitySprintPoint {\n sprintId: string;\n sprintName: string;\n sequenceNumber: number;\n completedPoints: number;\n completedCount: number;\n plannedPoints: number | null;\n}\n\ninterface ReleaseNode {\n id: string;\n name: string;\n status: string;\n plannedDate: string | null;\n}\n\nfunction formatPeriod(iso: string): string {\n const d = new Date(iso);\n return `${d.getUTCMonth() + 1}/${d.getUTCDate()}`;\n}\n\n/** One release's readiness — its own query, independent of the others (§4.2.3: a handful of cards, no batching). */\nfunction ReleaseReadinessCard({ release }: { release: ReleaseNode }) {\n const { t } = useI18n();\n const { data, loading, error } = useQuery<{\n planmagnetReleaseReadiness: {\n releaseId: string;\n doneItems: number;\n totalItems: number;\n blockers: { workItem: { id: string; key: string; title: string } }[];\n };\n }>(GET_RELEASE_READINESS, { variables: { releaseId: release.id } });\n\n const readiness = data?.planmagnetReleaseReadiness;\n const percent =\n readiness && readiness.totalItems > 0\n ? Math.round((readiness.doneItems / readiness.totalItems) * 100)\n : null;\n const ready = readiness\n ? readiness.doneItems >= readiness.totalItems && readiness.blockers.length === 0\n : null;\n\n return (\n <Card data-testid={`release-readiness-${release.id}`}>\n <CardHeader>\n <CardTitle className=\"flex items-center justify-between text-sm\">\n <span>{release.name}</span>\n <Badge variant=\"outline\">{enumTitleCase(release.status)}</Badge>\n </CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-2\">\n {loading ? (\n <p className=\"text-sm text-muted-foreground\">\n {t('planmagnet.reports.loading', 'Loading…')}\n </p>\n ) : error ? (\n <p className=\"text-sm text-destructive\">\n {t('planmagnet.reports.readiness.error', 'Readiness could not be loaded')}\n </p>\n ) : !readiness ? null : (\n <>\n <p className=\"text-sm\">\n <span className=\"font-semibold\">{readiness.doneItems}</span> /{' '}\n <span className=\"text-muted-foreground\">{readiness.totalItems}</span>{' '}\n {t('planmagnet.reports.readiness.itemsDone', 'items done')}\n {percent !== null && <span className=\"text-muted-foreground\"> ({percent}%)</span>}\n </p>\n <Badge variant={ready ? 'success' : 'warning'}>\n {ready\n ? t('planmagnet.reports.readiness.ready', 'Ready')\n : t('planmagnet.reports.readiness.notReady', 'Not ready')}\n </Badge>\n {readiness.blockers.length > 0 && (\n <p className=\"text-xs text-muted-foreground\">\n {t('planmagnet.reports.readiness.blockers', '{{count}} blocker(s)', {\n count: readiness.blockers.length,\n })}\n </p>\n )}\n </>\n )}\n </CardContent>\n </Card>\n );\n}\n\nfunction enumTitleCase(value: string): string {\n const words = value.toLowerCase().replace(/_/g, ' ');\n return words.charAt(0).toUpperCase() + words.slice(1);\n}\n\nfunction ProjectReportsPanels({\n workspaceId,\n projectId,\n}: {\n workspaceId?: string | null;\n projectId: string;\n}) {\n const { t } = useI18n();\n\n const { data: velocityData, loading: velocityLoading } = useQuery<{\n planmagnetVelocity: {\n averageVelocity: number;\n forecastNextSprintPoints: number;\n sprints: VelocitySprintPoint[];\n };\n }>(GET_REPORTS_VELOCITY, {\n variables: { workspaceId, projectId, trailingSprintCount: 10 },\n skip: !workspaceId || !projectId,\n });\n\n const {\n data: throughputData,\n loading: throughputLoading,\n error: throughputError,\n } = useQuery<{\n planmagnetThroughput: {\n points: { periodStart: string; completedCount: number; completedPoints: number }[];\n };\n }>(GET_REPORTS_THROUGHPUT, {\n variables: { workspaceId, projectId, bucket: 'WEEK' },\n skip: !workspaceId || !projectId,\n });\n\n const { data: releasesData } = useQuery<{\n planmagnetReleases: { items: ReleaseNode[]; totalCount: number };\n }>(GET_REPORTS_RELEASES, {\n variables: { workspaceId, projectId },\n skip: !workspaceId || !projectId,\n });\n\n const velocity = velocityData?.planmagnetVelocity;\n const velocityChartData =\n velocity?.sprints.map((s) => ({\n name: s.sprintName,\n completed: s.completedPoints,\n planned: s.plannedPoints ?? undefined,\n })) ?? [];\n const avgVelocity = velocity ? Math.round(velocity.averageVelocity) : 0;\n\n const throughputChartData =\n throughputData?.planmagnetThroughput.points.map((p) => ({\n period: formatPeriod(p.periodStart),\n count: p.completedCount,\n points: p.completedPoints,\n })) ?? [];\n\n const upcomingReleases = (releasesData?.planmagnetReleases.items ?? []).filter((r) =>\n OPEN_RELEASE_STATUSES.has(r.status)\n );\n\n return (\n <div className=\"space-y-6\">\n <div className=\"grid grid-cols-1 lg:grid-cols-2 gap-6\">\n <Card>\n <CardHeader>\n <CardTitle className=\"flex items-center gap-2\">\n <TrendingUp className=\"h-4 w-4\" />\n {t('planmagnet.reports.velocity.title', 'Sprint Velocity')} (\n {velocityChartData.length} {t('planmagnet.reports.velocity.sprints', 'sprints')})\n </CardTitle>\n </CardHeader>\n <CardContent>\n {velocityLoading ? (\n <div className=\"flex justify-center py-12\">\n <div className=\"animate-spin h-6 w-6 border-2 border-primary border-t-transparent rounded-full\" />\n </div>\n ) : velocityChartData.length > 0 ? (\n // recharts' `fill`/`stroke` render as literal SVG paint attributes, not Tailwind classNames — they\n // cannot consume semantic bg-*/text-* tokens. Same accepted exception as\n // AnalyticsAnalyticsPagePage.tsx's CFD_STATUS_COLORS (lint warns, does not error, here and there).\n <ResponsiveContainer width=\"100%\" height={220}>\n <BarChart data={velocityChartData}>\n <CartesianGrid strokeDasharray=\"3 3\" opacity={0.2} />\n <XAxis dataKey=\"name\" tick={{ fontSize: 11 }} />\n <YAxis tick={{ fontSize: 11 }} allowDecimals={false} />\n <Tooltip />\n <Legend wrapperStyle={{ fontSize: 12 }} />\n <Bar\n dataKey=\"planned\"\n name={t('planmagnet.reports.velocity.planned', 'Planned')}\n fill=\"#cbd5e1\"\n />\n <Bar\n dataKey=\"completed\"\n name={t('planmagnet.reports.velocity.completed', 'Completed')}\n fill=\"#6366f1\"\n />\n <ReferenceLine y={avgVelocity} stroke=\"#22c55e\" strokeDasharray=\"4 4\" />\n </BarChart>\n </ResponsiveContainer>\n ) : (\n <p className=\"text-sm text-muted-foreground py-8 text-center\">\n {t(\n 'planmagnet.reports.velocity.empty',\n 'No completed sprints yet for this project'\n )}\n </p>\n )}\n </CardContent>\n </Card>\n\n <Card>\n <CardHeader>\n <CardTitle className=\"flex items-center gap-2\">\n <BarChart3 className=\"h-4 w-4\" />\n {t('planmagnet.reports.throughput.title', 'Throughput')}\n </CardTitle>\n <p className=\"text-xs text-muted-foreground\">\n {t(\n 'planmagnet.reports.throughput.subtitle',\n 'Work items completed per week, trailing 12 weeks.'\n )}\n </p>\n </CardHeader>\n <CardContent>\n {throughputLoading ? (\n <div className=\"flex justify-center py-12\">\n <div className=\"animate-spin h-6 w-6 border-2 border-primary border-t-transparent rounded-full\" />\n </div>\n ) : throughputError ? (\n <p className=\"text-sm text-muted-foreground py-8 text-center\">\n {t(\n 'planmagnet.reports.throughput.unavailable',\n 'Throughput is not available yet for this workspace.'\n )}\n </p>\n ) : throughputChartData.length > 0 ? (\n <ResponsiveContainer width=\"100%\" height={220}>\n <BarChart data={throughputChartData}>\n <CartesianGrid strokeDasharray=\"3 3\" opacity={0.2} />\n <XAxis dataKey=\"period\" tick={{ fontSize: 11 }} />\n <YAxis tick={{ fontSize: 11 }} allowDecimals={false} />\n <Tooltip />\n <Legend wrapperStyle={{ fontSize: 12 }} />\n <Bar\n dataKey=\"count\"\n name={t('planmagnet.reports.throughput.items', 'Items done')}\n fill=\"#0ea5e9\"\n />\n <Bar\n dataKey=\"points\"\n name={t('planmagnet.reports.throughput.points', 'Points done')}\n fill=\"#a855f7\"\n />\n </BarChart>\n </ResponsiveContainer>\n ) : (\n <p className=\"text-sm text-muted-foreground py-8 text-center\">\n {t('planmagnet.reports.throughput.empty', 'No work completed in this project yet')}\n </p>\n )}\n </CardContent>\n </Card>\n </div>\n\n <CycleTimeCard workspaceId={workspaceId} projectId={projectId} />\n\n <Card>\n <CardHeader>\n <CardTitle className=\"flex items-center gap-2\">\n <ShieldCheck className=\"h-4 w-4\" />\n {t('planmagnet.reports.readiness.title', 'Release readiness')}\n </CardTitle>\n <p className=\"text-xs text-muted-foreground\">\n {t(\n 'planmagnet.reports.readiness.subtitle',\n 'Open releases for this project, and what still blocks each.'\n )}\n </p>\n </CardHeader>\n <CardContent>\n {upcomingReleases.length === 0 ? (\n <p className=\"text-sm text-muted-foreground py-4 text-center\">\n {t('planmagnet.reports.readiness.empty', 'No open releases for this project')}\n </p>\n ) : (\n <div className=\"grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-3\">\n {upcomingReleases.map((release) => (\n <ReleaseReadinessCard key={release.id} release={release} />\n ))}\n </div>\n )}\n </CardContent>\n </Card>\n </div>\n );\n}\n\nfunction TeamReportsPanel({ workspaceId }: { workspaceId?: string | null }) {\n const { t } = useI18n();\n const [teamId, setTeamId] = useState('');\n\n const { data: teamsData } = useQuery<{\n planmagnetTeams: { items: { id: string; name: string }[] };\n }>(GET_REPORTS_TEAMS, { variables: { workspaceId }, skip: !workspaceId });\n const teams = teamsData?.planmagnetTeams.items ?? [];\n const effectiveTeamId = teamId || teams[0]?.id || '';\n\n const { data, loading } = useQuery<{\n planmagnetTeamVelocity: {\n averageVelocity: number;\n forecastNextSprintPoints: number;\n sprints: {\n sprintId: string;\n sprintName: string;\n completedPoints: number;\n plannedPoints: number | null;\n }[];\n };\n }>(GET_REPORTS_TEAM_VELOCITY, {\n variables: { workspaceId, teamId: effectiveTeamId, trailingSprintCount: 10 },\n skip: !workspaceId || !effectiveTeamId,\n });\n\n const velocity = data?.planmagnetTeamVelocity;\n const chartData =\n velocity?.sprints.map((s) => ({\n name: s.sprintName,\n completed: s.completedPoints,\n planned: s.plannedPoints ?? undefined,\n })) ?? [];\n\n if (teams.length === 0) {\n return (\n <p className=\"text-sm text-muted-foreground py-8 text-center\">\n {t(\n 'planmagnet.reports.team.empty',\n 'No teams in this workspace yet — create one under Teams.'\n )}\n </p>\n );\n }\n\n return (\n <div className=\"space-y-4\">\n <Select value={effectiveTeamId} onValueChange={setTeamId}>\n <SelectTrigger className=\"h-8 w-56\">\n <SelectValue placeholder={t('planmagnet.reports.team.pick', 'Select team')} />\n </SelectTrigger>\n <SelectContent>\n {teams.map((team) => (\n <SelectItem key={team.id} value={team.id}>\n {team.name}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n <Card>\n <CardHeader>\n <CardTitle className=\"flex items-center gap-2\">\n <Users className=\"h-4 w-4\" />\n {t('planmagnet.reports.team.velocityTitle', 'Team velocity')} ({chartData.length}{' '}\n {t('planmagnet.reports.velocity.sprints', 'sprints')})\n </CardTitle>\n <p className=\"text-xs text-muted-foreground\">\n {t(\n 'planmagnet.reports.team.velocitySubtitle',\n 'Whole-team completed points across the trailing 10 completed team sprints (BOFF-8044 per-project split, no double counting).'\n )}\n </p>\n </CardHeader>\n <CardContent>\n {loading ? (\n <div className=\"flex justify-center py-12\">\n <div className=\"animate-spin h-6 w-6 border-2 border-primary border-t-transparent rounded-full\" />\n </div>\n ) : chartData.length > 0 ? (\n <ResponsiveContainer width=\"100%\" height={220}>\n <BarChart data={chartData}>\n <CartesianGrid strokeDasharray=\"3 3\" opacity={0.2} />\n <XAxis dataKey=\"name\" tick={{ fontSize: 11 }} />\n <YAxis tick={{ fontSize: 11 }} allowDecimals={false} />\n <Tooltip />\n <Legend wrapperStyle={{ fontSize: 12 }} />\n <Bar\n dataKey=\"planned\"\n name={t('planmagnet.reports.velocity.planned', 'Planned')}\n fill=\"#cbd5e1\"\n />\n <Bar\n dataKey=\"completed\"\n name={t('planmagnet.reports.velocity.completed', 'Completed')}\n fill=\"#6366f1\"\n />\n </BarChart>\n </ResponsiveContainer>\n ) : (\n <p className=\"text-sm text-muted-foreground py-8 text-center\">\n {t('planmagnet.reports.team.velocityEmpty', 'No completed team sprints yet')}\n </p>\n )}\n </CardContent>\n </Card>\n </div>\n );\n}\n\nexport function ReportsReportsPagePage() {\n const { workspaceId } = usePlanMagnet();\n const { t } = useI18n();\n const [selectedProjectId, setSelectedProjectId] = useState('');\n\n const { data, loading, error } = useQuery<{ planmagnetProjects: { items: ProjectNode[] } }>(\n GET_REPORTS_PROJECTS,\n { variables: { workspaceId }, skip: !workspaceId }\n );\n\n const projects = data?.planmagnetProjects.items ?? [];\n const effectiveProjectId = selectedProjectId || projects[0]?.id || '';\n const effectiveProjectName = projects.find((p) => p.id === effectiveProjectId)?.name ?? '';\n\n // Only before the first load: a refetch must not blank the page.\n if (loading && !data) {\n return (\n <div className=\"flex items-center justify-center p-12\">\n <div className=\"animate-spin h-8 w-8 border-2 border-primary border-t-transparent rounded-full\" />\n </div>\n );\n }\n\n if (error) {\n return (\n <div className=\"p-6 text-destructive\">\n {t('planmagnet.reports.errorLoading', 'Reports could not be loaded')}: {error.message}\n </div>\n );\n }\n\n return (\n <div className=\"space-y-6 p-6\">\n <div>\n <h1 className=\"text-2xl font-semibold flex items-center gap-2\">\n <BarChart3 className=\"h-6 w-6\" />\n {t('planmagnet.reports.title', 'Reports')}\n </h1>\n <p className=\"text-sm text-muted-foreground\">\n {t(\n 'planmagnet.reports.subtitle',\n 'Delivery numbers computed on the server — velocity, cycle time, throughput and release readiness.'\n )}\n </p>\n </div>\n\n {projects.length === 0 ? (\n <Card>\n <CardContent className=\"py-12 text-center text-sm text-muted-foreground\">\n {t('planmagnet.reports.noProjects', 'No projects in this workspace yet.')}\n </CardContent>\n </Card>\n ) : (\n <Tabs defaultValue=\"project\">\n <div className=\"flex flex-col sm:flex-row gap-3 items-start sm:items-center sm:justify-between\">\n <TabsList>\n <TabsTrigger value=\"project\" data-testid=\"reports-tab-project\">\n {t('planmagnet.reports.tabs.project', 'Project')}\n </TabsTrigger>\n <TabsTrigger value=\"team\" data-testid=\"reports-tab-team\">\n {t('planmagnet.reports.tabs.team', 'Team')}\n </TabsTrigger>\n </TabsList>\n <Select value={effectiveProjectId} onValueChange={setSelectedProjectId}>\n <SelectTrigger className=\"h-8 w-56\" data-testid=\"reports-project-select\">\n <SelectValue placeholder={t('planmagnet.reports.pickProject', 'Select project')} />\n </SelectTrigger>\n <SelectContent>\n {projects.map((p) => (\n <SelectItem key={p.id} value={p.id}>\n {p.name}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n\n <TabsContent value=\"project\" className=\"mt-4\">\n {effectiveProjectId ? (\n <ProjectReportsPanels workspaceId={workspaceId} projectId={effectiveProjectId} />\n ) : (\n <p className=\"text-sm text-muted-foreground py-8 text-center\">\n {t('planmagnet.reports.pickProjectHint', 'Select a project to see its report.')}\n </p>\n )}\n {effectiveProjectName && (\n <p className=\"sr-only\" data-testid=\"reports-current-project\">\n {effectiveProjectName}\n </p>\n )}\n </TabsContent>\n <TabsContent value=\"team\" className=\"mt-4\">\n <TeamReportsPanel workspaceId={workspaceId} />\n </TabsContent>\n </Tabs>\n )}\n </div>\n );\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TasksMyWorkPagePage.d.ts","sourceRoot":"","sources":["../../../src/planmagnet/pages/TasksMyWorkPagePage.tsx"],"names":[],"mappings":"AA+HA,wBAAgB,mBAAmB,4CAuNlC"}
|