@burdenoff/microfe-planmagnet 2026.1002.1 → 2026.1002.3
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-operations.d.ts +2533 -546
- package/dist/generated/wspace-operations.d.ts.map +1 -1
- package/dist/generated/wspace-types.d.ts +5654 -71
- package/dist/generated/wspace-types.d.ts.map +1 -1
- package/dist/index.js +8 -8
- package/dist/planmagnet/PlanMagnetRoot.d.ts.map +1 -1
- package/dist/planmagnet/PlanMagnetRoot.js +180 -162
- package/dist/planmagnet/PlanMagnetRoot.js.map +1 -1
- package/dist/planmagnet/PlanMagnetRoutes.d.ts.map +1 -1
- package/dist/planmagnet/PlanMagnetRoutes.js +100 -84
- package/dist/planmagnet/PlanMagnetRoutes.js.map +1 -1
- package/dist/planmagnet/board/BulkActions.d.ts.map +1 -1
- package/dist/planmagnet/board/BulkActions.js +106 -55
- package/dist/planmagnet/board/BulkActions.js.map +1 -1
- package/dist/planmagnet/controls/Pickers.d.ts +10 -5
- package/dist/planmagnet/controls/Pickers.d.ts.map +1 -1
- package/dist/planmagnet/controls/Pickers.js +10 -9
- package/dist/planmagnet/controls/Pickers.js.map +1 -1
- package/dist/planmagnet/dashboards/DashboardUI.d.ts +0 -4
- package/dist/planmagnet/dashboards/DashboardUI.d.ts.map +1 -1
- package/dist/planmagnet/dashboards/DashboardUI.js +6 -13
- package/dist/planmagnet/dashboards/DashboardUI.js.map +1 -1
- package/dist/planmagnet/dashboards/cards/SprintCapacityCard.d.ts.map +1 -1
- package/dist/planmagnet/dashboards/cards/SprintCapacityCard.js +70 -59
- package/dist/planmagnet/dashboards/cards/SprintCapacityCard.js.map +1 -1
- package/dist/planmagnet/forecast/ResourceForecastCard.js +1 -1
- package/dist/planmagnet/forecast/ResourceForecastCard.js.map +1 -1
- package/dist/planmagnet/index.d.ts +1 -1
- package/dist/planmagnet/index.d.ts.map +1 -1
- package/dist/planmagnet/pages/DashboardsProjectManagerPagePage.d.ts +3 -3
- package/dist/planmagnet/pages/DashboardsProjectManagerPagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/DashboardsProjectManagerPagePage.js +26 -19
- package/dist/planmagnet/pages/DashboardsProjectManagerPagePage.js.map +1 -1
- package/dist/planmagnet/pages/DashboardsTeamUtilizationPagePage.d.ts +2 -2
- package/dist/planmagnet/pages/DashboardsTeamUtilizationPagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/DashboardsTeamUtilizationPagePage.js +18 -12
- package/dist/planmagnet/pages/DashboardsTeamUtilizationPagePage.js.map +1 -1
- package/dist/planmagnet/pages/ProductsCustomerSatisfactionPagePage.d.ts +2 -0
- package/dist/planmagnet/pages/ProductsCustomerSatisfactionPagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/ProductsCustomerSatisfactionPagePage.js +251 -0
- package/dist/planmagnet/pages/ProductsCustomerSatisfactionPagePage.js.map +1 -0
- package/dist/planmagnet/pages/ProductsFeatureAnalyticsPagePage.js +4 -4
- package/dist/planmagnet/pages/ProductsFeatureAnalyticsPagePage.js.map +1 -1
- package/dist/planmagnet/pages/ProductsFeatureDetailPagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/ProductsFeatureDetailPagePage.js +133 -131
- 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 +5 -5
- package/dist/planmagnet/pages/ProductsFeaturesPagePage.js.map +1 -1
- package/dist/planmagnet/pages/ProductsNewFeaturePagePage.js +6 -6
- 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 +107 -82
- package/dist/planmagnet/pages/ProductsProductDetailPagePage.js.map +1 -1
- package/dist/planmagnet/pages/ProductsProductFeatureDetailPagePage.d.ts +2 -0
- package/dist/planmagnet/pages/ProductsProductFeatureDetailPagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/ProductsProductFeatureDetailPagePage.js +174 -0
- package/dist/planmagnet/pages/ProductsProductFeatureDetailPagePage.js.map +1 -0
- package/dist/planmagnet/pages/ProductsProductHierarchyPagePage.d.ts +2 -0
- package/dist/planmagnet/pages/ProductsProductHierarchyPagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/ProductsProductHierarchyPagePage.js +350 -0
- package/dist/planmagnet/pages/ProductsProductHierarchyPagePage.js.map +1 -0
- package/dist/planmagnet/pages/ProductsProductLinesPagePage.d.ts +2 -0
- package/dist/planmagnet/pages/ProductsProductLinesPagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/ProductsProductLinesPagePage.js +168 -0
- package/dist/planmagnet/pages/ProductsProductLinesPagePage.js.map +1 -0
- package/dist/planmagnet/pages/ProductsProductsPagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/ProductsProductsPagePage.js +1 -1
- package/dist/planmagnet/pages/ProductsProductsPagePage.js.map +1 -1
- package/dist/planmagnet/pages/ProductsReleaseDetailPagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/ProductsReleaseDetailPagePage.js +116 -114
- package/dist/planmagnet/pages/ProductsReleaseDetailPagePage.js.map +1 -1
- package/dist/planmagnet/pages/ProjectsPlanningDetailPagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/ProjectsPlanningDetailPagePage.js +174 -159
- package/dist/planmagnet/pages/ProjectsPlanningDetailPagePage.js.map +1 -1
- package/dist/planmagnet/pages/TasksCreateTaskPagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/TasksCreateTaskPagePage.js +159 -145
- 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 +161 -143
- package/dist/planmagnet/pages/TasksEditTaskPagePage.js.map +1 -1
- package/dist/planmagnet/pages/TasksTaskDetailPagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/TasksTaskDetailPagePage.js +160 -156
- package/dist/planmagnet/pages/TasksTaskDetailPagePage.js.map +1 -1
- package/dist/planmagnet/pages/analytics/DeliveryKpisCard.d.ts.map +1 -1
- package/dist/planmagnet/pages/analytics/DeliveryKpisCard.js +97 -99
- package/dist/planmagnet/pages/analytics/DeliveryKpisCard.js.map +1 -1
- package/dist/planmagnet/product/FeatureLinkPanels.d.ts +29 -0
- package/dist/planmagnet/product/FeatureLinkPanels.d.ts.map +1 -0
- package/dist/planmagnet/product/FeatureLinkPanels.js +373 -0
- package/dist/planmagnet/product/FeatureLinkPanels.js.map +1 -0
- package/dist/planmagnet/product/ProductControls.js +1 -1
- package/dist/planmagnet/product/ProductControls.js.map +1 -1
- package/dist/planmagnet/product/ProductFeatureControls.d.ts +39 -0
- package/dist/planmagnet/product/ProductFeatureControls.d.ts.map +1 -0
- package/dist/planmagnet/product/ProductFeatureControls.js +315 -0
- package/dist/planmagnet/product/ProductFeatureControls.js.map +1 -0
- package/dist/planmagnet/product/ProductFeatureLinkCard.d.ts +4 -0
- package/dist/planmagnet/product/ProductFeatureLinkCard.d.ts.map +1 -0
- package/dist/planmagnet/product/ProductFeatureLinkCard.js +192 -0
- package/dist/planmagnet/product/ProductFeatureLinkCard.js.map +1 -0
- package/dist/planmagnet/product/ProductLineControls.d.ts +52 -0
- package/dist/planmagnet/product/ProductLineControls.d.ts.map +1 -0
- package/dist/planmagnet/product/ProductLineControls.js +417 -0
- package/dist/planmagnet/product/ProductLineControls.js.map +1 -0
- package/dist/planmagnet/product/ProductTeamsPanel.d.ts +4 -0
- package/dist/planmagnet/product/ProductTeamsPanel.d.ts.map +1 -0
- package/dist/planmagnet/product/ProductTeamsPanel.js +129 -0
- package/dist/planmagnet/product/ProductTeamsPanel.js.map +1 -0
- package/dist/planmagnet/product/WorkItemProductFeatureChip.d.ts +4 -0
- package/dist/planmagnet/product/WorkItemProductFeatureChip.d.ts.map +1 -0
- package/dist/planmagnet/product/WorkItemProductFeatureChip.js +41 -0
- package/dist/planmagnet/product/WorkItemProductFeatureChip.js.map +1 -0
- package/dist/planmagnet/product/hierarchy.d.ts +127 -0
- package/dist/planmagnet/product/hierarchy.d.ts.map +1 -0
- package/dist/planmagnet/product/hierarchy.js +173 -0
- package/dist/planmagnet/product/hierarchy.js.map +1 -0
- package/dist/planmagnet/product/hierarchyOperations.d.ts +35 -0
- package/dist/planmagnet/product/hierarchyOperations.d.ts.map +1 -0
- package/dist/planmagnet/product/hierarchyOperations.js +440 -0
- package/dist/planmagnet/product/hierarchyOperations.js.map +1 -0
- package/dist/planmagnet/product/refusal.d.ts +14 -0
- package/dist/planmagnet/product/refusal.d.ts.map +1 -0
- package/dist/planmagnet/product/refusal.js +10 -0
- package/dist/planmagnet/product/refusal.js.map +1 -0
- package/dist/planmagnet/product/routes.d.ts +10 -0
- package/dist/planmagnet/product/routes.d.ts.map +1 -1
- package/dist/planmagnet/product/routes.js +2 -2
- package/dist/planmagnet/product/routes.js.map +1 -1
- package/dist/planmagnet/satisfaction/DeliverySatisfactionSection.d.ts +20 -0
- package/dist/planmagnet/satisfaction/DeliverySatisfactionSection.d.ts.map +1 -0
- package/dist/planmagnet/satisfaction/DeliverySatisfactionSection.js +55 -0
- package/dist/planmagnet/satisfaction/DeliverySatisfactionSection.js.map +1 -0
- package/dist/planmagnet/satisfaction/SatisfactionFigures.d.ts +30 -0
- package/dist/planmagnet/satisfaction/SatisfactionFigures.d.ts.map +1 -0
- package/dist/planmagnet/satisfaction/SatisfactionFigures.js +282 -0
- package/dist/planmagnet/satisfaction/SatisfactionFigures.js.map +1 -0
- package/dist/planmagnet/satisfaction/SatisfactionImportDialog.d.ts +9 -0
- package/dist/planmagnet/satisfaction/SatisfactionImportDialog.d.ts.map +1 -0
- package/dist/planmagnet/satisfaction/SatisfactionImportDialog.js +390 -0
- package/dist/planmagnet/satisfaction/SatisfactionImportDialog.js.map +1 -0
- package/dist/planmagnet/satisfaction/SatisfactionLinkFields.d.ts +17 -0
- package/dist/planmagnet/satisfaction/SatisfactionLinkFields.d.ts.map +1 -0
- package/dist/planmagnet/satisfaction/SatisfactionLinkFields.js +77 -0
- package/dist/planmagnet/satisfaction/SatisfactionLinkFields.js.map +1 -0
- package/dist/planmagnet/satisfaction/SatisfactionReleaseSelect.d.ts +18 -0
- package/dist/planmagnet/satisfaction/SatisfactionReleaseSelect.d.ts.map +1 -0
- package/dist/planmagnet/satisfaction/SatisfactionReleaseSelect.js +87 -0
- package/dist/planmagnet/satisfaction/SatisfactionReleaseSelect.js.map +1 -0
- package/dist/planmagnet/satisfaction/SatisfactionResponseDialog.d.ts +13 -0
- package/dist/planmagnet/satisfaction/SatisfactionResponseDialog.d.ts.map +1 -0
- package/dist/planmagnet/satisfaction/SatisfactionResponseDialog.js +326 -0
- package/dist/planmagnet/satisfaction/SatisfactionResponseDialog.js.map +1 -0
- package/dist/planmagnet/satisfaction/SatisfactionResponsesTable.d.ts +23 -0
- package/dist/planmagnet/satisfaction/SatisfactionResponsesTable.d.ts.map +1 -0
- package/dist/planmagnet/satisfaction/SatisfactionResponsesTable.js +258 -0
- package/dist/planmagnet/satisfaction/SatisfactionResponsesTable.js.map +1 -0
- package/dist/planmagnet/satisfaction/SatisfactionSummaryCard.d.ts +6 -0
- package/dist/planmagnet/satisfaction/SatisfactionSummaryCard.d.ts.map +1 -0
- package/dist/planmagnet/satisfaction/SatisfactionSummaryCard.js +56 -0
- package/dist/planmagnet/satisfaction/SatisfactionSummaryCard.js.map +1 -0
- package/dist/planmagnet/satisfaction/SatisfactionWindowPicker.d.ts +16 -0
- package/dist/planmagnet/satisfaction/SatisfactionWindowPicker.d.ts.map +1 -0
- package/dist/planmagnet/satisfaction/SatisfactionWindowPicker.js +102 -0
- package/dist/planmagnet/satisfaction/SatisfactionWindowPicker.js.map +1 -0
- package/dist/planmagnet/satisfaction/satisfaction.d.ts +154 -0
- package/dist/planmagnet/satisfaction/satisfaction.d.ts.map +1 -0
- package/dist/planmagnet/satisfaction/satisfaction.js +210 -0
- package/dist/planmagnet/satisfaction/satisfaction.js.map +1 -0
- package/dist/planmagnet/satisfaction/satisfactionCsv.d.ts +108 -0
- package/dist/planmagnet/satisfaction/satisfactionCsv.d.ts.map +1 -0
- package/dist/planmagnet/satisfaction/satisfactionCsv.js +211 -0
- package/dist/planmagnet/satisfaction/satisfactionCsv.js.map +1 -0
- package/dist/planmagnet/satisfaction/satisfactionForm.d.ts +90 -0
- package/dist/planmagnet/satisfaction/satisfactionForm.d.ts.map +1 -0
- package/dist/planmagnet/satisfaction/satisfactionForm.js +90 -0
- package/dist/planmagnet/satisfaction/satisfactionForm.js.map +1 -0
- package/dist/planmagnet/satisfaction/satisfactionOperations.d.ts +116 -0
- package/dist/planmagnet/satisfaction/satisfactionOperations.d.ts.map +1 -0
- package/dist/planmagnet/satisfaction/satisfactionOperations.js +86 -0
- package/dist/planmagnet/satisfaction/satisfactionOperations.js.map +1 -0
- package/dist/planmagnet/satisfaction/useSatisfactionAccess.d.ts +20 -0
- package/dist/planmagnet/satisfaction/useSatisfactionAccess.d.ts.map +1 -0
- package/dist/planmagnet/satisfaction/useSatisfactionAccess.js +31 -0
- package/dist/planmagnet/satisfaction/useSatisfactionAccess.js.map +1 -0
- package/dist/planmagnet/skills/RequiredSkillsEditor.d.ts +35 -0
- package/dist/planmagnet/skills/RequiredSkillsEditor.d.ts.map +1 -0
- package/dist/planmagnet/skills/RequiredSkillsEditor.js +124 -0
- package/dist/planmagnet/skills/RequiredSkillsEditor.js.map +1 -0
- package/dist/planmagnet/skills/SkillChips.d.ts +30 -0
- package/dist/planmagnet/skills/SkillChips.d.ts.map +1 -0
- package/dist/planmagnet/skills/SkillChips.js +57 -0
- package/dist/planmagnet/skills/SkillChips.js.map +1 -0
- package/dist/planmagnet/skills/SkillCoverageCard.d.ts +24 -0
- package/dist/planmagnet/skills/SkillCoverageCard.d.ts.map +1 -0
- package/dist/planmagnet/skills/SkillCoverageCard.js +256 -0
- package/dist/planmagnet/skills/SkillCoverageCard.js.map +1 -0
- package/dist/planmagnet/skills/WorkItemRequiredSkills.d.ts +10 -0
- package/dist/planmagnet/skills/WorkItemRequiredSkills.d.ts.map +1 -0
- package/dist/planmagnet/skills/WorkItemRequiredSkills.js +65 -0
- package/dist/planmagnet/skills/WorkItemRequiredSkills.js.map +1 -0
- package/dist/planmagnet/skills/skillOperations.d.ts +52 -0
- package/dist/planmagnet/skills/skillOperations.d.ts.map +1 -0
- package/dist/planmagnet/skills/skillOperations.js +44 -0
- package/dist/planmagnet/skills/skillOperations.js.map +1 -0
- package/dist/planmagnet/skills/skillTags.d.ts +103 -0
- package/dist/planmagnet/skills/skillTags.d.ts.map +1 -0
- package/dist/planmagnet/skills/skillTags.js +115 -0
- package/dist/planmagnet/skills/skillTags.js.map +1 -0
- package/dist/planmagnet/skills/useRequiredSkillsDraft.d.ts +28 -0
- package/dist/planmagnet/skills/useRequiredSkillsDraft.d.ts.map +1 -0
- package/dist/planmagnet/skills/useRequiredSkillsDraft.js +30 -0
- package/dist/planmagnet/skills/useRequiredSkillsDraft.js.map +1 -0
- package/dist/shared/utils/i18n.d.ts +3 -0
- package/dist/shared/utils/i18n.d.ts.map +1 -1
- package/dist/shared/utils/i18n.js +1 -1
- package/dist/shared/utils/i18n.js.map +1 -1
- package/package.json +4 -4
|
@@ -6,15 +6,16 @@ import { FeatureTriageActions as a, isOpenRequest as o, isSnoozed as s } from ".
|
|
|
6
6
|
import { CategoryBadge as c, RatingDisplay as l } from "../controls/FeedbackControls.js";
|
|
7
7
|
import { FeatureHeaderActions as u, FeaturePrioritizationCard as d, FeatureVoteButton as f } from "../controls/FeatureControls.js";
|
|
8
8
|
import { FeatureInitiativeCard as p } from "../roadmaps/FeatureInitiativeCard.js";
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
9
|
+
import { ProductFeatureLinkCard as m } from "../product/ProductFeatureLinkCard.js";
|
|
10
|
+
import { useState as h } from "react";
|
|
11
|
+
import { Loader2 as g, MessageSquare as _, Star as v, Target as y, ThumbsUp as b } from "lucide-react";
|
|
12
|
+
import { useParams as x } from "react-router";
|
|
13
|
+
import { gql as S } from "@apollo/client";
|
|
14
|
+
import { useQuery as C } from "@apollo/client/react";
|
|
15
|
+
import { Fragment as w, jsx as T, jsxs as E } from "react/jsx-runtime";
|
|
16
|
+
import { Badge as D, Card as O, CardContent as k, CardHeader as A, CardTitle as j } from "@burdenoff/fe-libs/ui";
|
|
16
17
|
//#region src/planmagnet/pages/ProductsFeatureDetailPagePage.tsx
|
|
17
|
-
var
|
|
18
|
+
var M = S`
|
|
18
19
|
query GetFeatureRequest($id: ID!) {
|
|
19
20
|
planmagnetFeatureRequest(id: $id) {
|
|
20
21
|
id
|
|
@@ -78,88 +79,88 @@ var j = x`
|
|
|
78
79
|
}
|
|
79
80
|
}
|
|
80
81
|
`;
|
|
81
|
-
function
|
|
82
|
-
let { workspaceId:
|
|
83
|
-
variables: { id:
|
|
84
|
-
skip: !
|
|
82
|
+
function N() {
|
|
83
|
+
let { workspaceId: S, currentUser: N } = e(), P = t(), [F] = h(() => Date.now()), I = x().id ?? "", { data: L, loading: R, error: z } = C(M, {
|
|
84
|
+
variables: { id: I },
|
|
85
|
+
skip: !I
|
|
85
86
|
});
|
|
86
|
-
if (
|
|
87
|
+
if (R && !L) return /* @__PURE__ */ T("div", {
|
|
87
88
|
className: "flex items-center justify-center p-12",
|
|
88
|
-
children: /* @__PURE__ */
|
|
89
|
+
children: /* @__PURE__ */ T(g, { className: "h-8 w-8 animate-spin text-muted-foreground" })
|
|
89
90
|
});
|
|
90
|
-
if (
|
|
91
|
+
if (z) return /* @__PURE__ */ E("div", {
|
|
91
92
|
className: "p-6 text-destructive",
|
|
92
|
-
children: ["Failed to load feature: ",
|
|
93
|
+
children: ["Failed to load feature request: ", z.message]
|
|
93
94
|
});
|
|
94
|
-
let
|
|
95
|
-
if (!
|
|
95
|
+
let B = L?.planmagnetFeatureRequest;
|
|
96
|
+
if (!B) return /* @__PURE__ */ T("div", {
|
|
96
97
|
className: "p-6 text-muted-foreground",
|
|
97
|
-
children: "Feature not found."
|
|
98
|
+
children: "Feature request not found."
|
|
98
99
|
});
|
|
99
|
-
let
|
|
100
|
-
return /* @__PURE__ */
|
|
100
|
+
let V = B.votes ?? [], H = B.competitors ?? [];
|
|
101
|
+
return /* @__PURE__ */ E("div", {
|
|
101
102
|
className: "space-y-6 p-6",
|
|
102
103
|
children: [
|
|
103
|
-
/* @__PURE__ */
|
|
104
|
+
/* @__PURE__ */ E("div", {
|
|
104
105
|
className: "flex items-center justify-between",
|
|
105
|
-
children: [/* @__PURE__ */
|
|
106
|
+
children: [/* @__PURE__ */ E("div", { children: [/* @__PURE__ */ T("h1", {
|
|
106
107
|
className: "text-2xl font-semibold",
|
|
107
|
-
children:
|
|
108
|
-
}), /* @__PURE__ */
|
|
108
|
+
children: B.title
|
|
109
|
+
}), /* @__PURE__ */ E("p", {
|
|
109
110
|
className: "text-sm text-muted-foreground",
|
|
110
111
|
children: [
|
|
111
112
|
"Submitted by: ",
|
|
112
|
-
/* @__PURE__ */
|
|
113
|
+
/* @__PURE__ */ T(n, { id: B.submittedBy }),
|
|
113
114
|
" · Effort:",
|
|
114
115
|
" ",
|
|
115
|
-
|
|
116
|
+
B.effortEstimate ?? "N/A"
|
|
116
117
|
]
|
|
117
|
-
})] }), /* @__PURE__ */
|
|
118
|
+
})] }), /* @__PURE__ */ E("div", {
|
|
118
119
|
className: "flex flex-col items-end gap-2",
|
|
119
|
-
children: [/* @__PURE__ */
|
|
120
|
-
featureId:
|
|
121
|
-
voted:
|
|
122
|
-
},
|
|
120
|
+
children: [/* @__PURE__ */ T(f, {
|
|
121
|
+
featureId: B.id,
|
|
122
|
+
voted: V.some((e) => e.voterId === N?.id)
|
|
123
|
+
}, B.id), /* @__PURE__ */ T(u, { feature: B })]
|
|
123
124
|
})]
|
|
124
125
|
}),
|
|
125
|
-
o(
|
|
126
|
+
o(B.status) && /* @__PURE__ */ E(O, {
|
|
126
127
|
"data-testid": "triage-card",
|
|
127
|
-
children: [/* @__PURE__ */
|
|
128
|
+
children: [/* @__PURE__ */ T(A, { children: /* @__PURE__ */ T(j, { children: "Triage" }) }), /* @__PURE__ */ E(k, {
|
|
128
129
|
className: "space-y-2",
|
|
129
|
-
children: [/* @__PURE__ */
|
|
130
|
+
children: [/* @__PURE__ */ T("p", {
|
|
130
131
|
className: "text-sm text-muted-foreground",
|
|
131
|
-
children: s(
|
|
132
|
-
}), /* @__PURE__ */
|
|
133
|
-
feature:
|
|
134
|
-
now:
|
|
132
|
+
children: s(B.snoozedUntil, F) ? `Snoozed until ${new Date(B.snoozedUntil).toLocaleString()} — it returns to the triage queue then.` : B.status === "SUBMITTED" ? "Waiting for a decision." : "Under review: accept it as planned, decline it, or merge it into its original."
|
|
133
|
+
}), /* @__PURE__ */ T(a, {
|
|
134
|
+
feature: B,
|
|
135
|
+
now: F
|
|
135
136
|
})]
|
|
136
137
|
})]
|
|
137
138
|
}),
|
|
138
|
-
|
|
139
|
+
B.status === "DECLINED" && B.declineReason && /* @__PURE__ */ T(O, {
|
|
139
140
|
"data-testid": "decline-reason",
|
|
140
|
-
children: /* @__PURE__ */
|
|
141
|
+
children: /* @__PURE__ */ E(k, {
|
|
141
142
|
className: "pt-4 text-sm",
|
|
142
|
-
children: [/* @__PURE__ */
|
|
143
|
+
children: [/* @__PURE__ */ T("span", {
|
|
143
144
|
className: "font-medium",
|
|
144
145
|
children: "Declined: "
|
|
145
|
-
}),
|
|
146
|
+
}), B.declineReason]
|
|
146
147
|
})
|
|
147
148
|
}),
|
|
148
|
-
|
|
149
|
+
B.status === "DUPLICATE" && B.duplicateOfId && /* @__PURE__ */ T(O, {
|
|
149
150
|
"data-testid": "duplicate-of",
|
|
150
|
-
children: /* @__PURE__ */
|
|
151
|
+
children: /* @__PURE__ */ E(k, {
|
|
151
152
|
className: "pt-4 text-sm",
|
|
152
153
|
children: [
|
|
153
|
-
/* @__PURE__ */
|
|
154
|
+
/* @__PURE__ */ T("span", {
|
|
154
155
|
className: "font-medium",
|
|
155
156
|
children: "Duplicate of "
|
|
156
157
|
}),
|
|
157
|
-
|
|
158
|
+
B.duplicateOf ? /* @__PURE__ */ T("button", {
|
|
158
159
|
type: "button",
|
|
159
160
|
className: "text-primary underline-offset-2 hover:underline",
|
|
160
|
-
onClick: () =>
|
|
161
|
-
children:
|
|
162
|
-
}) : /* @__PURE__ */
|
|
161
|
+
onClick: () => P(r("/products/feature-detail-page", B.duplicateOf.id)),
|
|
162
|
+
children: B.duplicateOf.title
|
|
163
|
+
}) : /* @__PURE__ */ T("span", {
|
|
163
164
|
className: "text-muted-foreground",
|
|
164
165
|
children: "a request that has since been deleted"
|
|
165
166
|
}),
|
|
@@ -168,60 +169,60 @@ function M() {
|
|
|
168
169
|
]
|
|
169
170
|
})
|
|
170
171
|
}),
|
|
171
|
-
/* @__PURE__ */
|
|
172
|
+
/* @__PURE__ */ E("div", {
|
|
172
173
|
className: "grid grid-cols-2 md:grid-cols-4 gap-4",
|
|
173
174
|
children: [
|
|
174
|
-
/* @__PURE__ */
|
|
175
|
+
/* @__PURE__ */ T(O, { children: /* @__PURE__ */ E(k, {
|
|
175
176
|
className: "pt-4 text-center",
|
|
176
177
|
children: [
|
|
177
|
-
/* @__PURE__ */
|
|
178
|
-
/* @__PURE__ */
|
|
178
|
+
/* @__PURE__ */ T(y, { className: "h-5 w-5 mx-auto text-primary" }),
|
|
179
|
+
/* @__PURE__ */ T("p", {
|
|
179
180
|
className: "text-2xl font-bold mt-1",
|
|
180
|
-
children:
|
|
181
|
+
children: B.priorityScore ?? 0
|
|
181
182
|
}),
|
|
182
|
-
/* @__PURE__ */
|
|
183
|
+
/* @__PURE__ */ T("p", {
|
|
183
184
|
className: "text-xs text-muted-foreground",
|
|
184
185
|
children: "Priority Score"
|
|
185
186
|
})
|
|
186
187
|
]
|
|
187
188
|
}) }),
|
|
188
|
-
/* @__PURE__ */
|
|
189
|
+
/* @__PURE__ */ T(O, { children: /* @__PURE__ */ E(k, {
|
|
189
190
|
className: "pt-4 text-center",
|
|
190
191
|
children: [
|
|
191
|
-
/* @__PURE__ */
|
|
192
|
-
/* @__PURE__ */
|
|
192
|
+
/* @__PURE__ */ T(b, { className: "h-5 w-5 mx-auto text-green-500" }),
|
|
193
|
+
/* @__PURE__ */ T("p", {
|
|
193
194
|
className: "text-2xl font-bold mt-1",
|
|
194
|
-
children:
|
|
195
|
+
children: B.voteCount
|
|
195
196
|
}),
|
|
196
|
-
/* @__PURE__ */
|
|
197
|
+
/* @__PURE__ */ T("p", {
|
|
197
198
|
className: "text-xs text-muted-foreground",
|
|
198
199
|
children: "Votes"
|
|
199
200
|
})
|
|
200
201
|
]
|
|
201
202
|
}) }),
|
|
202
|
-
/* @__PURE__ */
|
|
203
|
+
/* @__PURE__ */ T(O, { children: /* @__PURE__ */ E(k, {
|
|
203
204
|
className: "pt-4 text-center",
|
|
204
205
|
children: [
|
|
205
|
-
/* @__PURE__ */
|
|
206
|
-
/* @__PURE__ */
|
|
206
|
+
/* @__PURE__ */ T(v, { className: "h-5 w-5 mx-auto text-yellow-500" }),
|
|
207
|
+
/* @__PURE__ */ T("p", {
|
|
207
208
|
className: "text-2xl font-bold mt-1",
|
|
208
|
-
children:
|
|
209
|
+
children: B.businessValue ?? 0
|
|
209
210
|
}),
|
|
210
|
-
/* @__PURE__ */
|
|
211
|
+
/* @__PURE__ */ T("p", {
|
|
211
212
|
className: "text-xs text-muted-foreground",
|
|
212
213
|
children: "Business Value"
|
|
213
214
|
})
|
|
214
215
|
]
|
|
215
216
|
}) }),
|
|
216
|
-
/* @__PURE__ */
|
|
217
|
+
/* @__PURE__ */ T(O, { children: /* @__PURE__ */ E(k, {
|
|
217
218
|
className: "pt-4 text-center",
|
|
218
219
|
children: [
|
|
219
|
-
/* @__PURE__ */
|
|
220
|
-
/* @__PURE__ */
|
|
220
|
+
/* @__PURE__ */ T(_, { className: "h-5 w-5 mx-auto text-blue-500" }),
|
|
221
|
+
/* @__PURE__ */ T("p", {
|
|
221
222
|
className: "text-2xl font-bold mt-1",
|
|
222
|
-
children:
|
|
223
|
+
children: H.length
|
|
223
224
|
}),
|
|
224
|
-
/* @__PURE__ */
|
|
225
|
+
/* @__PURE__ */ T("p", {
|
|
225
226
|
className: "text-xs text-muted-foreground",
|
|
226
227
|
children: "Competitors"
|
|
227
228
|
})
|
|
@@ -229,147 +230,148 @@ function M() {
|
|
|
229
230
|
}) })
|
|
230
231
|
]
|
|
231
232
|
}),
|
|
232
|
-
/* @__PURE__ */
|
|
233
|
+
/* @__PURE__ */ E("div", {
|
|
233
234
|
className: "grid grid-cols-1 lg:grid-cols-3 gap-6",
|
|
234
|
-
children: [/* @__PURE__ */
|
|
235
|
+
children: [/* @__PURE__ */ E("div", {
|
|
235
236
|
className: "lg:col-span-2 space-y-6",
|
|
236
237
|
children: [
|
|
237
|
-
/* @__PURE__ */
|
|
238
|
+
/* @__PURE__ */ E(O, { children: [/* @__PURE__ */ T(A, { children: /* @__PURE__ */ T(j, { children: "Description" }) }), /* @__PURE__ */ T(k, { children: /* @__PURE__ */ T("p", {
|
|
238
239
|
className: "text-sm",
|
|
239
|
-
children:
|
|
240
|
+
children: B.description ?? "No description provided."
|
|
240
241
|
}) })] }),
|
|
241
|
-
/* @__PURE__ */
|
|
242
|
+
/* @__PURE__ */ E(O, { children: [/* @__PURE__ */ T(A, { children: /* @__PURE__ */ E(j, { children: [
|
|
242
243
|
"Votes (",
|
|
243
|
-
|
|
244
|
+
V.length,
|
|
244
245
|
")"
|
|
245
|
-
] }) }), /* @__PURE__ */
|
|
246
|
+
] }) }), /* @__PURE__ */ E(k, {
|
|
246
247
|
className: "space-y-3",
|
|
247
|
-
children: [
|
|
248
|
+
children: [V.length === 0 && /* @__PURE__ */ T("p", {
|
|
248
249
|
className: "text-sm text-muted-foreground",
|
|
249
250
|
children: "No votes yet."
|
|
250
|
-
}),
|
|
251
|
+
}), V.map((e) => /* @__PURE__ */ E("div", {
|
|
251
252
|
className: "flex items-start justify-between border rounded-md p-3",
|
|
252
|
-
children: [/* @__PURE__ */
|
|
253
|
+
children: [/* @__PURE__ */ E("div", { children: [/* @__PURE__ */ E("p", {
|
|
253
254
|
className: "text-sm font-medium",
|
|
254
|
-
children: ["Voter: ", /* @__PURE__ */
|
|
255
|
-
}), e.comment && /* @__PURE__ */
|
|
255
|
+
children: ["Voter: ", /* @__PURE__ */ T(n, { id: e.voterId })]
|
|
256
|
+
}), e.comment && /* @__PURE__ */ T("p", {
|
|
256
257
|
className: "text-xs text-muted-foreground mt-1",
|
|
257
258
|
children: e.comment
|
|
258
|
-
})] }), /* @__PURE__ */
|
|
259
|
+
})] }), /* @__PURE__ */ E("div", {
|
|
259
260
|
className: "flex items-center gap-1",
|
|
260
|
-
children: [/* @__PURE__ */
|
|
261
|
+
children: [/* @__PURE__ */ T(b, { className: "h-3 w-3 text-green-500" }), /* @__PURE__ */ T("span", {
|
|
261
262
|
className: "text-sm font-bold",
|
|
262
263
|
children: e.weight
|
|
263
264
|
})]
|
|
264
265
|
})]
|
|
265
266
|
}, e.id))]
|
|
266
267
|
})] }),
|
|
267
|
-
/* @__PURE__ */
|
|
268
|
+
/* @__PURE__ */ E(O, { children: [/* @__PURE__ */ T(A, { children: /* @__PURE__ */ E(j, { children: [
|
|
268
269
|
"Competitors (",
|
|
269
|
-
|
|
270
|
+
H.length,
|
|
270
271
|
")"
|
|
271
|
-
] }) }), /* @__PURE__ */
|
|
272
|
-
featureRequestId:
|
|
273
|
-
competitors:
|
|
272
|
+
] }) }), /* @__PURE__ */ T(k, { children: /* @__PURE__ */ T(i, {
|
|
273
|
+
featureRequestId: B.id,
|
|
274
|
+
competitors: H
|
|
274
275
|
}) })] })
|
|
275
276
|
]
|
|
276
|
-
}), /* @__PURE__ */
|
|
277
|
+
}), /* @__PURE__ */ E("div", {
|
|
277
278
|
className: "space-y-6",
|
|
278
279
|
children: [
|
|
279
|
-
/* @__PURE__ */
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
280
|
+
/* @__PURE__ */ T(m, { featureRequestId: B.id }),
|
|
281
|
+
/* @__PURE__ */ T(p, {
|
|
282
|
+
featureId: B.id,
|
|
283
|
+
productId: B.productId ?? null,
|
|
284
|
+
initiative: B.roadmapItem ?? null
|
|
283
285
|
}),
|
|
284
|
-
/* @__PURE__ */
|
|
285
|
-
/* @__PURE__ */
|
|
286
|
+
/* @__PURE__ */ T(d, { feature: B }),
|
|
287
|
+
/* @__PURE__ */ E(O, { children: [/* @__PURE__ */ T(A, { children: /* @__PURE__ */ T(j, { children: "Details" }) }), /* @__PURE__ */ E(k, {
|
|
286
288
|
className: "space-y-3 text-sm",
|
|
287
289
|
children: [
|
|
288
|
-
/* @__PURE__ */
|
|
290
|
+
/* @__PURE__ */ E("div", {
|
|
289
291
|
className: "flex justify-between",
|
|
290
|
-
children: [/* @__PURE__ */
|
|
292
|
+
children: [/* @__PURE__ */ T("span", {
|
|
291
293
|
className: "text-muted-foreground",
|
|
292
294
|
children: "Status"
|
|
293
|
-
}), /* @__PURE__ */
|
|
295
|
+
}), /* @__PURE__ */ T(D, {
|
|
294
296
|
variant: "secondary",
|
|
295
297
|
className: "capitalize",
|
|
296
|
-
children:
|
|
298
|
+
children: B.status.toLowerCase().replace("_", " ")
|
|
297
299
|
})]
|
|
298
300
|
}),
|
|
299
|
-
/* @__PURE__ */
|
|
301
|
+
/* @__PURE__ */ E("div", {
|
|
300
302
|
className: "flex justify-between",
|
|
301
|
-
children: [/* @__PURE__ */
|
|
303
|
+
children: [/* @__PURE__ */ T("span", {
|
|
302
304
|
className: "text-muted-foreground",
|
|
303
305
|
children: "Priority Score"
|
|
304
|
-
}), /* @__PURE__ */
|
|
306
|
+
}), /* @__PURE__ */ T(D, {
|
|
305
307
|
variant: "outline",
|
|
306
|
-
children:
|
|
308
|
+
children: B.priorityScore ?? "N/A"
|
|
307
309
|
})]
|
|
308
310
|
}),
|
|
309
|
-
/* @__PURE__ */
|
|
311
|
+
/* @__PURE__ */ E("div", {
|
|
310
312
|
className: "flex justify-between",
|
|
311
|
-
children: [/* @__PURE__ */
|
|
313
|
+
children: [/* @__PURE__ */ T("span", {
|
|
312
314
|
className: "text-muted-foreground",
|
|
313
315
|
children: "Effort"
|
|
314
|
-
}), /* @__PURE__ */
|
|
316
|
+
}), /* @__PURE__ */ T(D, {
|
|
315
317
|
variant: "outline",
|
|
316
318
|
className: "capitalize",
|
|
317
|
-
children:
|
|
319
|
+
children: B.effortEstimate ?? "N/A"
|
|
318
320
|
})]
|
|
319
321
|
}),
|
|
320
|
-
/* @__PURE__ */
|
|
322
|
+
/* @__PURE__ */ E("div", {
|
|
321
323
|
className: "flex justify-between",
|
|
322
|
-
children: [/* @__PURE__ */
|
|
324
|
+
children: [/* @__PURE__ */ T("span", {
|
|
323
325
|
className: "text-muted-foreground",
|
|
324
326
|
children: "Business Value"
|
|
325
|
-
}), /* @__PURE__ */
|
|
327
|
+
}), /* @__PURE__ */ T("span", {
|
|
326
328
|
className: "font-medium",
|
|
327
|
-
children:
|
|
329
|
+
children: B.businessValue ?? "N/A"
|
|
328
330
|
})]
|
|
329
331
|
}),
|
|
330
|
-
/* @__PURE__ */
|
|
332
|
+
/* @__PURE__ */ E("div", {
|
|
331
333
|
className: "flex justify-between items-center",
|
|
332
|
-
children: [/* @__PURE__ */
|
|
334
|
+
children: [/* @__PURE__ */ T("span", {
|
|
333
335
|
className: "text-muted-foreground",
|
|
334
336
|
children: "Rating"
|
|
335
|
-
}), /* @__PURE__ */
|
|
337
|
+
}), /* @__PURE__ */ T(l, { rating: B.rating ?? null })]
|
|
336
338
|
}),
|
|
337
|
-
/* @__PURE__ */
|
|
339
|
+
/* @__PURE__ */ E("div", {
|
|
338
340
|
className: "flex justify-between items-center",
|
|
339
|
-
children: [/* @__PURE__ */
|
|
341
|
+
children: [/* @__PURE__ */ T("span", {
|
|
340
342
|
className: "text-muted-foreground",
|
|
341
343
|
children: "Category"
|
|
342
|
-
}),
|
|
344
|
+
}), B.category ? /* @__PURE__ */ T(c, { category: B.category }) : /* @__PURE__ */ T("span", {
|
|
343
345
|
className: "text-sm text-muted-foreground",
|
|
344
346
|
children: "Not set"
|
|
345
347
|
})]
|
|
346
348
|
}),
|
|
347
|
-
/* @__PURE__ */
|
|
349
|
+
/* @__PURE__ */ E("div", {
|
|
348
350
|
className: "flex justify-between",
|
|
349
|
-
children: [/* @__PURE__ */
|
|
351
|
+
children: [/* @__PURE__ */ T("span", {
|
|
350
352
|
className: "text-muted-foreground",
|
|
351
353
|
children: "Submitted By"
|
|
352
|
-
}), /* @__PURE__ */
|
|
354
|
+
}), /* @__PURE__ */ T(n, { id: B.submittedBy })]
|
|
353
355
|
}),
|
|
354
|
-
|
|
356
|
+
B.triagedAt && /* @__PURE__ */ E("div", {
|
|
355
357
|
className: "flex justify-between",
|
|
356
|
-
children: [/* @__PURE__ */
|
|
358
|
+
children: [/* @__PURE__ */ T("span", {
|
|
357
359
|
className: "text-muted-foreground",
|
|
358
360
|
children: "Decided"
|
|
359
|
-
}), /* @__PURE__ */
|
|
361
|
+
}), /* @__PURE__ */ E("span", { children: [new Date(B.triagedAt).toLocaleDateString(), B.triagedBy && /* @__PURE__ */ E(w, { children: [" by ", /* @__PURE__ */ T(n, { id: B.triagedBy })] })] })]
|
|
360
362
|
}),
|
|
361
|
-
/* @__PURE__ */
|
|
363
|
+
/* @__PURE__ */ E("div", {
|
|
362
364
|
className: "flex justify-between",
|
|
363
|
-
children: [/* @__PURE__ */
|
|
365
|
+
children: [/* @__PURE__ */ T("span", {
|
|
364
366
|
className: "text-muted-foreground",
|
|
365
367
|
children: "Updated"
|
|
366
|
-
}), /* @__PURE__ */
|
|
368
|
+
}), /* @__PURE__ */ T("span", { children: new Date(B.updatedAt).toLocaleDateString() })]
|
|
367
369
|
})
|
|
368
370
|
]
|
|
369
371
|
})] }),
|
|
370
|
-
|
|
372
|
+
B.tags?.length > 0 && /* @__PURE__ */ E(O, { children: [/* @__PURE__ */ T(A, { children: /* @__PURE__ */ T(j, { children: "Tags" }) }), /* @__PURE__ */ T(k, {
|
|
371
373
|
className: "flex flex-wrap gap-1",
|
|
372
|
-
children:
|
|
374
|
+
children: B.tags.map((e) => /* @__PURE__ */ T(D, {
|
|
373
375
|
variant: "outline",
|
|
374
376
|
className: "text-xs",
|
|
375
377
|
children: e
|
|
@@ -382,6 +384,6 @@ function M() {
|
|
|
382
384
|
});
|
|
383
385
|
}
|
|
384
386
|
//#endregion
|
|
385
|
-
export {
|
|
387
|
+
export { N as ProductsFeatureDetailPagePage };
|
|
386
388
|
|
|
387
389
|
//# sourceMappingURL=ProductsFeatureDetailPagePage.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ProductsFeatureDetailPagePage.js","names":[],"sources":["../../../src/planmagnet/pages/ProductsFeatureDetailPagePage.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 } from '@burdenoff/fe-libs/ui';\nimport { Star, ThumbsUp, MessageSquare, Target, Loader2 } from 'lucide-react';\nimport { usePlanMagnet, usePlanMagnetNavigate } from '../providers/PlanMagnetProvider';\nimport { detailPath } from '../utils/rowNavigation';\nimport { FeatureTriageActions, isOpenRequest, isSnoozed } from '../controls/FeatureTriage';\nimport { useParams } from 'react-router';\nimport { PersonName } from '../people/People';\nimport {\n FeatureHeaderActions,\n FeaturePrioritizationCard,\n FeatureVoteButton,\n} from '../controls/FeatureControls';\nimport { CompetitorLinkCard } from '../controls/CompetitorControls';\nimport { FeatureInitiativeCard } from '../roadmaps/FeatureInitiativeCard';\nimport { CategoryBadge, RatingDisplay } from '../controls/FeedbackControls';\n\nconst GET_FEATURE_REQUEST = gql`\n query GetFeatureRequest($id: ID!) {\n planmagnetFeatureRequest(id: $id) {\n id\n workspaceId\n projectId\n title\n description\n status\n businessValue\n effortEstimate\n priorityScore\n voteCount\n submittedBy\n workItemId\n tags\n snoozedUntil\n rating\n category\n isAnonymous\n moscow\n kano\n valueScore\n effortScore\n valueEffortQuadrant\n reach\n impact\n confidence\n riceScore\n declineReason\n duplicateOfId\n duplicateOf {\n id\n title\n }\n triagedAt\n triagedBy\n createdAt\n updatedAt\n productId\n roadmapItem {\n id\n title\n roadmap {\n id\n name\n }\n }\n votes {\n id\n voterId\n weight\n comment\n createdAt\n }\n competitors {\n id\n name\n description\n website\n }\n }\n }\n`;\n\ninterface FeatureVoteNode {\n id: string;\n voterId: string;\n weight: number;\n comment: string | null;\n createdAt: string;\n}\n\ninterface CompetitorNode {\n id: string;\n name: string;\n description: string | null;\n website: string | null;\n}\n\nexport function ProductsFeatureDetailPagePage() {\n const { workspaceId, currentUser } = usePlanMagnet();\n const navigate = usePlanMagnetNavigate();\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 const params = useParams<{ id: string }>();\n const featureId = params.id ?? '';\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>>(GET_FEATURE_REQUEST, {\n variables: { id: featureId },\n skip: !featureId,\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 feature: {error.message}</div>;\n }\n\n const feature = data?.planmagnetFeatureRequest;\n if (!feature) return <div className=\"p-6 text-muted-foreground\">Feature not found.</div>;\n\n const votes: FeatureVoteNode[] = feature.votes ?? [];\n const competitors: CompetitorNode[] = feature.competitors ?? [];\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\">{feature.title}</h1>\n <p className=\"text-sm text-muted-foreground\">\n Submitted by: <PersonName id={feature.submittedBy} /> · Effort:{' '}\n {feature.effortEstimate ?? 'N/A'}\n </p>\n </div>\n {/* Vote, status, Edit and Delete (BOFF-7951): the request was read-only. */}\n <div className=\"flex flex-col items-end gap-2\">\n <FeatureVoteButton\n key={feature.id}\n featureId={feature.id}\n voted={votes.some((v) => v.voterId === currentUser?.id)}\n />\n <FeatureHeaderActions feature={feature} />\n </div>\n </div>\n\n {/* Triage (P1.3): an undecided request is accepted, declined, snoozed or merged from here. */}\n {isOpenRequest(feature.status) && (\n <Card data-testid=\"triage-card\">\n <CardHeader>\n <CardTitle>Triage</CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-2\">\n <p className=\"text-sm text-muted-foreground\">\n {isSnoozed(feature.snoozedUntil, now)\n ? `Snoozed until ${new Date(feature.snoozedUntil).toLocaleString()} — it returns to the triage queue then.`\n : feature.status === 'SUBMITTED'\n ? 'Waiting for a decision.'\n : 'Under review: accept it as planned, decline it, or merge it into its original.'}\n </p>\n <FeatureTriageActions feature={feature} now={now} />\n </CardContent>\n </Card>\n )}\n {feature.status === 'DECLINED' && feature.declineReason && (\n <Card data-testid=\"decline-reason\">\n <CardContent className=\"pt-4 text-sm\">\n <span className=\"font-medium\">Declined: </span>\n {feature.declineReason}\n </CardContent>\n </Card>\n )}\n {feature.status === 'DUPLICATE' && feature.duplicateOfId && (\n <Card data-testid=\"duplicate-of\">\n <CardContent className=\"pt-4 text-sm\">\n <span className=\"font-medium\">Duplicate of </span>\n {feature.duplicateOf ? (\n <button\n type=\"button\"\n className=\"text-primary underline-offset-2 hover:underline\"\n onClick={() =>\n navigate(detailPath('/products/feature-detail-page', feature.duplicateOf.id))\n }\n >\n {feature.duplicateOf.title}\n </button>\n ) : (\n <span className=\"text-muted-foreground\">a request that has since been deleted</span>\n )}{' '}\n — its votes were moved there.\n </CardContent>\n </Card>\n )}\n\n <div className=\"grid grid-cols-2 md:grid-cols-4 gap-4\">\n <Card>\n <CardContent className=\"pt-4 text-center\">\n <Target className=\"h-5 w-5 mx-auto text-primary\" />\n <p className=\"text-2xl font-bold mt-1\">{feature.priorityScore ?? 0}</p>\n <p className=\"text-xs text-muted-foreground\">Priority Score</p>\n </CardContent>\n </Card>\n <Card>\n <CardContent className=\"pt-4 text-center\">\n <ThumbsUp className=\"h-5 w-5 mx-auto text-green-500\" />\n <p className=\"text-2xl font-bold mt-1\">{feature.voteCount}</p>\n <p className=\"text-xs text-muted-foreground\">Votes</p>\n </CardContent>\n </Card>\n <Card>\n <CardContent className=\"pt-4 text-center\">\n <Star className=\"h-5 w-5 mx-auto text-yellow-500\" />\n <p className=\"text-2xl font-bold mt-1\">{feature.businessValue ?? 0}</p>\n <p className=\"text-xs text-muted-foreground\">Business Value</p>\n </CardContent>\n </Card>\n <Card>\n <CardContent className=\"pt-4 text-center\">\n <MessageSquare className=\"h-5 w-5 mx-auto text-blue-500\" />\n <p className=\"text-2xl font-bold mt-1\">{competitors.length}</p>\n <p className=\"text-xs text-muted-foreground\">Competitors</p>\n </CardContent>\n </Card>\n </div>\n\n <div className=\"grid grid-cols-1 lg:grid-cols-3 gap-6\">\n <div className=\"lg:col-span-2 space-y-6\">\n <Card>\n <CardHeader>\n <CardTitle>Description</CardTitle>\n </CardHeader>\n <CardContent>\n <p className=\"text-sm\">{feature.description ?? 'No description provided.'}</p>\n </CardContent>\n </Card>\n\n <Card>\n <CardHeader>\n <CardTitle>Votes ({votes.length})</CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n {votes.length === 0 && <p className=\"text-sm text-muted-foreground\">No votes yet.</p>}\n {votes.map((vote) => (\n <div\n key={vote.id}\n className=\"flex items-start justify-between border rounded-md p-3\"\n >\n <div>\n <p className=\"text-sm font-medium\">\n Voter: <PersonName id={vote.voterId} />\n </p>\n {vote.comment && (\n <p className=\"text-xs text-muted-foreground mt-1\">{vote.comment}</p>\n )}\n </div>\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\">{vote.weight}</span>\n </div>\n </div>\n ))}\n </CardContent>\n </Card>\n\n {/* Competitor tracking (BOFF-8047): add, remove and browse to the competitors linked here. */}\n <Card>\n <CardHeader>\n <CardTitle>Competitors ({competitors.length})</CardTitle>\n </CardHeader>\n <CardContent>\n <CompetitorLinkCard featureRequestId={feature.id} competitors={competitors} />\n </CardContent>\n </Card>\n </div>\n\n <div className=\"space-y-6\">\n {/* PRM-24: the roadmap initiative that addresses this request. */}\n <FeatureInitiativeCard\n featureId={feature.id}\n productId={feature.productId ?? null}\n initiative={feature.roadmapItem ?? null}\n />\n {/* PRM-27: MoSCoW/Kano/Value-Effort scoring, edited in place with the computed quadrant read back\n from the save's own response. */}\n <FeaturePrioritizationCard feature={feature} />\n <Card>\n <CardHeader>\n <CardTitle>Details</CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-3 text-sm\">\n <div className=\"flex justify-between\">\n <span className=\"text-muted-foreground\">Status</span>\n <Badge variant=\"secondary\" className=\"capitalize\">\n {feature.status.toLowerCase().replace('_', ' ')}\n </Badge>\n </div>\n <div className=\"flex justify-between\">\n <span className=\"text-muted-foreground\">Priority Score</span>\n <Badge variant=\"outline\">{feature.priorityScore ?? 'N/A'}</Badge>\n </div>\n <div className=\"flex justify-between\">\n <span className=\"text-muted-foreground\">Effort</span>\n <Badge variant=\"outline\" className=\"capitalize\">\n {feature.effortEstimate ?? 'N/A'}\n </Badge>\n </div>\n <div className=\"flex justify-between\">\n <span className=\"text-muted-foreground\">Business Value</span>\n <span className=\"font-medium\">{feature.businessValue ?? 'N/A'}</span>\n </div>\n {/* CWF-15 */}\n <div className=\"flex justify-between items-center\">\n <span className=\"text-muted-foreground\">Rating</span>\n <RatingDisplay rating={feature.rating ?? null} />\n </div>\n <div className=\"flex justify-between items-center\">\n <span className=\"text-muted-foreground\">Category</span>\n {feature.category ? (\n <CategoryBadge category={feature.category} />\n ) : (\n <span className=\"text-sm text-muted-foreground\">Not set</span>\n )}\n </div>\n <div className=\"flex justify-between\">\n <span className=\"text-muted-foreground\">Submitted By</span>\n <PersonName id={feature.submittedBy} />\n </div>\n {feature.triagedAt && (\n <div className=\"flex justify-between\">\n <span className=\"text-muted-foreground\">Decided</span>\n <span>\n {new Date(feature.triagedAt).toLocaleDateString()}\n {feature.triagedBy && (\n <>\n {' by '}\n <PersonName id={feature.triagedBy} />\n </>\n )}\n </span>\n </div>\n )}\n <div className=\"flex justify-between\">\n <span className=\"text-muted-foreground\">Updated</span>\n <span>{new Date(feature.updatedAt).toLocaleDateString()}</span>\n </div>\n </CardContent>\n </Card>\n\n {feature.tags?.length > 0 && (\n <Card>\n <CardHeader>\n <CardTitle>Tags</CardTitle>\n </CardHeader>\n <CardContent className=\"flex flex-wrap gap-1\">\n {feature.tags.map((tag: string) => (\n <Badge key={tag} variant=\"outline\" className=\"text-xs\">\n {tag}\n </Badge>\n ))}\n </CardContent>\n </Card>\n )}\n </div>\n </div>\n </div>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ProductsFeatureDetailPagePage.js","names":[],"sources":["../../../src/planmagnet/pages/ProductsFeatureDetailPagePage.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 } from '@burdenoff/fe-libs/ui';\nimport { Star, ThumbsUp, MessageSquare, Target, Loader2 } from 'lucide-react';\nimport { usePlanMagnet, usePlanMagnetNavigate } from '../providers/PlanMagnetProvider';\nimport { detailPath } from '../utils/rowNavigation';\nimport { FeatureTriageActions, isOpenRequest, isSnoozed } from '../controls/FeatureTriage';\nimport { useParams } from 'react-router';\nimport { PersonName } from '../people/People';\nimport {\n FeatureHeaderActions,\n FeaturePrioritizationCard,\n FeatureVoteButton,\n} from '../controls/FeatureControls';\nimport { CompetitorLinkCard } from '../controls/CompetitorControls';\nimport { FeatureInitiativeCard } from '../roadmaps/FeatureInitiativeCard';\nimport { CategoryBadge, RatingDisplay } from '../controls/FeedbackControls';\nimport { ProductFeatureLinkCard } from '../product/ProductFeatureLinkCard';\n\nconst GET_FEATURE_REQUEST = gql`\n query GetFeatureRequest($id: ID!) {\n planmagnetFeatureRequest(id: $id) {\n id\n workspaceId\n projectId\n title\n description\n status\n businessValue\n effortEstimate\n priorityScore\n voteCount\n submittedBy\n workItemId\n tags\n snoozedUntil\n rating\n category\n isAnonymous\n moscow\n kano\n valueScore\n effortScore\n valueEffortQuadrant\n reach\n impact\n confidence\n riceScore\n declineReason\n duplicateOfId\n duplicateOf {\n id\n title\n }\n triagedAt\n triagedBy\n createdAt\n updatedAt\n productId\n roadmapItem {\n id\n title\n roadmap {\n id\n name\n }\n }\n votes {\n id\n voterId\n weight\n comment\n createdAt\n }\n competitors {\n id\n name\n description\n website\n }\n }\n }\n`;\n\ninterface FeatureVoteNode {\n id: string;\n voterId: string;\n weight: number;\n comment: string | null;\n createdAt: string;\n}\n\ninterface CompetitorNode {\n id: string;\n name: string;\n description: string | null;\n website: string | null;\n}\n\nexport function ProductsFeatureDetailPagePage() {\n const { workspaceId, currentUser } = usePlanMagnet();\n const navigate = usePlanMagnetNavigate();\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 const params = useParams<{ id: string }>();\n const featureId = params.id ?? '';\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>>(GET_FEATURE_REQUEST, {\n variables: { id: featureId },\n skip: !featureId,\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 (\n <div className=\"p-6 text-destructive\">Failed to load feature request: {error.message}</div>\n );\n }\n\n const feature = data?.planmagnetFeatureRequest;\n if (!feature) return <div className=\"p-6 text-muted-foreground\">Feature request not found.</div>;\n\n const votes: FeatureVoteNode[] = feature.votes ?? [];\n const competitors: CompetitorNode[] = feature.competitors ?? [];\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\">{feature.title}</h1>\n <p className=\"text-sm text-muted-foreground\">\n Submitted by: <PersonName id={feature.submittedBy} /> · Effort:{' '}\n {feature.effortEstimate ?? 'N/A'}\n </p>\n </div>\n {/* Vote, status, Edit and Delete (BOFF-7951): the request was read-only. */}\n <div className=\"flex flex-col items-end gap-2\">\n <FeatureVoteButton\n key={feature.id}\n featureId={feature.id}\n voted={votes.some((v) => v.voterId === currentUser?.id)}\n />\n <FeatureHeaderActions feature={feature} />\n </div>\n </div>\n\n {/* Triage (P1.3): an undecided request is accepted, declined, snoozed or merged from here. */}\n {isOpenRequest(feature.status) && (\n <Card data-testid=\"triage-card\">\n <CardHeader>\n <CardTitle>Triage</CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-2\">\n <p className=\"text-sm text-muted-foreground\">\n {isSnoozed(feature.snoozedUntil, now)\n ? `Snoozed until ${new Date(feature.snoozedUntil).toLocaleString()} — it returns to the triage queue then.`\n : feature.status === 'SUBMITTED'\n ? 'Waiting for a decision.'\n : 'Under review: accept it as planned, decline it, or merge it into its original.'}\n </p>\n <FeatureTriageActions feature={feature} now={now} />\n </CardContent>\n </Card>\n )}\n {feature.status === 'DECLINED' && feature.declineReason && (\n <Card data-testid=\"decline-reason\">\n <CardContent className=\"pt-4 text-sm\">\n <span className=\"font-medium\">Declined: </span>\n {feature.declineReason}\n </CardContent>\n </Card>\n )}\n {feature.status === 'DUPLICATE' && feature.duplicateOfId && (\n <Card data-testid=\"duplicate-of\">\n <CardContent className=\"pt-4 text-sm\">\n <span className=\"font-medium\">Duplicate of </span>\n {feature.duplicateOf ? (\n <button\n type=\"button\"\n className=\"text-primary underline-offset-2 hover:underline\"\n onClick={() =>\n navigate(detailPath('/products/feature-detail-page', feature.duplicateOf.id))\n }\n >\n {feature.duplicateOf.title}\n </button>\n ) : (\n <span className=\"text-muted-foreground\">a request that has since been deleted</span>\n )}{' '}\n — its votes were moved there.\n </CardContent>\n </Card>\n )}\n\n <div className=\"grid grid-cols-2 md:grid-cols-4 gap-4\">\n <Card>\n <CardContent className=\"pt-4 text-center\">\n <Target className=\"h-5 w-5 mx-auto text-primary\" />\n <p className=\"text-2xl font-bold mt-1\">{feature.priorityScore ?? 0}</p>\n <p className=\"text-xs text-muted-foreground\">Priority Score</p>\n </CardContent>\n </Card>\n <Card>\n <CardContent className=\"pt-4 text-center\">\n <ThumbsUp className=\"h-5 w-5 mx-auto text-green-500\" />\n <p className=\"text-2xl font-bold mt-1\">{feature.voteCount}</p>\n <p className=\"text-xs text-muted-foreground\">Votes</p>\n </CardContent>\n </Card>\n <Card>\n <CardContent className=\"pt-4 text-center\">\n <Star className=\"h-5 w-5 mx-auto text-yellow-500\" />\n <p className=\"text-2xl font-bold mt-1\">{feature.businessValue ?? 0}</p>\n <p className=\"text-xs text-muted-foreground\">Business Value</p>\n </CardContent>\n </Card>\n <Card>\n <CardContent className=\"pt-4 text-center\">\n <MessageSquare className=\"h-5 w-5 mx-auto text-blue-500\" />\n <p className=\"text-2xl font-bold mt-1\">{competitors.length}</p>\n <p className=\"text-xs text-muted-foreground\">Competitors</p>\n </CardContent>\n </Card>\n </div>\n\n <div className=\"grid grid-cols-1 lg:grid-cols-3 gap-6\">\n <div className=\"lg:col-span-2 space-y-6\">\n <Card>\n <CardHeader>\n <CardTitle>Description</CardTitle>\n </CardHeader>\n <CardContent>\n <p className=\"text-sm\">{feature.description ?? 'No description provided.'}</p>\n </CardContent>\n </Card>\n\n <Card>\n <CardHeader>\n <CardTitle>Votes ({votes.length})</CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n {votes.length === 0 && <p className=\"text-sm text-muted-foreground\">No votes yet.</p>}\n {votes.map((vote) => (\n <div\n key={vote.id}\n className=\"flex items-start justify-between border rounded-md p-3\"\n >\n <div>\n <p className=\"text-sm font-medium\">\n Voter: <PersonName id={vote.voterId} />\n </p>\n {vote.comment && (\n <p className=\"text-xs text-muted-foreground mt-1\">{vote.comment}</p>\n )}\n </div>\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\">{vote.weight}</span>\n </div>\n </div>\n ))}\n </CardContent>\n </Card>\n\n {/* Competitor tracking (BOFF-8047): add, remove and browse to the competitors linked here. */}\n <Card>\n <CardHeader>\n <CardTitle>Competitors ({competitors.length})</CardTitle>\n </CardHeader>\n <CardContent>\n <CompetitorLinkCard featureRequestId={feature.id} competitors={competitors} />\n </CardContent>\n </Card>\n </div>\n\n <div className=\"space-y-6\">\n {/* PRM-01: the product feature (a capability the team builds) that answers this request. */}\n <ProductFeatureLinkCard featureRequestId={feature.id} />\n {/* PRM-24: the roadmap initiative that addresses this request. */}\n <FeatureInitiativeCard\n featureId={feature.id}\n productId={feature.productId ?? null}\n initiative={feature.roadmapItem ?? null}\n />\n {/* PRM-27: MoSCoW/Kano/Value-Effort scoring, edited in place with the computed quadrant read back\n from the save's own response. */}\n <FeaturePrioritizationCard feature={feature} />\n <Card>\n <CardHeader>\n <CardTitle>Details</CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-3 text-sm\">\n <div className=\"flex justify-between\">\n <span className=\"text-muted-foreground\">Status</span>\n <Badge variant=\"secondary\" className=\"capitalize\">\n {feature.status.toLowerCase().replace('_', ' ')}\n </Badge>\n </div>\n <div className=\"flex justify-between\">\n <span className=\"text-muted-foreground\">Priority Score</span>\n <Badge variant=\"outline\">{feature.priorityScore ?? 'N/A'}</Badge>\n </div>\n <div className=\"flex justify-between\">\n <span className=\"text-muted-foreground\">Effort</span>\n <Badge variant=\"outline\" className=\"capitalize\">\n {feature.effortEstimate ?? 'N/A'}\n </Badge>\n </div>\n <div className=\"flex justify-between\">\n <span className=\"text-muted-foreground\">Business Value</span>\n <span className=\"font-medium\">{feature.businessValue ?? 'N/A'}</span>\n </div>\n {/* CWF-15 */}\n <div className=\"flex justify-between items-center\">\n <span className=\"text-muted-foreground\">Rating</span>\n <RatingDisplay rating={feature.rating ?? null} />\n </div>\n <div className=\"flex justify-between items-center\">\n <span className=\"text-muted-foreground\">Category</span>\n {feature.category ? (\n <CategoryBadge category={feature.category} />\n ) : (\n <span className=\"text-sm text-muted-foreground\">Not set</span>\n )}\n </div>\n <div className=\"flex justify-between\">\n <span className=\"text-muted-foreground\">Submitted By</span>\n <PersonName id={feature.submittedBy} />\n </div>\n {feature.triagedAt && (\n <div className=\"flex justify-between\">\n <span className=\"text-muted-foreground\">Decided</span>\n <span>\n {new Date(feature.triagedAt).toLocaleDateString()}\n {feature.triagedBy && (\n <>\n {' by '}\n <PersonName id={feature.triagedBy} />\n </>\n )}\n </span>\n </div>\n )}\n <div className=\"flex justify-between\">\n <span className=\"text-muted-foreground\">Updated</span>\n <span>{new Date(feature.updatedAt).toLocaleDateString()}</span>\n </div>\n </CardContent>\n </Card>\n\n {feature.tags?.length > 0 && (\n <Card>\n <CardHeader>\n <CardTitle>Tags</CardTitle>\n </CardHeader>\n <CardContent className=\"flex flex-wrap gap-1\">\n {feature.tags.map((tag: string) => (\n <Badge key={tag} variant=\"outline\" className=\"text-xs\">\n {tag}\n </Badge>\n ))}\n </CardContent>\n </Card>\n )}\n </div>\n </div>\n </div>\n );\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ProductsFeaturesPagePage.d.ts","sourceRoot":"","sources":["../../../src/planmagnet/pages/ProductsFeaturesPagePage.tsx"],"names":[],"mappings":"AA8GA,wBAAgB,wBAAwB,
|
|
1
|
+
{"version":3,"file":"ProductsFeaturesPagePage.d.ts","sourceRoot":"","sources":["../../../src/planmagnet/pages/ProductsFeaturesPagePage.tsx"],"names":[],"mappings":"AA8GA,wBAAgB,wBAAwB,4CAsXvC"}
|
|
@@ -84,7 +84,7 @@ function M() {
|
|
|
84
84
|
});
|
|
85
85
|
if (Y) return /* @__PURE__ */ T("div", {
|
|
86
86
|
className: "p-6 text-destructive",
|
|
87
|
-
children: ["Failed to load
|
|
87
|
+
children: ["Failed to load feature requests: ", Y.message]
|
|
88
88
|
});
|
|
89
89
|
let X = J?.planmagnetFeatureRequests?.items ?? [], Z = J?.planmagnetFeatureRequests?.totalCount ?? 0, Q = R ? [...X].sort((e, t) => e.riceScore == null && t.riceScore == null ? 0 : e.riceScore == null ? 1 : t.riceScore == null ? -1 : t.riceScore - e.riceScore) : X, se = [
|
|
90
90
|
"all",
|
|
@@ -110,14 +110,14 @@ function M() {
|
|
|
110
110
|
className: "flex items-center justify-between",
|
|
111
111
|
children: [/* @__PURE__ */ T("div", { children: [/* @__PURE__ */ w("h1", {
|
|
112
112
|
className: "text-2xl font-semibold",
|
|
113
|
-
children: "
|
|
113
|
+
children: "Feature requests"
|
|
114
114
|
}), /* @__PURE__ */ w("p", {
|
|
115
115
|
className: "text-sm text-muted-foreground",
|
|
116
116
|
children: N === "all" ? `${$.total} feature requests` : N === "TRIAGE" ? `${Z} waiting for triage` : `${Z} ${N.toLowerCase().replace("_", " ")} match`
|
|
117
117
|
})] }), /* @__PURE__ */ T(D, {
|
|
118
118
|
size: "sm",
|
|
119
119
|
onClick: () => S("/products/new-feature-page"),
|
|
120
|
-
children: [/* @__PURE__ */ w(re, { className: "mr-1 h-4 w-4" }), "New
|
|
120
|
+
children: [/* @__PURE__ */ w(re, { className: "mr-1 h-4 w-4" }), "New feature request"]
|
|
121
121
|
})]
|
|
122
122
|
}),
|
|
123
123
|
/* @__PURE__ */ T("div", {
|
|
@@ -127,7 +127,7 @@ function M() {
|
|
|
127
127
|
className: "pt-4",
|
|
128
128
|
children: [/* @__PURE__ */ w("p", {
|
|
129
129
|
className: "text-xs text-muted-foreground",
|
|
130
|
-
children: "Total
|
|
130
|
+
children: "Total feature requests"
|
|
131
131
|
}), /* @__PURE__ */ w("p", {
|
|
132
132
|
className: "text-xl font-bold",
|
|
133
133
|
children: $.total
|
|
@@ -397,7 +397,7 @@ function M() {
|
|
|
397
397
|
}),
|
|
398
398
|
Q.length === 0 && /* @__PURE__ */ w("p", {
|
|
399
399
|
className: "text-center text-muted-foreground py-8",
|
|
400
|
-
children: N === "TRIAGE" ? "Nothing waits for triage." : "No
|
|
400
|
+
children: N === "TRIAGE" ? "Nothing waits for triage." : "No feature requests match the selected filters."
|
|
401
401
|
})
|
|
402
402
|
]
|
|
403
403
|
});
|