@burdenoff/microfe-planmagnet 2026.930.23 → 2026.930.25
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/comments/CommentThread.d.ts +8 -1
- package/dist/planmagnet/comments/CommentThread.d.ts.map +1 -1
- package/dist/planmagnet/comments/CommentThread.js +188 -181
- package/dist/planmagnet/comments/CommentThread.js.map +1 -1
- package/dist/planmagnet/comments/TargetComments.d.ts +10 -2
- package/dist/planmagnet/comments/TargetComments.d.ts.map +1 -1
- package/dist/planmagnet/comments/TargetComments.js +10 -8
- package/dist/planmagnet/comments/TargetComments.js.map +1 -1
- package/dist/planmagnet/comments/WorkItemComments.d.ts +7 -1
- package/dist/planmagnet/comments/WorkItemComments.d.ts.map +1 -1
- package/dist/planmagnet/comments/WorkItemComments.js +5 -4
- package/dist/planmagnet/comments/WorkItemComments.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/discussion/WorkItemDiscussionPanel.d.ts +8 -0
- package/dist/planmagnet/discussion/WorkItemDiscussionPanel.d.ts.map +1 -0
- package/dist/planmagnet/discussion/WorkItemDiscussionPanel.js +217 -0
- package/dist/planmagnet/discussion/WorkItemDiscussionPanel.js.map +1 -0
- package/dist/planmagnet/docs/DocDiffView.d.ts +26 -0
- package/dist/planmagnet/docs/DocDiffView.d.ts.map +1 -0
- package/dist/planmagnet/docs/DocDiffView.js +52 -0
- package/dist/planmagnet/docs/DocDiffView.js.map +1 -0
- package/dist/planmagnet/docs/DocSuggestionsPanel.d.ts +13 -0
- package/dist/planmagnet/docs/DocSuggestionsPanel.d.ts.map +1 -0
- package/dist/planmagnet/docs/DocSuggestionsPanel.js +308 -0
- package/dist/planmagnet/docs/DocSuggestionsPanel.js.map +1 -0
- package/dist/planmagnet/docs/DocVersionCompare.d.ts +7 -0
- package/dist/planmagnet/docs/DocVersionCompare.d.ts.map +1 -0
- package/dist/planmagnet/docs/DocVersionCompare.js +105 -0
- package/dist/planmagnet/docs/DocVersionCompare.js.map +1 -0
- package/dist/planmagnet/hooks/usePresence.d.ts +39 -0
- package/dist/planmagnet/hooks/usePresence.d.ts.map +1 -0
- package/dist/planmagnet/hooks/usePresence.js +146 -0
- package/dist/planmagnet/hooks/usePresence.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/links/CodeLinksPanel.d.ts +22 -0
- package/dist/planmagnet/links/CodeLinksPanel.d.ts.map +1 -0
- package/dist/planmagnet/links/CodeLinksPanel.js +94 -0
- package/dist/planmagnet/links/CodeLinksPanel.js.map +1 -0
- package/dist/planmagnet/pages/DocsDocDetailPagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/DocsDocDetailPagePage.js +488 -217
- package/dist/planmagnet/pages/DocsDocDetailPagePage.js.map +1 -1
- 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 +144 -128
- package/dist/planmagnet/pages/ProductsRoadmapDetailPagePage.js.map +1 -1
- package/dist/planmagnet/pages/ProjectsProjectDetailPagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/ProjectsProjectDetailPagePage.js +205 -196
- package/dist/planmagnet/pages/ProjectsProjectDetailPagePage.js.map +1 -1
- package/dist/planmagnet/pages/TasksTaskDetailPagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/TasksTaskDetailPagePage.js +194 -160
- package/dist/planmagnet/pages/TasksTaskDetailPagePage.js.map +1 -1
- package/dist/planmagnet/presence/PresenceAvatars.d.ts +16 -0
- package/dist/planmagnet/presence/PresenceAvatars.d.ts.map +1 -0
- package/dist/planmagnet/presence/PresenceAvatars.js +56 -0
- package/dist/planmagnet/presence/PresenceAvatars.js.map +1 -0
- 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/dist/planmagnet/utils/graphqlErrors.d.ts +6 -0
- package/dist/planmagnet/utils/graphqlErrors.d.ts.map +1 -1
- package/dist/planmagnet/utils/graphqlErrors.js +5 -2
- package/dist/planmagnet/utils/graphqlErrors.js.map +1 -1
- package/dist/planmagnet/utils/lineDiff.d.ts +21 -0
- package/dist/planmagnet/utils/lineDiff.d.ts.map +1 -0
- package/dist/planmagnet/utils/lineDiff.js +36 -0
- package/dist/planmagnet/utils/lineDiff.js.map +1 -0
- package/package.json +1 -1
|
@@ -3,14 +3,15 @@ import { PersonName as n } from "../people/People.js";
|
|
|
3
3
|
import { countLabel as r, useFeatureCounts as i } from "../hooks/useCounts.js";
|
|
4
4
|
import { detailPath as a, rowLinkProps as o } from "../utils/rowNavigation.js";
|
|
5
5
|
import { FeatureTriageActions as s, isSnoozed as c } from "../controls/FeatureTriage.js";
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
6
|
+
import { KANO_META as l, KANO_VALUES as u, MOSCOW_META as d, MOSCOW_VALUES as f, QUADRANT_META as p, QUADRANT_VALUES as m, QuadrantBadge as h } from "../controls/PrioritizationControls.js";
|
|
7
|
+
import { useState as g } from "react";
|
|
8
|
+
import { ArrowUpDown as _, Filter as v, Loader2 as y, Plus as b, Star as x, Target as S, ThumbsUp as ee } from "lucide-react";
|
|
9
|
+
import { gql as C } from "@apollo/client";
|
|
10
|
+
import { useQuery as w } from "@apollo/client/react";
|
|
11
|
+
import { jsx as T, jsxs as E } from "react/jsx-runtime";
|
|
12
|
+
import { Badge as D, Button as O, Card as k, CardContent as A } from "@burdenoff/fe-libs/ui";
|
|
12
13
|
//#region src/planmagnet/pages/ProductsFeaturesPagePage.tsx
|
|
13
|
-
var
|
|
14
|
+
var j = C`
|
|
14
15
|
query ListFeatureRequests(
|
|
15
16
|
$workspaceId: ID!
|
|
16
17
|
$filter: PlanmagnetFeatureRequestFilter
|
|
@@ -36,13 +37,16 @@ var T = _`
|
|
|
36
37
|
tags
|
|
37
38
|
projectId
|
|
38
39
|
snoozedUntil
|
|
40
|
+
moscow
|
|
41
|
+
kano
|
|
42
|
+
valueEffortQuadrant
|
|
39
43
|
createdAt
|
|
40
44
|
updatedAt
|
|
41
45
|
}
|
|
42
46
|
totalCount
|
|
43
47
|
}
|
|
44
48
|
}
|
|
45
|
-
`,
|
|
49
|
+
`, M = {
|
|
46
50
|
SUBMITTED: "bg-gray-100 text-gray-800",
|
|
47
51
|
UNDER_REVIEW: "bg-yellow-100 text-yellow-800",
|
|
48
52
|
PLANNED: "bg-blue-100 text-blue-800",
|
|
@@ -51,25 +55,30 @@ var T = _`
|
|
|
51
55
|
DECLINED: "bg-red-100 text-red-800",
|
|
52
56
|
DUPLICATE: "bg-orange-100 text-orange-800"
|
|
53
57
|
};
|
|
54
|
-
function
|
|
55
|
-
let
|
|
58
|
+
function N() {
|
|
59
|
+
let C = t(), { workspaceId: N } = e(), [P, F] = g("all"), [I] = g(() => Date.now()), [L, te] = g("NEWEST"), [R, z] = g(""), [B, V] = g(""), [H, U] = g(""), W = i(), G = {
|
|
60
|
+
...P === "TRIAGE" ? { triage: !0 } : P === "SNOOZED" ? { snoozed: !0 } : P === "all" ? {} : { status: P },
|
|
61
|
+
...R ? { moscow: R } : {},
|
|
62
|
+
...B ? { kano: B } : {},
|
|
63
|
+
...H ? { quadrant: H } : {}
|
|
64
|
+
}, { data: K, loading: q, error: J } = w(j, {
|
|
56
65
|
variables: {
|
|
57
|
-
workspaceId:
|
|
58
|
-
filter:
|
|
66
|
+
workspaceId: N,
|
|
67
|
+
filter: Object.keys(G).length > 0 ? G : void 0,
|
|
59
68
|
pagination: { first: 50 },
|
|
60
|
-
orderBy:
|
|
69
|
+
orderBy: L
|
|
61
70
|
},
|
|
62
|
-
skip: !
|
|
71
|
+
skip: !N
|
|
63
72
|
});
|
|
64
|
-
if (
|
|
73
|
+
if (q && !K) return /* @__PURE__ */ T("div", {
|
|
65
74
|
className: "flex items-center justify-center p-12",
|
|
66
|
-
children: /* @__PURE__ */ y
|
|
75
|
+
children: /* @__PURE__ */ T(y, { className: "h-8 w-8 animate-spin text-muted-foreground" })
|
|
67
76
|
});
|
|
68
|
-
if (
|
|
77
|
+
if (J) return /* @__PURE__ */ E("div", {
|
|
69
78
|
className: "p-6 text-destructive",
|
|
70
|
-
children: ["Failed to load features: ",
|
|
79
|
+
children: ["Failed to load features: ", J.message]
|
|
71
80
|
});
|
|
72
|
-
let
|
|
81
|
+
let Y = K?.planmagnetFeatureRequests?.items ?? [], X = K?.planmagnetFeatureRequests?.totalCount ?? 0, Z = Y, Q = [
|
|
73
82
|
"all",
|
|
74
83
|
"TRIAGE",
|
|
75
84
|
"SNOOZED",
|
|
@@ -80,180 +89,255 @@ function D() {
|
|
|
80
89
|
"COMPLETED",
|
|
81
90
|
"DECLINED",
|
|
82
91
|
"DUPLICATE"
|
|
83
|
-
],
|
|
84
|
-
total: r(
|
|
85
|
-
open: r(
|
|
86
|
-
inProgress: r(
|
|
87
|
-
completed: r(
|
|
92
|
+
], $ = {
|
|
93
|
+
total: r(W?.all),
|
|
94
|
+
open: r(W?.open),
|
|
95
|
+
inProgress: r(W?.byStatus.IN_PROGRESS),
|
|
96
|
+
completed: r(W?.byStatus.COMPLETED)
|
|
88
97
|
};
|
|
89
|
-
return /* @__PURE__ */
|
|
98
|
+
return /* @__PURE__ */ E("div", {
|
|
90
99
|
className: "space-y-6 p-6",
|
|
91
100
|
children: [
|
|
92
|
-
/* @__PURE__ */
|
|
101
|
+
/* @__PURE__ */ E("div", {
|
|
93
102
|
className: "flex items-center justify-between",
|
|
94
|
-
children: [/* @__PURE__ */
|
|
103
|
+
children: [/* @__PURE__ */ E("div", { children: [/* @__PURE__ */ T("h1", {
|
|
95
104
|
className: "text-2xl font-semibold",
|
|
96
105
|
children: "Features"
|
|
97
|
-
}), /* @__PURE__ */
|
|
106
|
+
}), /* @__PURE__ */ T("p", {
|
|
98
107
|
className: "text-sm text-muted-foreground",
|
|
99
|
-
children:
|
|
100
|
-
})] }), /* @__PURE__ */
|
|
108
|
+
children: P === "all" ? `${$.total} feature requests` : P === "TRIAGE" ? `${X} waiting for triage` : `${X} ${P.toLowerCase().replace("_", " ")} match`
|
|
109
|
+
})] }), /* @__PURE__ */ E(O, {
|
|
101
110
|
size: "sm",
|
|
102
|
-
onClick: () =>
|
|
103
|
-
children: [/* @__PURE__ */
|
|
111
|
+
onClick: () => C("/products/new-feature-page"),
|
|
112
|
+
children: [/* @__PURE__ */ T(b, { className: "mr-1 h-4 w-4" }), "New Feature"]
|
|
104
113
|
})]
|
|
105
114
|
}),
|
|
106
|
-
/* @__PURE__ */
|
|
115
|
+
/* @__PURE__ */ E("div", {
|
|
107
116
|
className: "grid grid-cols-2 md:grid-cols-4 gap-4",
|
|
108
117
|
children: [
|
|
109
|
-
/* @__PURE__ */
|
|
118
|
+
/* @__PURE__ */ T(k, { children: /* @__PURE__ */ E(A, {
|
|
110
119
|
className: "pt-4",
|
|
111
|
-
children: [/* @__PURE__ */
|
|
120
|
+
children: [/* @__PURE__ */ T("p", {
|
|
112
121
|
className: "text-xs text-muted-foreground",
|
|
113
122
|
children: "Total Features"
|
|
114
|
-
}), /* @__PURE__ */
|
|
123
|
+
}), /* @__PURE__ */ T("p", {
|
|
115
124
|
className: "text-xl font-bold",
|
|
116
|
-
children:
|
|
125
|
+
children: $.total
|
|
117
126
|
})]
|
|
118
127
|
}) }),
|
|
119
|
-
/* @__PURE__ */
|
|
128
|
+
/* @__PURE__ */ T(k, { children: /* @__PURE__ */ E(A, {
|
|
120
129
|
className: "pt-4",
|
|
121
|
-
children: [/* @__PURE__ */
|
|
130
|
+
children: [/* @__PURE__ */ T("p", {
|
|
122
131
|
className: "text-xs text-muted-foreground",
|
|
123
132
|
children: "In Progress"
|
|
124
|
-
}), /* @__PURE__ */
|
|
133
|
+
}), /* @__PURE__ */ T("p", {
|
|
125
134
|
className: "text-xl font-bold",
|
|
126
|
-
children:
|
|
135
|
+
children: $.inProgress
|
|
127
136
|
})]
|
|
128
137
|
}) }),
|
|
129
|
-
/* @__PURE__ */
|
|
138
|
+
/* @__PURE__ */ T(k, { children: /* @__PURE__ */ E(A, {
|
|
130
139
|
className: "pt-4",
|
|
131
|
-
children: [/* @__PURE__ */
|
|
140
|
+
children: [/* @__PURE__ */ T("p", {
|
|
132
141
|
className: "text-xs text-muted-foreground",
|
|
133
142
|
children: "Completed"
|
|
134
|
-
}), /* @__PURE__ */
|
|
143
|
+
}), /* @__PURE__ */ T("p", {
|
|
135
144
|
className: "text-xl font-bold",
|
|
136
|
-
children:
|
|
145
|
+
children: $.completed
|
|
137
146
|
})]
|
|
138
147
|
}) }),
|
|
139
|
-
/* @__PURE__ */
|
|
148
|
+
/* @__PURE__ */ T(k, { children: /* @__PURE__ */ E(A, {
|
|
140
149
|
className: "pt-4",
|
|
141
|
-
children: [/* @__PURE__ */
|
|
150
|
+
children: [/* @__PURE__ */ T("p", {
|
|
142
151
|
className: "text-xs text-muted-foreground",
|
|
143
152
|
children: "Open"
|
|
144
|
-
}), /* @__PURE__ */
|
|
153
|
+
}), /* @__PURE__ */ T("p", {
|
|
145
154
|
className: "text-xl font-bold",
|
|
146
|
-
children:
|
|
155
|
+
children: $.open
|
|
147
156
|
})]
|
|
148
157
|
}) })
|
|
149
158
|
]
|
|
150
159
|
}),
|
|
151
|
-
/* @__PURE__ */
|
|
160
|
+
/* @__PURE__ */ E("div", {
|
|
152
161
|
className: "flex items-center justify-between flex-wrap gap-2",
|
|
153
|
-
children: [/* @__PURE__ */
|
|
162
|
+
children: [/* @__PURE__ */ E("div", {
|
|
154
163
|
className: "flex items-center gap-2",
|
|
155
|
-
children: [/* @__PURE__ */
|
|
156
|
-
onClick: () =>
|
|
157
|
-
className: `px-2 py-1 text-xs rounded-md capitalize ${
|
|
158
|
-
children: e === "all" ? "All" : e === "TRIAGE" ? `Triage (${r(
|
|
164
|
+
children: [/* @__PURE__ */ T(v, { className: "h-4 w-4 text-muted-foreground" }), Q.map((e) => /* @__PURE__ */ T("button", {
|
|
165
|
+
onClick: () => F(e),
|
|
166
|
+
className: `px-2 py-1 text-xs rounded-md capitalize ${P === e ? "bg-primary text-primary-foreground" : "bg-muted text-muted-foreground"}`,
|
|
167
|
+
children: e === "all" ? "All" : e === "TRIAGE" ? `Triage (${r(W?.triage)})` : e === "SNOOZED" ? `Snoozed (${r(W?.snoozed)})` : e.toLowerCase().replace("_", " ")
|
|
159
168
|
}, e))]
|
|
160
|
-
}), /* @__PURE__ */
|
|
169
|
+
}), /* @__PURE__ */ E("div", {
|
|
161
170
|
className: "flex items-center gap-2",
|
|
162
|
-
children: [/* @__PURE__ */
|
|
163
|
-
onClick: () =>
|
|
164
|
-
className: `px-2 py-1 text-xs rounded-md ${
|
|
171
|
+
children: [/* @__PURE__ */ T(_, { className: "h-4 w-4 text-muted-foreground" }), ["NEWEST", "MOST_VOTED"].map((e) => /* @__PURE__ */ T("button", {
|
|
172
|
+
onClick: () => te(e),
|
|
173
|
+
className: `px-2 py-1 text-xs rounded-md ${L === e ? "bg-primary text-primary-foreground" : "bg-muted text-muted-foreground"}`,
|
|
165
174
|
children: e === "NEWEST" ? "Newest" : "Most voted"
|
|
166
175
|
}, e))]
|
|
167
176
|
})]
|
|
168
177
|
}),
|
|
169
|
-
/* @__PURE__ */
|
|
178
|
+
/* @__PURE__ */ E("div", {
|
|
179
|
+
className: "flex flex-wrap items-center gap-3",
|
|
180
|
+
children: [
|
|
181
|
+
/* @__PURE__ */ E("div", {
|
|
182
|
+
className: "flex items-center gap-1",
|
|
183
|
+
children: [/* @__PURE__ */ T("label", {
|
|
184
|
+
htmlFor: "feature-filter-moscow",
|
|
185
|
+
className: "text-xs text-muted-foreground",
|
|
186
|
+
children: "MoSCoW"
|
|
187
|
+
}), /* @__PURE__ */ E("select", {
|
|
188
|
+
id: "feature-filter-moscow",
|
|
189
|
+
"data-testid": "feature-filter-moscow",
|
|
190
|
+
className: "rounded-md border border-input bg-background px-2 py-1 text-xs",
|
|
191
|
+
value: R,
|
|
192
|
+
onChange: (e) => z(e.target.value),
|
|
193
|
+
children: [/* @__PURE__ */ T("option", {
|
|
194
|
+
value: "",
|
|
195
|
+
children: "All"
|
|
196
|
+
}), f.map((e) => /* @__PURE__ */ T("option", {
|
|
197
|
+
value: e,
|
|
198
|
+
children: d[e].label
|
|
199
|
+
}, e))]
|
|
200
|
+
})]
|
|
201
|
+
}),
|
|
202
|
+
/* @__PURE__ */ E("div", {
|
|
203
|
+
className: "flex items-center gap-1",
|
|
204
|
+
children: [/* @__PURE__ */ T("label", {
|
|
205
|
+
htmlFor: "feature-filter-kano",
|
|
206
|
+
className: "text-xs text-muted-foreground",
|
|
207
|
+
children: "Kano"
|
|
208
|
+
}), /* @__PURE__ */ E("select", {
|
|
209
|
+
id: "feature-filter-kano",
|
|
210
|
+
"data-testid": "feature-filter-kano",
|
|
211
|
+
className: "rounded-md border border-input bg-background px-2 py-1 text-xs",
|
|
212
|
+
value: B,
|
|
213
|
+
onChange: (e) => V(e.target.value),
|
|
214
|
+
children: [/* @__PURE__ */ T("option", {
|
|
215
|
+
value: "",
|
|
216
|
+
children: "All"
|
|
217
|
+
}), u.map((e) => /* @__PURE__ */ T("option", {
|
|
218
|
+
value: e,
|
|
219
|
+
children: l[e].label
|
|
220
|
+
}, e))]
|
|
221
|
+
})]
|
|
222
|
+
}),
|
|
223
|
+
/* @__PURE__ */ E("div", {
|
|
224
|
+
className: "flex items-center gap-1",
|
|
225
|
+
children: [/* @__PURE__ */ T("label", {
|
|
226
|
+
htmlFor: "feature-filter-quadrant",
|
|
227
|
+
className: "text-xs text-muted-foreground",
|
|
228
|
+
children: "Quadrant"
|
|
229
|
+
}), /* @__PURE__ */ E("select", {
|
|
230
|
+
id: "feature-filter-quadrant",
|
|
231
|
+
"data-testid": "feature-filter-quadrant",
|
|
232
|
+
className: "rounded-md border border-input bg-background px-2 py-1 text-xs",
|
|
233
|
+
value: H,
|
|
234
|
+
onChange: (e) => U(e.target.value),
|
|
235
|
+
children: [/* @__PURE__ */ T("option", {
|
|
236
|
+
value: "",
|
|
237
|
+
children: "All"
|
|
238
|
+
}), m.map((e) => /* @__PURE__ */ T("option", {
|
|
239
|
+
value: e,
|
|
240
|
+
children: p[e].label
|
|
241
|
+
}, e))]
|
|
242
|
+
})]
|
|
243
|
+
})
|
|
244
|
+
]
|
|
245
|
+
}),
|
|
246
|
+
/* @__PURE__ */ T("div", {
|
|
170
247
|
className: "space-y-3",
|
|
171
|
-
children:
|
|
172
|
-
...o(() =>
|
|
173
|
-
children: /* @__PURE__ */
|
|
248
|
+
children: Z.map((e) => /* @__PURE__ */ T(k, {
|
|
249
|
+
...o(() => C(a("/products/feature-detail-page", e.id)), e.title),
|
|
250
|
+
children: /* @__PURE__ */ T(A, {
|
|
174
251
|
className: "py-4",
|
|
175
|
-
children: /* @__PURE__ */
|
|
252
|
+
children: /* @__PURE__ */ E("div", {
|
|
176
253
|
className: "flex items-start justify-between gap-4",
|
|
177
|
-
children: [/* @__PURE__ */
|
|
254
|
+
children: [/* @__PURE__ */ E("div", {
|
|
178
255
|
className: "flex-1 space-y-2",
|
|
179
256
|
children: [
|
|
180
|
-
/* @__PURE__ */
|
|
257
|
+
/* @__PURE__ */ E("div", {
|
|
181
258
|
className: "flex items-center gap-2",
|
|
182
|
-
children: [
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
259
|
+
children: [
|
|
260
|
+
/* @__PURE__ */ T("span", {
|
|
261
|
+
className: "text-sm font-medium",
|
|
262
|
+
children: e.title
|
|
263
|
+
}),
|
|
264
|
+
/* @__PURE__ */ T("span", {
|
|
265
|
+
className: `text-[10px] px-1.5 py-0.5 rounded-full capitalize ${M[e.status] ?? "bg-gray-100"}`,
|
|
266
|
+
children: e.status.toLowerCase().replace("_", " ")
|
|
267
|
+
}),
|
|
268
|
+
/* @__PURE__ */ T(h, {
|
|
269
|
+
quadrant: e.valueEffortQuadrant,
|
|
270
|
+
hideWhenUnscored: !0
|
|
271
|
+
})
|
|
272
|
+
]
|
|
189
273
|
}),
|
|
190
|
-
/* @__PURE__ */
|
|
274
|
+
/* @__PURE__ */ T("p", {
|
|
191
275
|
className: "text-xs text-muted-foreground",
|
|
192
276
|
children: e.description
|
|
193
277
|
}),
|
|
194
|
-
/* @__PURE__ */
|
|
278
|
+
/* @__PURE__ */ E("div", {
|
|
195
279
|
className: "flex items-center gap-4 text-xs text-muted-foreground",
|
|
196
280
|
children: [
|
|
197
|
-
/* @__PURE__ */
|
|
198
|
-
/* @__PURE__ */
|
|
199
|
-
/* @__PURE__ */
|
|
281
|
+
/* @__PURE__ */ E("span", { children: ["Effort: ", e.effortEstimate ?? "N/A"] }),
|
|
282
|
+
/* @__PURE__ */ E("span", { children: ["Submitted by: ", /* @__PURE__ */ T(n, { id: e.submittedBy })] }),
|
|
283
|
+
/* @__PURE__ */ T("span", { children: new Date(e.updatedAt).toLocaleDateString() })
|
|
200
284
|
]
|
|
201
285
|
}),
|
|
202
|
-
c(e.snoozedUntil,
|
|
286
|
+
c(e.snoozedUntil, I) && /* @__PURE__ */ E("p", {
|
|
203
287
|
className: "text-xs text-muted-foreground",
|
|
204
288
|
children: ["Snoozed until ", new Date(e.snoozedUntil).toLocaleDateString()]
|
|
205
289
|
}),
|
|
206
|
-
/* @__PURE__ */
|
|
290
|
+
/* @__PURE__ */ T(s, {
|
|
207
291
|
feature: e,
|
|
208
|
-
now:
|
|
292
|
+
now: I
|
|
209
293
|
}),
|
|
210
|
-
e.tags.length > 0 && /* @__PURE__ */
|
|
294
|
+
e.tags.length > 0 && /* @__PURE__ */ T("div", {
|
|
211
295
|
className: "flex gap-1",
|
|
212
|
-
children: e.tags.map((e) => /* @__PURE__ */
|
|
296
|
+
children: e.tags.map((e) => /* @__PURE__ */ T(D, {
|
|
213
297
|
variant: "outline",
|
|
214
298
|
className: "text-[10px]",
|
|
215
299
|
children: e
|
|
216
300
|
}, e))
|
|
217
301
|
})
|
|
218
302
|
]
|
|
219
|
-
}), /* @__PURE__ */
|
|
303
|
+
}), /* @__PURE__ */ E("div", {
|
|
220
304
|
className: "flex items-center gap-4 shrink-0",
|
|
221
305
|
children: [
|
|
222
|
-
/* @__PURE__ */
|
|
306
|
+
/* @__PURE__ */ E("div", {
|
|
223
307
|
className: "text-center",
|
|
224
|
-
children: [/* @__PURE__ */
|
|
308
|
+
children: [/* @__PURE__ */ E("div", {
|
|
225
309
|
className: "flex items-center gap-1",
|
|
226
|
-
children: [/* @__PURE__ */
|
|
310
|
+
children: [/* @__PURE__ */ T(S, { className: "h-3 w-3 text-primary" }), /* @__PURE__ */ T("span", {
|
|
227
311
|
className: "text-sm font-bold",
|
|
228
312
|
children: e.priorityScore ?? 0
|
|
229
313
|
})]
|
|
230
|
-
}), /* @__PURE__ */
|
|
314
|
+
}), /* @__PURE__ */ T("p", {
|
|
231
315
|
className: "text-[10px] text-muted-foreground",
|
|
232
316
|
children: "Priority"
|
|
233
317
|
})]
|
|
234
318
|
}),
|
|
235
|
-
/* @__PURE__ */
|
|
319
|
+
/* @__PURE__ */ E("div", {
|
|
236
320
|
className: "text-center",
|
|
237
|
-
children: [/* @__PURE__ */
|
|
321
|
+
children: [/* @__PURE__ */ E("div", {
|
|
238
322
|
className: "flex items-center gap-1",
|
|
239
|
-
children: [/* @__PURE__ */
|
|
323
|
+
children: [/* @__PURE__ */ T(ee, { className: "h-3 w-3 text-green-500" }), /* @__PURE__ */ T("span", {
|
|
240
324
|
className: "text-sm font-bold",
|
|
241
325
|
children: e.voteCount
|
|
242
326
|
})]
|
|
243
|
-
}), /* @__PURE__ */
|
|
327
|
+
}), /* @__PURE__ */ T("p", {
|
|
244
328
|
className: "text-[10px] text-muted-foreground",
|
|
245
329
|
children: "Votes"
|
|
246
330
|
})]
|
|
247
331
|
}),
|
|
248
|
-
/* @__PURE__ */
|
|
332
|
+
/* @__PURE__ */ E("div", {
|
|
249
333
|
className: "text-center",
|
|
250
|
-
children: [/* @__PURE__ */
|
|
334
|
+
children: [/* @__PURE__ */ E("div", {
|
|
251
335
|
className: "flex items-center gap-1",
|
|
252
|
-
children: [/* @__PURE__ */
|
|
336
|
+
children: [/* @__PURE__ */ T(x, { className: "h-3 w-3 text-yellow-500" }), /* @__PURE__ */ T("span", {
|
|
253
337
|
className: "text-sm font-bold",
|
|
254
338
|
children: e.businessValue ?? 0
|
|
255
339
|
})]
|
|
256
|
-
}), /* @__PURE__ */
|
|
340
|
+
}), /* @__PURE__ */ T("p", {
|
|
257
341
|
className: "text-[10px] text-muted-foreground",
|
|
258
342
|
children: "Value"
|
|
259
343
|
})]
|
|
@@ -264,14 +348,14 @@ function D() {
|
|
|
264
348
|
})
|
|
265
349
|
}, e.id))
|
|
266
350
|
}),
|
|
267
|
-
|
|
351
|
+
Z.length === 0 && /* @__PURE__ */ T("p", {
|
|
268
352
|
className: "text-center text-muted-foreground py-8",
|
|
269
|
-
children:
|
|
353
|
+
children: P === "TRIAGE" ? "Nothing waits for triage." : "No features match the selected filters."
|
|
270
354
|
})
|
|
271
355
|
]
|
|
272
356
|
});
|
|
273
357
|
}
|
|
274
358
|
//#endregion
|
|
275
|
-
export {
|
|
359
|
+
export { N as ProductsFeaturesPagePage };
|
|
276
360
|
|
|
277
361
|
//# sourceMappingURL=ProductsFeaturesPagePage.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ProductsFeaturesPagePage.js","names":[],"sources":["../../../src/planmagnet/pages/ProductsFeaturesPagePage.tsx"],"sourcesContent":["// eslint-disable-next-line @typescript-eslint/ban-ts-comment\n// @ts-nocheck\nimport { useState } from 'react';\nimport { gql } from '@apollo/client';\nimport { useQuery } from '@apollo/client/react';\nimport { Card, CardContent, CardHeader, CardTitle, Badge, Button } from '@burdenoff/fe-libs/ui';\nimport {\n Star,\n Plus,\n ThumbsUp,\n MessageSquare,\n Target,\n Filter,\n ArrowUpDown,\n Loader2,\n} from 'lucide-react';\nimport { countLabel, useFeatureCounts } from '../hooks/useCounts';\nimport { usePlanMagnet, usePlanMagnetNavigate } from '../providers/PlanMagnetProvider';\nimport { rowLinkProps, detailPath } from '../utils/rowNavigation';\nimport { PersonName } from '../people/People';\nimport { FeatureTriageActions, isSnoozed } from '../controls/FeatureTriage';\n\nconst LIST_FEATURE_REQUESTS = gql`\n query ListFeatureRequests(\n $workspaceId: ID!\n $filter: PlanmagnetFeatureRequestFilter\n $pagination: PlanmagnetPaginationInput\n $orderBy: PlanmagnetFeatureOrder\n ) {\n planmagnetFeatureRequests(\n workspaceId: $workspaceId\n filter: $filter\n pagination: $pagination\n orderBy: $orderBy\n ) {\n items {\n id\n title\n description\n status\n businessValue\n effortEstimate\n priorityScore\n voteCount\n submittedBy\n tags\n projectId\n snoozedUntil\n createdAt\n updatedAt\n }\n totalCount\n }\n }\n`;\n\ninterface FeatureRequestNode {\n id: string;\n title: string;\n description: string | null;\n status: string;\n businessValue: number | null;\n effortEstimate: string | null;\n priorityScore: number | null;\n voteCount: number;\n submittedBy: string;\n tags: string[];\n createdAt: string;\n updatedAt: string;\n}\n\nconst statusColor: Record<string, string> = {\n SUBMITTED: 'bg-gray-100 text-gray-800',\n UNDER_REVIEW: 'bg-yellow-100 text-yellow-800',\n PLANNED: 'bg-blue-100 text-blue-800',\n IN_PROGRESS: 'bg-purple-100 text-purple-800',\n COMPLETED: 'bg-green-100 text-green-800',\n DECLINED: 'bg-red-100 text-red-800',\n DUPLICATE: 'bg-orange-100 text-orange-800',\n};\n\nexport function ProductsFeaturesPagePage() {\n const navigate = usePlanMagnetNavigate();\n const { workspaceId } = usePlanMagnet();\n const [statusFilter, setStatusFilter] = useState<string>('all');\n // Snooze state is read against the moment the page opened (Date.now() may not run during render).\n const [now] = useState(() => Date.now());\n // Sorting happens on the server over every request (BOFF-7965: it re-sorted only the 50 loaded rows).\n const [sortBy, setSortBy] = useState<'NEWEST' | 'MOST_VOTED'>('NEWEST');\n const counts = useFeatureCounts();\n\n const {\n data,\n loading,\n error,\n } = // eslint-disable-next-line @typescript-eslint/no-explicit-any\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n useQuery<Record<string, any>>(LIST_FEATURE_REQUESTS, {\n variables: {\n workspaceId,\n // Triage (P1.3): the queue and the snoozed requests are server filters, like the status tabs.\n filter:\n statusFilter === 'TRIAGE'\n ? { triage: true }\n : statusFilter === 'SNOOZED'\n ? { snoozed: true }\n : statusFilter !== 'all'\n ? { status: statusFilter }\n : undefined,\n pagination: { first: 50 },\n orderBy: sortBy,\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 <Loader2 className=\"h-8 w-8 animate-spin text-muted-foreground\" />\n </div>\n );\n }\n\n if (error) {\n return <div className=\"p-6 text-destructive\">Failed to load features: {error.message}</div>;\n }\n\n const features: FeatureRequestNode[] = data?.planmagnetFeatureRequests?.items ?? [];\n const totalCount = data?.planmagnetFeatureRequests?.totalCount ?? 0;\n\n const sorted = features;\n\n const statuses = [\n 'all',\n 'TRIAGE',\n 'SNOOZED',\n 'SUBMITTED',\n 'UNDER_REVIEW',\n 'PLANNED',\n 'IN_PROGRESS',\n 'COMPLETED',\n 'DECLINED',\n 'DUPLICATE',\n ];\n\n // Tiles are unfiltered server counts; the tabs change only the list (BOFF-7965).\n const stats = {\n total: countLabel(counts?.all),\n open: countLabel(counts?.open),\n inProgress: countLabel(counts?.byStatus.IN_PROGRESS),\n completed: countLabel(counts?.byStatus.COMPLETED),\n };\n\n return (\n <div className=\"space-y-6 p-6\">\n <div className=\"flex items-center justify-between\">\n <div>\n <h1 className=\"text-2xl font-semibold\">Features</h1>\n {/* Under a tab, the count is of what matches it (BOFF-7990). */}\n <p className=\"text-sm text-muted-foreground\">\n {statusFilter === 'all'\n ? `${stats.total} feature requests`\n : statusFilter === 'TRIAGE'\n ? `${totalCount} waiting for triage`\n : `${totalCount} ${statusFilter.toLowerCase().replace('_', ' ')} match`}\n </p>\n </div>\n <Button size=\"sm\" onClick={() => navigate('/products/new-feature-page')}>\n <Plus className=\"mr-1 h-4 w-4\" />\n New Feature\n </Button>\n </div>\n\n <div className=\"grid grid-cols-2 md:grid-cols-4 gap-4\">\n <Card>\n <CardContent className=\"pt-4\">\n <p className=\"text-xs text-muted-foreground\">Total Features</p>\n <p className=\"text-xl font-bold\">{stats.total}</p>\n </CardContent>\n </Card>\n <Card>\n <CardContent className=\"pt-4\">\n <p className=\"text-xs text-muted-foreground\">In Progress</p>\n <p className=\"text-xl font-bold\">{stats.inProgress}</p>\n </CardContent>\n </Card>\n <Card>\n <CardContent className=\"pt-4\">\n <p className=\"text-xs text-muted-foreground\">Completed</p>\n <p className=\"text-xl font-bold\">{stats.completed}</p>\n </CardContent>\n </Card>\n <Card>\n <CardContent className=\"pt-4\">\n <p className=\"text-xs text-muted-foreground\">Open</p>\n <p className=\"text-xl font-bold\">{stats.open}</p>\n </CardContent>\n </Card>\n </div>\n\n <div className=\"flex items-center justify-between flex-wrap gap-2\">\n <div className=\"flex items-center gap-2\">\n <Filter className=\"h-4 w-4 text-muted-foreground\" />\n {statuses.map((s) => (\n <button\n key={s}\n onClick={() => setStatusFilter(s)}\n className={`px-2 py-1 text-xs rounded-md capitalize ${statusFilter === s ? 'bg-primary text-primary-foreground' : 'bg-muted text-muted-foreground'}`}\n >\n {s === 'all'\n ? 'All'\n : s === 'TRIAGE'\n ? `Triage (${countLabel(counts?.triage)})`\n : s === 'SNOOZED'\n ? `Snoozed (${countLabel(counts?.snoozed)})`\n : s.toLowerCase().replace('_', ' ')}\n </button>\n ))}\n </div>\n <div className=\"flex items-center gap-2\">\n <ArrowUpDown className=\"h-4 w-4 text-muted-foreground\" />\n {(['NEWEST', 'MOST_VOTED'] as const).map((s) => (\n <button\n key={s}\n onClick={() => setSortBy(s)}\n className={`px-2 py-1 text-xs rounded-md ${sortBy === s ? 'bg-primary text-primary-foreground' : 'bg-muted text-muted-foreground'}`}\n >\n {s === 'NEWEST' ? 'Newest' : 'Most voted'}\n </button>\n ))}\n </div>\n </div>\n\n <div className=\"space-y-3\">\n {sorted.map((feature) => (\n <Card\n key={feature.id}\n {...rowLinkProps(\n () => navigate(detailPath('/products/feature-detail-page', feature.id)),\n feature.title\n )}\n >\n <CardContent className=\"py-4\">\n <div className=\"flex items-start justify-between gap-4\">\n <div className=\"flex-1 space-y-2\">\n <div className=\"flex items-center gap-2\">\n <span className=\"text-sm font-medium\">{feature.title}</span>\n <span\n className={`text-[10px] px-1.5 py-0.5 rounded-full capitalize ${statusColor[feature.status] ?? 'bg-gray-100'}`}\n >\n {feature.status.toLowerCase().replace('_', ' ')}\n </span>\n </div>\n <p className=\"text-xs text-muted-foreground\">{feature.description}</p>\n <div className=\"flex items-center gap-4 text-xs text-muted-foreground\">\n <span>Effort: {feature.effortEstimate ?? 'N/A'}</span>\n {/* By name, not user UUID (BOFF-7950). */}\n <span>\n Submitted by: <PersonName id={feature.submittedBy} />\n </span>\n <span>{new Date(feature.updatedAt).toLocaleDateString()}</span>\n </div>\n {isSnoozed(feature.snoozedUntil, now) && (\n <p className=\"text-xs text-muted-foreground\">\n Snoozed until {new Date(feature.snoozedUntil).toLocaleDateString()}\n </p>\n )}\n <FeatureTriageActions feature={feature} now={now} />\n {feature.tags.length > 0 && (\n <div className=\"flex gap-1\">\n {feature.tags.map((tag) => (\n <Badge key={tag} variant=\"outline\" className=\"text-[10px]\">\n {tag}\n </Badge>\n ))}\n </div>\n )}\n </div>\n <div className=\"flex items-center gap-4 shrink-0\">\n <div className=\"text-center\">\n <div className=\"flex items-center gap-1\">\n <Target className=\"h-3 w-3 text-primary\" />\n <span className=\"text-sm font-bold\">{feature.priorityScore ?? 0}</span>\n </div>\n <p className=\"text-[10px] text-muted-foreground\">Priority</p>\n </div>\n <div className=\"text-center\">\n <div className=\"flex items-center gap-1\">\n <ThumbsUp className=\"h-3 w-3 text-green-500\" />\n <span className=\"text-sm font-bold\">{feature.voteCount}</span>\n </div>\n <p className=\"text-[10px] text-muted-foreground\">Votes</p>\n </div>\n <div className=\"text-center\">\n <div className=\"flex items-center gap-1\">\n <Star className=\"h-3 w-3 text-yellow-500\" />\n <span className=\"text-sm font-bold\">{feature.businessValue ?? 0}</span>\n </div>\n <p className=\"text-[10px] text-muted-foreground\">Value</p>\n </div>\n </div>\n </div>\n </CardContent>\n </Card>\n ))}\n </div>\n {sorted.length === 0 && (\n <p className=\"text-center text-muted-foreground py-8\">\n {statusFilter === 'TRIAGE'\n ? 'Nothing waits for triage.'\n : 'No features match the selected filters.'}\n </p>\n )}\n </div>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ProductsFeaturesPagePage.js","names":[],"sources":["../../../src/planmagnet/pages/ProductsFeaturesPagePage.tsx"],"sourcesContent":["// eslint-disable-next-line @typescript-eslint/ban-ts-comment\n// @ts-nocheck\nimport { useState } from 'react';\nimport { gql } from '@apollo/client';\nimport { useQuery } from '@apollo/client/react';\nimport { Card, CardContent, CardHeader, CardTitle, Badge, Button } from '@burdenoff/fe-libs/ui';\nimport {\n Star,\n Plus,\n ThumbsUp,\n MessageSquare,\n Target,\n Filter,\n ArrowUpDown,\n Loader2,\n} from 'lucide-react';\nimport { countLabel, useFeatureCounts } from '../hooks/useCounts';\nimport { usePlanMagnet, usePlanMagnetNavigate } from '../providers/PlanMagnetProvider';\nimport { rowLinkProps, detailPath } from '../utils/rowNavigation';\nimport { PersonName } from '../people/People';\nimport { FeatureTriageActions, isSnoozed } from '../controls/FeatureTriage';\nimport {\n MOSCOW_VALUES,\n MOSCOW_META,\n KANO_VALUES,\n KANO_META,\n QUADRANT_VALUES,\n QUADRANT_META,\n QuadrantBadge,\n} from '../controls/PrioritizationControls';\n\nconst LIST_FEATURE_REQUESTS = gql`\n query ListFeatureRequests(\n $workspaceId: ID!\n $filter: PlanmagnetFeatureRequestFilter\n $pagination: PlanmagnetPaginationInput\n $orderBy: PlanmagnetFeatureOrder\n ) {\n planmagnetFeatureRequests(\n workspaceId: $workspaceId\n filter: $filter\n pagination: $pagination\n orderBy: $orderBy\n ) {\n items {\n id\n title\n description\n status\n businessValue\n effortEstimate\n priorityScore\n voteCount\n submittedBy\n tags\n projectId\n snoozedUntil\n moscow\n kano\n valueEffortQuadrant\n createdAt\n updatedAt\n }\n totalCount\n }\n }\n`;\n\ninterface FeatureRequestNode {\n id: string;\n title: string;\n description: string | null;\n status: string;\n businessValue: number | null;\n effortEstimate: string | null;\n priorityScore: number | null;\n voteCount: number;\n submittedBy: string;\n tags: string[];\n createdAt: string;\n updatedAt: string;\n}\n\nconst statusColor: Record<string, string> = {\n SUBMITTED: 'bg-gray-100 text-gray-800',\n UNDER_REVIEW: 'bg-yellow-100 text-yellow-800',\n PLANNED: 'bg-blue-100 text-blue-800',\n IN_PROGRESS: 'bg-purple-100 text-purple-800',\n COMPLETED: 'bg-green-100 text-green-800',\n DECLINED: 'bg-red-100 text-red-800',\n DUPLICATE: 'bg-orange-100 text-orange-800',\n};\n\nexport function ProductsFeaturesPagePage() {\n const navigate = usePlanMagnetNavigate();\n const { workspaceId } = usePlanMagnet();\n const [statusFilter, setStatusFilter] = useState<string>('all');\n // Snooze state is read against the moment the page opened (Date.now() may not run during render).\n const [now] = useState(() => Date.now());\n // Sorting happens on the server over every request (BOFF-7965: it re-sorted only the 50 loaded rows).\n const [sortBy, setSortBy] = useState<'NEWEST' | 'MOST_VOTED'>('NEWEST');\n // PRM-27: MoSCoW/Kano/quadrant are server filters too, combined with the status tabs above — not a\n // client-side re-filter of the 50 loaded rows (same reasoning as BOFF-7965 for sorting).\n const [moscowFilter, setMoscowFilter] = useState('');\n const [kanoFilter, setKanoFilter] = useState('');\n const [quadrantFilter, setQuadrantFilter] = useState('');\n const counts = useFeatureCounts();\n\n const baseFilter =\n statusFilter === 'TRIAGE'\n ? { triage: true }\n : statusFilter === 'SNOOZED'\n ? { snoozed: true }\n : statusFilter !== 'all'\n ? { status: statusFilter }\n : {};\n const filter = {\n ...baseFilter,\n ...(moscowFilter ? { moscow: moscowFilter } : {}),\n ...(kanoFilter ? { kano: kanoFilter } : {}),\n ...(quadrantFilter ? { quadrant: quadrantFilter } : {}),\n };\n\n const {\n data,\n loading,\n error,\n } = // eslint-disable-next-line @typescript-eslint/no-explicit-any\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n useQuery<Record<string, any>>(LIST_FEATURE_REQUESTS, {\n variables: {\n workspaceId,\n filter: Object.keys(filter).length > 0 ? filter : undefined,\n pagination: { first: 50 },\n orderBy: sortBy,\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 <Loader2 className=\"h-8 w-8 animate-spin text-muted-foreground\" />\n </div>\n );\n }\n\n if (error) {\n return <div className=\"p-6 text-destructive\">Failed to load features: {error.message}</div>;\n }\n\n const features: FeatureRequestNode[] = data?.planmagnetFeatureRequests?.items ?? [];\n const totalCount = data?.planmagnetFeatureRequests?.totalCount ?? 0;\n\n const sorted = features;\n\n const statuses = [\n 'all',\n 'TRIAGE',\n 'SNOOZED',\n 'SUBMITTED',\n 'UNDER_REVIEW',\n 'PLANNED',\n 'IN_PROGRESS',\n 'COMPLETED',\n 'DECLINED',\n 'DUPLICATE',\n ];\n\n // Tiles are unfiltered server counts; the tabs change only the list (BOFF-7965).\n const stats = {\n total: countLabel(counts?.all),\n open: countLabel(counts?.open),\n inProgress: countLabel(counts?.byStatus.IN_PROGRESS),\n completed: countLabel(counts?.byStatus.COMPLETED),\n };\n\n return (\n <div className=\"space-y-6 p-6\">\n <div className=\"flex items-center justify-between\">\n <div>\n <h1 className=\"text-2xl font-semibold\">Features</h1>\n {/* Under a tab, the count is of what matches it (BOFF-7990). */}\n <p className=\"text-sm text-muted-foreground\">\n {statusFilter === 'all'\n ? `${stats.total} feature requests`\n : statusFilter === 'TRIAGE'\n ? `${totalCount} waiting for triage`\n : `${totalCount} ${statusFilter.toLowerCase().replace('_', ' ')} match`}\n </p>\n </div>\n <Button size=\"sm\" onClick={() => navigate('/products/new-feature-page')}>\n <Plus className=\"mr-1 h-4 w-4\" />\n New Feature\n </Button>\n </div>\n\n <div className=\"grid grid-cols-2 md:grid-cols-4 gap-4\">\n <Card>\n <CardContent className=\"pt-4\">\n <p className=\"text-xs text-muted-foreground\">Total Features</p>\n <p className=\"text-xl font-bold\">{stats.total}</p>\n </CardContent>\n </Card>\n <Card>\n <CardContent className=\"pt-4\">\n <p className=\"text-xs text-muted-foreground\">In Progress</p>\n <p className=\"text-xl font-bold\">{stats.inProgress}</p>\n </CardContent>\n </Card>\n <Card>\n <CardContent className=\"pt-4\">\n <p className=\"text-xs text-muted-foreground\">Completed</p>\n <p className=\"text-xl font-bold\">{stats.completed}</p>\n </CardContent>\n </Card>\n <Card>\n <CardContent className=\"pt-4\">\n <p className=\"text-xs text-muted-foreground\">Open</p>\n <p className=\"text-xl font-bold\">{stats.open}</p>\n </CardContent>\n </Card>\n </div>\n\n <div className=\"flex items-center justify-between flex-wrap gap-2\">\n <div className=\"flex items-center gap-2\">\n <Filter className=\"h-4 w-4 text-muted-foreground\" />\n {statuses.map((s) => (\n <button\n key={s}\n onClick={() => setStatusFilter(s)}\n className={`px-2 py-1 text-xs rounded-md capitalize ${statusFilter === s ? 'bg-primary text-primary-foreground' : 'bg-muted text-muted-foreground'}`}\n >\n {s === 'all'\n ? 'All'\n : s === 'TRIAGE'\n ? `Triage (${countLabel(counts?.triage)})`\n : s === 'SNOOZED'\n ? `Snoozed (${countLabel(counts?.snoozed)})`\n : s.toLowerCase().replace('_', ' ')}\n </button>\n ))}\n </div>\n <div className=\"flex items-center gap-2\">\n <ArrowUpDown className=\"h-4 w-4 text-muted-foreground\" />\n {(['NEWEST', 'MOST_VOTED'] as const).map((s) => (\n <button\n key={s}\n onClick={() => setSortBy(s)}\n className={`px-2 py-1 text-xs rounded-md ${sortBy === s ? 'bg-primary text-primary-foreground' : 'bg-muted text-muted-foreground'}`}\n >\n {s === 'NEWEST' ? 'Newest' : 'Most voted'}\n </button>\n ))}\n </div>\n </div>\n\n {/* PRM-27: MoSCoW/Kano/Value-Effort quadrant filters — server-side, combined with the status tabs above. */}\n <div className=\"flex flex-wrap items-center gap-3\">\n <div className=\"flex items-center gap-1\">\n <label htmlFor=\"feature-filter-moscow\" className=\"text-xs text-muted-foreground\">\n MoSCoW\n </label>\n <select\n id=\"feature-filter-moscow\"\n data-testid=\"feature-filter-moscow\"\n className=\"rounded-md border border-input bg-background px-2 py-1 text-xs\"\n value={moscowFilter}\n onChange={(e) => setMoscowFilter(e.target.value)}\n >\n <option value=\"\">All</option>\n {MOSCOW_VALUES.map((v) => (\n <option key={v} value={v}>\n {MOSCOW_META[v].label}\n </option>\n ))}\n </select>\n </div>\n <div className=\"flex items-center gap-1\">\n <label htmlFor=\"feature-filter-kano\" className=\"text-xs text-muted-foreground\">\n Kano\n </label>\n <select\n id=\"feature-filter-kano\"\n data-testid=\"feature-filter-kano\"\n className=\"rounded-md border border-input bg-background px-2 py-1 text-xs\"\n value={kanoFilter}\n onChange={(e) => setKanoFilter(e.target.value)}\n >\n <option value=\"\">All</option>\n {KANO_VALUES.map((v) => (\n <option key={v} value={v}>\n {KANO_META[v].label}\n </option>\n ))}\n </select>\n </div>\n <div className=\"flex items-center gap-1\">\n <label htmlFor=\"feature-filter-quadrant\" className=\"text-xs text-muted-foreground\">\n Quadrant\n </label>\n <select\n id=\"feature-filter-quadrant\"\n data-testid=\"feature-filter-quadrant\"\n className=\"rounded-md border border-input bg-background px-2 py-1 text-xs\"\n value={quadrantFilter}\n onChange={(e) => setQuadrantFilter(e.target.value)}\n >\n <option value=\"\">All</option>\n {QUADRANT_VALUES.map((v) => (\n <option key={v} value={v}>\n {QUADRANT_META[v].label}\n </option>\n ))}\n </select>\n </div>\n </div>\n\n <div className=\"space-y-3\">\n {sorted.map((feature) => (\n <Card\n key={feature.id}\n {...rowLinkProps(\n () => navigate(detailPath('/products/feature-detail-page', feature.id)),\n feature.title\n )}\n >\n <CardContent className=\"py-4\">\n <div className=\"flex items-start justify-between gap-4\">\n <div className=\"flex-1 space-y-2\">\n <div className=\"flex items-center gap-2\">\n <span className=\"text-sm font-medium\">{feature.title}</span>\n <span\n className={`text-[10px] px-1.5 py-0.5 rounded-full capitalize ${statusColor[feature.status] ?? 'bg-gray-100'}`}\n >\n {feature.status.toLowerCase().replace('_', ' ')}\n </span>\n {/* PRM-27 — hidden when unscored so most cards (not yet prioritized) stay uncluttered. */}\n <QuadrantBadge quadrant={feature.valueEffortQuadrant} hideWhenUnscored />\n </div>\n <p className=\"text-xs text-muted-foreground\">{feature.description}</p>\n <div className=\"flex items-center gap-4 text-xs text-muted-foreground\">\n <span>Effort: {feature.effortEstimate ?? 'N/A'}</span>\n {/* By name, not user UUID (BOFF-7950). */}\n <span>\n Submitted by: <PersonName id={feature.submittedBy} />\n </span>\n <span>{new Date(feature.updatedAt).toLocaleDateString()}</span>\n </div>\n {isSnoozed(feature.snoozedUntil, now) && (\n <p className=\"text-xs text-muted-foreground\">\n Snoozed until {new Date(feature.snoozedUntil).toLocaleDateString()}\n </p>\n )}\n <FeatureTriageActions feature={feature} now={now} />\n {feature.tags.length > 0 && (\n <div className=\"flex gap-1\">\n {feature.tags.map((tag) => (\n <Badge key={tag} variant=\"outline\" className=\"text-[10px]\">\n {tag}\n </Badge>\n ))}\n </div>\n )}\n </div>\n <div className=\"flex items-center gap-4 shrink-0\">\n <div className=\"text-center\">\n <div className=\"flex items-center gap-1\">\n <Target className=\"h-3 w-3 text-primary\" />\n <span className=\"text-sm font-bold\">{feature.priorityScore ?? 0}</span>\n </div>\n <p className=\"text-[10px] text-muted-foreground\">Priority</p>\n </div>\n <div className=\"text-center\">\n <div className=\"flex items-center gap-1\">\n <ThumbsUp className=\"h-3 w-3 text-green-500\" />\n <span className=\"text-sm font-bold\">{feature.voteCount}</span>\n </div>\n <p className=\"text-[10px] text-muted-foreground\">Votes</p>\n </div>\n <div className=\"text-center\">\n <div className=\"flex items-center gap-1\">\n <Star className=\"h-3 w-3 text-yellow-500\" />\n <span className=\"text-sm font-bold\">{feature.businessValue ?? 0}</span>\n </div>\n <p className=\"text-[10px] text-muted-foreground\">Value</p>\n </div>\n </div>\n </div>\n </CardContent>\n </Card>\n ))}\n </div>\n {sorted.length === 0 && (\n <p className=\"text-center text-muted-foreground py-8\">\n {statusFilter === 'TRIAGE'\n ? 'Nothing waits for triage.'\n : 'No features match the selected filters.'}\n </p>\n )}\n </div>\n );\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ProductsNewFeaturePagePage.d.ts","sourceRoot":"","sources":["../../../src/planmagnet/pages/ProductsNewFeaturePagePage.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ProductsNewFeaturePagePage.d.ts","sourceRoot":"","sources":["../../../src/planmagnet/pages/ProductsNewFeaturePagePage.tsx"],"names":[],"mappings":"AA+BA,wBAAgB,0BAA0B,4CAyQzC"}
|