@burdenoff/microfe-planmagnet 2026.930.23 → 2026.930.24
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/index.js +6 -5
- package/dist/planmagnet/PlanMagnetRoot.d.ts.map +1 -1
- package/dist/planmagnet/PlanMagnetRoot.js +154 -147
- package/dist/planmagnet/PlanMagnetRoot.js.map +1 -1
- package/dist/planmagnet/PlanMagnetRoutes.d.ts.map +1 -1
- package/dist/planmagnet/PlanMagnetRoutes.js +66 -62
- package/dist/planmagnet/PlanMagnetRoutes.js.map +1 -1
- package/dist/planmagnet/controls/FeatureControls.d.ts +11 -0
- package/dist/planmagnet/controls/FeatureControls.d.ts.map +1 -1
- package/dist/planmagnet/controls/FeatureControls.js +305 -135
- package/dist/planmagnet/controls/FeatureControls.js.map +1 -1
- package/dist/planmagnet/controls/Pickers.d.ts +18 -0
- package/dist/planmagnet/controls/Pickers.d.ts.map +1 -1
- package/dist/planmagnet/controls/Pickers.js +78 -1
- package/dist/planmagnet/controls/Pickers.js.map +1 -1
- package/dist/planmagnet/controls/PrioritizationControls.d.ts +72 -0
- package/dist/planmagnet/controls/PrioritizationControls.d.ts.map +1 -0
- package/dist/planmagnet/controls/PrioritizationControls.js +246 -0
- package/dist/planmagnet/controls/PrioritizationControls.js.map +1 -0
- package/dist/planmagnet/index.d.ts +1 -0
- package/dist/planmagnet/index.d.ts.map +1 -1
- package/dist/planmagnet/index.js +1 -0
- package/dist/planmagnet/pages/ProductsFeatureDetailPagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/ProductsFeatureDetailPagePage.js +131 -125
- 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 +183 -99
- 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 +113 -97
- package/dist/planmagnet/pages/ProductsNewFeaturePagePage.js.map +1 -1
- package/dist/planmagnet/pages/ProductsPrioritizationPagePage.d.ts +2 -0
- package/dist/planmagnet/pages/ProductsPrioritizationPagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/ProductsPrioritizationPagePage.js +363 -0
- package/dist/planmagnet/pages/ProductsPrioritizationPagePage.js.map +1 -0
- package/dist/planmagnet/pages/ProductsProductDetailPagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/ProductsProductDetailPagePage.js +96 -79
- package/dist/planmagnet/pages/ProductsProductDetailPagePage.js.map +1 -1
- package/dist/planmagnet/pages/ProductsRoadmapDetailPagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/ProductsRoadmapDetailPagePage.js +133 -123
- package/dist/planmagnet/pages/ProductsRoadmapDetailPagePage.js.map +1 -1
- package/dist/planmagnet/product/ProductControls.d.ts +33 -0
- package/dist/planmagnet/product/ProductControls.d.ts.map +1 -1
- package/dist/planmagnet/product/ProductControls.js +593 -268
- package/dist/planmagnet/product/ProductControls.js.map +1 -1
- package/dist/planmagnet/product/routes.d.ts +10 -0
- package/dist/planmagnet/product/routes.d.ts.map +1 -0
- package/dist/planmagnet/product/routes.js +6 -0
- package/dist/planmagnet/product/routes.js.map +1 -0
- package/dist/planmagnet/roadmaps/RoadmapControls.d.ts +10 -0
- package/dist/planmagnet/roadmaps/RoadmapControls.d.ts.map +1 -1
- package/dist/planmagnet/roadmaps/RoadmapControls.js +235 -184
- package/dist/planmagnet/roadmaps/RoadmapControls.js.map +1 -1
- package/package.json +1 -1
|
@@ -2,17 +2,19 @@ import { usePlanMagnetNavigate as e } from "../providers/PlanMagnetProvider.js";
|
|
|
2
2
|
import { LEAVES_PAGE_CONTEXT as t, throwOnError as n } from "../utils/mutationResult.js";
|
|
3
3
|
import { ConfirmButton as r, ErrorLine as i } from "./ConfirmButton.js";
|
|
4
4
|
import { enumLabel as a } from "./WorkItemControls.js";
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
5
|
+
import { mutationErrorMessage as o } from "../utils/graphqlErrors.js";
|
|
6
|
+
import { detailPath as s } from "../utils/rowNavigation.js";
|
|
7
|
+
import { ProjectSelect as c, WorkItemSearchSelect as l } from "./Pickers.js";
|
|
8
|
+
import { parseIntField as u } from "../utils/formValidation.js";
|
|
9
|
+
import { PrioritizationScoreFields as d, QuadrantBadge as f, kanoLabel as p, moscowLabel as m, prioritizationScoresValid as h } from "./PrioritizationControls.js";
|
|
10
|
+
import { useState as g } from "react";
|
|
11
|
+
import { BarChart3 as _, Pencil as v, ThumbsUp as y, Trash2 as b } from "lucide-react";
|
|
12
|
+
import { gql as x } from "@apollo/client";
|
|
13
|
+
import { useMutation as S } from "@apollo/client/react";
|
|
14
|
+
import { Fragment as C, jsx as w, jsxs as T } from "react/jsx-runtime";
|
|
15
|
+
import { Button as E, Card as D, CardContent as O, CardHeader as k, CardTitle as A, Input as j, ResponsiveDialog as M, ResponsiveDialogContent as N, ResponsiveDialogDescription as P, ResponsiveDialogFooter as F, ResponsiveDialogHeader as I, ResponsiveDialogTitle as L, ResponsiveDialogTrigger as R } from "@burdenoff/fe-libs/ui";
|
|
14
16
|
//#region src/planmagnet/controls/FeatureControls.tsx
|
|
15
|
-
var
|
|
17
|
+
var z = [
|
|
16
18
|
"SUBMITTED",
|
|
17
19
|
"UNDER_REVIEW",
|
|
18
20
|
"PLANNED",
|
|
@@ -20,7 +22,7 @@ var O = [
|
|
|
20
22
|
"COMPLETED",
|
|
21
23
|
"DECLINED",
|
|
22
24
|
"DUPLICATE"
|
|
23
|
-
],
|
|
25
|
+
], B = [
|
|
24
26
|
"GetFeatureRequest",
|
|
25
27
|
"ListFeatureRequests",
|
|
26
28
|
"ListFeatureRequestsForProduct",
|
|
@@ -28,17 +30,17 @@ var O = [
|
|
|
28
30
|
"ListAllFeaturesAnalytics",
|
|
29
31
|
"GetFeatureRequestAnalytics",
|
|
30
32
|
"ReleaseCustomerRequests"
|
|
31
|
-
],
|
|
33
|
+
], V = x`
|
|
32
34
|
mutation FeatureControlsVote($id: ID!) {
|
|
33
35
|
planmagnetVoteOnFeature(featureRequestId: $id) {
|
|
34
36
|
id
|
|
35
37
|
}
|
|
36
38
|
}
|
|
37
|
-
`,
|
|
39
|
+
`, H = x`
|
|
38
40
|
mutation FeatureControlsUnvote($id: ID!) {
|
|
39
41
|
planmagnetRemoveFeatureVote(featureRequestId: $id)
|
|
40
42
|
}
|
|
41
|
-
`,
|
|
43
|
+
`, U = x`
|
|
42
44
|
mutation FeatureControlsUpdate($id: ID!, $input: PlanmagnetUpdateFeatureRequestInput!) {
|
|
43
45
|
planmagnetUpdateFeatureRequest(id: $id, input: $input) {
|
|
44
46
|
id
|
|
@@ -49,18 +51,23 @@ var O = [
|
|
|
49
51
|
effortEstimate
|
|
50
52
|
projectId
|
|
51
53
|
workItemId
|
|
54
|
+
moscow
|
|
55
|
+
kano
|
|
56
|
+
valueScore
|
|
57
|
+
effortScore
|
|
58
|
+
valueEffortQuadrant
|
|
52
59
|
}
|
|
53
60
|
}
|
|
54
|
-
`,
|
|
61
|
+
`, W = x`
|
|
55
62
|
mutation FeatureControlsDelete($id: ID!) {
|
|
56
63
|
planmagnetDeleteFeatureRequest(id: $id)
|
|
57
64
|
}
|
|
58
|
-
`,
|
|
59
|
-
refetchQueries:
|
|
65
|
+
`, G = {
|
|
66
|
+
refetchQueries: B,
|
|
60
67
|
awaitRefetchQueries: !0
|
|
61
68
|
};
|
|
62
|
-
function
|
|
63
|
-
let [r, a] =
|
|
69
|
+
function K({ featureId: e, voted: t }) {
|
|
70
|
+
let [r, a] = S(V, G), [o, s] = S(H, G), [c, l] = g(null), u = a.loading || s.loading, d = async () => {
|
|
64
71
|
l(null);
|
|
65
72
|
try {
|
|
66
73
|
await n((t ? o : r)({ variables: { id: e } }));
|
|
@@ -68,84 +75,84 @@ function F({ featureId: e, voted: t }) {
|
|
|
68
75
|
l(e instanceof Error ? e.message : "Your vote could not be saved.");
|
|
69
76
|
}
|
|
70
77
|
};
|
|
71
|
-
return /* @__PURE__ */
|
|
78
|
+
return /* @__PURE__ */ T("div", {
|
|
72
79
|
className: "flex flex-col items-end gap-1",
|
|
73
|
-
children: [/* @__PURE__ */
|
|
80
|
+
children: [/* @__PURE__ */ T(E, {
|
|
74
81
|
size: "sm",
|
|
75
82
|
variant: t ? "default" : "outline",
|
|
76
83
|
"data-testid": "feature-vote",
|
|
77
84
|
"aria-pressed": t,
|
|
78
|
-
disabled:
|
|
79
|
-
onClick: () => void
|
|
80
|
-
children: [/* @__PURE__ */
|
|
81
|
-
}), c && /* @__PURE__ */
|
|
85
|
+
disabled: u,
|
|
86
|
+
onClick: () => void d(),
|
|
87
|
+
children: [/* @__PURE__ */ w(y, { className: "mr-1 h-4 w-4" }), t ? "Voted" : "Vote"]
|
|
88
|
+
}), c && /* @__PURE__ */ w(i, { message: c })]
|
|
82
89
|
});
|
|
83
90
|
}
|
|
84
|
-
function
|
|
85
|
-
let c = e(), [l,
|
|
86
|
-
refetchQueries:
|
|
91
|
+
function q({ feature: o }) {
|
|
92
|
+
let c = e(), [l, u] = S(U, G), [d, f] = S(W, {
|
|
93
|
+
refetchQueries: B.filter((e) => e !== "GetFeatureRequest"),
|
|
87
94
|
context: t
|
|
88
|
-
}), [
|
|
89
|
-
|
|
95
|
+
}), [p, m] = g(null), h = u.loading || f.loading, v = z.includes(o.status) ? z : [o.status, ...z], y = async (e) => {
|
|
96
|
+
m(null);
|
|
90
97
|
try {
|
|
91
98
|
await n(l({ variables: {
|
|
92
|
-
id:
|
|
99
|
+
id: o.id,
|
|
93
100
|
input: { status: e }
|
|
94
101
|
} }));
|
|
95
102
|
} catch (e) {
|
|
96
|
-
|
|
103
|
+
m(e instanceof Error ? e.message : "The status could not be changed.");
|
|
97
104
|
}
|
|
98
|
-
},
|
|
99
|
-
|
|
105
|
+
}, x = async () => {
|
|
106
|
+
m(null);
|
|
100
107
|
try {
|
|
101
|
-
await n(
|
|
108
|
+
await n(d({ variables: { id: o.id } })), c("/products/features-page");
|
|
102
109
|
} catch (e) {
|
|
103
|
-
|
|
110
|
+
m(e instanceof Error ? e.message : "The request could not be deleted.");
|
|
104
111
|
}
|
|
105
112
|
};
|
|
106
|
-
return /* @__PURE__ */
|
|
113
|
+
return /* @__PURE__ */ T("div", {
|
|
107
114
|
className: "flex flex-col items-end gap-2",
|
|
108
|
-
children: [/* @__PURE__ */
|
|
115
|
+
children: [/* @__PURE__ */ T("div", {
|
|
109
116
|
className: "flex flex-wrap items-center justify-end gap-2",
|
|
110
117
|
children: [
|
|
111
|
-
/* @__PURE__ */
|
|
118
|
+
/* @__PURE__ */ w("select", {
|
|
112
119
|
"aria-label": "Status",
|
|
113
120
|
"data-testid": "feature-status",
|
|
114
121
|
className: "rounded-md border border-input bg-background px-2 py-1 text-sm disabled:opacity-60",
|
|
115
|
-
value:
|
|
116
|
-
disabled:
|
|
122
|
+
value: o.status,
|
|
123
|
+
disabled: h,
|
|
117
124
|
onChange: (e) => {
|
|
118
|
-
e.target.value !==
|
|
125
|
+
e.target.value !== o.status && y(e.target.value);
|
|
119
126
|
},
|
|
120
|
-
children:
|
|
127
|
+
children: v.map((e) => /* @__PURE__ */ w("option", {
|
|
121
128
|
value: e,
|
|
122
129
|
children: a(e)
|
|
123
130
|
}, e))
|
|
124
131
|
}),
|
|
125
|
-
/* @__PURE__ */
|
|
126
|
-
/* @__PURE__ */
|
|
132
|
+
/* @__PURE__ */ w(J, { feature: o }),
|
|
133
|
+
/* @__PURE__ */ T(E, {
|
|
127
134
|
size: "sm",
|
|
128
135
|
variant: "outline",
|
|
129
136
|
"data-testid": "feature-analytics",
|
|
130
|
-
onClick: () => c(
|
|
131
|
-
children: [/* @__PURE__ */ _
|
|
137
|
+
onClick: () => c(s("/products/feature-analytics-page", o.id)),
|
|
138
|
+
children: [/* @__PURE__ */ w(_, { className: "mr-1 h-4 w-4" }), "Analytics"]
|
|
132
139
|
}),
|
|
133
|
-
/* @__PURE__ */
|
|
140
|
+
/* @__PURE__ */ w(r, {
|
|
134
141
|
label: "Delete",
|
|
135
142
|
variant: "outline",
|
|
136
|
-
icon: /* @__PURE__ */
|
|
137
|
-
title: `Delete "${
|
|
143
|
+
icon: /* @__PURE__ */ w(b, { className: "mr-1 h-4 w-4" }),
|
|
144
|
+
title: `Delete "${o.title}"?`,
|
|
138
145
|
description: "The request and its votes are deleted. This cannot be undone here.",
|
|
139
146
|
confirmLabel: "Delete request",
|
|
140
147
|
destructive: !0,
|
|
141
|
-
disabled:
|
|
142
|
-
onConfirm: () => void
|
|
148
|
+
disabled: h,
|
|
149
|
+
onConfirm: () => void x()
|
|
143
150
|
})
|
|
144
151
|
]
|
|
145
|
-
}),
|
|
152
|
+
}), p && /* @__PURE__ */ w(i, { message: p })]
|
|
146
153
|
});
|
|
147
154
|
}
|
|
148
|
-
function
|
|
155
|
+
function J({ feature: e }) {
|
|
149
156
|
let t = {
|
|
150
157
|
title: e.title,
|
|
151
158
|
description: e.description ?? "",
|
|
@@ -153,169 +160,332 @@ function L({ feature: e }) {
|
|
|
153
160
|
effortEstimate: e.effortEstimate ?? "",
|
|
154
161
|
projectId: e.projectId ?? "",
|
|
155
162
|
workItemId: e.workItemId ?? ""
|
|
156
|
-
},
|
|
163
|
+
}, r = {
|
|
164
|
+
moscow: e.moscow ?? "",
|
|
165
|
+
kano: e.kano ?? "",
|
|
166
|
+
valueScore: e.valueScore == null ? "" : String(e.valueScore),
|
|
167
|
+
effortScore: e.effortScore == null ? "" : String(e.effortScore)
|
|
168
|
+
}, [a, s] = g(!1), [p, m] = g(t), [_, y] = g(r), [b, x] = g(null), [C, D] = S(U, G), O = u(p.businessValue, {
|
|
157
169
|
min: 0,
|
|
158
170
|
max: 100
|
|
159
|
-
}),
|
|
160
|
-
|
|
161
|
-
let
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
171
|
+
}), k = p.title.trim() !== "" && !O.invalid && h(_) && !D.loading, A = async () => {
|
|
172
|
+
x(null);
|
|
173
|
+
let i = (e) => e.trim() ? e.trim() : null, a = u(_.valueScore, {
|
|
174
|
+
min: 1,
|
|
175
|
+
max: 10
|
|
176
|
+
}), c = u(_.effortScore, {
|
|
177
|
+
min: 1,
|
|
178
|
+
max: 10
|
|
179
|
+
}), l = {
|
|
180
|
+
title: p.title.trim(),
|
|
181
|
+
description: i(p.description),
|
|
182
|
+
businessValue: O.value ?? null,
|
|
183
|
+
effortEstimate: i(p.effortEstimate),
|
|
184
|
+
projectId: p.projectId || null,
|
|
185
|
+
workItemId: p.workItemId || null,
|
|
186
|
+
moscow: _.moscow || null,
|
|
187
|
+
kano: _.kano || null,
|
|
188
|
+
valueScore: a.value ?? null,
|
|
189
|
+
effortScore: c.value ?? null
|
|
190
|
+
}, d = {
|
|
169
191
|
title: t.title,
|
|
170
|
-
description:
|
|
192
|
+
description: i(t.description),
|
|
171
193
|
businessValue: t.businessValue === "" ? null : Number(t.businessValue),
|
|
172
|
-
effortEstimate:
|
|
194
|
+
effortEstimate: i(t.effortEstimate),
|
|
173
195
|
projectId: t.projectId || null,
|
|
174
|
-
workItemId: t.workItemId || null
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
196
|
+
workItemId: t.workItemId || null,
|
|
197
|
+
moscow: r.moscow || null,
|
|
198
|
+
kano: r.kano || null,
|
|
199
|
+
valueScore: r.valueScore === "" ? null : Number(r.valueScore),
|
|
200
|
+
effortScore: r.effortScore === "" ? null : Number(r.effortScore)
|
|
201
|
+
}, f = Object.fromEntries(Object.entries(l).filter(([e, t]) => t !== d[e]));
|
|
202
|
+
if (Object.keys(f).length === 0) {
|
|
203
|
+
s(!1);
|
|
178
204
|
return;
|
|
179
205
|
}
|
|
180
206
|
try {
|
|
181
|
-
await n(
|
|
207
|
+
await n(C({ variables: {
|
|
182
208
|
id: e.id,
|
|
183
|
-
input:
|
|
184
|
-
} })),
|
|
209
|
+
input: f
|
|
210
|
+
} })), s(!1);
|
|
185
211
|
} catch (e) {
|
|
186
|
-
|
|
212
|
+
x(o(e, "The request could not be saved."));
|
|
187
213
|
}
|
|
188
|
-
},
|
|
189
|
-
return /* @__PURE__ */
|
|
190
|
-
open:
|
|
214
|
+
}, z = "text-sm font-medium";
|
|
215
|
+
return /* @__PURE__ */ T(M, {
|
|
216
|
+
open: a,
|
|
191
217
|
onOpenChange: (e) => {
|
|
192
|
-
|
|
218
|
+
s(e), e ? (m(t), y(r)) : x(null);
|
|
193
219
|
},
|
|
194
|
-
children: [/* @__PURE__ */
|
|
220
|
+
children: [/* @__PURE__ */ w(R, {
|
|
195
221
|
asChild: !0,
|
|
196
|
-
children: /* @__PURE__ */
|
|
222
|
+
children: /* @__PURE__ */ T(E, {
|
|
197
223
|
size: "sm",
|
|
198
224
|
variant: "outline",
|
|
199
225
|
"data-testid": "feature-edit",
|
|
200
|
-
children: [/* @__PURE__ */
|
|
226
|
+
children: [/* @__PURE__ */ w(v, { className: "mr-1 h-4 w-4" }), "Edit"]
|
|
201
227
|
})
|
|
202
|
-
}), /* @__PURE__ */
|
|
228
|
+
}), /* @__PURE__ */ T(N, {
|
|
203
229
|
className: "max-w-lg",
|
|
204
230
|
children: [
|
|
205
|
-
/* @__PURE__ */
|
|
206
|
-
/* @__PURE__ */
|
|
231
|
+
/* @__PURE__ */ T(I, { children: [/* @__PURE__ */ w(L, { children: "Edit feature request" }), /* @__PURE__ */ w(P, { children: "Link the request to the work item that delivers it so releases can show who is waiting on it." })] }),
|
|
232
|
+
/* @__PURE__ */ T("div", {
|
|
207
233
|
className: "space-y-3",
|
|
208
234
|
children: [
|
|
209
|
-
/* @__PURE__ */
|
|
235
|
+
/* @__PURE__ */ T("div", { children: [/* @__PURE__ */ w("label", {
|
|
210
236
|
htmlFor: "feature-edit-title",
|
|
211
|
-
className:
|
|
237
|
+
className: z,
|
|
212
238
|
children: "Title"
|
|
213
|
-
}), /* @__PURE__ */
|
|
239
|
+
}), /* @__PURE__ */ w(j, {
|
|
214
240
|
id: "feature-edit-title",
|
|
215
241
|
className: "mt-1",
|
|
216
|
-
value:
|
|
217
|
-
onChange: (e) =>
|
|
218
|
-
...
|
|
242
|
+
value: p.title,
|
|
243
|
+
onChange: (e) => m({
|
|
244
|
+
...p,
|
|
219
245
|
title: e.target.value
|
|
220
246
|
})
|
|
221
247
|
})] }),
|
|
222
|
-
/* @__PURE__ */
|
|
248
|
+
/* @__PURE__ */ T("div", { children: [/* @__PURE__ */ w("label", {
|
|
223
249
|
htmlFor: "feature-edit-description",
|
|
224
|
-
className:
|
|
250
|
+
className: z,
|
|
225
251
|
children: "Description"
|
|
226
|
-
}), /* @__PURE__ */
|
|
252
|
+
}), /* @__PURE__ */ w("textarea", {
|
|
227
253
|
id: "feature-edit-description",
|
|
228
254
|
className: "mt-1 w-full rounded-md border border-input bg-background px-3 py-2 text-sm min-h-[72px]",
|
|
229
|
-
value:
|
|
230
|
-
onChange: (e) =>
|
|
231
|
-
...
|
|
255
|
+
value: p.description,
|
|
256
|
+
onChange: (e) => m({
|
|
257
|
+
...p,
|
|
232
258
|
description: e.target.value
|
|
233
259
|
})
|
|
234
260
|
})] }),
|
|
235
|
-
/* @__PURE__ */
|
|
261
|
+
/* @__PURE__ */ T("div", {
|
|
236
262
|
className: "grid grid-cols-2 gap-3",
|
|
237
|
-
children: [/* @__PURE__ */
|
|
263
|
+
children: [/* @__PURE__ */ T("div", { children: [/* @__PURE__ */ w("label", {
|
|
238
264
|
htmlFor: "feature-edit-value",
|
|
239
|
-
className:
|
|
265
|
+
className: z,
|
|
240
266
|
children: "Business value (0–100)"
|
|
241
|
-
}), /* @__PURE__ */
|
|
267
|
+
}), /* @__PURE__ */ w(j, {
|
|
242
268
|
id: "feature-edit-value",
|
|
243
269
|
type: "number",
|
|
244
270
|
min: 0,
|
|
245
271
|
max: 100,
|
|
246
272
|
className: "mt-1",
|
|
247
|
-
value:
|
|
248
|
-
"aria-invalid":
|
|
249
|
-
onChange: (e) =>
|
|
250
|
-
...
|
|
273
|
+
value: p.businessValue,
|
|
274
|
+
"aria-invalid": O.invalid,
|
|
275
|
+
onChange: (e) => m({
|
|
276
|
+
...p,
|
|
251
277
|
businessValue: e.target.value
|
|
252
278
|
})
|
|
253
|
-
})] }), /* @__PURE__ */
|
|
279
|
+
})] }), /* @__PURE__ */ T("div", { children: [/* @__PURE__ */ w("label", {
|
|
254
280
|
htmlFor: "feature-edit-effort",
|
|
255
|
-
className:
|
|
281
|
+
className: z,
|
|
256
282
|
children: "Effort"
|
|
257
|
-
}), /* @__PURE__ */
|
|
283
|
+
}), /* @__PURE__ */ w(j, {
|
|
258
284
|
id: "feature-edit-effort",
|
|
259
285
|
className: "mt-1",
|
|
260
286
|
placeholder: "e.g. M",
|
|
261
|
-
value:
|
|
262
|
-
onChange: (e) =>
|
|
263
|
-
...
|
|
287
|
+
value: p.effortEstimate,
|
|
288
|
+
onChange: (e) => m({
|
|
289
|
+
...p,
|
|
264
290
|
effortEstimate: e.target.value
|
|
265
291
|
})
|
|
266
292
|
})] })]
|
|
267
293
|
}),
|
|
268
|
-
|
|
269
|
-
/* @__PURE__ */
|
|
294
|
+
O.invalid && /* @__PURE__ */ w(i, { message: "Business value is a whole number from 0 to 100." }),
|
|
295
|
+
/* @__PURE__ */ T("div", { children: [/* @__PURE__ */ w("label", {
|
|
270
296
|
htmlFor: "feature-edit-project",
|
|
271
|
-
className:
|
|
297
|
+
className: z,
|
|
272
298
|
children: "Project"
|
|
273
|
-
}), /* @__PURE__ */
|
|
299
|
+
}), /* @__PURE__ */ w("div", {
|
|
274
300
|
className: "mt-1",
|
|
275
|
-
children: /* @__PURE__ */
|
|
301
|
+
children: /* @__PURE__ */ w(c, {
|
|
276
302
|
id: "feature-edit-project",
|
|
277
|
-
value:
|
|
303
|
+
value: p.projectId,
|
|
278
304
|
noneLabel: "No project",
|
|
279
|
-
onChange: (e) =>
|
|
280
|
-
...
|
|
305
|
+
onChange: (e) => m({
|
|
306
|
+
...p,
|
|
281
307
|
projectId: e,
|
|
282
308
|
workItemId: ""
|
|
283
309
|
})
|
|
284
310
|
})
|
|
285
311
|
})] }),
|
|
286
|
-
/* @__PURE__ */
|
|
312
|
+
/* @__PURE__ */ T("div", { children: [/* @__PURE__ */ w("label", {
|
|
287
313
|
htmlFor: "feature-edit-workitem",
|
|
288
|
-
className:
|
|
314
|
+
className: z,
|
|
289
315
|
children: "Delivered by work item"
|
|
290
|
-
}), /* @__PURE__ */
|
|
316
|
+
}), /* @__PURE__ */ w("div", {
|
|
291
317
|
className: "mt-1",
|
|
292
|
-
children: /* @__PURE__ */
|
|
318
|
+
children: /* @__PURE__ */ w(l, {
|
|
293
319
|
id: "feature-edit-workitem",
|
|
294
|
-
projectId:
|
|
295
|
-
value:
|
|
296
|
-
onChange: (e) =>
|
|
297
|
-
...
|
|
320
|
+
projectId: p.projectId || void 0,
|
|
321
|
+
value: p.workItemId,
|
|
322
|
+
onChange: (e) => m({
|
|
323
|
+
...p,
|
|
298
324
|
workItemId: e
|
|
299
325
|
})
|
|
300
326
|
})
|
|
301
327
|
})] }),
|
|
302
|
-
|
|
328
|
+
/* @__PURE__ */ T("div", {
|
|
329
|
+
className: "border-t pt-3",
|
|
330
|
+
children: [
|
|
331
|
+
/* @__PURE__ */ w("p", {
|
|
332
|
+
className: z,
|
|
333
|
+
children: "Prioritization"
|
|
334
|
+
}),
|
|
335
|
+
/* @__PURE__ */ T("div", {
|
|
336
|
+
className: "mt-1 flex items-center gap-2",
|
|
337
|
+
children: [/* @__PURE__ */ w("span", {
|
|
338
|
+
className: "text-xs text-muted-foreground",
|
|
339
|
+
children: "Current quadrant:"
|
|
340
|
+
}), /* @__PURE__ */ w(f, { quadrant: e.valueEffortQuadrant ?? null })]
|
|
341
|
+
}),
|
|
342
|
+
/* @__PURE__ */ w("div", {
|
|
343
|
+
className: "mt-2",
|
|
344
|
+
children: /* @__PURE__ */ w(d, {
|
|
345
|
+
idPrefix: "feature-edit",
|
|
346
|
+
values: _,
|
|
347
|
+
onChange: y
|
|
348
|
+
})
|
|
349
|
+
})
|
|
350
|
+
]
|
|
351
|
+
}),
|
|
352
|
+
b && /* @__PURE__ */ w(i, { message: b })
|
|
303
353
|
]
|
|
304
354
|
}),
|
|
305
|
-
/* @__PURE__ */
|
|
355
|
+
/* @__PURE__ */ T(F, { children: [/* @__PURE__ */ w(E, {
|
|
306
356
|
variant: "outline",
|
|
307
|
-
onClick: () =>
|
|
357
|
+
onClick: () => s(!1),
|
|
308
358
|
children: "Cancel"
|
|
309
|
-
}), /* @__PURE__ */
|
|
310
|
-
onClick: () => void
|
|
311
|
-
disabled: !
|
|
312
|
-
children:
|
|
359
|
+
}), /* @__PURE__ */ w(E, {
|
|
360
|
+
onClick: () => void A(),
|
|
361
|
+
disabled: !k,
|
|
362
|
+
children: D.loading ? "Saving…" : "Save"
|
|
313
363
|
})] })
|
|
314
364
|
]
|
|
315
365
|
})]
|
|
316
366
|
});
|
|
317
367
|
}
|
|
368
|
+
function Y({ feature: e }) {
|
|
369
|
+
let t = {
|
|
370
|
+
moscow: e.moscow ?? "",
|
|
371
|
+
kano: e.kano ?? "",
|
|
372
|
+
valueScore: e.valueScore == null ? "" : String(e.valueScore),
|
|
373
|
+
effortScore: e.effortScore == null ? "" : String(e.effortScore)
|
|
374
|
+
}, [r, a] = g(!1), [s, c] = g(t), [l, _] = g(null), [y, b] = S(U, G), x = () => {
|
|
375
|
+
c(t), _(null), a(!0);
|
|
376
|
+
}, j = async () => {
|
|
377
|
+
_(null);
|
|
378
|
+
let t = u(s.valueScore, {
|
|
379
|
+
min: 1,
|
|
380
|
+
max: 10
|
|
381
|
+
}), r = u(s.effortScore, {
|
|
382
|
+
min: 1,
|
|
383
|
+
max: 10
|
|
384
|
+
}), i = {
|
|
385
|
+
moscow: s.moscow || null,
|
|
386
|
+
kano: s.kano || null,
|
|
387
|
+
valueScore: t.value ?? null,
|
|
388
|
+
effortScore: r.value ?? null
|
|
389
|
+
};
|
|
390
|
+
try {
|
|
391
|
+
await n(y({ variables: {
|
|
392
|
+
id: e.id,
|
|
393
|
+
input: i
|
|
394
|
+
} })), a(!1);
|
|
395
|
+
} catch (e) {
|
|
396
|
+
_(o(e, "The prioritization could not be saved."));
|
|
397
|
+
}
|
|
398
|
+
};
|
|
399
|
+
return /* @__PURE__ */ T(D, {
|
|
400
|
+
"data-testid": "feature-prioritization-card",
|
|
401
|
+
children: [/* @__PURE__ */ T(k, {
|
|
402
|
+
className: "flex flex-row items-center justify-between gap-2",
|
|
403
|
+
children: [/* @__PURE__ */ w(A, { children: "Prioritization" }), !r && /* @__PURE__ */ T(E, {
|
|
404
|
+
size: "sm",
|
|
405
|
+
variant: "outline",
|
|
406
|
+
"data-testid": "feature-prioritization-edit",
|
|
407
|
+
onClick: x,
|
|
408
|
+
children: [/* @__PURE__ */ w(v, { className: "mr-1 h-4 w-4" }), "Edit"]
|
|
409
|
+
})]
|
|
410
|
+
}), /* @__PURE__ */ w(O, {
|
|
411
|
+
className: "space-y-3",
|
|
412
|
+
children: r ? /* @__PURE__ */ T(C, { children: [
|
|
413
|
+
/* @__PURE__ */ w(d, {
|
|
414
|
+
idPrefix: "feature-prio",
|
|
415
|
+
values: s,
|
|
416
|
+
onChange: c
|
|
417
|
+
}),
|
|
418
|
+
l && /* @__PURE__ */ w(i, { message: l }),
|
|
419
|
+
/* @__PURE__ */ T("div", {
|
|
420
|
+
className: "flex justify-end gap-2",
|
|
421
|
+
children: [/* @__PURE__ */ w(E, {
|
|
422
|
+
size: "sm",
|
|
423
|
+
variant: "outline",
|
|
424
|
+
onClick: () => a(!1),
|
|
425
|
+
children: "Cancel"
|
|
426
|
+
}), /* @__PURE__ */ w(E, {
|
|
427
|
+
size: "sm",
|
|
428
|
+
"data-testid": "feature-prioritization-save",
|
|
429
|
+
disabled: b.loading || !h(s),
|
|
430
|
+
onClick: () => void j(),
|
|
431
|
+
children: b.loading ? "Saving…" : "Save"
|
|
432
|
+
})]
|
|
433
|
+
})
|
|
434
|
+
] }) : /* @__PURE__ */ T(C, { children: [/* @__PURE__ */ T("div", {
|
|
435
|
+
className: "flex items-center gap-2",
|
|
436
|
+
children: [/* @__PURE__ */ w("span", {
|
|
437
|
+
className: "text-xs text-muted-foreground",
|
|
438
|
+
children: "Quadrant:"
|
|
439
|
+
}), /* @__PURE__ */ w(f, { quadrant: e.valueEffortQuadrant ?? null })]
|
|
440
|
+
}), /* @__PURE__ */ T("div", {
|
|
441
|
+
className: "grid grid-cols-2 gap-2 text-sm",
|
|
442
|
+
children: [
|
|
443
|
+
/* @__PURE__ */ T("div", {
|
|
444
|
+
className: "flex justify-between",
|
|
445
|
+
children: [/* @__PURE__ */ w("span", {
|
|
446
|
+
className: "text-muted-foreground",
|
|
447
|
+
children: "MoSCoW"
|
|
448
|
+
}), /* @__PURE__ */ w("span", {
|
|
449
|
+
className: "font-medium",
|
|
450
|
+
children: m(e.moscow)
|
|
451
|
+
})]
|
|
452
|
+
}),
|
|
453
|
+
/* @__PURE__ */ T("div", {
|
|
454
|
+
className: "flex justify-between",
|
|
455
|
+
children: [/* @__PURE__ */ w("span", {
|
|
456
|
+
className: "text-muted-foreground",
|
|
457
|
+
children: "Kano"
|
|
458
|
+
}), /* @__PURE__ */ w("span", {
|
|
459
|
+
className: "font-medium",
|
|
460
|
+
children: p(e.kano)
|
|
461
|
+
})]
|
|
462
|
+
}),
|
|
463
|
+
/* @__PURE__ */ T("div", {
|
|
464
|
+
className: "flex justify-between",
|
|
465
|
+
children: [/* @__PURE__ */ w("span", {
|
|
466
|
+
className: "text-muted-foreground",
|
|
467
|
+
children: "Value score"
|
|
468
|
+
}), /* @__PURE__ */ w("span", {
|
|
469
|
+
className: "font-medium",
|
|
470
|
+
children: e.valueScore ?? "Not set"
|
|
471
|
+
})]
|
|
472
|
+
}),
|
|
473
|
+
/* @__PURE__ */ T("div", {
|
|
474
|
+
className: "flex justify-between",
|
|
475
|
+
children: [/* @__PURE__ */ w("span", {
|
|
476
|
+
className: "text-muted-foreground",
|
|
477
|
+
children: "Effort score"
|
|
478
|
+
}), /* @__PURE__ */ w("span", {
|
|
479
|
+
className: "font-medium",
|
|
480
|
+
children: e.effortScore ?? "Not set"
|
|
481
|
+
})]
|
|
482
|
+
})
|
|
483
|
+
]
|
|
484
|
+
})] })
|
|
485
|
+
})]
|
|
486
|
+
});
|
|
487
|
+
}
|
|
318
488
|
//#endregion
|
|
319
|
-
export {
|
|
489
|
+
export { q as FeatureHeaderActions, Y as FeaturePrioritizationCard, K as FeatureVoteButton };
|
|
320
490
|
|
|
321
491
|
//# sourceMappingURL=FeatureControls.js.map
|