@burdenoff/microfe-planmagnet 2026.1001.5 → 2026.1001.6
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/controls/CompetitorControls.d.ts +71 -0
- package/dist/planmagnet/controls/CompetitorControls.d.ts.map +1 -1
- package/dist/planmagnet/controls/CompetitorControls.js +346 -12
- package/dist/planmagnet/controls/CompetitorControls.js.map +1 -1
- package/dist/planmagnet/controls/FeatureControls.d.ts +5 -0
- package/dist/planmagnet/controls/FeatureControls.d.ts.map +1 -1
- package/dist/planmagnet/controls/FeatureControls.js +363 -218
- package/dist/planmagnet/controls/FeatureControls.js.map +1 -1
- package/dist/planmagnet/controls/Pickers.d.ts +15 -0
- package/dist/planmagnet/controls/Pickers.d.ts.map +1 -1
- package/dist/planmagnet/controls/Pickers.js +61 -1
- package/dist/planmagnet/controls/Pickers.js.map +1 -1
- package/dist/planmagnet/controls/PrioritizationControls.d.ts +36 -0
- package/dist/planmagnet/controls/PrioritizationControls.d.ts.map +1 -1
- package/dist/planmagnet/controls/PrioritizationControls.js +118 -1
- package/dist/planmagnet/controls/PrioritizationControls.js.map +1 -1
- package/dist/planmagnet/dashboards/DashboardUI.js +1 -1
- package/dist/planmagnet/dashboards/cards/SprintCapacityCard.d.ts.map +1 -1
- package/dist/planmagnet/dashboards/cards/SprintCapacityCard.js +67 -59
- package/dist/planmagnet/dashboards/cards/SprintCapacityCard.js.map +1 -1
- package/dist/planmagnet/pages/AnalyticsAnalyticsPagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/AnalyticsAnalyticsPagePage.js +289 -282
- package/dist/planmagnet/pages/AnalyticsAnalyticsPagePage.js.map +1 -1
- package/dist/planmagnet/pages/CompetitorsCompetitorDetailPagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/CompetitorsCompetitorDetailPagePage.js +126 -63
- package/dist/planmagnet/pages/CompetitorsCompetitorDetailPagePage.js.map +1 -1
- package/dist/planmagnet/pages/CompetitorsCompetitorsPagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/CompetitorsCompetitorsPagePage.js +14 -0
- package/dist/planmagnet/pages/CompetitorsCompetitorsPagePage.js.map +1 -1
- package/dist/planmagnet/pages/CompetitorsCreateCompetitorPagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/CompetitorsCreateCompetitorPagePage.js +93 -57
- package/dist/planmagnet/pages/CompetitorsCreateCompetitorPagePage.js.map +1 -1
- package/dist/planmagnet/pages/CompetitorsEditCompetitorPagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/CompetitorsEditCompetitorPagePage.js +125 -83
- package/dist/planmagnet/pages/CompetitorsEditCompetitorPagePage.js.map +1 -1
- package/dist/planmagnet/pages/PortfoliosPortfolioDetailPagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/PortfoliosPortfolioDetailPagePage.js +226 -126
- package/dist/planmagnet/pages/PortfoliosPortfolioDetailPagePage.js.map +1 -1
- package/dist/planmagnet/pages/ProductsFeaturesPagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/ProductsFeaturesPagePage.js +162 -122
- package/dist/planmagnet/pages/ProductsFeaturesPagePage.js.map +1 -1
- package/dist/planmagnet/pages/ProductsNewFeaturePagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/ProductsNewFeaturePagePage.js +135 -109
- package/dist/planmagnet/pages/ProductsNewFeaturePagePage.js.map +1 -1
- package/dist/planmagnet/pages/ProjectsPlanningDetailPagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/ProjectsPlanningDetailPagePage.js +15 -3
- package/dist/planmagnet/pages/ProjectsPlanningDetailPagePage.js.map +1 -1
- package/dist/planmagnet/pages/TeamTeamPagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/TeamTeamPagePage.js +59 -53
- package/dist/planmagnet/pages/TeamTeamPagePage.js.map +1 -1
- package/dist/planmagnet/pages/analytics/MetricsCard.d.ts +8 -0
- package/dist/planmagnet/pages/analytics/MetricsCard.d.ts.map +1 -0
- package/dist/planmagnet/pages/analytics/MetricsCard.js +164 -0
- package/dist/planmagnet/pages/analytics/MetricsCard.js.map +1 -0
- package/dist/planmagnet/team/UnmatchedCrewIdentities.d.ts +2 -0
- package/dist/planmagnet/team/UnmatchedCrewIdentities.d.ts.map +1 -0
- package/dist/planmagnet/team/UnmatchedCrewIdentities.js +155 -0
- package/dist/planmagnet/team/UnmatchedCrewIdentities.js.map +1 -0
- package/package.json +1 -1
|
@@ -18,20 +18,21 @@ import { DeliveryForecastCard as le } from "../forecast/DeliveryForecastCard.js"
|
|
|
18
18
|
import { BudgetPerformanceCard as ue, CycleTimeCard as de } from "./analytics/DeliveryHealthCards.js";
|
|
19
19
|
import { QualityMetricsCard as fe } from "./analytics/QualityMetricsCard.js";
|
|
20
20
|
import { DeliveryKpisCard as pe } from "./analytics/DeliveryKpisCard.js";
|
|
21
|
-
import {
|
|
22
|
-
import {
|
|
23
|
-
import {
|
|
24
|
-
import {
|
|
21
|
+
import { MetricsSection as me } from "./analytics/MetricsCard.js";
|
|
22
|
+
import { ThroughputCard as he } from "./analytics/ThroughputCard.js";
|
|
23
|
+
import { StatusFlowCard as ge } from "./analytics/StatusFlowCard.js";
|
|
24
|
+
import { WorkBreakdownCard as _e } from "./analytics/WorkBreakdownCard.js";
|
|
25
|
+
import { activePreset as ve, isValidRange as l, presetRange as ye, scopeToProjectId as be, toRangeVariables as xe } from "./analytics/analyticsRange.js";
|
|
25
26
|
import { useState as u } from "react";
|
|
26
|
-
import { BarChart3 as
|
|
27
|
+
import { BarChart3 as Se, FolderKanban as Ce, Target as we, TrendingUp as d, Zap as Te } from "lucide-react";
|
|
27
28
|
import { useSearchParams as Ee } from "react-router";
|
|
28
|
-
import { gql as
|
|
29
|
-
import { useQuery as
|
|
30
|
-
import { Fragment as De, jsx as
|
|
29
|
+
import { gql as f } from "@apollo/client";
|
|
30
|
+
import { useQuery as p } from "@apollo/client/react";
|
|
31
|
+
import { Fragment as De, jsx as m, jsxs as h } from "react/jsx-runtime";
|
|
31
32
|
import { useI18n as Oe } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
|
|
32
|
-
import { Badge as ke, Card as
|
|
33
|
+
import { Badge as ke, Card as g, CardContent as _, CardHeader as v, CardTitle as y, Input as b, Select as x, SelectContent as S, SelectItem as C, SelectTrigger as Ae, SelectValue as je } from "@burdenoff/fe-libs/ui";
|
|
33
34
|
//#region src/planmagnet/pages/AnalyticsAnalyticsPagePage.tsx
|
|
34
|
-
var
|
|
35
|
+
var Me = f`
|
|
35
36
|
query AnalyticsProjectSprints($workspaceId: ID!, $projectId: String) {
|
|
36
37
|
planmagnetSprints(
|
|
37
38
|
workspaceId: $workspaceId
|
|
@@ -47,7 +48,7 @@ var Ae = d`
|
|
|
47
48
|
}
|
|
48
49
|
}
|
|
49
50
|
}
|
|
50
|
-
`,
|
|
51
|
+
`, Ne = f`
|
|
51
52
|
query AnalyticsMilestoneRisk($workspaceId: ID!, $yesterday: DateTime) {
|
|
52
53
|
missed: planmagnetMilestones(
|
|
53
54
|
workspaceId: $workspaceId
|
|
@@ -64,7 +65,7 @@ var Ae = d`
|
|
|
64
65
|
totalCount
|
|
65
66
|
}
|
|
66
67
|
}
|
|
67
|
-
`,
|
|
68
|
+
`, Pe = f`
|
|
68
69
|
query GetAnalyticsWorkItemCounts($workspaceId: ID!) {
|
|
69
70
|
planmagnetWorkItemCounts(workspaceId: $workspaceId) {
|
|
70
71
|
total
|
|
@@ -82,7 +83,7 @@ var Ae = d`
|
|
|
82
83
|
}
|
|
83
84
|
}
|
|
84
85
|
}
|
|
85
|
-
`,
|
|
86
|
+
`, Fe = f`
|
|
86
87
|
query GetAnalyticsData($workspaceId: ID!, $projectPagination: PlanmagnetPaginationInput) {
|
|
87
88
|
planmagnetProjects(workspaceId: $workspaceId, pagination: $projectPagination) {
|
|
88
89
|
items {
|
|
@@ -97,7 +98,7 @@ var Ae = d`
|
|
|
97
98
|
totalCount
|
|
98
99
|
}
|
|
99
100
|
}
|
|
100
|
-
`,
|
|
101
|
+
`, Ie = f`
|
|
101
102
|
query GetSprintBurndown($workspaceId: ID!, $sprintId: ID!) {
|
|
102
103
|
planmagnetSprintBurndown(workspaceId: $workspaceId, sprintId: $sprintId) {
|
|
103
104
|
sprintId
|
|
@@ -114,7 +115,7 @@ var Ae = d`
|
|
|
114
115
|
}
|
|
115
116
|
}
|
|
116
117
|
}
|
|
117
|
-
`,
|
|
118
|
+
`, Le = f`
|
|
118
119
|
query GetVelocity($workspaceId: ID!, $projectId: ID!, $trailingSprintCount: Int) {
|
|
119
120
|
planmagnetVelocity(
|
|
120
121
|
workspaceId: $workspaceId
|
|
@@ -139,7 +140,7 @@ var Ae = d`
|
|
|
139
140
|
}
|
|
140
141
|
}
|
|
141
142
|
}
|
|
142
|
-
`,
|
|
143
|
+
`, Re = f`
|
|
143
144
|
query GetCumulativeFlow(
|
|
144
145
|
$workspaceId: ID!
|
|
145
146
|
$projectId: ID!
|
|
@@ -164,7 +165,7 @@ var Ae = d`
|
|
|
164
165
|
}
|
|
165
166
|
}
|
|
166
167
|
}
|
|
167
|
-
`,
|
|
168
|
+
`, w = {
|
|
168
169
|
BACKLOG: "#9ca3af",
|
|
169
170
|
TODO: "#60a5fa",
|
|
170
171
|
IN_PROGRESS: "#fbbf24",
|
|
@@ -173,436 +174,436 @@ var Ae = d`
|
|
|
173
174
|
DONE: "#4ade80",
|
|
174
175
|
CANCELLED: "#f87171"
|
|
175
176
|
};
|
|
176
|
-
function
|
|
177
|
+
function T(e) {
|
|
177
178
|
let t = new Date(e);
|
|
178
179
|
return `${t.getUTCMonth() + 1}/${t.getUTCDate()}`;
|
|
179
180
|
}
|
|
180
|
-
function
|
|
181
|
-
let { workspaceId:
|
|
182
|
-
from:
|
|
183
|
-
to:
|
|
184
|
-
} :
|
|
185
|
-
function
|
|
186
|
-
|
|
187
|
-
let n = new URLSearchParams(
|
|
188
|
-
n.set("from", e.from), n.set("to", e.to), t === "all" ? n.delete("project") : n.set("project", t),
|
|
181
|
+
function E() {
|
|
182
|
+
let { workspaceId: f } = e(), { t: E } = Oe(), [ze, D] = u(""), [O, Be] = Ee(), k = O.get("from"), A = O.get("to"), [j, M] = u(() => k && A && l(k, A) ? {
|
|
183
|
+
from: k,
|
|
184
|
+
to: A
|
|
185
|
+
} : ye("30")), [Ve, He] = u(j), [N, Ue] = u(O.get("project") || "all"), P = be(N), F = ve(j), I = l(j.from, j.to), We = I ? null : E("planmagnet.analytics.range.invalid", "\"From\" must be on or before \"To\".");
|
|
186
|
+
function L(e, t) {
|
|
187
|
+
M(e), l(e.from, e.to) && He(e);
|
|
188
|
+
let n = new URLSearchParams(O);
|
|
189
|
+
n.set("from", e.from), n.set("to", e.to), t === "all" ? n.delete("project") : n.set("project", t), Be(n, { replace: !0 });
|
|
189
190
|
}
|
|
190
191
|
function Ge(e) {
|
|
191
|
-
|
|
192
|
+
L(ye(e), N);
|
|
192
193
|
}
|
|
193
194
|
function Ke(e) {
|
|
194
|
-
e &&
|
|
195
|
+
e && j.to && l(e, j.to) ? L({
|
|
195
196
|
from: e,
|
|
196
|
-
to:
|
|
197
|
-
},
|
|
197
|
+
to: j.to
|
|
198
|
+
}, N) : M((t) => ({
|
|
198
199
|
...t,
|
|
199
200
|
from: e
|
|
200
201
|
}));
|
|
201
202
|
}
|
|
202
203
|
function qe(e) {
|
|
203
|
-
e &&
|
|
204
|
-
from:
|
|
204
|
+
e && j.from && l(j.from, e) ? L({
|
|
205
|
+
from: j.from,
|
|
205
206
|
to: e
|
|
206
|
-
},
|
|
207
|
+
}, N) : M((t) => ({
|
|
207
208
|
...t,
|
|
208
209
|
to: e
|
|
209
210
|
}));
|
|
210
211
|
}
|
|
211
212
|
function Je(e) {
|
|
212
|
-
|
|
213
|
+
Ue(e), D(""), L(j, e);
|
|
213
214
|
}
|
|
214
|
-
let { startDate:
|
|
215
|
+
let { startDate: R, endDate: z } = xe(I ? j : Ve), { data: Ye, loading: Xe, error: Ze } = p(Fe, {
|
|
215
216
|
variables: {
|
|
216
|
-
workspaceId:
|
|
217
|
+
workspaceId: f,
|
|
217
218
|
projectPagination: { first: 100 }
|
|
218
219
|
},
|
|
219
|
-
skip: !
|
|
220
|
-
}), { data: Qe } =
|
|
221
|
-
variables: { workspaceId:
|
|
222
|
-
skip: !
|
|
223
|
-
}),
|
|
220
|
+
skip: !f
|
|
221
|
+
}), { data: Qe } = p(Pe, {
|
|
222
|
+
variables: { workspaceId: f },
|
|
223
|
+
skip: !f
|
|
224
|
+
}), B = Qe?.planmagnetWorkItemCounts, $e = se(), et = ce(), [tt] = u(() => (/* @__PURE__ */ new Date(Date.now() - 864e5)).toISOString().slice(0, 10)), { data: V } = p(Ne, {
|
|
224
225
|
variables: {
|
|
225
|
-
workspaceId:
|
|
226
|
+
workspaceId: f,
|
|
226
227
|
yesterday: tt
|
|
227
228
|
},
|
|
228
|
-
skip: !
|
|
229
|
-
}),
|
|
229
|
+
skip: !f
|
|
230
|
+
}), H = Ye?.planmagnetProjects?.items ?? [], U = P || H[0]?.id || "", { data: nt } = p(Me, {
|
|
230
231
|
variables: {
|
|
231
|
-
workspaceId:
|
|
232
|
-
projectId:
|
|
232
|
+
workspaceId: f,
|
|
233
|
+
projectId: U
|
|
233
234
|
},
|
|
234
|
-
skip: !
|
|
235
|
-
}),
|
|
235
|
+
skip: !f || !U
|
|
236
|
+
}), W = nt?.planmagnetSprints.items ?? [], rt = W.filter((e) => e.status === "COMPLETED").sort((e, t) => (t.completedAt ?? t.endDate ?? "").localeCompare(e.completedAt ?? e.endDate ?? ""))[0], it = W.find((e) => e.status === "ACTIVE" || e.status === "REVIEW") ?? rt ?? W[0], G = ze || it?.id || "", K = H.find((e) => e.id === U)?.name ?? "", { data: at, loading: ot } = p(Ie, {
|
|
236
237
|
variables: {
|
|
237
|
-
workspaceId:
|
|
238
|
-
sprintId:
|
|
238
|
+
workspaceId: f,
|
|
239
|
+
sprintId: G
|
|
239
240
|
},
|
|
240
|
-
skip: !
|
|
241
|
-
}), { data: st, loading: ct } =
|
|
241
|
+
skip: !f || !G
|
|
242
|
+
}), { data: st, loading: ct } = p(Le, {
|
|
242
243
|
variables: {
|
|
243
|
-
workspaceId:
|
|
244
|
-
projectId:
|
|
244
|
+
workspaceId: f,
|
|
245
|
+
projectId: U,
|
|
245
246
|
trailingSprintCount: 6
|
|
246
247
|
},
|
|
247
|
-
skip: !
|
|
248
|
-
}), { data: lt, loading: ut } =
|
|
248
|
+
skip: !f || !U
|
|
249
|
+
}), { data: lt, loading: ut } = p(Re, {
|
|
249
250
|
variables: {
|
|
250
|
-
workspaceId:
|
|
251
|
-
projectId:
|
|
252
|
-
startDate:
|
|
253
|
-
endDate:
|
|
251
|
+
workspaceId: f,
|
|
252
|
+
projectId: U,
|
|
253
|
+
startDate: R,
|
|
254
|
+
endDate: z
|
|
254
255
|
},
|
|
255
|
-
skip: !
|
|
256
|
+
skip: !f || !U
|
|
256
257
|
});
|
|
257
|
-
if (Xe && !Ye) return /* @__PURE__ */
|
|
258
|
+
if (Xe && !Ye) return /* @__PURE__ */ m("div", {
|
|
258
259
|
className: "flex items-center justify-center p-12",
|
|
259
|
-
children: /* @__PURE__ */
|
|
260
|
+
children: /* @__PURE__ */ m("div", { className: "animate-spin h-8 w-8 border-2 border-primary border-t-transparent rounded-full" })
|
|
260
261
|
});
|
|
261
|
-
if (Ze) return /* @__PURE__ */
|
|
262
|
+
if (Ze) return /* @__PURE__ */ h("div", {
|
|
262
263
|
className: "p-6 text-red-500",
|
|
263
264
|
children: [
|
|
264
|
-
|
|
265
|
+
E("planmagnet.analytics.errorLoading", "Error loading analytics"),
|
|
265
266
|
": ",
|
|
266
267
|
Ze.message
|
|
267
268
|
]
|
|
268
269
|
});
|
|
269
|
-
let
|
|
270
|
-
let t =
|
|
270
|
+
let q = (e) => B?.byStatus.find((t) => t.status === e), dt = q("CANCELLED")?.count ?? 0, J = B ? q("DONE")?.count ?? 0 : null, Y = B ? B.total : null, X = B ? B.blocked : null, ft = B ? B.points : null, pt = B ? q("DONE")?.points ?? 0 : null, mt = (e) => {
|
|
271
|
+
let t = B?.byProject.filter((t) => t.projectId === e) ?? [], n = t.filter((e) => e.status !== "CANCELLED").reduce((e, t) => e + t.count, 0), r = t.filter((e) => e.status === "DONE").reduce((e, t) => e + t.count, 0);
|
|
271
272
|
return n > 0 ? Math.round(r / n * 100) : 0;
|
|
272
|
-
}, ht = et?.running ?? null, gt =
|
|
273
|
-
day:
|
|
273
|
+
}, ht = et?.running ?? null, gt = V ? V.missed.totalCount + V.overdue.totalCount : null, _t = $e?.active ?? null, vt = Y != null && J != null && Y - dt > 0 ? Math.round(J / (Y - dt) * 100) : null, yt = (at?.planmagnetSprintBurndown)?.points.map((e) => ({
|
|
274
|
+
day: T(e.date),
|
|
274
275
|
remaining: e.remainingPoints,
|
|
275
276
|
completed: e.completedPoints
|
|
276
|
-
})) ?? [],
|
|
277
|
+
})) ?? [], Z = st?.planmagnetVelocity, Q = Z?.sprints.map((e) => ({
|
|
277
278
|
name: e.sprintName,
|
|
278
279
|
completed: e.completedPoints,
|
|
279
280
|
planned: e.plannedPoints ?? void 0
|
|
280
|
-
})) ?? [], bt =
|
|
281
|
-
let t = { day:
|
|
281
|
+
})) ?? [], bt = Z ? Math.round(Z.averageVelocity) : 0, xt = Z ? Math.round(Z.forecastNextSprintPoints) : 0, $ = Z?.forecastRange ?? null, St = Z?.insufficientHistory ?? !1, Ct = lt?.planmagnetCumulativeFlow, wt = Array.from(new Set(Ct?.points.flatMap((e) => e.statuses.map((e) => e.status)) ?? [])), Tt = Ct?.points.map((e) => {
|
|
282
|
+
let t = { day: T(e.date) };
|
|
282
283
|
for (let n of e.statuses) t[n.status] = n.count;
|
|
283
284
|
return t;
|
|
284
|
-
}) ?? [],
|
|
285
|
+
}) ?? [], Et = [
|
|
285
286
|
{
|
|
286
|
-
label:
|
|
287
|
-
value: c(
|
|
288
|
-
trend: `${c(vt)}% ${
|
|
287
|
+
label: E("planmagnet.analytics.metrics.totalWorkItems.label", "Total Work Items"),
|
|
288
|
+
value: c(Y),
|
|
289
|
+
trend: `${c(vt)}% ${E("planmagnet.analytics.metrics.totalWorkItems.trend", "completed")}`
|
|
289
290
|
},
|
|
290
291
|
{
|
|
291
|
-
label:
|
|
292
|
+
label: E("planmagnet.analytics.metrics.storyPoints.label", "Story Points"),
|
|
292
293
|
value: c(ft),
|
|
293
|
-
trend: `${c(pt)} ${
|
|
294
|
+
trend: `${c(pt)} ${E("planmagnet.analytics.metrics.storyPoints.trend", "completed")}`
|
|
294
295
|
},
|
|
295
296
|
{
|
|
296
|
-
label:
|
|
297
|
+
label: E("planmagnet.analytics.metrics.activeProjects.label", "Active Projects"),
|
|
297
298
|
value: c(_t),
|
|
298
|
-
trend: `${c($e?.all)} ${
|
|
299
|
+
trend: `${c($e?.all)} ${E("planmagnet.analytics.metrics.activeProjects.trend", "total")}`
|
|
299
300
|
},
|
|
300
301
|
{
|
|
301
|
-
label:
|
|
302
|
-
value: c(
|
|
303
|
-
trend:
|
|
302
|
+
label: E("planmagnet.analytics.metrics.blockedItems.label", "Blocked Items"),
|
|
303
|
+
value: c(X),
|
|
304
|
+
trend: X == null ? "" : X > 0 ? E("planmagnet.analytics.metrics.blockedItems.attention", "Needs attention") : E("planmagnet.analytics.metrics.blockedItems.clear", "All clear")
|
|
304
305
|
}
|
|
305
306
|
];
|
|
306
|
-
return /* @__PURE__ */
|
|
307
|
+
return /* @__PURE__ */ h("div", {
|
|
307
308
|
className: "space-y-6 p-6",
|
|
308
309
|
children: [
|
|
309
|
-
/* @__PURE__ */
|
|
310
|
+
/* @__PURE__ */ h("div", { children: [/* @__PURE__ */ m("h1", {
|
|
310
311
|
className: "text-2xl font-semibold",
|
|
311
|
-
children:
|
|
312
|
-
}), /* @__PURE__ */
|
|
312
|
+
children: E("planmagnet.analytics.title", "Analytics Dashboard")
|
|
313
|
+
}), /* @__PURE__ */ m("p", {
|
|
313
314
|
className: "text-sm text-muted-foreground",
|
|
314
|
-
children:
|
|
315
|
+
children: E("planmagnet.analytics.subtitle", "Overview of project health and team performance")
|
|
315
316
|
})] }),
|
|
316
|
-
/* @__PURE__ */
|
|
317
|
+
/* @__PURE__ */ h("div", {
|
|
317
318
|
className: "flex flex-col gap-3 rounded-lg border p-3 sm:flex-row sm:flex-wrap sm:items-center sm:justify-between",
|
|
318
319
|
"data-testid": "analytics-range",
|
|
319
|
-
children: [/* @__PURE__ */
|
|
320
|
+
children: [/* @__PURE__ */ h("div", {
|
|
320
321
|
className: "flex flex-wrap items-center gap-2",
|
|
321
322
|
children: [
|
|
322
|
-
/* @__PURE__ */
|
|
323
|
+
/* @__PURE__ */ m("div", {
|
|
323
324
|
className: "flex items-center gap-1 rounded-md border p-0.5",
|
|
324
325
|
role: "group",
|
|
325
|
-
"aria-label":
|
|
326
|
+
"aria-label": E("planmagnet.analytics.range.presetLabel", "Date range preset"),
|
|
326
327
|
"data-testid": "analytics-range-preset",
|
|
327
328
|
children: [
|
|
328
329
|
"7",
|
|
329
330
|
"30",
|
|
330
331
|
"90"
|
|
331
|
-
].map((e) => /* @__PURE__ */
|
|
332
|
+
].map((e) => /* @__PURE__ */ m("button", {
|
|
332
333
|
type: "button",
|
|
333
|
-
"aria-pressed":
|
|
334
|
+
"aria-pressed": F === e,
|
|
334
335
|
onClick: () => Ge(e),
|
|
335
|
-
className: `px-2.5 py-1 text-xs rounded ${
|
|
336
|
-
children:
|
|
336
|
+
className: `px-2.5 py-1 text-xs rounded ${F === e ? "bg-primary text-primary-foreground" : "text-muted-foreground hover:bg-muted"}`,
|
|
337
|
+
children: E("planmagnet.analytics.range.last", "Last {{days}} days", { days: e })
|
|
337
338
|
}, e))
|
|
338
339
|
}),
|
|
339
|
-
/* @__PURE__ */
|
|
340
|
+
/* @__PURE__ */ h("div", {
|
|
340
341
|
className: "flex items-center gap-1.5",
|
|
341
342
|
children: [
|
|
342
|
-
/* @__PURE__ */
|
|
343
|
+
/* @__PURE__ */ m("label", {
|
|
343
344
|
htmlFor: "analytics-range-from",
|
|
344
345
|
className: "sr-only",
|
|
345
|
-
children:
|
|
346
|
+
children: E("planmagnet.analytics.range.from", "From")
|
|
346
347
|
}),
|
|
347
|
-
/* @__PURE__ */
|
|
348
|
+
/* @__PURE__ */ m(b, {
|
|
348
349
|
id: "analytics-range-from",
|
|
349
350
|
type: "date",
|
|
350
351
|
className: "h-8 w-36",
|
|
351
|
-
value:
|
|
352
|
-
max:
|
|
352
|
+
value: j.from,
|
|
353
|
+
max: j.to,
|
|
353
354
|
onChange: (e) => Ke(e.target.value)
|
|
354
355
|
}),
|
|
355
|
-
/* @__PURE__ */
|
|
356
|
+
/* @__PURE__ */ m("span", {
|
|
356
357
|
className: "text-muted-foreground text-sm",
|
|
357
358
|
children: "–"
|
|
358
359
|
}),
|
|
359
|
-
/* @__PURE__ */
|
|
360
|
+
/* @__PURE__ */ m("label", {
|
|
360
361
|
htmlFor: "analytics-range-to",
|
|
361
362
|
className: "sr-only",
|
|
362
|
-
children:
|
|
363
|
+
children: E("planmagnet.analytics.range.to", "To")
|
|
363
364
|
}),
|
|
364
|
-
/* @__PURE__ */
|
|
365
|
+
/* @__PURE__ */ m(b, {
|
|
365
366
|
id: "analytics-range-to",
|
|
366
367
|
type: "date",
|
|
367
368
|
className: "h-8 w-36",
|
|
368
|
-
value:
|
|
369
|
-
min:
|
|
369
|
+
value: j.to,
|
|
370
|
+
min: j.from,
|
|
370
371
|
onChange: (e) => qe(e.target.value)
|
|
371
372
|
})
|
|
372
373
|
]
|
|
373
374
|
}),
|
|
374
|
-
We && /* @__PURE__ */
|
|
375
|
+
We && /* @__PURE__ */ m("p", {
|
|
375
376
|
role: "alert",
|
|
376
377
|
className: "text-xs text-status-error-text",
|
|
377
378
|
children: We
|
|
378
379
|
})
|
|
379
380
|
]
|
|
380
|
-
}), /* @__PURE__ */
|
|
381
|
-
value:
|
|
381
|
+
}), /* @__PURE__ */ h(x, {
|
|
382
|
+
value: N,
|
|
382
383
|
onValueChange: Je,
|
|
383
|
-
children: [/* @__PURE__ */
|
|
384
|
+
children: [/* @__PURE__ */ m(Ae, {
|
|
384
385
|
className: "h-8 w-56",
|
|
385
386
|
"data-testid": "analytics-project",
|
|
386
|
-
children: /* @__PURE__ */
|
|
387
|
-
}), /* @__PURE__ */
|
|
387
|
+
children: /* @__PURE__ */ m(je, { placeholder: E("planmagnet.analytics.range.allProjects", "All projects") })
|
|
388
|
+
}), /* @__PURE__ */ h(S, { children: [/* @__PURE__ */ m(C, {
|
|
388
389
|
value: "all",
|
|
389
|
-
children:
|
|
390
|
-
}),
|
|
390
|
+
children: E("planmagnet.analytics.range.allProjects", "All projects")
|
|
391
|
+
}), H.map((e) => /* @__PURE__ */ m(C, {
|
|
391
392
|
value: e.id,
|
|
392
393
|
children: e.name
|
|
393
394
|
}, e.id))] })]
|
|
394
395
|
})]
|
|
395
396
|
}),
|
|
396
|
-
/* @__PURE__ */
|
|
397
|
+
/* @__PURE__ */ m("div", {
|
|
397
398
|
className: "grid grid-cols-2 md:grid-cols-4 gap-4",
|
|
398
|
-
children:
|
|
399
|
+
children: Et.map((e) => /* @__PURE__ */ m(g, { children: /* @__PURE__ */ h(_, {
|
|
399
400
|
className: "pt-4",
|
|
400
401
|
children: [
|
|
401
|
-
/* @__PURE__ */
|
|
402
|
+
/* @__PURE__ */ m("p", {
|
|
402
403
|
className: "text-xs text-muted-foreground",
|
|
403
404
|
children: e.label
|
|
404
405
|
}),
|
|
405
|
-
/* @__PURE__ */
|
|
406
|
+
/* @__PURE__ */ m("p", {
|
|
406
407
|
className: "text-xl font-bold mt-1",
|
|
407
408
|
children: e.value
|
|
408
409
|
}),
|
|
409
|
-
/* @__PURE__ */
|
|
410
|
+
/* @__PURE__ */ m("p", {
|
|
410
411
|
className: "text-xs text-green-600 mt-1",
|
|
411
412
|
children: e.trend
|
|
412
413
|
})
|
|
413
414
|
]
|
|
414
415
|
}) }, e.label))
|
|
415
416
|
}),
|
|
416
|
-
/* @__PURE__ */
|
|
417
|
+
/* @__PURE__ */ h("div", {
|
|
417
418
|
className: "grid grid-cols-2 md:grid-cols-4 gap-4",
|
|
418
419
|
children: [
|
|
419
|
-
/* @__PURE__ */
|
|
420
|
+
/* @__PURE__ */ m(g, { children: /* @__PURE__ */ h(_, {
|
|
420
421
|
className: "pt-4",
|
|
421
|
-
children: [/* @__PURE__ */
|
|
422
|
+
children: [/* @__PURE__ */ h("div", {
|
|
422
423
|
className: "flex items-center gap-2 text-muted-foreground text-xs",
|
|
423
|
-
children: [/* @__PURE__ */
|
|
424
|
-
}), /* @__PURE__ */
|
|
424
|
+
children: [/* @__PURE__ */ m(Ce, { className: "h-4 w-4" }), E("planmagnet.analytics.summary.activeProjects", "Active Projects")]
|
|
425
|
+
}), /* @__PURE__ */ m("p", {
|
|
425
426
|
className: "text-xl font-bold mt-1",
|
|
426
427
|
children: c(_t)
|
|
427
428
|
})]
|
|
428
429
|
}) }),
|
|
429
|
-
/* @__PURE__ */
|
|
430
|
+
/* @__PURE__ */ m(g, { children: /* @__PURE__ */ h(_, {
|
|
430
431
|
className: "pt-4",
|
|
431
|
-
children: [/* @__PURE__ */
|
|
432
|
+
children: [/* @__PURE__ */ h("div", {
|
|
432
433
|
className: "flex items-center gap-2 text-muted-foreground text-xs",
|
|
433
|
-
children: [/* @__PURE__ */
|
|
434
|
-
}), /* @__PURE__ */
|
|
434
|
+
children: [/* @__PURE__ */ m(Te, { className: "h-4 w-4" }), E("planmagnet.analytics.summary.activeSprints", "Active Sprints")]
|
|
435
|
+
}), /* @__PURE__ */ m("p", {
|
|
435
436
|
className: "text-xl font-bold mt-1",
|
|
436
437
|
children: c(ht)
|
|
437
438
|
})]
|
|
438
439
|
}) }),
|
|
439
|
-
/* @__PURE__ */
|
|
440
|
+
/* @__PURE__ */ m(g, { children: /* @__PURE__ */ h(_, {
|
|
440
441
|
className: "pt-4",
|
|
441
442
|
children: [
|
|
442
|
-
/* @__PURE__ */
|
|
443
|
+
/* @__PURE__ */ h("div", {
|
|
443
444
|
className: "flex items-center gap-2 text-muted-foreground text-xs",
|
|
444
|
-
children: [/* @__PURE__ */
|
|
445
|
+
children: [/* @__PURE__ */ m(d, { className: "h-4 w-4" }), E("planmagnet.analytics.summary.avgVelocity", "Avg Velocity")]
|
|
445
446
|
}),
|
|
446
|
-
/* @__PURE__ */
|
|
447
|
+
/* @__PURE__ */ m("p", {
|
|
447
448
|
className: "text-xs text-muted-foreground truncate",
|
|
448
|
-
children:
|
|
449
|
+
children: K || "—"
|
|
449
450
|
}),
|
|
450
|
-
/* @__PURE__ */
|
|
451
|
+
/* @__PURE__ */ h("p", {
|
|
451
452
|
className: "text-xl font-bold mt-1",
|
|
452
453
|
children: [
|
|
453
454
|
bt,
|
|
454
455
|
" ",
|
|
455
|
-
|
|
456
|
+
E("planmagnet.analytics.summary.pointsShort", "pts")
|
|
456
457
|
]
|
|
457
458
|
})
|
|
458
459
|
]
|
|
459
460
|
}) }),
|
|
460
|
-
/* @__PURE__ */
|
|
461
|
+
/* @__PURE__ */ m(g, { children: /* @__PURE__ */ h(_, {
|
|
461
462
|
className: "pt-4",
|
|
462
|
-
children: [/* @__PURE__ */
|
|
463
|
+
children: [/* @__PURE__ */ h("div", {
|
|
463
464
|
className: "flex items-center gap-2 text-muted-foreground text-xs",
|
|
464
|
-
children: [/* @__PURE__ */
|
|
465
|
-
}), /* @__PURE__ */
|
|
465
|
+
children: [/* @__PURE__ */ m(we, { className: "h-4 w-4" }), E("planmagnet.analytics.summary.atRisk", "At Risk")]
|
|
466
|
+
}), /* @__PURE__ */ h("p", {
|
|
466
467
|
className: "text-xl font-bold mt-1",
|
|
467
468
|
children: [
|
|
468
469
|
c(gt),
|
|
469
470
|
" ",
|
|
470
|
-
|
|
471
|
+
E("planmagnet.analytics.summary.milestones", "milestones")
|
|
471
472
|
]
|
|
472
473
|
})]
|
|
473
474
|
}) })
|
|
474
475
|
]
|
|
475
476
|
}),
|
|
476
|
-
/* @__PURE__ */
|
|
477
|
+
/* @__PURE__ */ h("div", {
|
|
477
478
|
className: "flex flex-col sm:flex-row gap-3 items-start sm:items-center",
|
|
478
|
-
children: [/* @__PURE__ */
|
|
479
|
+
children: [/* @__PURE__ */ h("div", { children: [/* @__PURE__ */ m("h2", {
|
|
479
480
|
className: "text-lg font-semibold",
|
|
480
|
-
children:
|
|
481
|
-
}), /* @__PURE__ */
|
|
481
|
+
children: E("planmagnet.analytics.delivery.title", "Sprint Delivery Analytics")
|
|
482
|
+
}), /* @__PURE__ */ m("p", {
|
|
482
483
|
className: "text-xs text-muted-foreground",
|
|
483
|
-
children:
|
|
484
|
-
})] }), /* @__PURE__ */
|
|
484
|
+
children: E("planmagnet.analytics.delivery.forProject", "For {{project}}", { project: K || E("planmagnet.analytics.delivery.noProject", "no project") })
|
|
485
|
+
})] }), /* @__PURE__ */ m("div", {
|
|
485
486
|
className: "flex gap-2 sm:ml-auto",
|
|
486
|
-
children: /* @__PURE__ */
|
|
487
|
-
value:
|
|
488
|
-
onValueChange:
|
|
489
|
-
children: [/* @__PURE__ */
|
|
487
|
+
children: /* @__PURE__ */ h(x, {
|
|
488
|
+
value: G,
|
|
489
|
+
onValueChange: D,
|
|
490
|
+
children: [/* @__PURE__ */ m(Ae, {
|
|
490
491
|
className: "h-8 w-48",
|
|
491
|
-
children: /* @__PURE__ */
|
|
492
|
-
}), /* @__PURE__ */
|
|
492
|
+
children: /* @__PURE__ */ m(je, { placeholder: E("planmagnet.analytics.delivery.sprintPlaceholder", "Select sprint") })
|
|
493
|
+
}), /* @__PURE__ */ m(S, { children: W.map((e) => /* @__PURE__ */ m(C, {
|
|
493
494
|
value: e.id,
|
|
494
495
|
children: e.name
|
|
495
496
|
}, e.id)) })]
|
|
496
497
|
})
|
|
497
498
|
})]
|
|
498
499
|
}),
|
|
499
|
-
/* @__PURE__ */
|
|
500
|
+
/* @__PURE__ */ h("div", {
|
|
500
501
|
className: "grid grid-cols-1 lg:grid-cols-2 gap-6",
|
|
501
|
-
children: [/* @__PURE__ */
|
|
502
|
+
children: [/* @__PURE__ */ h(g, { children: [/* @__PURE__ */ m(v, { children: /* @__PURE__ */ h(y, {
|
|
502
503
|
className: "flex items-center gap-2",
|
|
503
|
-
children: [/* @__PURE__ */
|
|
504
|
-
}) }), /* @__PURE__ */
|
|
504
|
+
children: [/* @__PURE__ */ m(Se, { className: "h-4 w-4" }), E("planmagnet.analytics.burndown.title", "Sprint Burndown")]
|
|
505
|
+
}) }), /* @__PURE__ */ m(_, { children: ot ? /* @__PURE__ */ m("div", {
|
|
505
506
|
className: "flex justify-center py-12",
|
|
506
|
-
children: /* @__PURE__ */
|
|
507
|
-
}) : yt.length > 0 ? /* @__PURE__ */
|
|
507
|
+
children: /* @__PURE__ */ m("div", { className: "animate-spin h-6 w-6 border-2 border-primary border-t-transparent rounded-full" })
|
|
508
|
+
}) : yt.length > 0 ? /* @__PURE__ */ m(r, {
|
|
508
509
|
width: "100%",
|
|
509
510
|
height: 220,
|
|
510
|
-
children: /* @__PURE__ */
|
|
511
|
+
children: /* @__PURE__ */ h(ie, {
|
|
511
512
|
data: yt,
|
|
512
513
|
children: [
|
|
513
|
-
/* @__PURE__ */
|
|
514
|
+
/* @__PURE__ */ m(a, {
|
|
514
515
|
strokeDasharray: "3 3",
|
|
515
516
|
opacity: .2
|
|
516
517
|
}),
|
|
517
|
-
/* @__PURE__ */
|
|
518
|
+
/* @__PURE__ */ m(o, {
|
|
518
519
|
dataKey: "day",
|
|
519
520
|
tick: { fontSize: 11 }
|
|
520
521
|
}),
|
|
521
|
-
/* @__PURE__ */
|
|
522
|
+
/* @__PURE__ */ m(s, {
|
|
522
523
|
tick: { fontSize: 11 },
|
|
523
524
|
allowDecimals: !1
|
|
524
525
|
}),
|
|
525
|
-
/* @__PURE__ */
|
|
526
|
-
/* @__PURE__ */
|
|
527
|
-
/* @__PURE__ */
|
|
526
|
+
/* @__PURE__ */ m(n, {}),
|
|
527
|
+
/* @__PURE__ */ m(t, { wrapperStyle: { fontSize: 12 } }),
|
|
528
|
+
/* @__PURE__ */ m(ne, {
|
|
528
529
|
type: "monotone",
|
|
529
530
|
dataKey: "remaining",
|
|
530
|
-
name:
|
|
531
|
+
name: E("planmagnet.analytics.burndown.remaining", "Remaining points"),
|
|
531
532
|
stroke: "#f59e0b",
|
|
532
533
|
strokeWidth: 2,
|
|
533
534
|
dot: { r: 2 }
|
|
534
535
|
}),
|
|
535
|
-
/* @__PURE__ */
|
|
536
|
+
/* @__PURE__ */ m(ne, {
|
|
536
537
|
type: "monotone",
|
|
537
538
|
dataKey: "completed",
|
|
538
|
-
name:
|
|
539
|
+
name: E("planmagnet.analytics.burndown.completed", "Completed points"),
|
|
539
540
|
stroke: "#22c55e",
|
|
540
541
|
strokeWidth: 2,
|
|
541
542
|
dot: { r: 2 }
|
|
542
543
|
})
|
|
543
544
|
]
|
|
544
545
|
})
|
|
545
|
-
}) : /* @__PURE__ */
|
|
546
|
+
}) : /* @__PURE__ */ m("p", {
|
|
546
547
|
className: "text-sm text-muted-foreground py-8 text-center",
|
|
547
|
-
children:
|
|
548
|
-
}) })] }), /* @__PURE__ */
|
|
548
|
+
children: E("planmagnet.analytics.burndown.empty", "No sprint selected, or the sprint has no work items yet")
|
|
549
|
+
}) })] }), /* @__PURE__ */ h(g, { children: [/* @__PURE__ */ m(v, { children: /* @__PURE__ */ h(y, {
|
|
549
550
|
className: "flex items-center gap-2",
|
|
550
551
|
children: [
|
|
551
|
-
/* @__PURE__ */
|
|
552
|
-
|
|
552
|
+
/* @__PURE__ */ m(d, { className: "h-4 w-4" }),
|
|
553
|
+
E("planmagnet.analytics.velocity.title", "Sprint Velocity"),
|
|
553
554
|
" (",
|
|
554
|
-
|
|
555
|
+
Q.length,
|
|
555
556
|
" ",
|
|
556
|
-
|
|
557
|
+
E("planmagnet.analytics.velocity.sprints", "Sprints"),
|
|
557
558
|
")"
|
|
558
559
|
]
|
|
559
|
-
}) }), /* @__PURE__ */
|
|
560
|
+
}) }), /* @__PURE__ */ m(_, { children: ct ? /* @__PURE__ */ m("div", {
|
|
560
561
|
className: "flex justify-center py-12",
|
|
561
|
-
children: /* @__PURE__ */
|
|
562
|
-
}) :
|
|
563
|
-
/* @__PURE__ */
|
|
562
|
+
children: /* @__PURE__ */ m("div", { className: "animate-spin h-6 w-6 border-2 border-primary border-t-transparent rounded-full" })
|
|
563
|
+
}) : Q.length > 0 ? /* @__PURE__ */ h(De, { children: [
|
|
564
|
+
/* @__PURE__ */ m(r, {
|
|
564
565
|
width: "100%",
|
|
565
566
|
height: 190,
|
|
566
|
-
children: /* @__PURE__ */
|
|
567
|
-
data:
|
|
567
|
+
children: /* @__PURE__ */ h(ae, {
|
|
568
|
+
data: Q,
|
|
568
569
|
children: [
|
|
569
|
-
/* @__PURE__ */
|
|
570
|
+
/* @__PURE__ */ m(a, {
|
|
570
571
|
strokeDasharray: "3 3",
|
|
571
572
|
opacity: .2
|
|
572
573
|
}),
|
|
573
|
-
/* @__PURE__ */
|
|
574
|
+
/* @__PURE__ */ m(o, {
|
|
574
575
|
dataKey: "name",
|
|
575
576
|
tick: { fontSize: 11 }
|
|
576
577
|
}),
|
|
577
|
-
/* @__PURE__ */
|
|
578
|
+
/* @__PURE__ */ m(s, {
|
|
578
579
|
tick: { fontSize: 11 },
|
|
579
580
|
allowDecimals: !1
|
|
580
581
|
}),
|
|
581
|
-
/* @__PURE__ */
|
|
582
|
-
/* @__PURE__ */
|
|
583
|
-
|
|
584
|
-
y1:
|
|
585
|
-
y2:
|
|
582
|
+
/* @__PURE__ */ m(n, {}),
|
|
583
|
+
/* @__PURE__ */ m(t, { wrapperStyle: { fontSize: 12 } }),
|
|
584
|
+
$ && /* @__PURE__ */ m(te, {
|
|
585
|
+
y1: $.p15,
|
|
586
|
+
y2: $.p85,
|
|
586
587
|
fill: "var(--color-chart-2)",
|
|
587
588
|
fillOpacity: .12,
|
|
588
589
|
stroke: "none"
|
|
589
590
|
}),
|
|
590
|
-
/* @__PURE__ */
|
|
591
|
+
/* @__PURE__ */ m(i, {
|
|
591
592
|
dataKey: "planned",
|
|
592
|
-
name:
|
|
593
|
+
name: E("planmagnet.analytics.velocity.planned", "Planned"),
|
|
593
594
|
fill: "#cbd5e1"
|
|
594
595
|
}),
|
|
595
|
-
/* @__PURE__ */
|
|
596
|
+
/* @__PURE__ */ m(i, {
|
|
596
597
|
dataKey: "completed",
|
|
597
|
-
name:
|
|
598
|
+
name: E("planmagnet.analytics.velocity.completed", "Completed"),
|
|
598
599
|
fill: "#6366f1"
|
|
599
600
|
}),
|
|
600
|
-
/* @__PURE__ */
|
|
601
|
+
/* @__PURE__ */ m(ee, {
|
|
601
602
|
y: bt,
|
|
602
603
|
stroke: "#22c55e",
|
|
603
604
|
strokeDasharray: "4 4",
|
|
604
605
|
label: {
|
|
605
|
-
value:
|
|
606
|
+
value: E("planmagnet.analytics.velocity.avgLabel", "avg"),
|
|
606
607
|
fontSize: 10,
|
|
607
608
|
position: "right"
|
|
608
609
|
}
|
|
@@ -610,168 +611,174 @@ function D() {
|
|
|
610
611
|
]
|
|
611
612
|
})
|
|
612
613
|
}),
|
|
613
|
-
/* @__PURE__ */
|
|
614
|
+
/* @__PURE__ */ h("p", {
|
|
614
615
|
className: "text-xs text-muted-foreground text-center mt-2",
|
|
615
|
-
children: [
|
|
616
|
+
children: [Q.length === 1 ? E("planmagnet.analytics.velocity.trailingAverageOne", "Median of the last completed sprint: {{points}} pts per sprint", { points: xt }) : E("planmagnet.analytics.velocity.trailingAverage", "Median of the last {{count}} completed sprints: {{points}} pts per sprint", {
|
|
616
617
|
points: xt,
|
|
617
|
-
count:
|
|
618
|
-
}),
|
|
619
|
-
low: Math.round(
|
|
620
|
-
high: Math.round(
|
|
618
|
+
count: Q.length
|
|
619
|
+
}), $ && ` · ${E("planmagnet.analytics.velocity.range", "likely range (p15–p85): {{low}}–{{high}} pts", {
|
|
620
|
+
low: Math.round($.p15),
|
|
621
|
+
high: Math.round($.p85)
|
|
621
622
|
})}`]
|
|
622
623
|
}),
|
|
623
|
-
St && /* @__PURE__ */
|
|
624
|
+
St && /* @__PURE__ */ m("p", {
|
|
624
625
|
className: "text-xs text-status-warning-text text-center mt-1",
|
|
625
|
-
children:
|
|
626
|
+
children: E("planmagnet.analytics.velocity.insufficientHistory", "Fewer than 3 sprints with completed points — this forecast is low-confidence.")
|
|
626
627
|
}),
|
|
627
|
-
/* @__PURE__ */
|
|
628
|
+
/* @__PURE__ */ m("p", {
|
|
628
629
|
className: "text-xs text-muted-foreground text-center mt-1",
|
|
629
|
-
children:
|
|
630
|
+
children: E("planmagnet.analytics.velocity.methodLabel", "Statistical forecast (not AI-generated).")
|
|
630
631
|
})
|
|
631
|
-
] }) : /* @__PURE__ */
|
|
632
|
+
] }) : /* @__PURE__ */ m("p", {
|
|
632
633
|
className: "text-sm text-muted-foreground py-8 text-center",
|
|
633
|
-
children:
|
|
634
|
+
children: E("planmagnet.analytics.velocity.empty", "No completed sprints yet for this project")
|
|
634
635
|
}) })] })]
|
|
635
636
|
}),
|
|
636
|
-
/* @__PURE__ */
|
|
637
|
-
workspaceId:
|
|
638
|
-
projectId:
|
|
639
|
-
sprintId:
|
|
640
|
-
sprintName:
|
|
637
|
+
/* @__PURE__ */ m(le, {
|
|
638
|
+
workspaceId: f,
|
|
639
|
+
projectId: U,
|
|
640
|
+
sprintId: G || void 0,
|
|
641
|
+
sprintName: W.find((e) => e.id === G)?.name
|
|
641
642
|
}),
|
|
642
|
-
/* @__PURE__ */
|
|
643
|
+
/* @__PURE__ */ h(g, { children: [/* @__PURE__ */ h(v, { children: [/* @__PURE__ */ h(y, {
|
|
643
644
|
className: "flex items-center gap-2",
|
|
644
|
-
children: [/* @__PURE__ */
|
|
645
|
-
}), /* @__PURE__ */
|
|
645
|
+
children: [/* @__PURE__ */ m(Se, { className: "h-4 w-4" }), E("planmagnet.analytics.cfd.title", "Cumulative Flow Diagram")]
|
|
646
|
+
}), /* @__PURE__ */ m("p", {
|
|
646
647
|
className: "text-xs text-muted-foreground",
|
|
647
|
-
children:
|
|
648
|
-
})] }), /* @__PURE__ */
|
|
648
|
+
children: E("planmagnet.analytics.cfd.subtitle", "Selected date range, for {{project}}.", { project: K || E("planmagnet.analytics.delivery.noProject", "no project") })
|
|
649
|
+
})] }), /* @__PURE__ */ m(_, { children: ut ? /* @__PURE__ */ m("div", {
|
|
649
650
|
className: "flex justify-center py-12",
|
|
650
|
-
children: /* @__PURE__ */
|
|
651
|
-
}) :
|
|
651
|
+
children: /* @__PURE__ */ m("div", { className: "animate-spin h-6 w-6 border-2 border-primary border-t-transparent rounded-full" })
|
|
652
|
+
}) : Tt.length > 0 ? /* @__PURE__ */ m(r, {
|
|
652
653
|
width: "100%",
|
|
653
654
|
height: 260,
|
|
654
|
-
children: /* @__PURE__ */
|
|
655
|
-
data:
|
|
655
|
+
children: /* @__PURE__ */ h(oe, {
|
|
656
|
+
data: Tt,
|
|
656
657
|
children: [
|
|
657
|
-
/* @__PURE__ */
|
|
658
|
+
/* @__PURE__ */ m(a, {
|
|
658
659
|
strokeDasharray: "3 3",
|
|
659
660
|
opacity: .2
|
|
660
661
|
}),
|
|
661
|
-
/* @__PURE__ */
|
|
662
|
+
/* @__PURE__ */ m(o, {
|
|
662
663
|
dataKey: "day",
|
|
663
664
|
tick: { fontSize: 11 }
|
|
664
665
|
}),
|
|
665
|
-
/* @__PURE__ */
|
|
666
|
+
/* @__PURE__ */ m(s, {
|
|
666
667
|
tick: { fontSize: 11 },
|
|
667
668
|
allowDecimals: !1
|
|
668
669
|
}),
|
|
669
|
-
/* @__PURE__ */
|
|
670
|
-
/* @__PURE__ */
|
|
671
|
-
wt.map((e) => /* @__PURE__ */
|
|
670
|
+
/* @__PURE__ */ m(n, {}),
|
|
671
|
+
/* @__PURE__ */ m(t, { wrapperStyle: { fontSize: 12 } }),
|
|
672
|
+
wt.map((e) => /* @__PURE__ */ m(re, {
|
|
672
673
|
type: "monotone",
|
|
673
674
|
dataKey: e,
|
|
674
675
|
name: e.toLowerCase().replace("_", " "),
|
|
675
676
|
stackId: "cfd",
|
|
676
|
-
stroke:
|
|
677
|
-
fill:
|
|
677
|
+
stroke: w[e] ?? "#a3a3a3",
|
|
678
|
+
fill: w[e] ?? "#a3a3a3",
|
|
678
679
|
fillOpacity: .7
|
|
679
680
|
}, e))
|
|
680
681
|
]
|
|
681
682
|
})
|
|
682
|
-
}) : /* @__PURE__ */
|
|
683
|
+
}) : /* @__PURE__ */ m("p", {
|
|
683
684
|
className: "text-sm text-muted-foreground py-8 text-center",
|
|
684
|
-
children:
|
|
685
|
+
children: E("planmagnet.analytics.cfd.empty", "No work items found for this project")
|
|
685
686
|
}) })] }),
|
|
686
|
-
/* @__PURE__ */
|
|
687
|
-
workspaceId:
|
|
688
|
-
projectId:
|
|
689
|
-
startDate:
|
|
690
|
-
endDate:
|
|
687
|
+
/* @__PURE__ */ m(he, {
|
|
688
|
+
workspaceId: f,
|
|
689
|
+
projectId: U,
|
|
690
|
+
startDate: R,
|
|
691
|
+
endDate: z
|
|
691
692
|
}),
|
|
692
|
-
/* @__PURE__ */
|
|
693
|
+
/* @__PURE__ */ h("div", {
|
|
693
694
|
className: "grid grid-cols-1 lg:grid-cols-2 gap-6",
|
|
694
|
-
children: [/* @__PURE__ */
|
|
695
|
-
workspaceId:
|
|
696
|
-
projectId:
|
|
697
|
-
startDate:
|
|
698
|
-
endDate:
|
|
699
|
-
}), /* @__PURE__ */
|
|
700
|
-
workspaceId:
|
|
701
|
-
projectId:
|
|
702
|
-
startDate:
|
|
703
|
-
endDate:
|
|
695
|
+
children: [/* @__PURE__ */ m(fe, {
|
|
696
|
+
workspaceId: f,
|
|
697
|
+
projectId: P,
|
|
698
|
+
startDate: R,
|
|
699
|
+
endDate: z
|
|
700
|
+
}), /* @__PURE__ */ m(pe, {
|
|
701
|
+
workspaceId: f,
|
|
702
|
+
projectId: P,
|
|
703
|
+
startDate: R,
|
|
704
|
+
endDate: z
|
|
704
705
|
})]
|
|
705
706
|
}),
|
|
706
|
-
/* @__PURE__ */ m(
|
|
707
|
+
/* @__PURE__ */ m(me, {
|
|
708
|
+
workspaceId: f,
|
|
709
|
+
projectId: P,
|
|
710
|
+
startDate: R,
|
|
711
|
+
endDate: z
|
|
712
|
+
}),
|
|
713
|
+
/* @__PURE__ */ h("div", {
|
|
707
714
|
className: "grid grid-cols-1 lg:grid-cols-2 gap-6",
|
|
708
|
-
children: [/* @__PURE__ */
|
|
709
|
-
workspaceId:
|
|
710
|
-
projectId:
|
|
711
|
-
startDate:
|
|
712
|
-
endDate:
|
|
713
|
-
}), /* @__PURE__ */
|
|
714
|
-
workspaceId:
|
|
715
|
-
projectId:
|
|
715
|
+
children: [/* @__PURE__ */ m(de, {
|
|
716
|
+
workspaceId: f,
|
|
717
|
+
projectId: U,
|
|
718
|
+
startDate: R,
|
|
719
|
+
endDate: z
|
|
720
|
+
}), /* @__PURE__ */ m(ue, {
|
|
721
|
+
workspaceId: f,
|
|
722
|
+
projectId: P
|
|
716
723
|
})]
|
|
717
724
|
}),
|
|
718
|
-
/* @__PURE__ */
|
|
725
|
+
/* @__PURE__ */ m("div", { children: /* @__PURE__ */ m("h2", {
|
|
719
726
|
className: "text-lg font-semibold",
|
|
720
|
-
children:
|
|
727
|
+
children: E("planmagnet.analytics.advanced.title", "Advanced visualizations")
|
|
721
728
|
}) }),
|
|
722
|
-
/* @__PURE__ */
|
|
729
|
+
/* @__PURE__ */ h("div", {
|
|
723
730
|
className: "grid grid-cols-1 lg:grid-cols-2 gap-6",
|
|
724
|
-
children: [/* @__PURE__ */
|
|
725
|
-
workspaceId:
|
|
726
|
-
projectId:
|
|
727
|
-
startDate:
|
|
728
|
-
endDate:
|
|
729
|
-
}), /* @__PURE__ */
|
|
730
|
-
workspaceId:
|
|
731
|
-
projectId:
|
|
731
|
+
children: [/* @__PURE__ */ m(ge, {
|
|
732
|
+
workspaceId: f,
|
|
733
|
+
projectId: U,
|
|
734
|
+
startDate: R,
|
|
735
|
+
endDate: z
|
|
736
|
+
}), /* @__PURE__ */ m(_e, {
|
|
737
|
+
workspaceId: f,
|
|
738
|
+
projectId: P
|
|
732
739
|
})]
|
|
733
740
|
}),
|
|
734
|
-
/* @__PURE__ */
|
|
741
|
+
/* @__PURE__ */ h(g, { children: [/* @__PURE__ */ m(v, { children: /* @__PURE__ */ m(y, { children: E("planmagnet.analytics.projectHealth.title", "Project Health") }) }), /* @__PURE__ */ m(_, { children: /* @__PURE__ */ h("div", {
|
|
735
742
|
className: "space-y-3",
|
|
736
|
-
children: [
|
|
743
|
+
children: [H.filter((e) => e.status === "ACTIVE").map((e) => {
|
|
737
744
|
let t = mt(e.id), n = e.endDate && new Date(e.endDate) < /* @__PURE__ */ new Date() && t < 100 ? "at_risk" : t >= 75 ? "on_track" : "in_progress";
|
|
738
|
-
return /* @__PURE__ */
|
|
745
|
+
return /* @__PURE__ */ h("div", {
|
|
739
746
|
className: "flex items-center gap-4",
|
|
740
747
|
children: [
|
|
741
|
-
/* @__PURE__ */
|
|
748
|
+
/* @__PURE__ */ m("span", {
|
|
742
749
|
className: "text-sm font-medium w-40 truncate",
|
|
743
750
|
children: e.name
|
|
744
751
|
}),
|
|
745
|
-
/* @__PURE__ */
|
|
752
|
+
/* @__PURE__ */ m("div", {
|
|
746
753
|
className: "flex-1",
|
|
747
|
-
children: /* @__PURE__ */
|
|
754
|
+
children: /* @__PURE__ */ m("div", {
|
|
748
755
|
className: "w-full h-2 rounded-full bg-muted overflow-hidden",
|
|
749
|
-
children: /* @__PURE__ */
|
|
756
|
+
children: /* @__PURE__ */ m("div", {
|
|
750
757
|
className: `h-full rounded-full ${n === "at_risk" ? "bg-orange-400" : n === "on_track" ? "bg-green-400" : "bg-blue-400"}`,
|
|
751
758
|
style: { width: `${t}%` }
|
|
752
759
|
})
|
|
753
760
|
})
|
|
754
761
|
}),
|
|
755
|
-
/* @__PURE__ */
|
|
762
|
+
/* @__PURE__ */ h("span", {
|
|
756
763
|
className: "text-sm w-12 text-right",
|
|
757
764
|
children: [t, "%"]
|
|
758
765
|
}),
|
|
759
|
-
/* @__PURE__ */
|
|
766
|
+
/* @__PURE__ */ m(ke, {
|
|
760
767
|
variant: "outline",
|
|
761
768
|
className: "capitalize text-xs w-20 justify-center",
|
|
762
769
|
children: n.replace("_", " ")
|
|
763
770
|
})
|
|
764
771
|
]
|
|
765
772
|
}, e.id);
|
|
766
|
-
}),
|
|
773
|
+
}), H.filter((e) => e.status === "ACTIVE").length === 0 && /* @__PURE__ */ m("p", {
|
|
767
774
|
className: "text-sm text-muted-foreground text-center py-4",
|
|
768
|
-
children:
|
|
775
|
+
children: E("planmagnet.analytics.projectHealth.empty", "No active projects found")
|
|
769
776
|
})]
|
|
770
777
|
}) })] })
|
|
771
778
|
]
|
|
772
779
|
});
|
|
773
780
|
}
|
|
774
781
|
//#endregion
|
|
775
|
-
export {
|
|
782
|
+
export { E as AnalyticsAnalyticsPagePage };
|
|
776
783
|
|
|
777
784
|
//# sourceMappingURL=AnalyticsAnalyticsPagePage.js.map
|