@burdenoff/microfe-planmagnet 2026.925.18 → 2026.926.2
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/generated/wspace-types.d.ts +61 -2
- package/dist/generated/wspace-types.d.ts.map +1 -1
- package/dist/planmagnet/PlanMagnetRoot.d.ts.map +1 -1
- package/dist/planmagnet/PlanMagnetRoot.js +90 -79
- package/dist/planmagnet/PlanMagnetRoot.js.map +1 -1
- package/dist/planmagnet/PlanMagnetRoutes.d.ts.map +1 -1
- package/dist/planmagnet/PlanMagnetRoutes.js +124 -127
- package/dist/planmagnet/PlanMagnetRoutes.js.map +1 -1
- package/dist/planmagnet/create/CreateDialogs.d.ts.map +1 -1
- package/dist/planmagnet/create/CreateDialogs.js +149 -124
- package/dist/planmagnet/create/CreateDialogs.js.map +1 -1
- package/dist/planmagnet/pages/DocsDocDetailPagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/DocsDocDetailPagePage.js +1 -1
- package/dist/planmagnet/pages/DocsDocDetailPagePage.js.map +1 -1
- package/dist/planmagnet/pages/NotFoundPage.d.ts +6 -0
- package/dist/planmagnet/pages/NotFoundPage.d.ts.map +1 -0
- package/dist/planmagnet/pages/NotFoundPage.js +18 -0
- package/dist/planmagnet/pages/NotFoundPage.js.map +1 -0
- package/dist/planmagnet/pages/ProductsCreateProductPagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/ProductsCreateProductPagePage.js +93 -98
- package/dist/planmagnet/pages/ProductsCreateProductPagePage.js.map +1 -1
- package/dist/planmagnet/pages/ProductsCreateRoadmapPagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/ProductsCreateRoadmapPagePage.js +72 -79
- package/dist/planmagnet/pages/ProductsCreateRoadmapPagePage.js.map +1 -1
- package/dist/planmagnet/pages/ProductsEditProductPagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/ProductsEditProductPagePage.js +112 -123
- package/dist/planmagnet/pages/ProductsEditProductPagePage.js.map +1 -1
- package/dist/planmagnet/pages/ProductsNewFeaturePagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/ProductsNewFeaturePagePage.js +103 -87
- package/dist/planmagnet/pages/ProductsNewFeaturePagePage.js.map +1 -1
- package/dist/planmagnet/pages/ProductsProductDetailPagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/ProductsProductDetailPagePage.js +92 -98
- package/dist/planmagnet/pages/ProductsProductDetailPagePage.js.map +1 -1
- package/dist/planmagnet/pages/ProductsProductsPagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/ProductsProductsPagePage.js +88 -96
- package/dist/planmagnet/pages/ProductsProductsPagePage.js.map +1 -1
- package/dist/planmagnet/pages/ProductsRoadmapAnalyticsPagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/ProductsRoadmapAnalyticsPagePage.js +116 -114
- package/dist/planmagnet/pages/ProductsRoadmapAnalyticsPagePage.js.map +1 -1
- package/dist/planmagnet/pages/ProductsRoadmapDetailPagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/ProductsRoadmapDetailPagePage.js +82 -88
- package/dist/planmagnet/pages/ProductsRoadmapDetailPagePage.js.map +1 -1
- package/dist/planmagnet/pages/ProductsRoadmapsPagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/ProductsRoadmapsPagePage.js +79 -79
- package/dist/planmagnet/pages/ProductsRoadmapsPagePage.js.map +1 -1
- package/dist/planmagnet/pages/ProjectsCreateProjectPagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/ProjectsCreateProjectPagePage.js +111 -91
- package/dist/planmagnet/pages/ProjectsCreateProjectPagePage.js.map +1 -1
- package/dist/planmagnet/pages/ProjectsEditProjectPagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/ProjectsEditProjectPagePage.js +117 -97
- package/dist/planmagnet/pages/ProjectsEditProjectPagePage.js.map +1 -1
- package/dist/planmagnet/pages/ProjectsPlanningDetailPagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/ProjectsPlanningDetailPagePage.js +150 -154
- package/dist/planmagnet/pages/ProjectsPlanningDetailPagePage.js.map +1 -1
- package/dist/planmagnet/pages/ProjectsPlanningEditPagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/ProjectsPlanningEditPagePage.js +154 -117
- package/dist/planmagnet/pages/ProjectsPlanningEditPagePage.js.map +1 -1
- package/dist/planmagnet/pages/SprintsStartSprintPagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/SprintsStartSprintPagePage.js +75 -31
- package/dist/planmagnet/pages/SprintsStartSprintPagePage.js.map +1 -1
- package/dist/planmagnet/pages/TasksCreateTaskPagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/TasksCreateTaskPagePage.js +161 -115
- package/dist/planmagnet/pages/TasksCreateTaskPagePage.js.map +1 -1
- package/dist/planmagnet/pages/TasksEditTaskPagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/TasksEditTaskPagePage.js +117 -102
- package/dist/planmagnet/pages/TasksEditTaskPagePage.js.map +1 -1
- package/dist/planmagnet/pages/TeamInviteMemberPagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/TeamInviteMemberPagePage.js +147 -147
- package/dist/planmagnet/pages/TeamInviteMemberPagePage.js.map +1 -1
- package/dist/planmagnet/pages/TeamTeamPagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/TeamTeamPagePage.js +77 -67
- package/dist/planmagnet/pages/TeamTeamPagePage.js.map +1 -1
- package/dist/planmagnet/roadmaps/planningFocus.d.ts +23 -0
- package/dist/planmagnet/roadmaps/planningFocus.d.ts.map +1 -0
- package/dist/planmagnet/roadmaps/planningFocus.js +76 -0
- package/dist/planmagnet/roadmaps/planningFocus.js.map +1 -0
- package/dist/planmagnet/sprints/SprintControls.d.ts.map +1 -1
- package/dist/planmagnet/sprints/SprintControls.js +48 -29
- package/dist/planmagnet/sprints/SprintControls.js.map +1 -1
- package/dist/planmagnet/sprints/SprintDates.d.ts +37 -0
- package/dist/planmagnet/sprints/SprintDates.d.ts.map +1 -0
- package/dist/planmagnet/sprints/SprintDates.js +114 -0
- package/dist/planmagnet/sprints/SprintDates.js.map +1 -0
- package/dist/planmagnet/utils/email.d.ts +9 -0
- package/dist/planmagnet/utils/email.d.ts.map +1 -0
- package/dist/planmagnet/utils/email.js +15 -0
- package/dist/planmagnet/utils/email.js.map +1 -0
- package/dist/planmagnet/utils/formValidation.d.ts +18 -0
- package/dist/planmagnet/utils/formValidation.d.ts.map +1 -0
- package/dist/planmagnet/utils/formValidation.js +17 -0
- package/dist/planmagnet/utils/formValidation.js.map +1 -0
- package/package.json +1 -1
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
import { usePlanMagnet as e } from "../providers/PlanMagnetProvider.js";
|
|
2
|
-
import { PersonName as
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
1
|
+
import { usePlanMagnet as e, usePlanMagnetNavigate as t } from "../providers/PlanMagnetProvider.js";
|
|
2
|
+
import { PersonName as n } from "../people/People.js";
|
|
3
|
+
import { UserPlus as r } from "lucide-react";
|
|
4
|
+
import { gql as i } from "@apollo/client";
|
|
5
|
+
import { useQuery as a } from "@apollo/client/react";
|
|
6
|
+
import { jsx as o, jsxs as s } from "react/jsx-runtime";
|
|
7
|
+
import { Badge as c, Button as l, Card as u, CardContent as d, CardHeader as f, CardTitle as p } from "@burdenoff/fe-libs/ui";
|
|
7
8
|
//#region src/planmagnet/pages/TeamTeamPagePage.tsx
|
|
8
|
-
var
|
|
9
|
+
var m = i`
|
|
9
10
|
query GetTeamData(
|
|
10
11
|
$workspaceId: ID!
|
|
11
12
|
$projectPagination: PlanmagnetPaginationInput
|
|
@@ -32,164 +33,173 @@ var d = n`
|
|
|
32
33
|
totalCount
|
|
33
34
|
}
|
|
34
35
|
}
|
|
35
|
-
`,
|
|
36
|
+
`, h = {
|
|
36
37
|
active: "bg-green-400",
|
|
37
38
|
away: "bg-yellow-400",
|
|
38
39
|
busy: "bg-red-400",
|
|
39
40
|
offline: "bg-gray-300"
|
|
40
41
|
};
|
|
41
|
-
function
|
|
42
|
-
let { workspaceId:
|
|
42
|
+
function g() {
|
|
43
|
+
let { workspaceId: i } = e(), g = t(), { data: _, loading: v, error: y } = a(m, {
|
|
43
44
|
variables: {
|
|
44
|
-
workspaceId:
|
|
45
|
+
workspaceId: i,
|
|
45
46
|
projectPagination: { first: 100 },
|
|
46
47
|
workItemPagination: { first: 500 }
|
|
47
48
|
},
|
|
48
|
-
skip: !
|
|
49
|
+
skip: !i
|
|
49
50
|
});
|
|
50
|
-
if (
|
|
51
|
+
if (v && !_) return /* @__PURE__ */ o("div", {
|
|
51
52
|
className: "flex items-center justify-center p-12",
|
|
52
|
-
children: /* @__PURE__ */
|
|
53
|
+
children: /* @__PURE__ */ o("div", { className: "animate-spin h-8 w-8 border-2 border-primary border-t-transparent rounded-full" })
|
|
53
54
|
});
|
|
54
|
-
if (
|
|
55
|
+
if (y) return /* @__PURE__ */ s("div", {
|
|
55
56
|
className: "p-6 text-red-500",
|
|
56
|
-
children: ["Error: ",
|
|
57
|
+
children: ["Error: ", y.message]
|
|
57
58
|
});
|
|
58
|
-
let
|
|
59
|
-
let t =
|
|
59
|
+
let b = _?.planmagnetProjects?.items ?? [], x = _?.planmagnetWorkItems?.items ?? [], S = new Set(x.filter((e) => e.assigneeId).map((e) => e.assigneeId)), C = new Set(b.filter((e) => e.ownerId).map((e) => e.ownerId)), w = new Set([...S, ...C]), T = Array.from(w).map((e) => {
|
|
60
|
+
let t = x.filter((t) => t.assigneeId === e), n = t.length, r = t.filter((e) => e.status === "DONE").length, i = t.filter((e) => e.status === "DONE").reduce((e, t) => e + (t.storyPoints ?? 0), 0);
|
|
60
61
|
return {
|
|
61
62
|
id: e,
|
|
62
63
|
name: e,
|
|
63
|
-
role:
|
|
64
|
+
role: b.filter((t) => t.ownerId === e).length > 0 ? "Project Owner" : "Contributor",
|
|
64
65
|
department: "Engineering",
|
|
65
66
|
tasksAssigned: n,
|
|
66
67
|
tasksCompleted: r,
|
|
67
68
|
velocity: i,
|
|
68
69
|
status: n > 0 ? "active" : "offline"
|
|
69
70
|
};
|
|
70
|
-
}),
|
|
71
|
+
}), E = b.reduce((e, t) => {
|
|
71
72
|
let n = t.methodology ?? "unassigned";
|
|
72
73
|
return e[n] || (e[n] = {
|
|
73
74
|
projects: [],
|
|
74
75
|
ownerIds: /* @__PURE__ */ new Set()
|
|
75
76
|
}), e[n].projects.push(t), t.ownerId && e[n].ownerIds.add(t.ownerId), e;
|
|
76
|
-
}, {}),
|
|
77
|
+
}, {}), D = Object.entries(E).map(([e, t]) => ({
|
|
77
78
|
id: e,
|
|
78
79
|
name: `${e.charAt(0).toUpperCase()}${e.slice(1)} Team`,
|
|
79
80
|
description: `Projects using ${e} methodology`,
|
|
80
81
|
projectsCount: t.projects.length,
|
|
81
82
|
leadId: Array.from(t.ownerIds)[0] ?? "Unassigned"
|
|
82
83
|
}));
|
|
83
|
-
return /* @__PURE__ */
|
|
84
|
+
return /* @__PURE__ */ s("div", {
|
|
84
85
|
className: "space-y-6 p-6",
|
|
85
86
|
children: [
|
|
86
|
-
/* @__PURE__ */
|
|
87
|
-
className: "
|
|
88
|
-
children: "
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
87
|
+
/* @__PURE__ */ s("div", {
|
|
88
|
+
className: "flex items-start justify-between gap-4",
|
|
89
|
+
children: [/* @__PURE__ */ s("div", { children: [/* @__PURE__ */ o("h1", {
|
|
90
|
+
className: "text-2xl font-semibold",
|
|
91
|
+
children: "Team Overview"
|
|
92
|
+
}), /* @__PURE__ */ s("p", {
|
|
93
|
+
className: "text-sm text-muted-foreground",
|
|
94
|
+
children: [
|
|
95
|
+
T.length,
|
|
96
|
+
" contributors across ",
|
|
97
|
+
D.length,
|
|
98
|
+
" teams"
|
|
99
|
+
]
|
|
100
|
+
})] }), /* @__PURE__ */ s(l, {
|
|
101
|
+
size: "sm",
|
|
102
|
+
variant: "outline",
|
|
103
|
+
onClick: () => g("/team/invite-member-page"),
|
|
104
|
+
"data-testid": "team-invite",
|
|
105
|
+
children: [/* @__PURE__ */ o(r, { className: "mr-1 h-4 w-4" }), "Invite member"]
|
|
106
|
+
})]
|
|
107
|
+
}),
|
|
108
|
+
/* @__PURE__ */ s("div", {
|
|
99
109
|
className: "space-y-4",
|
|
100
|
-
children: [/* @__PURE__ */
|
|
110
|
+
children: [/* @__PURE__ */ o("h2", {
|
|
101
111
|
className: "text-lg font-medium",
|
|
102
112
|
children: "Teams"
|
|
103
|
-
}), /* @__PURE__ */
|
|
113
|
+
}), /* @__PURE__ */ s("div", {
|
|
104
114
|
className: "grid grid-cols-1 md:grid-cols-2 gap-4",
|
|
105
|
-
children: [
|
|
115
|
+
children: [D.map((e) => /* @__PURE__ */ s(u, { children: [/* @__PURE__ */ o(f, {
|
|
106
116
|
className: "pb-2",
|
|
107
|
-
children: /* @__PURE__ */
|
|
117
|
+
children: /* @__PURE__ */ s("div", {
|
|
108
118
|
className: "flex items-center justify-between",
|
|
109
|
-
children: [/* @__PURE__ */
|
|
119
|
+
children: [/* @__PURE__ */ o(p, {
|
|
110
120
|
className: "text-base",
|
|
111
121
|
children: e.name
|
|
112
|
-
}), /* @__PURE__ */
|
|
122
|
+
}), /* @__PURE__ */ s(c, {
|
|
113
123
|
variant: "outline",
|
|
114
124
|
children: [e.projectsCount, " projects"]
|
|
115
125
|
})]
|
|
116
126
|
})
|
|
117
|
-
}), /* @__PURE__ */
|
|
127
|
+
}), /* @__PURE__ */ s(d, { children: [/* @__PURE__ */ o("p", {
|
|
118
128
|
className: "text-sm text-muted-foreground",
|
|
119
129
|
children: e.description
|
|
120
|
-
}), /* @__PURE__ */
|
|
130
|
+
}), /* @__PURE__ */ s("p", {
|
|
121
131
|
className: "text-xs text-muted-foreground mt-2",
|
|
122
|
-
children: ["Lead: ", /* @__PURE__ */
|
|
123
|
-
})] })] }, e.id)),
|
|
132
|
+
children: ["Lead: ", /* @__PURE__ */ o(n, { id: e.leadId })]
|
|
133
|
+
})] })] }, e.id)), D.length === 0 && /* @__PURE__ */ o("p", {
|
|
124
134
|
className: "text-sm text-muted-foreground col-span-2 text-center py-4",
|
|
125
135
|
children: "No teams found. Create projects to see team groupings."
|
|
126
136
|
})]
|
|
127
137
|
})]
|
|
128
138
|
}),
|
|
129
|
-
/* @__PURE__ */
|
|
139
|
+
/* @__PURE__ */ s("div", {
|
|
130
140
|
className: "space-y-4",
|
|
131
|
-
children: [/* @__PURE__ */
|
|
141
|
+
children: [/* @__PURE__ */ o("h2", {
|
|
132
142
|
className: "text-lg font-medium",
|
|
133
143
|
children: "Members"
|
|
134
|
-
}), /* @__PURE__ */
|
|
144
|
+
}), /* @__PURE__ */ s("div", {
|
|
135
145
|
className: "grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4",
|
|
136
|
-
children: [
|
|
146
|
+
children: [T.map((e) => /* @__PURE__ */ o(u, { children: /* @__PURE__ */ s(d, {
|
|
137
147
|
className: "pt-4 space-y-3",
|
|
138
148
|
children: [
|
|
139
|
-
/* @__PURE__ */
|
|
149
|
+
/* @__PURE__ */ s("div", {
|
|
140
150
|
className: "flex items-center gap-3",
|
|
141
|
-
children: [/* @__PURE__ */
|
|
151
|
+
children: [/* @__PURE__ */ s("div", {
|
|
142
152
|
className: "relative",
|
|
143
|
-
children: [/* @__PURE__ */
|
|
153
|
+
children: [/* @__PURE__ */ o("div", {
|
|
144
154
|
className: "h-10 w-10 rounded-full bg-primary/10 flex items-center justify-center text-sm font-medium text-primary",
|
|
145
155
|
children: e.name.split(/[\s-]+/).slice(0, 2).map((e) => e[0]?.toUpperCase() ?? "").join("")
|
|
146
|
-
}), /* @__PURE__ */
|
|
147
|
-
}), /* @__PURE__ */
|
|
156
|
+
}), /* @__PURE__ */ o("div", { className: `absolute -bottom-0.5 -right-0.5 h-3 w-3 rounded-full border-2 border-background ${h[e.status]}` })]
|
|
157
|
+
}), /* @__PURE__ */ s("div", { children: [/* @__PURE__ */ o("p", {
|
|
148
158
|
className: "text-sm font-medium",
|
|
149
159
|
children: e.name
|
|
150
|
-
}), /* @__PURE__ */
|
|
160
|
+
}), /* @__PURE__ */ o("p", {
|
|
151
161
|
className: "text-xs text-muted-foreground",
|
|
152
162
|
children: e.role
|
|
153
163
|
})] })]
|
|
154
164
|
}),
|
|
155
|
-
/* @__PURE__ */
|
|
165
|
+
/* @__PURE__ */ s("div", {
|
|
156
166
|
className: "grid grid-cols-3 gap-2 text-center text-xs",
|
|
157
167
|
children: [
|
|
158
|
-
/* @__PURE__ */
|
|
168
|
+
/* @__PURE__ */ s("div", { children: [/* @__PURE__ */ o("p", {
|
|
159
169
|
className: "font-semibold",
|
|
160
170
|
children: e.tasksAssigned
|
|
161
|
-
}), /* @__PURE__ */
|
|
171
|
+
}), /* @__PURE__ */ o("p", {
|
|
162
172
|
className: "text-muted-foreground",
|
|
163
173
|
children: "Assigned"
|
|
164
174
|
})] }),
|
|
165
|
-
/* @__PURE__ */
|
|
175
|
+
/* @__PURE__ */ s("div", { children: [/* @__PURE__ */ o("p", {
|
|
166
176
|
className: "font-semibold",
|
|
167
177
|
children: e.tasksCompleted
|
|
168
|
-
}), /* @__PURE__ */
|
|
178
|
+
}), /* @__PURE__ */ o("p", {
|
|
169
179
|
className: "text-muted-foreground",
|
|
170
180
|
children: "Done"
|
|
171
181
|
})] }),
|
|
172
|
-
/* @__PURE__ */
|
|
182
|
+
/* @__PURE__ */ s("div", { children: [/* @__PURE__ */ o("p", {
|
|
173
183
|
className: "font-semibold",
|
|
174
184
|
children: e.velocity
|
|
175
|
-
}), /* @__PURE__ */
|
|
185
|
+
}), /* @__PURE__ */ o("p", {
|
|
176
186
|
className: "text-muted-foreground",
|
|
177
187
|
children: "Velocity"
|
|
178
188
|
})] })
|
|
179
189
|
]
|
|
180
190
|
}),
|
|
181
|
-
/* @__PURE__ */
|
|
191
|
+
/* @__PURE__ */ s("div", {
|
|
182
192
|
className: "flex justify-between text-xs",
|
|
183
|
-
children: [/* @__PURE__ */
|
|
193
|
+
children: [/* @__PURE__ */ o("span", {
|
|
184
194
|
className: "text-muted-foreground",
|
|
185
195
|
children: e.department
|
|
186
|
-
}), /* @__PURE__ */
|
|
196
|
+
}), /* @__PURE__ */ o("span", {
|
|
187
197
|
className: "capitalize text-muted-foreground",
|
|
188
198
|
children: e.status
|
|
189
199
|
})]
|
|
190
200
|
})
|
|
191
201
|
]
|
|
192
|
-
}) }, e.id)),
|
|
202
|
+
}) }, e.id)), T.length === 0 && /* @__PURE__ */ o("p", {
|
|
193
203
|
className: "text-sm text-muted-foreground col-span-3 text-center py-4",
|
|
194
204
|
children: "No team members found. Assign work items to see members here."
|
|
195
205
|
})]
|
|
@@ -199,6 +209,6 @@ function p() {
|
|
|
199
209
|
});
|
|
200
210
|
}
|
|
201
211
|
//#endregion
|
|
202
|
-
export {
|
|
212
|
+
export { g as TeamTeamPagePage };
|
|
203
213
|
|
|
204
214
|
//# sourceMappingURL=TeamTeamPagePage.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TeamTeamPagePage.js","names":[],"sources":["../../../src/planmagnet/pages/TeamTeamPagePage.tsx"],"sourcesContent":["// eslint-disable-next-line @typescript-eslint/ban-ts-comment\n// @ts-nocheck\nimport { gql } from '@apollo/client';\nimport { useQuery } from '@apollo/client/react';\nimport { Card, CardContent, CardHeader, CardTitle, Badge } from '@burdenoff/fe-libs/ui';\nimport { Users } from 'lucide-react';\nimport { usePlanMagnet } from '../providers/PlanMagnetProvider';\nimport { PersonName } from '../people/People';\n\nconst GET_TEAM_DATA = gql`\n query GetTeamData(\n $workspaceId: ID!\n $projectPagination: PlanmagnetPaginationInput\n $workItemPagination: PlanmagnetPaginationInput\n ) {\n planmagnetProjects(workspaceId: $workspaceId, pagination: $projectPagination) {\n items {\n id\n name\n key\n status\n ownerId\n methodology\n }\n totalCount\n }\n planmagnetWorkItems(workspaceId: $workspaceId, pagination: $workItemPagination) {\n items {\n id\n status\n assigneeId\n storyPoints\n }\n totalCount\n }\n }\n`;\n\ninterface ProjectNode {\n id: string;\n name: string;\n key: string;\n status: string;\n ownerId: string | null;\n methodology: string | null;\n}\n\ninterface WorkItemNode {\n id: string;\n status: string;\n assigneeId: string | null;\n storyPoints: number | null;\n}\n\ninterface TeamData {\n projects: { items: ProjectNode[]; totalCount: number };\n workItems: { items: WorkItemNode[]; totalCount: number };\n}\n\nconst statusColor: Record<string, string> = {\n active: 'bg-green-400',\n away: 'bg-yellow-400',\n busy: 'bg-red-400',\n offline: 'bg-gray-300',\n};\n\nexport function TeamTeamPagePage() {\n const { workspaceId } = usePlanMagnet();\n\n const { data, loading, error } = useQuery<TeamData>(GET_TEAM_DATA, {\n variables: {\n workspaceId,\n projectPagination: { first: 100 },\n workItemPagination: { first: 500 },\n },\n skip: !workspaceId,\n });\n\n // Only before the first load: a refetch must not blank the page (it\n\n // unmounts every component on it and loses their state).\n\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 <div className=\"p-6 text-red-500\">Error: {error.message}</div>;\n }\n\n const projects = data?.planmagnetProjects?.items ?? [];\n const workItems = data?.planmagnetWorkItems?.items ?? [];\n\n const assigneeIds = new Set(\n workItems.filter((wi) => wi.assigneeId).map((wi) => wi.assigneeId as string)\n );\n const ownerIds = new Set(projects.filter((p) => p.ownerId).map((p) => p.ownerId as string));\n const allMemberIds = new Set([...assigneeIds, ...ownerIds]);\n\n const members = Array.from(allMemberIds).map((memberId) => {\n const memberWorkItems = workItems.filter((wi) => wi.assigneeId === memberId);\n const assigned = memberWorkItems.length;\n const completed = memberWorkItems.filter((wi) => wi.status === 'DONE').length;\n const velocity = memberWorkItems\n .filter((wi) => wi.status === 'DONE')\n .reduce((s, wi) => s + (wi.storyPoints ?? 0), 0);\n const memberProjects = projects.filter((p) => p.ownerId === memberId);\n\n return {\n id: memberId,\n name: memberId,\n role: memberProjects.length > 0 ? 'Project Owner' : 'Contributor',\n department: 'Engineering',\n tasksAssigned: assigned,\n tasksCompleted: completed,\n velocity,\n status: assigned > 0 ? 'active' : 'offline',\n };\n });\n\n const teamsByMethodology = projects.reduce(\n (acc, p) => {\n const method = p.methodology ?? 'unassigned';\n if (!acc[method]) {\n acc[method] = { projects: [], ownerIds: new Set<string>() };\n }\n acc[method].projects.push(p);\n if (p.ownerId) acc[method].ownerIds.add(p.ownerId);\n return acc;\n },\n {} as Record<string, { projects: ProjectNode[]; ownerIds: Set<string> }>\n );\n\n const teams = Object.entries(teamsByMethodology).map(([methodology, group]) => ({\n id: methodology,\n name: `${methodology.charAt(0).toUpperCase()}${methodology.slice(1)} Team`,\n description: `Projects using ${methodology} methodology`,\n projectsCount: group.projects.length,\n leadId: Array.from(group.ownerIds)[0] ?? 'Unassigned',\n }));\n\n return (\n <div className=\"space-y-6 p-6\">\n <div>\n <h1 className=\"text-2xl font-semibold\">Team Overview</h1>\n <p className=\"text-sm text-muted-foreground\">\n {members.length} contributors across {teams.length} teams\n </p>\n </div>\n\n <div className=\"space-y-4\">\n <h2 className=\"text-lg font-medium\">Teams</h2>\n <div className=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\n {teams.map((team) => (\n <Card key={team.id}>\n <CardHeader className=\"pb-2\">\n <div className=\"flex items-center justify-between\">\n <CardTitle className=\"text-base\">{team.name}</CardTitle>\n <Badge variant=\"outline\">{team.projectsCount} projects</Badge>\n </div>\n </CardHeader>\n <CardContent>\n <p className=\"text-sm text-muted-foreground\">{team.description}</p>\n <p className=\"text-xs text-muted-foreground mt-2\">\n Lead: <PersonName id={team.leadId} />\n </p>\n </CardContent>\n </Card>\n ))}\n {teams.length === 0 && (\n <p className=\"text-sm text-muted-foreground col-span-2 text-center py-4\">\n No teams found. Create projects to see team groupings.\n </p>\n )}\n </div>\n </div>\n\n <div className=\"space-y-4\">\n <h2 className=\"text-lg font-medium\">Members</h2>\n <div className=\"grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4\">\n {members.map((member) => (\n <Card key={member.id}>\n <CardContent className=\"pt-4 space-y-3\">\n <div className=\"flex items-center gap-3\">\n <div className=\"relative\">\n <div className=\"h-10 w-10 rounded-full bg-primary/10 flex items-center justify-center text-sm font-medium text-primary\">\n {member.name\n .split(/[\\s-]+/)\n .slice(0, 2)\n .map((n) => n[0]?.toUpperCase() ?? '')\n .join('')}\n </div>\n <div\n className={`absolute -bottom-0.5 -right-0.5 h-3 w-3 rounded-full border-2 border-background ${statusColor[member.status]}`}\n />\n </div>\n <div>\n <p className=\"text-sm font-medium\">{member.name}</p>\n <p className=\"text-xs text-muted-foreground\">{member.role}</p>\n </div>\n </div>\n <div className=\"grid grid-cols-3 gap-2 text-center text-xs\">\n <div>\n <p className=\"font-semibold\">{member.tasksAssigned}</p>\n <p className=\"text-muted-foreground\">Assigned</p>\n </div>\n <div>\n <p className=\"font-semibold\">{member.tasksCompleted}</p>\n <p className=\"text-muted-foreground\">Done</p>\n </div>\n <div>\n <p className=\"font-semibold\">{member.velocity}</p>\n <p className=\"text-muted-foreground\">Velocity</p>\n </div>\n </div>\n <div className=\"flex justify-between text-xs\">\n <span className=\"text-muted-foreground\">{member.department}</span>\n <span className=\"capitalize text-muted-foreground\">{member.status}</span>\n </div>\n </CardContent>\n </Card>\n ))}\n {members.length === 0 && (\n <p className=\"text-sm text-muted-foreground col-span-3 text-center py-4\">\n No team members found. Assign work items to see members here.\n </p>\n )}\n </div>\n </div>\n </div>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"TeamTeamPagePage.js","names":[],"sources":["../../../src/planmagnet/pages/TeamTeamPagePage.tsx"],"sourcesContent":["// eslint-disable-next-line @typescript-eslint/ban-ts-comment\n// @ts-nocheck\nimport { gql } from '@apollo/client';\nimport { useQuery } from '@apollo/client/react';\nimport { Card, CardContent, CardHeader, CardTitle, Badge, Button } from '@burdenoff/fe-libs/ui';\nimport { UserPlus, Users } from 'lucide-react';\nimport { usePlanMagnet, usePlanMagnetNavigate } from '../providers/PlanMagnetProvider';\nimport { PersonName } from '../people/People';\n\nconst GET_TEAM_DATA = gql`\n query GetTeamData(\n $workspaceId: ID!\n $projectPagination: PlanmagnetPaginationInput\n $workItemPagination: PlanmagnetPaginationInput\n ) {\n planmagnetProjects(workspaceId: $workspaceId, pagination: $projectPagination) {\n items {\n id\n name\n key\n status\n ownerId\n methodology\n }\n totalCount\n }\n planmagnetWorkItems(workspaceId: $workspaceId, pagination: $workItemPagination) {\n items {\n id\n status\n assigneeId\n storyPoints\n }\n totalCount\n }\n }\n`;\n\ninterface ProjectNode {\n id: string;\n name: string;\n key: string;\n status: string;\n ownerId: string | null;\n methodology: string | null;\n}\n\ninterface WorkItemNode {\n id: string;\n status: string;\n assigneeId: string | null;\n storyPoints: number | null;\n}\n\ninterface TeamData {\n projects: { items: ProjectNode[]; totalCount: number };\n workItems: { items: WorkItemNode[]; totalCount: number };\n}\n\nconst statusColor: Record<string, string> = {\n active: 'bg-green-400',\n away: 'bg-yellow-400',\n busy: 'bg-red-400',\n offline: 'bg-gray-300',\n};\n\nexport function TeamTeamPagePage() {\n const { workspaceId } = usePlanMagnet();\n const navigate = usePlanMagnetNavigate();\n\n const { data, loading, error } = useQuery<TeamData>(GET_TEAM_DATA, {\n variables: {\n workspaceId,\n projectPagination: { first: 100 },\n workItemPagination: { first: 500 },\n },\n skip: !workspaceId,\n });\n\n // Only before the first load: a refetch must not blank the page (it\n\n // unmounts every component on it and loses their state).\n\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 <div className=\"p-6 text-red-500\">Error: {error.message}</div>;\n }\n\n const projects = data?.planmagnetProjects?.items ?? [];\n const workItems = data?.planmagnetWorkItems?.items ?? [];\n\n const assigneeIds = new Set(\n workItems.filter((wi) => wi.assigneeId).map((wi) => wi.assigneeId as string)\n );\n const ownerIds = new Set(projects.filter((p) => p.ownerId).map((p) => p.ownerId as string));\n const allMemberIds = new Set([...assigneeIds, ...ownerIds]);\n\n const members = Array.from(allMemberIds).map((memberId) => {\n const memberWorkItems = workItems.filter((wi) => wi.assigneeId === memberId);\n const assigned = memberWorkItems.length;\n const completed = memberWorkItems.filter((wi) => wi.status === 'DONE').length;\n const velocity = memberWorkItems\n .filter((wi) => wi.status === 'DONE')\n .reduce((s, wi) => s + (wi.storyPoints ?? 0), 0);\n const memberProjects = projects.filter((p) => p.ownerId === memberId);\n\n return {\n id: memberId,\n name: memberId,\n role: memberProjects.length > 0 ? 'Project Owner' : 'Contributor',\n department: 'Engineering',\n tasksAssigned: assigned,\n tasksCompleted: completed,\n velocity,\n status: assigned > 0 ? 'active' : 'offline',\n };\n });\n\n const teamsByMethodology = projects.reduce(\n (acc, p) => {\n const method = p.methodology ?? 'unassigned';\n if (!acc[method]) {\n acc[method] = { projects: [], ownerIds: new Set<string>() };\n }\n acc[method].projects.push(p);\n if (p.ownerId) acc[method].ownerIds.add(p.ownerId);\n return acc;\n },\n {} as Record<string, { projects: ProjectNode[]; ownerIds: Set<string> }>\n );\n\n const teams = Object.entries(teamsByMethodology).map(([methodology, group]) => ({\n id: methodology,\n name: `${methodology.charAt(0).toUpperCase()}${methodology.slice(1)} Team`,\n description: `Projects using ${methodology} methodology`,\n projectsCount: group.projects.length,\n leadId: Array.from(group.ownerIds)[0] ?? 'Unassigned',\n }));\n\n return (\n <div className=\"space-y-6 p-6\">\n <div className=\"flex items-start justify-between gap-4\">\n <div>\n <h1 className=\"text-2xl font-semibold\">Team Overview</h1>\n <p className=\"text-sm text-muted-foreground\">\n {members.length} contributors across {teams.length} teams\n </p>\n </div>\n <Button\n size=\"sm\"\n variant=\"outline\"\n onClick={() => navigate('/team/invite-member-page')}\n data-testid=\"team-invite\"\n >\n <UserPlus className=\"mr-1 h-4 w-4\" />\n Invite member\n </Button>\n </div>\n\n <div className=\"space-y-4\">\n <h2 className=\"text-lg font-medium\">Teams</h2>\n <div className=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\n {teams.map((team) => (\n <Card key={team.id}>\n <CardHeader className=\"pb-2\">\n <div className=\"flex items-center justify-between\">\n <CardTitle className=\"text-base\">{team.name}</CardTitle>\n <Badge variant=\"outline\">{team.projectsCount} projects</Badge>\n </div>\n </CardHeader>\n <CardContent>\n <p className=\"text-sm text-muted-foreground\">{team.description}</p>\n <p className=\"text-xs text-muted-foreground mt-2\">\n Lead: <PersonName id={team.leadId} />\n </p>\n </CardContent>\n </Card>\n ))}\n {teams.length === 0 && (\n <p className=\"text-sm text-muted-foreground col-span-2 text-center py-4\">\n No teams found. Create projects to see team groupings.\n </p>\n )}\n </div>\n </div>\n\n <div className=\"space-y-4\">\n <h2 className=\"text-lg font-medium\">Members</h2>\n <div className=\"grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4\">\n {members.map((member) => (\n <Card key={member.id}>\n <CardContent className=\"pt-4 space-y-3\">\n <div className=\"flex items-center gap-3\">\n <div className=\"relative\">\n <div className=\"h-10 w-10 rounded-full bg-primary/10 flex items-center justify-center text-sm font-medium text-primary\">\n {member.name\n .split(/[\\s-]+/)\n .slice(0, 2)\n .map((n) => n[0]?.toUpperCase() ?? '')\n .join('')}\n </div>\n <div\n className={`absolute -bottom-0.5 -right-0.5 h-3 w-3 rounded-full border-2 border-background ${statusColor[member.status]}`}\n />\n </div>\n <div>\n <p className=\"text-sm font-medium\">{member.name}</p>\n <p className=\"text-xs text-muted-foreground\">{member.role}</p>\n </div>\n </div>\n <div className=\"grid grid-cols-3 gap-2 text-center text-xs\">\n <div>\n <p className=\"font-semibold\">{member.tasksAssigned}</p>\n <p className=\"text-muted-foreground\">Assigned</p>\n </div>\n <div>\n <p className=\"font-semibold\">{member.tasksCompleted}</p>\n <p className=\"text-muted-foreground\">Done</p>\n </div>\n <div>\n <p className=\"font-semibold\">{member.velocity}</p>\n <p className=\"text-muted-foreground\">Velocity</p>\n </div>\n </div>\n <div className=\"flex justify-between text-xs\">\n <span className=\"text-muted-foreground\">{member.department}</span>\n <span className=\"capitalize text-muted-foreground\">{member.status}</span>\n </div>\n </CardContent>\n </Card>\n ))}\n {members.length === 0 && (\n <p className=\"text-sm text-muted-foreground col-span-3 text-center py-4\">\n No team members found. Assign work items to see members here.\n </p>\n )}\n </div>\n </div>\n </div>\n );\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What a roadmap is organised around (BOFF-7934). Separate from how it is
|
|
3
|
+
* displayed: the roadmap page has ONE layout today (items grouped by lane with
|
|
4
|
+
* their dates), so the service accepts only the TIMELINE display and these
|
|
5
|
+
* pages no longer offer Gantt / Swimlane / Custom — a stored label is not a
|
|
6
|
+
* view. Legacy roadmaps were never classified, so a missing focus is shown as
|
|
7
|
+
* "not set", never guessed.
|
|
8
|
+
*/
|
|
9
|
+
export type PlanningFocus = 'THEME' | 'FEATURE' | 'TECHNOLOGY' | 'PORTFOLIO';
|
|
10
|
+
export declare const PLANNING_FOCUSES: readonly PlanningFocus[];
|
|
11
|
+
/** The only display the roadmap page has; the create/update inputs require one. */
|
|
12
|
+
export declare const ROADMAP_DISPLAY = "TIMELINE";
|
|
13
|
+
export declare function planningFocusLabel(focus: string | null | undefined): string;
|
|
14
|
+
/** Icon AND label, never colour alone. */
|
|
15
|
+
export declare function PlanningFocusBadge({ focus }: {
|
|
16
|
+
focus: string | null | undefined;
|
|
17
|
+
}): import("react/jsx-runtime").JSX.Element;
|
|
18
|
+
export declare function PlanningFocusSelect({ value, onChange, id, }: {
|
|
19
|
+
value: PlanningFocus | null;
|
|
20
|
+
onChange: (value: PlanningFocus | null) => void;
|
|
21
|
+
id?: string;
|
|
22
|
+
}): import("react/jsx-runtime").JSX.Element;
|
|
23
|
+
//# sourceMappingURL=planningFocus.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"planningFocus.d.ts","sourceRoot":"","sources":["../../../src/planmagnet/roadmaps/planningFocus.tsx"],"names":[],"mappings":"AAEA;;;;;;;GAOG;AACH,MAAM,MAAM,aAAa,GAAG,OAAO,GAAG,SAAS,GAAG,YAAY,GAAG,WAAW,CAAC;AAE7E,eAAO,MAAM,gBAAgB,EAAE,SAAS,aAAa,EAKpD,CAAC;AASF,mFAAmF;AACnF,eAAO,MAAM,eAAe,aAAa,CAAC;AAE1C,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,CAE3E;AAED,0CAA0C;AAC1C,wBAAgB,kBAAkB,CAAC,EAAE,KAAK,EAAE,EAAE;IAAE,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAA;CAAE,2CAoBjF;AAED,wBAAgB,mBAAmB,CAAC,EAClC,KAAK,EACL,QAAQ,EACR,EAAqB,GACtB,EAAE;IACD,KAAK,EAAE,aAAa,GAAG,IAAI,CAAC;IAC5B,QAAQ,EAAE,CAAC,KAAK,EAAE,aAAa,GAAG,IAAI,KAAK,IAAI,CAAC;IAChD,EAAE,CAAC,EAAE,MAAM,CAAC;CACb,2CAwBA"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { Boxes as e, Cpu as t, Layers as n, Lightbulb as r } from "lucide-react";
|
|
2
|
+
import { jsx as i, jsxs as a } from "react/jsx-runtime";
|
|
3
|
+
//#region src/planmagnet/roadmaps/planningFocus.tsx
|
|
4
|
+
var o = [
|
|
5
|
+
"THEME",
|
|
6
|
+
"FEATURE",
|
|
7
|
+
"TECHNOLOGY",
|
|
8
|
+
"PORTFOLIO"
|
|
9
|
+
], s = {
|
|
10
|
+
THEME: {
|
|
11
|
+
label: "Theme",
|
|
12
|
+
icon: r
|
|
13
|
+
},
|
|
14
|
+
FEATURE: {
|
|
15
|
+
label: "Feature",
|
|
16
|
+
icon: n
|
|
17
|
+
},
|
|
18
|
+
TECHNOLOGY: {
|
|
19
|
+
label: "Technology",
|
|
20
|
+
icon: t
|
|
21
|
+
},
|
|
22
|
+
PORTFOLIO: {
|
|
23
|
+
label: "Portfolio",
|
|
24
|
+
icon: e
|
|
25
|
+
}
|
|
26
|
+
}, c = "TIMELINE";
|
|
27
|
+
function l(e) {
|
|
28
|
+
return e && e in s ? s[e].label : "Focus not set";
|
|
29
|
+
}
|
|
30
|
+
function u({ focus: e }) {
|
|
31
|
+
if (!e || !(e in s)) return /* @__PURE__ */ i("span", {
|
|
32
|
+
className: "inline-flex items-center gap-1 text-xs text-muted-foreground",
|
|
33
|
+
"data-testid": "planning-focus",
|
|
34
|
+
children: "Focus not set"
|
|
35
|
+
});
|
|
36
|
+
let { label: t, icon: n } = s[e];
|
|
37
|
+
return /* @__PURE__ */ a("span", {
|
|
38
|
+
className: "inline-flex items-center gap-1 rounded-full bg-muted px-2 py-0.5 text-xs text-foreground",
|
|
39
|
+
"data-testid": "planning-focus",
|
|
40
|
+
children: [
|
|
41
|
+
/* @__PURE__ */ i(n, { className: "h-3 w-3" }),
|
|
42
|
+
" ",
|
|
43
|
+
t
|
|
44
|
+
]
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
function d({ value: e, onChange: t, id: n = "planning-focus" }) {
|
|
48
|
+
return /* @__PURE__ */ a("div", { children: [
|
|
49
|
+
/* @__PURE__ */ i("label", {
|
|
50
|
+
htmlFor: n,
|
|
51
|
+
className: "text-sm font-medium",
|
|
52
|
+
children: "Planning focus"
|
|
53
|
+
}),
|
|
54
|
+
/* @__PURE__ */ a("select", {
|
|
55
|
+
id: n,
|
|
56
|
+
className: "mt-1 w-full rounded-md border border-input bg-background px-3 py-2 text-sm",
|
|
57
|
+
value: e ?? "",
|
|
58
|
+
onChange: (e) => t(e.target.value ? e.target.value : null),
|
|
59
|
+
children: [/* @__PURE__ */ i("option", {
|
|
60
|
+
value: "",
|
|
61
|
+
children: "Not set"
|
|
62
|
+
}), o.map((e) => /* @__PURE__ */ i("option", {
|
|
63
|
+
value: e,
|
|
64
|
+
children: s[e].label
|
|
65
|
+
}, e))]
|
|
66
|
+
}),
|
|
67
|
+
/* @__PURE__ */ i("p", {
|
|
68
|
+
className: "mt-1 text-xs text-muted-foreground",
|
|
69
|
+
children: "What the roadmap is organised around. Roadmaps are shown in one layout for now."
|
|
70
|
+
})
|
|
71
|
+
] });
|
|
72
|
+
}
|
|
73
|
+
//#endregion
|
|
74
|
+
export { o as PLANNING_FOCUSES, u as PlanningFocusBadge, d as PlanningFocusSelect, c as ROADMAP_DISPLAY, l as planningFocusLabel };
|
|
75
|
+
|
|
76
|
+
//# sourceMappingURL=planningFocus.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"planningFocus.js","names":[],"sources":["../../../src/planmagnet/roadmaps/planningFocus.tsx"],"sourcesContent":["import { Boxes, Cpu, Layers, Lightbulb, type LucideIcon } from 'lucide-react';\n\n/**\n * What a roadmap is organised around (BOFF-7934). Separate from how it is\n * displayed: the roadmap page has ONE layout today (items grouped by lane with\n * their dates), so the service accepts only the TIMELINE display and these\n * pages no longer offer Gantt / Swimlane / Custom — a stored label is not a\n * view. Legacy roadmaps were never classified, so a missing focus is shown as\n * \"not set\", never guessed.\n */\nexport type PlanningFocus = 'THEME' | 'FEATURE' | 'TECHNOLOGY' | 'PORTFOLIO';\n\nexport const PLANNING_FOCUSES: readonly PlanningFocus[] = [\n 'THEME',\n 'FEATURE',\n 'TECHNOLOGY',\n 'PORTFOLIO',\n];\n\nconst FOCUS: Record<PlanningFocus, { label: string; icon: LucideIcon }> = {\n THEME: { label: 'Theme', icon: Lightbulb },\n FEATURE: { label: 'Feature', icon: Layers },\n TECHNOLOGY: { label: 'Technology', icon: Cpu },\n PORTFOLIO: { label: 'Portfolio', icon: Boxes },\n};\n\n/** The only display the roadmap page has; the create/update inputs require one. */\nexport const ROADMAP_DISPLAY = 'TIMELINE';\n\nexport function planningFocusLabel(focus: string | null | undefined): string {\n return focus && focus in FOCUS ? FOCUS[focus as PlanningFocus].label : 'Focus not set';\n}\n\n/** Icon AND label, never colour alone. */\nexport function PlanningFocusBadge({ focus }: { focus: string | null | undefined }) {\n if (!focus || !(focus in FOCUS)) {\n return (\n <span\n className=\"inline-flex items-center gap-1 text-xs text-muted-foreground\"\n data-testid=\"planning-focus\"\n >\n Focus not set\n </span>\n );\n }\n const { label, icon: Icon } = FOCUS[focus as PlanningFocus];\n return (\n <span\n className=\"inline-flex items-center gap-1 rounded-full bg-muted px-2 py-0.5 text-xs text-foreground\"\n data-testid=\"planning-focus\"\n >\n <Icon className=\"h-3 w-3\" /> {label}\n </span>\n );\n}\n\nexport function PlanningFocusSelect({\n value,\n onChange,\n id = 'planning-focus',\n}: {\n value: PlanningFocus | null;\n onChange: (value: PlanningFocus | null) => void;\n id?: string;\n}) {\n return (\n <div>\n <label htmlFor={id} className=\"text-sm font-medium\">\n Planning focus\n </label>\n <select\n id={id}\n className=\"mt-1 w-full rounded-md border border-input bg-background px-3 py-2 text-sm\"\n value={value ?? ''}\n onChange={(e) => onChange(e.target.value ? (e.target.value as PlanningFocus) : null)}\n >\n <option value=\"\">Not set</option>\n {PLANNING_FOCUSES.map((f) => (\n <option key={f} value={f}>\n {FOCUS[f].label}\n </option>\n ))}\n </select>\n <p className=\"mt-1 text-xs text-muted-foreground\">\n What the roadmap is organised around. Roadmaps are shown in one layout for now.\n </p>\n </div>\n );\n}\n"],"mappings":";;;AAYA,IAAa,IAA6C;CACxD;CACA;CACA;CACA;CACD,EAEK,IAAoE;CACxE,OAAO;EAAE,OAAO;EAAS,MAAM;EAAW;CAC1C,SAAS;EAAE,OAAO;EAAW,MAAM;EAAQ;CAC3C,YAAY;EAAE,OAAO;EAAc,MAAM;EAAK;CAC9C,WAAW;EAAE,OAAO;EAAa,MAAM;EAAO;CAC/C,EAGY,IAAkB;AAE/B,SAAgB,EAAmB,GAA0C;AAC3E,QAAO,KAAS,KAAS,IAAQ,EAAM,GAAwB,QAAQ;;AAIzE,SAAgB,EAAmB,EAAE,YAA+C;AAClF,KAAI,CAAC,KAAS,EAAE,KAAS,GACvB,QACE,kBAAC,QAAD;EACE,WAAU;EACV,eAAY;YACb;EAEM,CAAA;CAGX,IAAM,EAAE,UAAO,MAAM,MAAS,EAAM;AACpC,QACE,kBAAC,QAAD;EACE,WAAU;EACV,eAAY;YAFd;GAIE,kBAAC,GAAD,EAAM,WAAU,WAAY,CAAA;;GAAE;GACzB;;;AAIX,SAAgB,EAAoB,EAClC,UACA,aACA,QAAK,oBAKJ;AACD,QACE,kBAAC,OAAD,EAAA,UAAA;EACE,kBAAC,SAAD;GAAO,SAAS;GAAI,WAAU;aAAsB;GAE5C,CAAA;EACR,kBAAC,UAAD;GACM;GACJ,WAAU;GACV,OAAO,KAAS;GAChB,WAAW,MAAM,EAAS,EAAE,OAAO,QAAS,EAAE,OAAO,QAA0B,KAAK;aAJtF,CAME,kBAAC,UAAD;IAAQ,OAAM;cAAG;IAAgB,CAAA,EAChC,EAAiB,KAAK,MACrB,kBAAC,UAAD;IAAgB,OAAO;cACpB,EAAM,GAAG;IACH,EAFI,EAEJ,CACT,CACK;;EACT,kBAAC,KAAD;GAAG,WAAU;aAAqC;GAE9C,CAAA;EACA,EAAA,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SprintControls.d.ts","sourceRoot":"","sources":["../../../src/planmagnet/sprints/SprintControls.tsx"],"names":[],"mappings":"AA6BA;;;;;;;;;;;;GAYG;AAEH,MAAM,MAAM,YAAY,GAAG,UAAU,GAAG,QAAQ,GAAG,QAAQ,GAAG,WAAW,GAAG,WAAW,CAAC;AACxF,MAAM,MAAM,YAAY,GAAG,OAAO,GAAG,UAAU,GAAG,QAAQ,CAAC;AAQ3D,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,YAAY,EAAE,CAI/D;AAED,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAExD;AAsCD,wBAAgB,sBAAsB,CAAC,EACrC,QAAQ,EACR,UAAU,EACV,MAAM,GACP,EAAE;IACD,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;CAChB,kDA2DA;AAsFD,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AAQD,wBAAgB,oBAAoB,CAAC,EACnC,QAAQ,EACR,SAAS,EACT,MAAM,EACN,KAAK,GACN,EAAE;IACD,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,cAAc,EAAE,CAAC;CACzB,2CA2EA;AAqKD,wBAAgB,eAAe,CAAC,EAAE,SAAS,EAAE,EAAE;IAAE,SAAS,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAA;CAAE,
|
|
1
|
+
{"version":3,"file":"SprintControls.d.ts","sourceRoot":"","sources":["../../../src/planmagnet/sprints/SprintControls.tsx"],"names":[],"mappings":"AA6BA;;;;;;;;;;;;GAYG;AAEH,MAAM,MAAM,YAAY,GAAG,UAAU,GAAG,QAAQ,GAAG,QAAQ,GAAG,WAAW,GAAG,WAAW,CAAC;AACxF,MAAM,MAAM,YAAY,GAAG,OAAO,GAAG,UAAU,GAAG,QAAQ,CAAC;AAQ3D,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,YAAY,EAAE,CAI/D;AAED,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAExD;AAsCD,wBAAgB,sBAAsB,CAAC,EACrC,QAAQ,EACR,UAAU,EACV,MAAM,GACP,EAAE;IACD,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;CAChB,kDA2DA;AAsFD,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AAQD,wBAAgB,oBAAoB,CAAC,EACnC,QAAQ,EACR,SAAS,EACT,MAAM,EACN,KAAK,GACN,EAAE;IACD,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,cAAc,EAAE,CAAC;CACzB,2CA2EA;AAqKD,wBAAgB,eAAe,CAAC,EAAE,SAAS,EAAE,EAAE;IAAE,SAAS,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAA;CAAE,2CAwMvF"}
|
|
@@ -371,13 +371,13 @@ var X = l`
|
|
|
371
371
|
capacity: ""
|
|
372
372
|
};
|
|
373
373
|
function $({ onCreated: n }) {
|
|
374
|
-
let { workspaceId: i } = e(), [a, s] = r(!1), [c, l] = r(Q), [m, h] = r(null), { data: g } = d(Z, {
|
|
374
|
+
let { workspaceId: i } = e(), [a, s] = r(!1), [c, l] = r(Q), [m, h] = r(null), { data: g, loading: _, error: v, refetch: y } = d(Z, {
|
|
375
375
|
variables: { workspaceId: i ?? "" },
|
|
376
376
|
skip: !a || !i
|
|
377
|
-
}),
|
|
377
|
+
}), b = g?.planmagnetProjects.items ?? [], x = c.projectId || b[0]?.id || "", [S, { loading: C }] = u(X, {
|
|
378
378
|
refetchQueries: L,
|
|
379
379
|
awaitRefetchQueries: !0
|
|
380
|
-
}),
|
|
380
|
+
}), T = c.capacity.trim() === "" ? void 0 : Number(c.capacity), P = T !== void 0 && (!Number.isInteger(T) || T < 0), F = !!(c.startDate && c.endDate && c.endDate < c.startDate), I = c.name.trim() !== "" && x !== "" && !P && !F && !C;
|
|
381
381
|
return /* @__PURE__ */ p(D, {
|
|
382
382
|
open: a,
|
|
383
383
|
onOpenChange: (e) => {
|
|
@@ -409,26 +409,45 @@ function $({ onCreated: n }) {
|
|
|
409
409
|
name: e.target.value
|
|
410
410
|
})
|
|
411
411
|
})] }),
|
|
412
|
-
/* @__PURE__ */ p("div", { children: [
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
id: "new-sprint-project",
|
|
418
|
-
className: "mt-1 w-full rounded-md border border-input bg-background px-3 py-2 text-sm",
|
|
419
|
-
value: v,
|
|
420
|
-
onChange: (e) => l({
|
|
421
|
-
...c,
|
|
422
|
-
projectId: e.target.value
|
|
412
|
+
/* @__PURE__ */ p("div", { children: [
|
|
413
|
+
/* @__PURE__ */ f("label", {
|
|
414
|
+
htmlFor: "new-sprint-project",
|
|
415
|
+
className: "text-sm font-medium",
|
|
416
|
+
children: "Project"
|
|
423
417
|
}),
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
418
|
+
/* @__PURE__ */ p("select", {
|
|
419
|
+
id: "new-sprint-project",
|
|
420
|
+
className: "mt-1 w-full rounded-md border border-input bg-background px-3 py-2 text-sm",
|
|
421
|
+
value: x,
|
|
422
|
+
onChange: (e) => l({
|
|
423
|
+
...c,
|
|
424
|
+
projectId: e.target.value
|
|
425
|
+
}),
|
|
426
|
+
children: [b.length === 0 && /* @__PURE__ */ f("option", {
|
|
427
|
+
value: "",
|
|
428
|
+
children: _ && !g ? "Loading projects…" : v ? "Projects could not be loaded" : "No projects yet"
|
|
429
|
+
}), b.map((e) => /* @__PURE__ */ f("option", {
|
|
430
|
+
value: e.id,
|
|
431
|
+
children: e.name
|
|
432
|
+
}, e.id))]
|
|
433
|
+
}),
|
|
434
|
+
v && /* @__PURE__ */ p("p", {
|
|
435
|
+
role: "alert",
|
|
436
|
+
className: "mt-1 flex items-center gap-2 text-xs text-destructive",
|
|
437
|
+
children: [v.message, /* @__PURE__ */ f(w, {
|
|
438
|
+
type: "button",
|
|
439
|
+
size: "sm",
|
|
440
|
+
variant: "ghost",
|
|
441
|
+
className: "h-6 px-2 text-xs",
|
|
442
|
+
onClick: () => void y(),
|
|
443
|
+
children: "Retry"
|
|
444
|
+
})]
|
|
445
|
+
}),
|
|
446
|
+
!_ && !v && g && b.length === 0 && /* @__PURE__ */ f("p", {
|
|
447
|
+
className: "mt-1 text-xs text-muted-foreground",
|
|
448
|
+
children: "Create a project first (Projects → New project)."
|
|
449
|
+
})
|
|
450
|
+
] }),
|
|
432
451
|
/* @__PURE__ */ p("div", {
|
|
433
452
|
className: "grid grid-cols-2 gap-3",
|
|
434
453
|
children: [/* @__PURE__ */ p("div", { children: [/* @__PURE__ */ f("label", {
|
|
@@ -459,7 +478,7 @@ function $({ onCreated: n }) {
|
|
|
459
478
|
})
|
|
460
479
|
})] })]
|
|
461
480
|
}),
|
|
462
|
-
|
|
481
|
+
F && /* @__PURE__ */ f(V, { message: "The end date is before the start date." }),
|
|
463
482
|
/* @__PURE__ */ p("div", { children: [/* @__PURE__ */ f("label", {
|
|
464
483
|
htmlFor: "new-sprint-capacity",
|
|
465
484
|
className: "text-sm font-medium",
|
|
@@ -475,7 +494,7 @@ function $({ onCreated: n }) {
|
|
|
475
494
|
capacity: e.target.value
|
|
476
495
|
})
|
|
477
496
|
})] }),
|
|
478
|
-
|
|
497
|
+
P && /* @__PURE__ */ f(V, { message: "Capacity must be a whole number, 0 or more." }),
|
|
479
498
|
/* @__PURE__ */ p("div", { children: [/* @__PURE__ */ f("label", {
|
|
480
499
|
htmlFor: "new-sprint-goal",
|
|
481
500
|
className: "text-sm font-medium",
|
|
@@ -496,22 +515,22 @@ function $({ onCreated: n }) {
|
|
|
496
515
|
onClick: async () => {
|
|
497
516
|
h(null);
|
|
498
517
|
try {
|
|
499
|
-
let e = (await t(
|
|
518
|
+
let e = (await t(S({ variables: { input: {
|
|
500
519
|
name: c.name.trim(),
|
|
501
|
-
projectId:
|
|
520
|
+
projectId: x,
|
|
502
521
|
startDate: c.startDate || void 0,
|
|
503
522
|
endDate: c.endDate || void 0,
|
|
504
523
|
goal: c.goal.trim() || void 0,
|
|
505
|
-
capacity:
|
|
524
|
+
capacity: T
|
|
506
525
|
} } }))).data?.planmagnetCreateSprint.id;
|
|
507
526
|
l(Q), s(!1), e && n(e);
|
|
508
527
|
} catch (e) {
|
|
509
528
|
h(e instanceof Error ? e.message : "The sprint could not be created.");
|
|
510
529
|
}
|
|
511
530
|
},
|
|
512
|
-
disabled: !
|
|
531
|
+
disabled: !I,
|
|
513
532
|
"data-testid": "new-sprint-submit",
|
|
514
|
-
children:
|
|
533
|
+
children: C ? "Creating…" : "Create sprint"
|
|
515
534
|
}) })
|
|
516
535
|
]
|
|
517
536
|
})]
|