@burdenoff/microfe-planmagnet 2026.1001.5 → 2026.1001.7
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 +10 -6
- package/dist/planmagnet/PlanMagnetRoutes.js.map +1 -1
- package/dist/planmagnet/automation/automationRuleTypes.d.ts +31 -19
- package/dist/planmagnet/automation/automationRuleTypes.d.ts.map +1 -1
- package/dist/planmagnet/automation/automationRuleTypes.js +4 -8
- package/dist/planmagnet/automation/automationRuleTypes.js.map +1 -1
- 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 +23 -1
- package/dist/planmagnet/controls/FeatureControls.d.ts.map +1 -1
- package/dist/planmagnet/controls/FeatureControls.js +431 -229
- package/dist/planmagnet/controls/FeatureControls.js.map +1 -1
- package/dist/planmagnet/controls/FeedbackControls.d.ts +70 -0
- package/dist/planmagnet/controls/FeedbackControls.d.ts.map +1 -0
- package/dist/planmagnet/controls/FeedbackControls.js +153 -0
- package/dist/planmagnet/controls/FeedbackControls.js.map +1 -0
- 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/controls/SyncControls.d.ts.map +1 -1
- package/dist/planmagnet/controls/SyncControls.js +1 -0
- package/dist/planmagnet/controls/SyncControls.js.map +1 -1
- package/dist/planmagnet/controls/WebhookSubscriptionControls.d.ts +47 -0
- package/dist/planmagnet/controls/WebhookSubscriptionControls.d.ts.map +1 -0
- package/dist/planmagnet/controls/WebhookSubscriptionControls.js +542 -0
- package/dist/planmagnet/controls/WebhookSubscriptionControls.js.map +1 -0
- package/dist/planmagnet/dashboards/DashboardUI.js +8 -8
- package/dist/planmagnet/dashboards/cards/RiskSeverityCard.js +4 -4
- 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/forecast/DeliveryForecastCard.js +8 -8
- package/dist/planmagnet/forecast/ProjectOutlookCard.js +10 -10
- package/dist/planmagnet/forecast/ProjectRiskSummaryCard.js +9 -9
- package/dist/planmagnet/forecast/ResourceForecastCard.js +6 -6
- package/dist/planmagnet/integrations/syncTypes.d.ts +2 -1
- package/dist/planmagnet/integrations/syncTypes.d.ts.map +1 -1
- package/dist/planmagnet/integrations/syncTypes.js +19 -9
- package/dist/planmagnet/integrations/syncTypes.js.map +1 -1
- package/dist/planmagnet/pages/AnalyticsAnalyticsPagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/AnalyticsAnalyticsPagePage.js +290 -283
- 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/DashboardDashboardPagePage.js +23 -23
- package/dist/planmagnet/pages/DocsDocDetailPagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/DocsDocDetailPagePage.js +340 -248
- package/dist/planmagnet/pages/DocsDocDetailPagePage.js.map +1 -1
- package/dist/planmagnet/pages/IntegrationsSyncDetailPagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/IntegrationsSyncDetailPagePage.js +172 -167
- package/dist/planmagnet/pages/IntegrationsSyncDetailPagePage.js.map +1 -1
- package/dist/planmagnet/pages/IntegrationsSyncsPagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/IntegrationsSyncsPagePage.js +92 -83
- package/dist/planmagnet/pages/IntegrationsSyncsPagePage.js.map +1 -1
- package/dist/planmagnet/pages/IntegrationsWebhooksPagePage.d.ts +2 -0
- package/dist/planmagnet/pages/IntegrationsWebhooksPagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/IntegrationsWebhooksPagePage.js +175 -0
- package/dist/planmagnet/pages/IntegrationsWebhooksPagePage.js.map +1 -0
- 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/ProductsFeatureDetailPagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/ProductsFeatureDetailPagePage.js +151 -126
- package/dist/planmagnet/pages/ProductsFeatureDetailPagePage.js.map +1 -1
- package/dist/planmagnet/pages/ProductsFeaturesPagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/ProductsFeaturesPagePage.js +169 -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 +165 -109
- package/dist/planmagnet/pages/ProductsNewFeaturePagePage.js.map +1 -1
- package/dist/planmagnet/pages/ProductsProductsPagePage.js +13 -13
- package/dist/planmagnet/pages/ProjectsAtRiskPagePage.js +9 -9
- package/dist/planmagnet/pages/ProjectsBudgetsPagePage.js +8 -8
- 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/ProjectsProjectsPagePage.js +12 -12
- package/dist/planmagnet/pages/ReportsReportsPagePage.js +23 -23
- package/dist/planmagnet/pages/TasksMyDashboardPagePage.js +18 -18
- package/dist/planmagnet/pages/TasksMyWorkPagePage.js +10 -10
- package/dist/planmagnet/pages/TasksTimeEntriesPagePage.js +5 -5
- 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/DeliveryHealthCards.js +8 -8
- package/dist/planmagnet/pages/analytics/DeliveryKpisCard.js +6 -6
- 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/pages/analytics/QualityMetricsCard.js +6 -6
- package/dist/planmagnet/pages/analytics/SprintDeliveryCards.js +8 -8
- package/dist/planmagnet/pages/analytics/StatusFlowCard.js +7 -7
- package/dist/planmagnet/pages/analytics/ThroughputCard.js +7 -7
- package/dist/planmagnet/pages/analytics/WorkBreakdownCard.js +7 -7
- package/dist/planmagnet/people/People.d.ts +14 -0
- package/dist/planmagnet/people/People.d.ts.map +1 -1
- package/dist/planmagnet/people/People.js +36 -22
- package/dist/planmagnet/people/People.js.map +1 -1
- 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/dist/planmagnet/webhooks/webhookTypes.d.ts +54 -0
- package/dist/planmagnet/webhooks/webhookTypes.d.ts.map +1 -0
- package/dist/planmagnet/webhooks/webhookTypes.js +17 -0
- package/dist/planmagnet/webhooks/webhookTypes.js.map +1 -0
- package/package.json +1 -1
|
@@ -3,8 +3,8 @@ import { ShieldAlert as t } from "lucide-react";
|
|
|
3
3
|
import { gql as n } from "@apollo/client";
|
|
4
4
|
import { useQuery as r } from "@apollo/client/react";
|
|
5
5
|
import { jsx as i, jsxs as a } from "react/jsx-runtime";
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
6
|
+
import { Badge as o } from "@burdenoff/fe-libs/ui";
|
|
7
|
+
import { useI18n as s } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
|
|
8
8
|
//#region src/planmagnet/dashboards/cards/RiskSeverityCard.tsx
|
|
9
9
|
var c = n`
|
|
10
10
|
query DashboardProjectRisks($workspaceId: ID!, $projectId: String!) {
|
|
@@ -39,7 +39,7 @@ var c = n`
|
|
|
39
39
|
NEGLIGIBLE: "secondary"
|
|
40
40
|
};
|
|
41
41
|
function f({ workspaceId: n, projectId: f, onDrillDown: p }) {
|
|
42
|
-
let { t: m } =
|
|
42
|
+
let { t: m } = s(), { data: h, loading: g, error: _ } = r(c, {
|
|
43
43
|
variables: {
|
|
44
44
|
workspaceId: n,
|
|
45
45
|
projectId: f
|
|
@@ -72,7 +72,7 @@ function f({ workspaceId: n, projectId: f, onDrillDown: p }) {
|
|
|
72
72
|
children: m("planmagnet.dashboards.pm.risks.noneOpen", "No open risks for this project.")
|
|
73
73
|
}) : /* @__PURE__ */ i("div", {
|
|
74
74
|
className: "flex flex-wrap gap-2",
|
|
75
|
-
children: u.filter((e) => x.has(e)).map((e) => /* @__PURE__ */ a(
|
|
75
|
+
children: u.filter((e) => x.has(e)).map((e) => /* @__PURE__ */ a(o, {
|
|
76
76
|
variant: d[e],
|
|
77
77
|
children: [
|
|
78
78
|
e.toLowerCase(),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SprintCapacityCard.d.ts","sourceRoot":"","sources":["../../../../src/planmagnet/dashboards/cards/SprintCapacityCard.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"SprintCapacityCard.d.ts","sourceRoot":"","sources":["../../../../src/planmagnet/dashboards/cards/SprintCapacityCard.tsx"],"names":[],"mappings":"AAmDA,wBAAgB,kBAAkB,CAAC,EACjC,QAAQ,EACR,WAAW,GACZ,EAAE;IACD,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,IAAI,CAAC;CACzB,2CAqHA"}
|
|
@@ -1,17 +1,18 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
1
|
+
import { usePlanMagnetNavigate as e } from "../../providers/PlanMagnetProvider.js";
|
|
2
|
+
import { PersonAvatar as t } from "../../people/People.js";
|
|
3
|
+
import { DashboardCard as n, DrillDownLink as r } from "../DashboardUI.js";
|
|
4
|
+
import { Users as i } from "lucide-react";
|
|
5
|
+
import { gql as a } from "@apollo/client";
|
|
6
|
+
import { useQuery as o } from "@apollo/client/react";
|
|
7
|
+
import { jsx as s, jsxs as c } from "react/jsx-runtime";
|
|
8
|
+
import { useI18n as l } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
|
|
8
9
|
//#region src/planmagnet/dashboards/cards/SprintCapacityCard.tsx
|
|
9
|
-
var
|
|
10
|
+
var u = a`
|
|
10
11
|
query DashboardSprintCapacity($sprintId: ID!) {
|
|
11
12
|
planmagnetSprintCapacity(sprintId: $sprintId) {
|
|
12
13
|
sprintId
|
|
13
14
|
crewfoundryUnavailable
|
|
14
|
-
|
|
15
|
+
unmatchedCount
|
|
15
16
|
members {
|
|
16
17
|
actorId
|
|
17
18
|
employeeName
|
|
@@ -26,100 +27,107 @@ var c = r`
|
|
|
26
27
|
}
|
|
27
28
|
}
|
|
28
29
|
`;
|
|
29
|
-
function
|
|
30
|
-
let { t:
|
|
31
|
-
variables: { sprintId:
|
|
32
|
-
skip: !
|
|
33
|
-
}),
|
|
34
|
-
return /* @__PURE__ */
|
|
35
|
-
icon: /* @__PURE__ */
|
|
36
|
-
title:
|
|
37
|
-
definition:
|
|
38
|
-
loading:
|
|
39
|
-
error:
|
|
40
|
-
empty: !
|
|
41
|
-
emptyMessage:
|
|
30
|
+
function d({ sprintId: a, onDrillDown: d }) {
|
|
31
|
+
let { t: f } = l(), p = e(), { data: m, loading: h, error: g } = o(u, {
|
|
32
|
+
variables: { sprintId: a },
|
|
33
|
+
skip: !a
|
|
34
|
+
}), _ = m?.planmagnetSprintCapacity;
|
|
35
|
+
return /* @__PURE__ */ s(n, {
|
|
36
|
+
icon: /* @__PURE__ */ s(i, { className: "h-4 w-4" }),
|
|
37
|
+
title: f("planmagnet.dashboards.pm.capacity.title", "Capacity"),
|
|
38
|
+
definition: f("planmagnet.dashboards.pm.capacity.definition", "Real CrewFoundry allocation for the active sprint's assignees — hours and story points, per person."),
|
|
39
|
+
loading: h && !m,
|
|
40
|
+
error: g,
|
|
41
|
+
empty: !a || !!_ && _.members.length === 0 && !_.crewfoundryUnavailable,
|
|
42
|
+
emptyMessage: a ? f("planmagnet.dashboards.pm.capacity.noMembers", "No CrewFoundry-matched assignees in this sprint.") : f("planmagnet.dashboards.pm.capacity.noSprint", "No active sprint for this project."),
|
|
42
43
|
drillDown: {
|
|
43
|
-
label:
|
|
44
|
-
onClick:
|
|
44
|
+
label: f("planmagnet.dashboards.pm.capacity.drillDown", "Open project"),
|
|
45
|
+
onClick: d
|
|
45
46
|
},
|
|
46
|
-
children:
|
|
47
|
+
children: _ ? _.crewfoundryUnavailable ? /* @__PURE__ */ s("p", {
|
|
47
48
|
className: "text-sm text-muted-foreground",
|
|
48
|
-
children:
|
|
49
|
-
}) : /* @__PURE__ */
|
|
49
|
+
children: f("planmagnet.dashboards.pm.capacity.unavailable", "Capacity data is unavailable — CrewFoundry could not be reached, or this workspace has no CrewFoundry roster.")
|
|
50
|
+
}) : /* @__PURE__ */ c("div", {
|
|
50
51
|
className: "space-y-2",
|
|
51
|
-
children: [/* @__PURE__ */
|
|
52
|
+
children: [/* @__PURE__ */ c("table", {
|
|
52
53
|
className: "w-full text-sm",
|
|
53
|
-
children: [/* @__PURE__ */
|
|
54
|
+
children: [/* @__PURE__ */ s("thead", { children: /* @__PURE__ */ c("tr", {
|
|
54
55
|
className: "text-left text-xs text-muted-foreground",
|
|
55
56
|
children: [
|
|
56
|
-
/* @__PURE__ */
|
|
57
|
+
/* @__PURE__ */ s("th", {
|
|
57
58
|
className: "py-1 pr-2 font-normal",
|
|
58
|
-
children:
|
|
59
|
+
children: f("planmagnet.dashboards.pm.capacity.person", "Person")
|
|
59
60
|
}),
|
|
60
|
-
/* @__PURE__ */
|
|
61
|
+
/* @__PURE__ */ s("th", {
|
|
61
62
|
className: "py-1 pr-2 text-right font-normal",
|
|
62
|
-
children:
|
|
63
|
+
children: f("planmagnet.dashboards.pm.capacity.allocated", "Allocated h")
|
|
63
64
|
}),
|
|
64
|
-
/* @__PURE__ */
|
|
65
|
+
/* @__PURE__ */ s("th", {
|
|
65
66
|
className: "py-1 pr-2 text-right font-normal",
|
|
66
|
-
children:
|
|
67
|
+
children: f("planmagnet.dashboards.pm.capacity.utilization", "Utilization")
|
|
67
68
|
}),
|
|
68
|
-
/* @__PURE__ */
|
|
69
|
+
/* @__PURE__ */ s("th", {
|
|
69
70
|
className: "py-1 text-right font-normal",
|
|
70
|
-
children:
|
|
71
|
+
children: f("planmagnet.dashboards.pm.capacity.items", "Items (pts)")
|
|
71
72
|
})
|
|
72
73
|
]
|
|
73
|
-
}) }), /* @__PURE__ */
|
|
74
|
+
}) }), /* @__PURE__ */ s("tbody", { children: _.members.map((e) => /* @__PURE__ */ c("tr", {
|
|
74
75
|
className: "border-t",
|
|
75
76
|
children: [
|
|
76
|
-
/* @__PURE__ */
|
|
77
|
+
/* @__PURE__ */ s("td", {
|
|
77
78
|
className: "py-1.5 pr-2",
|
|
78
|
-
children: /* @__PURE__ */
|
|
79
|
+
children: /* @__PURE__ */ c("div", {
|
|
79
80
|
className: "flex items-center gap-2",
|
|
80
|
-
children: [/* @__PURE__ */
|
|
81
|
-
id:
|
|
81
|
+
children: [/* @__PURE__ */ s(t, {
|
|
82
|
+
id: e.actorId,
|
|
82
83
|
className: "flex h-6 w-6 shrink-0 items-center justify-center rounded-full bg-primary/10 text-[10px] font-medium text-primary"
|
|
83
|
-
}), /* @__PURE__ */
|
|
84
|
+
}), /* @__PURE__ */ c("div", { children: [/* @__PURE__ */ s("div", {
|
|
84
85
|
className: "font-medium",
|
|
85
|
-
children:
|
|
86
|
-
}), /* @__PURE__ */
|
|
86
|
+
children: e.employeeName
|
|
87
|
+
}), /* @__PURE__ */ c("div", {
|
|
87
88
|
className: "text-xs text-muted-foreground",
|
|
88
89
|
children: [
|
|
89
|
-
|
|
90
|
+
e.position,
|
|
90
91
|
" · ",
|
|
91
|
-
|
|
92
|
+
e.department
|
|
92
93
|
]
|
|
93
94
|
})] })]
|
|
94
95
|
})
|
|
95
96
|
}),
|
|
96
|
-
/* @__PURE__ */
|
|
97
|
+
/* @__PURE__ */ s("td", {
|
|
97
98
|
className: "py-1.5 pr-2 text-right tabular-nums",
|
|
98
|
-
children:
|
|
99
|
+
children: e.allocatedHours.toFixed(1)
|
|
99
100
|
}),
|
|
100
|
-
/* @__PURE__ */
|
|
101
|
+
/* @__PURE__ */ s("td", {
|
|
101
102
|
className: "py-1.5 pr-2 text-right tabular-nums",
|
|
102
|
-
children:
|
|
103
|
+
children: e.utilizationPercent == null ? "—" : `${e.utilizationPercent}%`
|
|
103
104
|
}),
|
|
104
|
-
/* @__PURE__ */
|
|
105
|
+
/* @__PURE__ */ c("td", {
|
|
105
106
|
className: "py-1.5 text-right tabular-nums",
|
|
106
107
|
children: [
|
|
107
|
-
|
|
108
|
+
e.assignedWorkItemCount,
|
|
108
109
|
" (",
|
|
109
|
-
|
|
110
|
+
e.assignedStoryPoints,
|
|
110
111
|
")"
|
|
111
112
|
]
|
|
112
113
|
})
|
|
113
114
|
]
|
|
114
|
-
},
|
|
115
|
-
}),
|
|
116
|
-
className: "
|
|
117
|
-
|
|
115
|
+
}, e.actorId)) })]
|
|
116
|
+
}), _.unmatchedCount > 0 ? /* @__PURE__ */ c("div", {
|
|
117
|
+
className: "flex items-center justify-between gap-2",
|
|
118
|
+
"data-testid": "sprint-capacity-card-unmatched",
|
|
119
|
+
children: [/* @__PURE__ */ s("p", {
|
|
120
|
+
className: "text-xs text-muted-foreground",
|
|
121
|
+
children: f("planmagnet.dashboards.pm.capacity.unmatched", "{{count}} sprint assignee(s) could not be matched to a CrewFoundry employee record.", { count: _.unmatchedCount })
|
|
122
|
+
}), /* @__PURE__ */ s(r, {
|
|
123
|
+
label: f("planmagnet.dashboards.pm.capacity.fixUnmatched", "Fix"),
|
|
124
|
+
onClick: () => p("/team/team-page?focus=unmatched-crew-identities")
|
|
125
|
+
})]
|
|
118
126
|
}) : null]
|
|
119
127
|
}) : null
|
|
120
128
|
});
|
|
121
129
|
}
|
|
122
130
|
//#endregion
|
|
123
|
-
export {
|
|
131
|
+
export { d as SprintCapacityCard };
|
|
124
132
|
|
|
125
133
|
//# sourceMappingURL=SprintCapacityCard.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SprintCapacityCard.js","names":[],"sources":["../../../../src/planmagnet/dashboards/cards/SprintCapacityCard.tsx"],"sourcesContent":["import { gql } from '@apollo/client';\nimport { useQuery } from '@apollo/client/react';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { Users } from 'lucide-react';\nimport { DashboardCard } from '../DashboardUI';\nimport { PersonAvatar } from '../../people/People';\n\n/** Capacity (ANR-07): `planmagnetSprintCapacity` (BOFF-4444) of the active sprint — real CrewFoundry\n * allocation/availability per assignee, cross-layer. There is no \"skill\" concept anywhere in this data:\n * capacity is hours and story points, per person, never per skill (the PM dashboard says so separately). */\nconst GET_SPRINT_CAPACITY = gql`\n query DashboardSprintCapacity($sprintId: ID!) {\n planmagnetSprintCapacity(sprintId: $sprintId) {\n sprintId\n crewfoundryUnavailable\n
|
|
1
|
+
{"version":3,"file":"SprintCapacityCard.js","names":[],"sources":["../../../../src/planmagnet/dashboards/cards/SprintCapacityCard.tsx"],"sourcesContent":["import { gql } from '@apollo/client';\nimport { useQuery } from '@apollo/client/react';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { Users } from 'lucide-react';\nimport { DashboardCard, DrillDownLink } from '../DashboardUI';\nimport { PersonAvatar } from '../../people/People';\nimport { usePlanMagnetNavigate } from '../../providers/PlanMagnetProvider';\n\n/** Capacity (ANR-07): `planmagnetSprintCapacity` (BOFF-4444) of the active sprint — real CrewFoundry\n * allocation/availability per assignee, cross-layer. There is no \"skill\" concept anywhere in this data:\n * capacity is hours and story points, per person, never per skill (the PM dashboard says so separately). */\nconst GET_SPRINT_CAPACITY = gql`\n query DashboardSprintCapacity($sprintId: ID!) {\n planmagnetSprintCapacity(sprintId: $sprintId) {\n sprintId\n crewfoundryUnavailable\n unmatchedCount\n members {\n actorId\n employeeName\n position\n department\n allocatedHours\n billableHours\n utilizationPercent\n assignedWorkItemCount\n assignedStoryPoints\n }\n }\n }\n`;\n\ninterface SprintCapacityData {\n planmagnetSprintCapacity: {\n sprintId: string;\n crewfoundryUnavailable: boolean;\n unmatchedCount: number;\n members: {\n actorId: string;\n employeeName: string;\n position: string;\n department: string;\n allocatedHours: number;\n billableHours: number;\n utilizationPercent: number | null;\n assignedWorkItemCount: number;\n assignedStoryPoints: number;\n }[];\n };\n}\n\nexport function SprintCapacityCard({\n sprintId,\n onDrillDown,\n}: {\n sprintId: string;\n onDrillDown: () => void;\n}) {\n const { t } = useI18n();\n const navigate = usePlanMagnetNavigate();\n const { data, loading, error } = useQuery<SprintCapacityData>(GET_SPRINT_CAPACITY, {\n variables: { sprintId },\n skip: !sprintId,\n });\n const capacity = data?.planmagnetSprintCapacity;\n\n return (\n <DashboardCard\n icon={<Users className=\"h-4 w-4\" />}\n title={t('planmagnet.dashboards.pm.capacity.title', 'Capacity')}\n definition={t(\n 'planmagnet.dashboards.pm.capacity.definition',\n \"Real CrewFoundry allocation for the active sprint's assignees — hours and story points, per person.\"\n )}\n loading={loading && !data}\n error={error}\n empty={\n !sprintId ||\n (!!capacity && capacity.members.length === 0 && !capacity.crewfoundryUnavailable)\n }\n emptyMessage={\n !sprintId\n ? t('planmagnet.dashboards.pm.capacity.noSprint', 'No active sprint for this project.')\n : t(\n 'planmagnet.dashboards.pm.capacity.noMembers',\n 'No CrewFoundry-matched assignees in this sprint.'\n )\n }\n drillDown={{\n label: t('planmagnet.dashboards.pm.capacity.drillDown', 'Open project'),\n onClick: onDrillDown,\n }}\n >\n {capacity ? (\n capacity.crewfoundryUnavailable ? (\n <p className=\"text-sm text-muted-foreground\">\n {t(\n 'planmagnet.dashboards.pm.capacity.unavailable',\n 'Capacity data is unavailable — CrewFoundry could not be reached, or this workspace has no CrewFoundry roster.'\n )}\n </p>\n ) : (\n <div className=\"space-y-2\">\n <table className=\"w-full text-sm\">\n <thead>\n <tr className=\"text-left text-xs text-muted-foreground\">\n <th className=\"py-1 pr-2 font-normal\">\n {t('planmagnet.dashboards.pm.capacity.person', 'Person')}\n </th>\n <th className=\"py-1 pr-2 text-right font-normal\">\n {t('planmagnet.dashboards.pm.capacity.allocated', 'Allocated h')}\n </th>\n <th className=\"py-1 pr-2 text-right font-normal\">\n {t('planmagnet.dashboards.pm.capacity.utilization', 'Utilization')}\n </th>\n <th className=\"py-1 text-right font-normal\">\n {t('planmagnet.dashboards.pm.capacity.items', 'Items (pts)')}\n </th>\n </tr>\n </thead>\n <tbody>\n {capacity.members.map((m) => (\n <tr key={m.actorId} className=\"border-t\">\n <td className=\"py-1.5 pr-2\">\n <div className=\"flex items-center gap-2\">\n <PersonAvatar\n id={m.actorId}\n className=\"flex h-6 w-6 shrink-0 items-center justify-center rounded-full bg-primary/10 text-[10px] font-medium text-primary\"\n />\n <div>\n <div className=\"font-medium\">{m.employeeName}</div>\n <div className=\"text-xs text-muted-foreground\">\n {m.position} · {m.department}\n </div>\n </div>\n </div>\n </td>\n <td className=\"py-1.5 pr-2 text-right tabular-nums\">\n {m.allocatedHours.toFixed(1)}\n </td>\n <td className=\"py-1.5 pr-2 text-right tabular-nums\">\n {m.utilizationPercent == null ? '—' : `${m.utilizationPercent}%`}\n </td>\n <td className=\"py-1.5 text-right tabular-nums\">\n {m.assignedWorkItemCount} ({m.assignedStoryPoints})\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n {capacity.unmatchedCount > 0 ? (\n <div\n className=\"flex items-center justify-between gap-2\"\n data-testid=\"sprint-capacity-card-unmatched\"\n >\n <p className=\"text-xs text-muted-foreground\">\n {t(\n 'planmagnet.dashboards.pm.capacity.unmatched',\n '{{count}} sprint assignee(s) could not be matched to a CrewFoundry employee record.',\n { count: capacity.unmatchedCount }\n )}\n </p>\n {/* CWF-30: the admin remediation panel on the Members page. */}\n <DrillDownLink\n label={t('planmagnet.dashboards.pm.capacity.fixUnmatched', 'Fix')}\n onClick={() => navigate('/team/team-page?focus=unmatched-crew-identities')}\n />\n </div>\n ) : null}\n </div>\n )\n ) : null}\n </DashboardCard>\n );\n}\n"],"mappings":";;;;;;;;;AAWA,IAAM,IAAsB,CAAG;;;;;;;;;;;;;;;;;;;;AAwC/B,SAAgB,EAAmB,EACjC,aACA,kBAIC;CACD,IAAM,EAAE,SAAM,GAAS,EACjB,IAAW,GAAuB,EAClC,EAAE,SAAM,YAAS,aAAU,EAA6B,GAAqB;EACjF,WAAW,EAAE,aAAU;EACvB,MAAM,CAAC;EACR,CAAC,EACI,IAAW,GAAM;AAEvB,QACE,kBAAC,GAAD;EACE,MAAM,kBAAC,GAAD,EAAO,WAAU,WAAY,CAAA;EACnC,OAAO,EAAE,2CAA2C,WAAW;EAC/D,YAAY,EACV,gDACA,sGACD;EACD,SAAS,KAAW,CAAC;EACd;EACP,OACE,CAAC,KACA,CAAC,CAAC,KAAY,EAAS,QAAQ,WAAW,KAAK,CAAC,EAAS;EAE5D,cACG,IAEG,EACE,+CACA,mDACD,GAJD,EAAE,8CAA8C,qCAAqC;EAM3F,WAAW;GACT,OAAO,EAAE,+CAA+C,eAAe;GACvE,SAAS;GACV;YAEA,IACC,EAAS,yBACP,kBAAC,KAAD;GAAG,WAAU;aACV,EACC,iDACA,gHACD;GACC,CAAA,GAEJ,kBAAC,OAAD;GAAK,WAAU;aAAf,CACE,kBAAC,SAAD;IAAO,WAAU;cAAjB,CACE,kBAAC,SAAD,EAAA,UACE,kBAAC,MAAD;KAAI,WAAU;eAAd;MACE,kBAAC,MAAD;OAAI,WAAU;iBACX,EAAE,4CAA4C,SAAS;OACrD,CAAA;MACL,kBAAC,MAAD;OAAI,WAAU;iBACX,EAAE,+CAA+C,cAAc;OAC7D,CAAA;MACL,kBAAC,MAAD;OAAI,WAAU;iBACX,EAAE,iDAAiD,cAAc;OAC/D,CAAA;MACL,kBAAC,MAAD;OAAI,WAAU;iBACX,EAAE,2CAA2C,cAAc;OACzD,CAAA;MACF;QACC,CAAA,EACR,kBAAC,SAAD,EAAA,UACG,EAAS,QAAQ,KAAK,MACrB,kBAAC,MAAD;KAAoB,WAAU;eAA9B;MACE,kBAAC,MAAD;OAAI,WAAU;iBACZ,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,GAAD;SACE,IAAI,EAAE;SACN,WAAU;SACV,CAAA,EACF,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,OAAD;SAAK,WAAU;mBAAe,EAAE;SAAmB,CAAA,EACnD,kBAAC,OAAD;SAAK,WAAU;mBAAf;UACG,EAAE;UAAS;UAAI,EAAE;UACd;WACF,EAAA,CAAA,CACF;;OACH,CAAA;MACL,kBAAC,MAAD;OAAI,WAAU;iBACX,EAAE,eAAe,QAAQ,EAAE;OACzB,CAAA;MACL,kBAAC,MAAD;OAAI,WAAU;iBACX,EAAE,sBAAsB,OAAO,MAAM,GAAG,EAAE,mBAAmB;OAC3D,CAAA;MACL,kBAAC,MAAD;OAAI,WAAU;iBAAd;QACG,EAAE;QAAsB;QAAG,EAAE;QAAoB;QAC/C;;MACF;OAxBI,EAAE,QAwBN,CACL,EACI,CAAA,CACF;OACP,EAAS,iBAAiB,IACzB,kBAAC,OAAD;IACE,WAAU;IACV,eAAY;cAFd,CAIE,kBAAC,KAAD;KAAG,WAAU;eACV,EACC,+CACA,uFACA,EAAE,OAAO,EAAS,gBAAgB,CACnC;KACC,CAAA,EAEJ,kBAAC,GAAD;KACE,OAAO,EAAE,kDAAkD,MAAM;KACjE,eAAe,EAAS,kDAAkD;KAC1E,CAAA,CACE;QACJ,KACA;OAEN;EACU,CAAA"}
|
|
@@ -4,8 +4,8 @@ import { CalendarRange as n } from "lucide-react";
|
|
|
4
4
|
import { gql as r } from "@apollo/client";
|
|
5
5
|
import { useQuery as i } from "@apollo/client/react";
|
|
6
6
|
import { jsx as a, jsxs as o } from "react/jsx-runtime";
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
7
|
+
import { Card as s, CardContent as c, CardHeader as l, CardTitle as u, Checkbox as d } from "@burdenoff/fe-libs/ui";
|
|
8
|
+
import { useI18n as f } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
|
|
9
9
|
//#region src/planmagnet/forecast/DeliveryForecastCard.tsx
|
|
10
10
|
var p = r`
|
|
11
11
|
query PlanmagnetDeliveryForecast(
|
|
@@ -49,7 +49,7 @@ function m(e) {
|
|
|
49
49
|
});
|
|
50
50
|
}
|
|
51
51
|
function h({ workspaceId: r, projectId: h, sprintId: g, sprintName: _ }) {
|
|
52
|
-
let { t: v } =
|
|
52
|
+
let { t: v } = f(), [y, b] = t(!1), x = y && !!g, { data: S, loading: C, error: w } = i(p, {
|
|
53
53
|
variables: {
|
|
54
54
|
workspaceId: r,
|
|
55
55
|
projectId: h,
|
|
@@ -57,10 +57,10 @@ function h({ workspaceId: r, projectId: h, sprintId: g, sprintName: _ }) {
|
|
|
57
57
|
},
|
|
58
58
|
skip: !r || !h
|
|
59
59
|
}), T = S?.planmagnetForecastDelivery;
|
|
60
|
-
return /* @__PURE__ */ o(
|
|
60
|
+
return /* @__PURE__ */ o(s, {
|
|
61
61
|
"data-testid": "forecast-card",
|
|
62
|
-
children: [/* @__PURE__ */ o(
|
|
63
|
-
/* @__PURE__ */ o(
|
|
62
|
+
children: [/* @__PURE__ */ o(l, { children: [
|
|
63
|
+
/* @__PURE__ */ o(u, {
|
|
64
64
|
className: "flex items-center gap-2",
|
|
65
65
|
children: [/* @__PURE__ */ a(n, { className: "h-4 w-4" }), v("planmagnet.forecast.delivery.title", "Delivery forecast")]
|
|
66
66
|
}),
|
|
@@ -71,13 +71,13 @@ function h({ workspaceId: r, projectId: h, sprintId: g, sprintName: _ }) {
|
|
|
71
71
|
g && /* @__PURE__ */ o("label", {
|
|
72
72
|
htmlFor: `forecast-scope-sprint-${h}`,
|
|
73
73
|
className: "flex items-center gap-2 pt-1 text-xs font-normal text-muted-foreground",
|
|
74
|
-
children: [/* @__PURE__ */ a(
|
|
74
|
+
children: [/* @__PURE__ */ a(d, {
|
|
75
75
|
id: `forecast-scope-sprint-${h}`,
|
|
76
76
|
checked: y,
|
|
77
77
|
onCheckedChange: (e) => b(e === !0)
|
|
78
78
|
}), v("planmagnet.forecast.delivery.scopeToggle", "Only this sprint's items ({{sprint}})", { sprint: _ ?? v("planmagnet.forecast.delivery.thisSprint", "this sprint") })]
|
|
79
79
|
})
|
|
80
|
-
] }), /* @__PURE__ */ a(
|
|
80
|
+
] }), /* @__PURE__ */ a(c, { children: h ? C && !S ? /* @__PURE__ */ a("div", {
|
|
81
81
|
className: "flex justify-center py-8",
|
|
82
82
|
children: /* @__PURE__ */ a("div", { className: "animate-spin h-6 w-6 border-2 border-primary border-t-transparent rounded-full" })
|
|
83
83
|
}) : w ? /* @__PURE__ */ a("p", {
|
|
@@ -5,8 +5,8 @@ import { Compass as r } from "lucide-react";
|
|
|
5
5
|
import { gql as i } from "@apollo/client";
|
|
6
6
|
import { useQuery as a } from "@apollo/client/react";
|
|
7
7
|
import { jsx as o, jsxs as s } from "react/jsx-runtime";
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
8
|
+
import { Badge as c, Card as l, CardContent as u, CardHeader as d, CardTitle as f } from "@burdenoff/fe-libs/ui";
|
|
9
|
+
import { useI18n as p } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
|
|
10
10
|
//#region src/planmagnet/forecast/ProjectOutlookCard.tsx
|
|
11
11
|
var m = i`
|
|
12
12
|
query PlanmagnetProjectOutlook($workspaceId: ID!, $projectId: ID!) {
|
|
@@ -57,28 +57,28 @@ function _(e) {
|
|
|
57
57
|
return e === null ? "—" : `${Math.round(e * 100)}%`;
|
|
58
58
|
}
|
|
59
59
|
function v({ workspaceId: i, projectId: v }) {
|
|
60
|
-
let { t: y } =
|
|
60
|
+
let { t: y } = p(), b = e(), { data: x, loading: S, error: C } = a(m, {
|
|
61
61
|
variables: {
|
|
62
62
|
workspaceId: i,
|
|
63
63
|
projectId: v
|
|
64
64
|
},
|
|
65
65
|
skip: !i || !v
|
|
66
66
|
}), w = x?.planmagnetProjectOutlook;
|
|
67
|
-
return /* @__PURE__ */ s(
|
|
67
|
+
return /* @__PURE__ */ s(l, {
|
|
68
68
|
"data-testid": "outlook-card",
|
|
69
|
-
children: [/* @__PURE__ */ s(
|
|
69
|
+
children: [/* @__PURE__ */ s(d, {
|
|
70
70
|
className: "flex flex-row items-start justify-between space-y-0",
|
|
71
|
-
children: [/* @__PURE__ */ s("div", { children: [/* @__PURE__ */ s(
|
|
71
|
+
children: [/* @__PURE__ */ s("div", { children: [/* @__PURE__ */ s(f, {
|
|
72
72
|
className: "flex items-center gap-2",
|
|
73
73
|
children: [/* @__PURE__ */ o(r, { className: "h-4 w-4" }), y("planmagnet.forecast.outlook.title", "Project outlook")]
|
|
74
74
|
}), /* @__PURE__ */ o("p", {
|
|
75
75
|
className: "text-xs text-muted-foreground",
|
|
76
76
|
children: y("planmagnet.forecast.outlook.subtitle", "Explicit rule-based heuristics over real data — never AI.")
|
|
77
|
-
})] }), /* @__PURE__ */ o(
|
|
77
|
+
})] }), /* @__PURE__ */ o(c, {
|
|
78
78
|
variant: "outline",
|
|
79
79
|
children: y("planmagnet.forecast.outlook.method", "HEURISTIC")
|
|
80
80
|
})]
|
|
81
|
-
}), /* @__PURE__ */ o(
|
|
81
|
+
}), /* @__PURE__ */ o(u, { children: S && !x ? /* @__PURE__ */ o("div", {
|
|
82
82
|
className: "flex justify-center py-8",
|
|
83
83
|
children: /* @__PURE__ */ o("div", { className: "animate-spin h-6 w-6 border-2 border-primary border-t-transparent rounded-full" })
|
|
84
84
|
}) : C ? /* @__PURE__ */ o("p", {
|
|
@@ -89,7 +89,7 @@ function v({ workspaceId: i, projectId: v }) {
|
|
|
89
89
|
children: [
|
|
90
90
|
/* @__PURE__ */ s("div", {
|
|
91
91
|
className: "flex flex-wrap items-center gap-2",
|
|
92
|
-
children: [/* @__PURE__ */ o(
|
|
92
|
+
children: [/* @__PURE__ */ o(c, {
|
|
93
93
|
variant: h[w.successLikelihood],
|
|
94
94
|
children: y("planmagnet.forecast.outlook.successLikelihood", "Success likelihood: {{level}}", { level: w.successLikelihood })
|
|
95
95
|
}), /* @__PURE__ */ o("span", {
|
|
@@ -107,7 +107,7 @@ function v({ workspaceId: i, projectId: v }) {
|
|
|
107
107
|
className: "rounded-md border p-3",
|
|
108
108
|
children: [/* @__PURE__ */ s("h3", {
|
|
109
109
|
className: "mb-1 flex items-center gap-2 text-sm font-medium",
|
|
110
|
-
children: [y("planmagnet.forecast.outlook.quality", "Quality trend"), /* @__PURE__ */ o(
|
|
110
|
+
children: [y("planmagnet.forecast.outlook.quality", "Quality trend"), /* @__PURE__ */ o(c, {
|
|
111
111
|
variant: g[w.qualityTrend.trend],
|
|
112
112
|
children: w.qualityTrend.trend
|
|
113
113
|
})]
|
|
@@ -6,8 +6,8 @@ import { ShieldAlert as s } from "lucide-react";
|
|
|
6
6
|
import { gql as c } from "@apollo/client";
|
|
7
7
|
import { useQuery as l } from "@apollo/client/react";
|
|
8
8
|
import { jsx as u, jsxs as d } from "react/jsx-runtime";
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
9
|
+
import { Badge as f, Card as p, CardContent as m, CardHeader as h, CardTitle as g } from "@burdenoff/fe-libs/ui";
|
|
10
|
+
import { useI18n as _ } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
|
|
11
11
|
//#region src/planmagnet/forecast/ProjectRiskSummaryCard.tsx
|
|
12
12
|
var v = c`
|
|
13
13
|
query PlanmagnetProjectRiskSummary($workspaceId: ID!, $projectId: ID!) {
|
|
@@ -26,28 +26,28 @@ var v = c`
|
|
|
26
26
|
}
|
|
27
27
|
`;
|
|
28
28
|
function y({ workspaceId: c, projectId: y }) {
|
|
29
|
-
let { t: b } =
|
|
29
|
+
let { t: b } = _(), x = e(), { data: S, loading: C, error: w } = l(v, {
|
|
30
30
|
variables: {
|
|
31
31
|
workspaceId: c,
|
|
32
32
|
projectId: y
|
|
33
33
|
},
|
|
34
34
|
skip: !c || !y
|
|
35
35
|
}), T = S?.planmagnetProjectRiskSummary, E = new Map(T?.byKind.map((e) => [e.kind, e.count]) ?? []), D = new Map(T?.bySeverity.map((e) => [e.severity, e.count]) ?? []);
|
|
36
|
-
return /* @__PURE__ */ d(
|
|
36
|
+
return /* @__PURE__ */ d(p, {
|
|
37
37
|
"data-testid": "risk-summary",
|
|
38
|
-
children: [/* @__PURE__ */ d(
|
|
38
|
+
children: [/* @__PURE__ */ d(h, {
|
|
39
39
|
className: "flex flex-row items-start justify-between space-y-0",
|
|
40
|
-
children: [/* @__PURE__ */ d("div", { children: [/* @__PURE__ */ d(
|
|
40
|
+
children: [/* @__PURE__ */ d("div", { children: [/* @__PURE__ */ d(g, {
|
|
41
41
|
className: "flex items-center gap-2",
|
|
42
42
|
children: [/* @__PURE__ */ u(s, { className: "h-4 w-4" }), b("planmagnet.forecast.riskSummary.title", "At-risk work")]
|
|
43
43
|
}), /* @__PURE__ */ u("p", {
|
|
44
44
|
className: "text-xs text-muted-foreground",
|
|
45
45
|
children: b("planmagnet.forecast.riskSummary.subtitle", "Explicit threshold rules — never AI.")
|
|
46
|
-
})] }), /* @__PURE__ */ u(
|
|
46
|
+
})] }), /* @__PURE__ */ u(f, {
|
|
47
47
|
variant: "outline",
|
|
48
48
|
children: b("planmagnet.forecast.riskSummary.method", "Rule-based")
|
|
49
49
|
})]
|
|
50
|
-
}), /* @__PURE__ */ u(
|
|
50
|
+
}), /* @__PURE__ */ u(m, { children: C && !S ? /* @__PURE__ */ u("p", {
|
|
51
51
|
className: "text-sm text-muted-foreground",
|
|
52
52
|
children: b("planmagnet.forecast.loading", "Loading…")
|
|
53
53
|
}) : w ? /* @__PURE__ */ u("p", {
|
|
@@ -61,7 +61,7 @@ function y({ workspaceId: c, projectId: y }) {
|
|
|
61
61
|
children: [
|
|
62
62
|
/* @__PURE__ */ u("div", {
|
|
63
63
|
className: "flex flex-wrap items-center gap-2",
|
|
64
|
-
children: i.filter((e) => (D.get(e) ?? 0) > 0).map((e) => /* @__PURE__ */ d(
|
|
64
|
+
children: i.filter((e) => (D.get(e) ?? 0) > 0).map((e) => /* @__PURE__ */ d(f, {
|
|
65
65
|
variant: o(e),
|
|
66
66
|
children: [
|
|
67
67
|
n(e),
|
|
@@ -4,8 +4,8 @@ import { Gauge as n } from "lucide-react";
|
|
|
4
4
|
import { gql as r } from "@apollo/client";
|
|
5
5
|
import { useQuery as i } from "@apollo/client/react";
|
|
6
6
|
import { jsx as a, jsxs as o } from "react/jsx-runtime";
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
7
|
+
import { Card as s, CardContent as c, CardHeader as l, CardTitle as u } from "@burdenoff/fe-libs/ui";
|
|
8
|
+
import { useI18n as d } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
|
|
9
9
|
//#region src/planmagnet/forecast/ResourceForecastCard.tsx
|
|
10
10
|
var f = r`
|
|
11
11
|
query PlanmagnetResourceForecast(
|
|
@@ -39,7 +39,7 @@ var f = r`
|
|
|
39
39
|
}
|
|
40
40
|
`;
|
|
41
41
|
function p({ workspaceId: r, teamId: p, projectId: m, horizonSprints: h = 3 }) {
|
|
42
|
-
let { t: g } =
|
|
42
|
+
let { t: g } = d(), { data: _, loading: v, error: y } = i(f, {
|
|
43
43
|
variables: {
|
|
44
44
|
workspaceId: r,
|
|
45
45
|
teamId: p,
|
|
@@ -48,15 +48,15 @@ function p({ workspaceId: r, teamId: p, projectId: m, horizonSprints: h = 3 }) {
|
|
|
48
48
|
},
|
|
49
49
|
skip: !r || !p && !m
|
|
50
50
|
}), b = _?.planmagnetResourceForecast, x = Math.max(1, ...b?.capacityGaps.map((e) => Math.abs(e.gapPoints)) ?? [1]);
|
|
51
|
-
return /* @__PURE__ */ o(
|
|
51
|
+
return /* @__PURE__ */ o(s, {
|
|
52
52
|
"data-testid": "resource-forecast",
|
|
53
|
-
children: [/* @__PURE__ */ o(
|
|
53
|
+
children: [/* @__PURE__ */ o(l, { children: [/* @__PURE__ */ o(u, {
|
|
54
54
|
className: "flex items-center gap-2",
|
|
55
55
|
children: [/* @__PURE__ */ a(n, { className: "h-4 w-4" }), g("planmagnet.forecast.resource.title", "Resource forecast")]
|
|
56
56
|
}), /* @__PURE__ */ a("p", {
|
|
57
57
|
className: "text-xs text-muted-foreground",
|
|
58
58
|
children: g("planmagnet.forecast.resource.subtitle", "Open backlog vs. historical velocity, over the next {{count}} sprint(s).", { count: h })
|
|
59
|
-
})] }), /* @__PURE__ */ a(
|
|
59
|
+
})] }), /* @__PURE__ */ a(c, { children: !p && !m ? null : v && !_ ? /* @__PURE__ */ a("div", {
|
|
60
60
|
className: "flex justify-center py-8",
|
|
61
61
|
children: /* @__PURE__ */ a("div", { className: "animate-spin h-6 w-6 border-2 border-primary border-t-transparent rounded-full" })
|
|
62
62
|
}) : y ? /* @__PURE__ */ a("p", {
|
|
@@ -28,7 +28,7 @@ export declare const SYNC_DIRECTIONS: readonly ["INBOUND", "OUTBOUND", "BIDIRECT
|
|
|
28
28
|
export type SyncDirection = (typeof SYNC_DIRECTIONS)[number];
|
|
29
29
|
export declare const SYNC_STATUSES: readonly ["IDLE", "SYNCING", "SUCCESS", "FAILED", "PAUSED", "DISABLED"];
|
|
30
30
|
export type SyncStatus = (typeof SYNC_STATUSES)[number];
|
|
31
|
-
export declare const CONFLICT_RESOLUTIONS: readonly ["SOURCE_WINS", "TARGET_WINS", "MANUAL"];
|
|
31
|
+
export declare const CONFLICT_RESOLUTIONS: readonly ["SOURCE_WINS", "TARGET_WINS", "MERGE", "MANUAL"];
|
|
32
32
|
export type ConflictResolution = (typeof CONFLICT_RESOLUTIONS)[number];
|
|
33
33
|
export declare const CONFLICT_STATUSES: readonly ["OPEN", "RESOLVED"];
|
|
34
34
|
export type ConflictStatus = (typeof CONFLICT_STATUSES)[number];
|
|
@@ -133,6 +133,7 @@ export interface SyncConnectionTestResult {
|
|
|
133
133
|
}
|
|
134
134
|
export declare function providerLabel(provider: string): string;
|
|
135
135
|
export declare function directionLabel(direction: string): string;
|
|
136
|
+
export declare function conflictStrategyLabel(value: string): string;
|
|
136
137
|
/** Whether a capability supports a given direction at all — the single gate the wizard and the edit form both use. */
|
|
137
138
|
export declare function directionSupported(capability: Pick<SyncProviderCapability, 'supportsImport' | 'supportsExport' | 'supportsBidirectional'>, direction: SyncDirection): boolean;
|
|
138
139
|
/** True once a provider can run at least one live direction — the gate for selecting it in the wizard at all. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"syncTypes.d.ts","sourceRoot":"","sources":["../../../src/planmagnet/integrations/syncTypes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,eAAO,MAAM,cAAc,qHAWjB,CAAC;AACX,MAAM,MAAM,YAAY,GAAG,CAAC,OAAO,cAAc,CAAC,CAAC,MAAM,CAAC,CAAC;AAE3D,eAAO,MAAM,eAAe,mDAAoD,CAAC;AACjF,MAAM,MAAM,aAAa,GAAG,CAAC,OAAO,eAAe,CAAC,CAAC,MAAM,CAAC,CAAC;AAE7D,eAAO,MAAM,aAAa,yEAOhB,CAAC;AACX,MAAM,MAAM,UAAU,GAAG,CAAC,OAAO,aAAa,CAAC,CAAC,MAAM,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"syncTypes.d.ts","sourceRoot":"","sources":["../../../src/planmagnet/integrations/syncTypes.ts"],"names":[],"mappings":"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"}
|
|
@@ -13,6 +13,7 @@ var e = [
|
|
|
13
13
|
], n = [
|
|
14
14
|
"SOURCE_WINS",
|
|
15
15
|
"TARGET_WINS",
|
|
16
|
+
"MERGE",
|
|
16
17
|
"MANUAL"
|
|
17
18
|
], r = ["priority", "dueDate"], i = {
|
|
18
19
|
priority: "priority:",
|
|
@@ -40,20 +41,29 @@ var s = {
|
|
|
40
41
|
function c(e) {
|
|
41
42
|
return s[e] ?? e;
|
|
42
43
|
}
|
|
43
|
-
|
|
44
|
+
var l = {
|
|
45
|
+
SOURCE_WINS: "PlanMagnet wins",
|
|
46
|
+
TARGET_WINS: "Provider wins",
|
|
47
|
+
MERGE: "Merge",
|
|
48
|
+
MANUAL: "Manual"
|
|
49
|
+
};
|
|
50
|
+
function u(e) {
|
|
51
|
+
return l[e] ?? e;
|
|
52
|
+
}
|
|
53
|
+
function d(e, t) {
|
|
44
54
|
return t === "INBOUND" ? e.supportsImport : t === "OUTBOUND" ? e.supportsExport : e.supportsBidirectional;
|
|
45
55
|
}
|
|
46
|
-
function
|
|
56
|
+
function f(e) {
|
|
47
57
|
return e.supportsImport || e.supportsExport || e.supportsBidirectional;
|
|
48
58
|
}
|
|
49
|
-
var
|
|
50
|
-
function
|
|
51
|
-
return
|
|
59
|
+
var p = /^[A-Za-z0-9](?:[A-Za-z0-9-]{0,37}[A-Za-z0-9])?$/, m = /^[A-Za-z0-9._-]{1,100}$/;
|
|
60
|
+
function h(e) {
|
|
61
|
+
return p.test(e.trim());
|
|
52
62
|
}
|
|
53
|
-
function
|
|
54
|
-
return
|
|
63
|
+
function g(e) {
|
|
64
|
+
return m.test(e.trim());
|
|
55
65
|
}
|
|
56
|
-
function
|
|
66
|
+
function _(e) {
|
|
57
67
|
let t = {
|
|
58
68
|
priority: "",
|
|
59
69
|
dueDate: ""
|
|
@@ -66,6 +76,6 @@ function h(e) {
|
|
|
66
76
|
return t;
|
|
67
77
|
}
|
|
68
78
|
//#endregion
|
|
69
|
-
export { n as CONFLICT_RESOLUTIONS, i as GITHUB_FIELD_MAPPING_DEFAULTS, e as SYNC_DIRECTIONS, t as SYNC_STATUSES, c as directionLabel,
|
|
79
|
+
export { n as CONFLICT_RESOLUTIONS, i as GITHUB_FIELD_MAPPING_DEFAULTS, e as SYNC_DIRECTIONS, t as SYNC_STATUSES, u as conflictStrategyLabel, c as directionLabel, d as directionSupported, h as isValidGithubOwner, g as isValidGithubRepo, _ as parseGithubFieldMapping, f as providerIsLive, o as providerLabel };
|
|
70
80
|
|
|
71
81
|
//# sourceMappingURL=syncTypes.js.map
|