@burdenoff/microfe-planmagnet 2026.509.103
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/README.md +12 -0
- package/dist/dev/main.d.ts +2 -0
- package/dist/dev/main.d.ts.map +1 -0
- package/dist/generated/global-operations.d.ts +2 -0
- package/dist/generated/global-operations.d.ts.map +1 -0
- package/dist/generated/global-types.d.ts +21253 -0
- package/dist/generated/global-types.d.ts.map +1 -0
- package/dist/generated/wspace-operations.d.ts +8370 -0
- package/dist/generated/wspace-operations.d.ts.map +1 -0
- package/dist/generated/wspace-types.d.ts +4182 -0
- package/dist/generated/wspace-types.d.ts.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +5 -0
- package/dist/node_modules/@apollo/client/errors/CombinedGraphQLErrors.js +24 -0
- package/dist/node_modules/@apollo/client/errors/CombinedGraphQLErrors.js.map +1 -0
- package/dist/node_modules/@apollo/client/errors/utils.js +16 -0
- package/dist/node_modules/@apollo/client/errors/utils.js.map +1 -0
- package/dist/planmagnet/PlanMagnetRoot.d.ts +5 -0
- package/dist/planmagnet/PlanMagnetRoot.d.ts.map +1 -0
- package/dist/planmagnet/PlanMagnetRoot.js +292 -0
- package/dist/planmagnet/PlanMagnetRoot.js.map +1 -0
- package/dist/planmagnet/PlanMagnetRoutes.d.ts +2 -0
- package/dist/planmagnet/PlanMagnetRoutes.d.ts.map +1 -0
- package/dist/planmagnet/PlanMagnetRoutes.js +211 -0
- package/dist/planmagnet/PlanMagnetRoutes.js.map +1 -0
- package/dist/planmagnet/index.d.ts +5 -0
- package/dist/planmagnet/index.d.ts.map +1 -0
- package/dist/planmagnet/index.js +3 -0
- package/dist/planmagnet/pages/AnalyticsAnalyticsPagePage.d.ts +2 -0
- package/dist/planmagnet/pages/AnalyticsAnalyticsPagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/AnalyticsAnalyticsPagePage.js +312 -0
- package/dist/planmagnet/pages/AnalyticsAnalyticsPagePage.js.map +1 -0
- package/dist/planmagnet/pages/CollaborationCollaborationPagePage.d.ts +2 -0
- package/dist/planmagnet/pages/CollaborationCollaborationPagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/CollaborationCollaborationPagePage.js +110 -0
- package/dist/planmagnet/pages/CollaborationCollaborationPagePage.js.map +1 -0
- package/dist/planmagnet/pages/CollaborationCreateChannelPagePage.d.ts +2 -0
- package/dist/planmagnet/pages/CollaborationCreateChannelPagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/CollaborationCreateChannelPagePage.js +96 -0
- package/dist/planmagnet/pages/CollaborationCreateChannelPagePage.js.map +1 -0
- package/dist/planmagnet/pages/CollaborationFilesPagePage.d.ts +2 -0
- package/dist/planmagnet/pages/CollaborationFilesPagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/CollaborationFilesPagePage.js +112 -0
- package/dist/planmagnet/pages/CollaborationFilesPagePage.js.map +1 -0
- package/dist/planmagnet/pages/CollaborationMessagesPagePage.d.ts +2 -0
- package/dist/planmagnet/pages/CollaborationMessagesPagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/CollaborationMessagesPagePage.js +141 -0
- package/dist/planmagnet/pages/CollaborationMessagesPagePage.js.map +1 -0
- package/dist/planmagnet/pages/CollaborationNewDiscussionPagePage.d.ts +2 -0
- package/dist/planmagnet/pages/CollaborationNewDiscussionPagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/CollaborationNewDiscussionPagePage.js +124 -0
- package/dist/planmagnet/pages/CollaborationNewDiscussionPagePage.js.map +1 -0
- package/dist/planmagnet/pages/DashboardDashboardPagePage.d.ts +2 -0
- package/dist/planmagnet/pages/DashboardDashboardPagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/DashboardDashboardPagePage.js +350 -0
- package/dist/planmagnet/pages/DashboardDashboardPagePage.js.map +1 -0
- package/dist/planmagnet/pages/MeetingsScheduleMeetingPagePage.d.ts +2 -0
- package/dist/planmagnet/pages/MeetingsScheduleMeetingPagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/MeetingsScheduleMeetingPagePage.js +290 -0
- package/dist/planmagnet/pages/MeetingsScheduleMeetingPagePage.js.map +1 -0
- package/dist/planmagnet/pages/ProductsCreateProductPagePage.d.ts +2 -0
- package/dist/planmagnet/pages/ProductsCreateProductPagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/ProductsCreateProductPagePage.js +189 -0
- package/dist/planmagnet/pages/ProductsCreateProductPagePage.js.map +1 -0
- package/dist/planmagnet/pages/ProductsCreateRoadmapPagePage.d.ts +2 -0
- package/dist/planmagnet/pages/ProductsCreateRoadmapPagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/ProductsCreateRoadmapPagePage.js +151 -0
- package/dist/planmagnet/pages/ProductsCreateRoadmapPagePage.js.map +1 -0
- package/dist/planmagnet/pages/ProductsEditProductPagePage.d.ts +2 -0
- package/dist/planmagnet/pages/ProductsEditProductPagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/ProductsEditProductPagePage.js +257 -0
- package/dist/planmagnet/pages/ProductsEditProductPagePage.js.map +1 -0
- package/dist/planmagnet/pages/ProductsEditReleasePagePage.d.ts +2 -0
- package/dist/planmagnet/pages/ProductsEditReleasePagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/ProductsEditReleasePagePage.js +221 -0
- package/dist/planmagnet/pages/ProductsEditReleasePagePage.js.map +1 -0
- package/dist/planmagnet/pages/ProductsFeatureAnalyticsPagePage.d.ts +2 -0
- package/dist/planmagnet/pages/ProductsFeatureAnalyticsPagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/ProductsFeatureAnalyticsPagePage.js +284 -0
- package/dist/planmagnet/pages/ProductsFeatureAnalyticsPagePage.js.map +1 -0
- package/dist/planmagnet/pages/ProductsFeatureDetailPagePage.d.ts +2 -0
- package/dist/planmagnet/pages/ProductsFeatureDetailPagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/ProductsFeatureDetailPagePage.js +291 -0
- package/dist/planmagnet/pages/ProductsFeatureDetailPagePage.js.map +1 -0
- package/dist/planmagnet/pages/ProductsFeaturesPagePage.d.ts +2 -0
- package/dist/planmagnet/pages/ProductsFeaturesPagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/ProductsFeaturesPagePage.js +257 -0
- package/dist/planmagnet/pages/ProductsFeaturesPagePage.js.map +1 -0
- package/dist/planmagnet/pages/ProductsNewFeaturePagePage.d.ts +2 -0
- package/dist/planmagnet/pages/ProductsNewFeaturePagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/ProductsNewFeaturePagePage.js +222 -0
- package/dist/planmagnet/pages/ProductsNewFeaturePagePage.js.map +1 -0
- package/dist/planmagnet/pages/ProductsProductDetailPagePage.d.ts +2 -0
- package/dist/planmagnet/pages/ProductsProductDetailPagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/ProductsProductDetailPagePage.js +288 -0
- package/dist/planmagnet/pages/ProductsProductDetailPagePage.js.map +1 -0
- package/dist/planmagnet/pages/ProductsProductsPagePage.d.ts +2 -0
- package/dist/planmagnet/pages/ProductsProductsPagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/ProductsProductsPagePage.js +225 -0
- package/dist/planmagnet/pages/ProductsProductsPagePage.js.map +1 -0
- package/dist/planmagnet/pages/ProductsReleaseDetailPagePage.d.ts +2 -0
- package/dist/planmagnet/pages/ProductsReleaseDetailPagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/ProductsReleaseDetailPagePage.js +262 -0
- package/dist/planmagnet/pages/ProductsReleaseDetailPagePage.js.map +1 -0
- package/dist/planmagnet/pages/ProductsReleasesPagePage.d.ts +2 -0
- package/dist/planmagnet/pages/ProductsReleasesPagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/ProductsReleasesPagePage.js +162 -0
- package/dist/planmagnet/pages/ProductsReleasesPagePage.js.map +1 -0
- package/dist/planmagnet/pages/ProductsRoadmapAnalyticsPagePage.d.ts +2 -0
- package/dist/planmagnet/pages/ProductsRoadmapAnalyticsPagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/ProductsRoadmapAnalyticsPagePage.js +342 -0
- package/dist/planmagnet/pages/ProductsRoadmapAnalyticsPagePage.js.map +1 -0
- package/dist/planmagnet/pages/ProductsRoadmapDetailPagePage.d.ts +2 -0
- package/dist/planmagnet/pages/ProductsRoadmapDetailPagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/ProductsRoadmapDetailPagePage.js +233 -0
- package/dist/planmagnet/pages/ProductsRoadmapDetailPagePage.js.map +1 -0
- package/dist/planmagnet/pages/ProductsRoadmapsPagePage.d.ts +2 -0
- package/dist/planmagnet/pages/ProductsRoadmapsPagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/ProductsRoadmapsPagePage.js +193 -0
- package/dist/planmagnet/pages/ProductsRoadmapsPagePage.js.map +1 -0
- package/dist/planmagnet/pages/ProjectsActiveProjectsPagePage.d.ts +2 -0
- package/dist/planmagnet/pages/ProjectsActiveProjectsPagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/ProjectsActiveProjectsPagePage.js +116 -0
- package/dist/planmagnet/pages/ProjectsActiveProjectsPagePage.js.map +1 -0
- package/dist/planmagnet/pages/ProjectsCreateProjectPagePage.d.ts +2 -0
- package/dist/planmagnet/pages/ProjectsCreateProjectPagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/ProjectsCreateProjectPagePage.js +199 -0
- package/dist/planmagnet/pages/ProjectsCreateProjectPagePage.js.map +1 -0
- package/dist/planmagnet/pages/ProjectsEditProjectPagePage.d.ts +2 -0
- package/dist/planmagnet/pages/ProjectsEditProjectPagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/ProjectsEditProjectPagePage.js +197 -0
- package/dist/planmagnet/pages/ProjectsEditProjectPagePage.js.map +1 -0
- package/dist/planmagnet/pages/ProjectsMilestoneDetailPagePage.d.ts +2 -0
- package/dist/planmagnet/pages/ProjectsMilestoneDetailPagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/ProjectsMilestoneDetailPagePage.js +173 -0
- package/dist/planmagnet/pages/ProjectsMilestoneDetailPagePage.js.map +1 -0
- package/dist/planmagnet/pages/ProjectsMilestonesPagePage.d.ts +2 -0
- package/dist/planmagnet/pages/ProjectsMilestonesPagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/ProjectsMilestonesPagePage.js +119 -0
- package/dist/planmagnet/pages/ProjectsMilestonesPagePage.js.map +1 -0
- package/dist/planmagnet/pages/ProjectsPlanningDetailPagePage.d.ts +2 -0
- package/dist/planmagnet/pages/ProjectsPlanningDetailPagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/ProjectsPlanningDetailPagePage.js +257 -0
- package/dist/planmagnet/pages/ProjectsPlanningDetailPagePage.js.map +1 -0
- package/dist/planmagnet/pages/ProjectsPlanningEditPagePage.d.ts +2 -0
- package/dist/planmagnet/pages/ProjectsPlanningEditPagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/ProjectsPlanningEditPagePage.js +222 -0
- package/dist/planmagnet/pages/ProjectsPlanningEditPagePage.js.map +1 -0
- package/dist/planmagnet/pages/ProjectsPlanningPagePage.d.ts +2 -0
- package/dist/planmagnet/pages/ProjectsPlanningPagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/ProjectsPlanningPagePage.js +142 -0
- package/dist/planmagnet/pages/ProjectsPlanningPagePage.js.map +1 -0
- package/dist/planmagnet/pages/ProjectsProjectDetailPagePage.d.ts +2 -0
- package/dist/planmagnet/pages/ProjectsProjectDetailPagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/ProjectsProjectDetailPagePage.js +363 -0
- package/dist/planmagnet/pages/ProjectsProjectDetailPagePage.js.map +1 -0
- package/dist/planmagnet/pages/ProjectsProjectsPagePage.d.ts +2 -0
- package/dist/planmagnet/pages/ProjectsProjectsPagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/ProjectsProjectsPagePage.js +176 -0
- package/dist/planmagnet/pages/ProjectsProjectsPagePage.js.map +1 -0
- package/dist/planmagnet/pages/ReportsCreateReportPagePage.d.ts +2 -0
- package/dist/planmagnet/pages/ReportsCreateReportPagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/ReportsCreateReportPagePage.js +173 -0
- package/dist/planmagnet/pages/ReportsCreateReportPagePage.js.map +1 -0
- package/dist/planmagnet/pages/ReportsReportsPagePage.d.ts +2 -0
- package/dist/planmagnet/pages/ReportsReportsPagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/ReportsReportsPagePage.js +221 -0
- package/dist/planmagnet/pages/ReportsReportsPagePage.js.map +1 -0
- package/dist/planmagnet/pages/SprintsStartSprintPagePage.d.ts +2 -0
- package/dist/planmagnet/pages/SprintsStartSprintPagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/SprintsStartSprintPagePage.js +282 -0
- package/dist/planmagnet/pages/SprintsStartSprintPagePage.js.map +1 -0
- package/dist/planmagnet/pages/TasksCreateTaskPagePage.d.ts +2 -0
- package/dist/planmagnet/pages/TasksCreateTaskPagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/TasksCreateTaskPagePage.js +227 -0
- package/dist/planmagnet/pages/TasksCreateTaskPagePage.js.map +1 -0
- package/dist/planmagnet/pages/TasksEditTaskPagePage.d.ts +2 -0
- package/dist/planmagnet/pages/TasksEditTaskPagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/TasksEditTaskPagePage.js +234 -0
- package/dist/planmagnet/pages/TasksEditTaskPagePage.js.map +1 -0
- package/dist/planmagnet/pages/TasksTaskDetailPagePage.d.ts +2 -0
- package/dist/planmagnet/pages/TasksTaskDetailPagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/TasksTaskDetailPagePage.js +232 -0
- package/dist/planmagnet/pages/TasksTaskDetailPagePage.js.map +1 -0
- package/dist/planmagnet/pages/TasksTasksPagePage.d.ts +2 -0
- package/dist/planmagnet/pages/TasksTasksPagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/TasksTasksPagePage.js +206 -0
- package/dist/planmagnet/pages/TasksTasksPagePage.js.map +1 -0
- package/dist/planmagnet/pages/TeamCreateTeamPagePage.d.ts +2 -0
- package/dist/planmagnet/pages/TeamCreateTeamPagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/TeamCreateTeamPagePage.js +138 -0
- package/dist/planmagnet/pages/TeamCreateTeamPagePage.js.map +1 -0
- package/dist/planmagnet/pages/TeamInviteMemberPagePage.d.ts +2 -0
- package/dist/planmagnet/pages/TeamInviteMemberPagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/TeamInviteMemberPagePage.js +161 -0
- package/dist/planmagnet/pages/TeamInviteMemberPagePage.js.map +1 -0
- package/dist/planmagnet/pages/TeamTeamPagePage.d.ts +2 -0
- package/dist/planmagnet/pages/TeamTeamPagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/TeamTeamPagePage.js +203 -0
- package/dist/planmagnet/pages/TeamTeamPagePage.js.map +1 -0
- package/dist/planmagnet/pages/WorkspaceCreateWorkspacePagePage.d.ts +2 -0
- package/dist/planmagnet/pages/WorkspaceCreateWorkspacePagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/WorkspaceCreateWorkspacePagePage.js +97 -0
- package/dist/planmagnet/pages/WorkspaceCreateWorkspacePagePage.js.map +1 -0
- package/dist/planmagnet/providers/PlanMagnetProvider.d.ts +31 -0
- package/dist/planmagnet/providers/PlanMagnetProvider.d.ts.map +1 -0
- package/dist/planmagnet/providers/PlanMagnetProvider.js +119 -0
- package/dist/planmagnet/providers/PlanMagnetProvider.js.map +1 -0
- package/dist/planmagnet/store/planmagnetStore.d.ts +30 -0
- package/dist/planmagnet/store/planmagnetStore.d.ts.map +1 -0
- package/dist/planmagnet/store/planmagnetStore.js +42 -0
- package/dist/planmagnet/store/planmagnetStore.js.map +1 -0
- package/dist/planmagnet/types/index.d.ts +317 -0
- package/dist/planmagnet/types/index.d.ts.map +1 -0
- package/dist/planmagnet/utils/cn.d.ts +4 -0
- package/dist/planmagnet/utils/cn.d.ts.map +1 -0
- package/dist/planmagnet/utils/navigation.d.ts +2 -0
- package/dist/planmagnet/utils/navigation.d.ts.map +1 -0
- package/dist/planmagnet/utils/navigation.js +8 -0
- package/dist/planmagnet/utils/navigation.js.map +1 -0
- package/package.json +107 -0
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
import { usePlanMagnet as e, usePlanMagnetNavigate as t } from "../providers/PlanMagnetProvider.js";
|
|
2
|
+
import { useMemo as n, useState as r } from "react";
|
|
3
|
+
import { ArrowLeft as i, Loader2 as a, Save as o } from "lucide-react";
|
|
4
|
+
import { useParams as s } from "react-router-dom";
|
|
5
|
+
import { gql as c } from "@apollo/client";
|
|
6
|
+
import { useMutation as l, useQuery as u } from "@apollo/client/react";
|
|
7
|
+
import { jsx as d, jsxs as f } from "react/jsx-runtime";
|
|
8
|
+
import { Button as p, Card as m, CardContent as h, CardHeader as g, CardTitle as _, Input as v } from "@burdenoff/fe-libs/ui";
|
|
9
|
+
//#region src/planmagnet/pages/ProductsEditReleasePagePage.tsx
|
|
10
|
+
var y = c`
|
|
11
|
+
query GetReleaseForEdit($id: ID!) {
|
|
12
|
+
planmagnetRelease(id: $id) {
|
|
13
|
+
id
|
|
14
|
+
name
|
|
15
|
+
description
|
|
16
|
+
version
|
|
17
|
+
status
|
|
18
|
+
plannedDate
|
|
19
|
+
releasedAt
|
|
20
|
+
releaseNotes
|
|
21
|
+
ownerId
|
|
22
|
+
tags
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
`, b = c`
|
|
26
|
+
mutation UpdateRelease($id: ID!, $input: UpdateReleaseInput!) {
|
|
27
|
+
planmagnetUpdateRelease(id: $id, input: $input) {
|
|
28
|
+
id
|
|
29
|
+
name
|
|
30
|
+
description
|
|
31
|
+
version
|
|
32
|
+
status
|
|
33
|
+
plannedDate
|
|
34
|
+
releaseNotes
|
|
35
|
+
tags
|
|
36
|
+
updatedAt
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
`;
|
|
40
|
+
function x() {
|
|
41
|
+
let { workspaceId: c } = e(), x = t(), S = s().id ?? "", { data: C, loading: w, error: T } = u(y, {
|
|
42
|
+
variables: { id: S },
|
|
43
|
+
skip: !S
|
|
44
|
+
}), [E, { loading: D, error: O }] = l(b, { refetchQueries: ["ListReleases", "GetReleaseForEdit"] }), k = C?.planmagnetRelease, A = n(() => ({
|
|
45
|
+
version: k?.version ?? "",
|
|
46
|
+
name: k?.name ?? "",
|
|
47
|
+
description: k?.description ?? "",
|
|
48
|
+
status: k?.status ?? "DRAFT",
|
|
49
|
+
plannedDate: k?.plannedDate ? new Date(k.plannedDate).toISOString().split("T")[0] : "",
|
|
50
|
+
releaseNotes: k?.releaseNotes ?? "",
|
|
51
|
+
tags: k?.tags?.join(", ") ?? ""
|
|
52
|
+
}), [k]), [j, M] = r({}), N = {
|
|
53
|
+
...A,
|
|
54
|
+
...j
|
|
55
|
+
}, P = (e) => M(e);
|
|
56
|
+
return w ? /* @__PURE__ */ d("div", {
|
|
57
|
+
className: "flex items-center justify-center p-12",
|
|
58
|
+
children: /* @__PURE__ */ d(a, { className: "h-8 w-8 animate-spin text-muted-foreground" })
|
|
59
|
+
}) : T ? /* @__PURE__ */ f("div", {
|
|
60
|
+
className: "p-6 text-destructive",
|
|
61
|
+
children: ["Failed to load release: ", T.message]
|
|
62
|
+
}) : k ? /* @__PURE__ */ f("div", {
|
|
63
|
+
className: "space-y-6 p-6 max-w-4xl",
|
|
64
|
+
children: [
|
|
65
|
+
/* @__PURE__ */ f("div", {
|
|
66
|
+
className: "flex items-center justify-between",
|
|
67
|
+
children: [/* @__PURE__ */ f("div", {
|
|
68
|
+
className: "flex items-center gap-3",
|
|
69
|
+
children: [/* @__PURE__ */ d(p, {
|
|
70
|
+
variant: "ghost",
|
|
71
|
+
size: "sm",
|
|
72
|
+
onClick: () => x("/products/releases"),
|
|
73
|
+
children: /* @__PURE__ */ d(i, { className: "h-4 w-4" })
|
|
74
|
+
}), /* @__PURE__ */ f("div", { children: [/* @__PURE__ */ d("h1", {
|
|
75
|
+
className: "text-2xl font-semibold",
|
|
76
|
+
children: "Edit Release"
|
|
77
|
+
}), /* @__PURE__ */ f("p", {
|
|
78
|
+
className: "text-sm text-muted-foreground",
|
|
79
|
+
children: [
|
|
80
|
+
k.version,
|
|
81
|
+
" - ",
|
|
82
|
+
k.name
|
|
83
|
+
]
|
|
84
|
+
})] })]
|
|
85
|
+
}), /* @__PURE__ */ f(p, {
|
|
86
|
+
size: "sm",
|
|
87
|
+
onClick: () => {
|
|
88
|
+
planmagnetUpdateRelease({ variables: {
|
|
89
|
+
id: S,
|
|
90
|
+
input: {
|
|
91
|
+
version: N.version || void 0,
|
|
92
|
+
name: N.name || void 0,
|
|
93
|
+
description: N.description || void 0,
|
|
94
|
+
status: N.status || void 0,
|
|
95
|
+
plannedDate: N.plannedDate || void 0,
|
|
96
|
+
releaseNotes: N.releaseNotes || void 0,
|
|
97
|
+
tags: N.tags ? N.tags.split(",").map((e) => e.trim()).filter(Boolean) : void 0
|
|
98
|
+
}
|
|
99
|
+
} });
|
|
100
|
+
},
|
|
101
|
+
disabled: D,
|
|
102
|
+
children: [D ? /* @__PURE__ */ d(a, { className: "mr-1 h-4 w-4 animate-spin" }) : /* @__PURE__ */ d(o, { className: "mr-1 h-4 w-4" }), "Save Changes"]
|
|
103
|
+
})]
|
|
104
|
+
}),
|
|
105
|
+
O && /* @__PURE__ */ f("div", {
|
|
106
|
+
className: "p-3 rounded-md bg-destructive/10 text-destructive text-sm",
|
|
107
|
+
children: ["Failed to save: ", O.message]
|
|
108
|
+
}),
|
|
109
|
+
/* @__PURE__ */ f(m, { children: [/* @__PURE__ */ d(g, { children: /* @__PURE__ */ d(_, { children: "Release Details" }) }), /* @__PURE__ */ f(h, {
|
|
110
|
+
className: "space-y-4",
|
|
111
|
+
children: [
|
|
112
|
+
/* @__PURE__ */ f("div", {
|
|
113
|
+
className: "grid grid-cols-2 gap-4",
|
|
114
|
+
children: [/* @__PURE__ */ f("div", { children: [/* @__PURE__ */ d("label", {
|
|
115
|
+
className: "text-sm font-medium",
|
|
116
|
+
children: "Version"
|
|
117
|
+
}), /* @__PURE__ */ d(v, {
|
|
118
|
+
value: N.version,
|
|
119
|
+
onChange: (e) => P({
|
|
120
|
+
...N,
|
|
121
|
+
version: e.target.value
|
|
122
|
+
}),
|
|
123
|
+
className: "mt-1",
|
|
124
|
+
placeholder: "v1.0.0"
|
|
125
|
+
})] }), /* @__PURE__ */ f("div", { children: [/* @__PURE__ */ d("label", {
|
|
126
|
+
className: "text-sm font-medium",
|
|
127
|
+
children: "Name"
|
|
128
|
+
}), /* @__PURE__ */ d(v, {
|
|
129
|
+
value: N.name,
|
|
130
|
+
onChange: (e) => P({
|
|
131
|
+
...N,
|
|
132
|
+
name: e.target.value
|
|
133
|
+
}),
|
|
134
|
+
className: "mt-1"
|
|
135
|
+
})] })]
|
|
136
|
+
}),
|
|
137
|
+
/* @__PURE__ */ f("div", { children: [/* @__PURE__ */ d("label", {
|
|
138
|
+
className: "text-sm font-medium",
|
|
139
|
+
children: "Description"
|
|
140
|
+
}), /* @__PURE__ */ d("textarea", {
|
|
141
|
+
className: "mt-1 w-full rounded-md border border-input bg-background px-3 py-2 text-sm min-h-[80px]",
|
|
142
|
+
value: N.description,
|
|
143
|
+
onChange: (e) => P({
|
|
144
|
+
...N,
|
|
145
|
+
description: e.target.value
|
|
146
|
+
})
|
|
147
|
+
})] }),
|
|
148
|
+
/* @__PURE__ */ f("div", {
|
|
149
|
+
className: "grid grid-cols-2 gap-4",
|
|
150
|
+
children: [/* @__PURE__ */ f("div", { children: [/* @__PURE__ */ d("label", {
|
|
151
|
+
className: "text-sm font-medium",
|
|
152
|
+
children: "Status"
|
|
153
|
+
}), /* @__PURE__ */ d("select", {
|
|
154
|
+
className: "mt-1 w-full rounded-md border border-input bg-background px-3 py-2 text-sm",
|
|
155
|
+
value: N.status,
|
|
156
|
+
onChange: (e) => P({
|
|
157
|
+
...N,
|
|
158
|
+
status: e.target.value
|
|
159
|
+
}),
|
|
160
|
+
children: [
|
|
161
|
+
"DRAFT",
|
|
162
|
+
"PLANNING",
|
|
163
|
+
"IN_PROGRESS",
|
|
164
|
+
"READY",
|
|
165
|
+
"RELEASED",
|
|
166
|
+
"CANCELLED",
|
|
167
|
+
"ROLLED_BACK"
|
|
168
|
+
].map((e) => /* @__PURE__ */ d("option", {
|
|
169
|
+
value: e,
|
|
170
|
+
className: "capitalize",
|
|
171
|
+
children: e.toLowerCase().replace("_", " ")
|
|
172
|
+
}, e))
|
|
173
|
+
})] }), /* @__PURE__ */ f("div", { children: [/* @__PURE__ */ d("label", {
|
|
174
|
+
className: "text-sm font-medium",
|
|
175
|
+
children: "Planned Date"
|
|
176
|
+
}), /* @__PURE__ */ d(v, {
|
|
177
|
+
type: "date",
|
|
178
|
+
value: N.plannedDate,
|
|
179
|
+
onChange: (e) => P({
|
|
180
|
+
...N,
|
|
181
|
+
plannedDate: e.target.value
|
|
182
|
+
}),
|
|
183
|
+
className: "mt-1"
|
|
184
|
+
})] })]
|
|
185
|
+
}),
|
|
186
|
+
/* @__PURE__ */ f("div", { children: [/* @__PURE__ */ d("label", {
|
|
187
|
+
className: "text-sm font-medium",
|
|
188
|
+
children: "Tags (comma-separated)"
|
|
189
|
+
}), /* @__PURE__ */ d(v, {
|
|
190
|
+
value: N.tags,
|
|
191
|
+
onChange: (e) => P({
|
|
192
|
+
...N,
|
|
193
|
+
tags: e.target.value
|
|
194
|
+
}),
|
|
195
|
+
className: "mt-1",
|
|
196
|
+
placeholder: "e.g. critical, security, performance"
|
|
197
|
+
})] }),
|
|
198
|
+
/* @__PURE__ */ f("div", { children: [/* @__PURE__ */ d("label", {
|
|
199
|
+
className: "text-sm font-medium",
|
|
200
|
+
children: "Release Notes"
|
|
201
|
+
}), /* @__PURE__ */ d("textarea", {
|
|
202
|
+
className: "mt-1 w-full rounded-md border border-input bg-background px-3 py-2 text-sm min-h-[120px] font-mono",
|
|
203
|
+
value: N.releaseNotes,
|
|
204
|
+
onChange: (e) => P({
|
|
205
|
+
...N,
|
|
206
|
+
releaseNotes: e.target.value
|
|
207
|
+
}),
|
|
208
|
+
placeholder: "Describe what changed in this release..."
|
|
209
|
+
})] })
|
|
210
|
+
]
|
|
211
|
+
})] })
|
|
212
|
+
]
|
|
213
|
+
}) : /* @__PURE__ */ d("div", {
|
|
214
|
+
className: "p-6 text-muted-foreground",
|
|
215
|
+
children: "Release not found."
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
//#endregion
|
|
219
|
+
export { x as ProductsEditReleasePagePage };
|
|
220
|
+
|
|
221
|
+
//# sourceMappingURL=ProductsEditReleasePagePage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ProductsEditReleasePagePage.js","names":[],"sources":["../../../src/planmagnet/pages/ProductsEditReleasePagePage.tsx"],"sourcesContent":["// eslint-disable-next-line @typescript-eslint/ban-ts-comment\n// @ts-nocheck\nimport { useState, useMemo } from 'react';\nimport { gql } from '@apollo/client';\nimport { useQuery, useMutation } from '@apollo/client/react';\nimport { Card, CardContent, CardHeader, CardTitle, Button, Input } from '@burdenoff/fe-libs/ui';\nimport { Save, ArrowLeft, Loader2 } from 'lucide-react';\nimport { usePlanMagnet, usePlanMagnetNavigate } from '../providers/PlanMagnetProvider';\nimport { useParams } from 'react-router-dom';\n\nconst GET_RELEASE = gql`\n query GetReleaseForEdit($id: ID!) {\n planmagnetRelease(id: $id) {\n id\n name\n description\n version\n status\n plannedDate\n releasedAt\n releaseNotes\n ownerId\n tags\n }\n }\n`;\n\nconst UPDATE_RELEASE = gql`\n mutation UpdateRelease($id: ID!, $input: UpdateReleaseInput!) {\n planmagnetUpdateRelease(id: $id, input: $input) {\n id\n name\n description\n version\n status\n plannedDate\n releaseNotes\n tags\n updatedAt\n }\n }\n`;\n\nexport function ProductsEditReleasePagePage() {\n const { workspaceId } = usePlanMagnet();\n const navigate = usePlanMagnetNavigate();\n const params = useParams<{ id: string }>();\n const releaseId = 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_RELEASE, {\n variables: { id: releaseId },\n skip: !releaseId,\n });\n\n const [updateRelease, { loading: saving, error: saveError }] = useMutation(UPDATE_RELEASE, {\n refetchQueries: ['ListReleases', 'GetReleaseForEdit'],\n });\n\n const release = data?.planmagnetRelease;\n\n const defaultForm = useMemo(\n () => ({\n version: release?.version ?? '',\n name: release?.name ?? '',\n description: release?.description ?? '',\n status: release?.status ?? 'DRAFT',\n plannedDate: release?.plannedDate\n ? new Date(release.plannedDate).toISOString().split('T')[0]\n : '',\n releaseNotes: release?.releaseNotes ?? '',\n tags: release?.tags?.join(', ') ?? '',\n }),\n [release]\n );\n\n const [formOverrides, setFormOverrides] = useState<Record<string, string>>({});\n const form = { ...defaultForm, ...formOverrides };\n const setForm = (val: Record<string, string>) => setFormOverrides(val);\n\n const statuses = [\n 'DRAFT',\n 'PLANNING',\n 'IN_PROGRESS',\n 'READY',\n 'RELEASED',\n 'CANCELLED',\n 'ROLLED_BACK',\n ] as const;\n\n const handleSave = () => {\n planmagnetUpdateRelease({\n variables: {\n id: releaseId,\n input: {\n version: form.version || undefined,\n name: form.name || undefined,\n description: form.description || undefined,\n status: form.status || undefined,\n plannedDate: form.plannedDate || undefined,\n releaseNotes: form.releaseNotes || undefined,\n tags: form.tags\n ? form.tags\n .split(',')\n .map((t: string) => t.trim())\n .filter(Boolean)\n : undefined,\n },\n },\n });\n };\n\n if (loading) {\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 release: {error.message}</div>;\n }\n\n if (!release) return <div className=\"p-6 text-muted-foreground\">Release not found.</div>;\n\n return (\n <div className=\"space-y-6 p-6 max-w-4xl\">\n <div className=\"flex items-center justify-between\">\n <div className=\"flex items-center gap-3\">\n <Button variant=\"ghost\" size=\"sm\" onClick={() => navigate('/products/releases')}>\n <ArrowLeft className=\"h-4 w-4\" />\n </Button>\n <div>\n <h1 className=\"text-2xl font-semibold\">Edit Release</h1>\n <p className=\"text-sm text-muted-foreground\">\n {release.version} - {release.name}\n </p>\n </div>\n </div>\n <Button size=\"sm\" onClick={handleSave} disabled={saving}>\n {saving ? (\n <Loader2 className=\"mr-1 h-4 w-4 animate-spin\" />\n ) : (\n <Save className=\"mr-1 h-4 w-4\" />\n )}\n Save Changes\n </Button>\n </div>\n\n {saveError && (\n <div className=\"p-3 rounded-md bg-destructive/10 text-destructive text-sm\">\n Failed to save: {saveError.message}\n </div>\n )}\n\n <Card>\n <CardHeader>\n <CardTitle>Release Details</CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-4\">\n <div className=\"grid grid-cols-2 gap-4\">\n <div>\n <label className=\"text-sm font-medium\">Version</label>\n <Input\n value={form.version}\n onChange={(e) => setForm({ ...form, version: e.target.value })}\n className=\"mt-1\"\n placeholder=\"v1.0.0\"\n />\n </div>\n <div>\n <label className=\"text-sm font-medium\">Name</label>\n <Input\n value={form.name}\n onChange={(e) => setForm({ ...form, name: e.target.value })}\n className=\"mt-1\"\n />\n </div>\n </div>\n <div>\n <label className=\"text-sm font-medium\">Description</label>\n <textarea\n className=\"mt-1 w-full rounded-md border border-input bg-background px-3 py-2 text-sm min-h-[80px]\"\n value={form.description}\n onChange={(e) => setForm({ ...form, description: e.target.value })}\n />\n </div>\n <div className=\"grid grid-cols-2 gap-4\">\n <div>\n <label className=\"text-sm font-medium\">Status</label>\n <select\n className=\"mt-1 w-full rounded-md border border-input bg-background px-3 py-2 text-sm\"\n value={form.status}\n onChange={(e) => setForm({ ...form, status: e.target.value })}\n >\n {statuses.map((s) => (\n <option key={s} value={s} className=\"capitalize\">\n {s.toLowerCase().replace('_', ' ')}\n </option>\n ))}\n </select>\n </div>\n <div>\n <label className=\"text-sm font-medium\">Planned Date</label>\n <Input\n type=\"date\"\n value={form.plannedDate}\n onChange={(e) => setForm({ ...form, plannedDate: e.target.value })}\n className=\"mt-1\"\n />\n </div>\n </div>\n <div>\n <label className=\"text-sm font-medium\">Tags (comma-separated)</label>\n <Input\n value={form.tags}\n onChange={(e) => setForm({ ...form, tags: e.target.value })}\n className=\"mt-1\"\n placeholder=\"e.g. critical, security, performance\"\n />\n </div>\n <div>\n <label className=\"text-sm font-medium\">Release Notes</label>\n <textarea\n className=\"mt-1 w-full rounded-md border border-input bg-background px-3 py-2 text-sm min-h-[120px] font-mono\"\n value={form.releaseNotes}\n onChange={(e) => setForm({ ...form, releaseNotes: e.target.value })}\n placeholder=\"Describe what changed in this release...\"\n />\n </div>\n </CardContent>\n </Card>\n </div>\n );\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ProductsFeatureAnalyticsPagePage.d.ts","sourceRoot":"","sources":["../../../src/planmagnet/pages/ProductsFeatureAnalyticsPagePage.tsx"],"names":[],"mappings":"AA8DA,wBAAgB,gCAAgC,4CA6P/C"}
|
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
import { usePlanMagnet as e } from "../providers/PlanMagnetProvider.js";
|
|
2
|
+
import { BarChart3 as t, Loader2 as n, Target as r, ThumbsUp as i, TrendingUp as a, Users as o } from "lucide-react";
|
|
3
|
+
import { useParams as s } from "react-router-dom";
|
|
4
|
+
import { gql as c } from "@apollo/client";
|
|
5
|
+
import { useQuery as l } from "@apollo/client/react";
|
|
6
|
+
import { jsx as u, jsxs as d } from "react/jsx-runtime";
|
|
7
|
+
import { Card as f, CardContent as p, CardHeader as m, CardTitle as h } from "@burdenoff/fe-libs/ui";
|
|
8
|
+
//#region src/planmagnet/pages/ProductsFeatureAnalyticsPagePage.tsx
|
|
9
|
+
var g = c`
|
|
10
|
+
query GetFeatureRequestAnalytics($id: ID!) {
|
|
11
|
+
planmagnetFeatureRequest(id: $id) {
|
|
12
|
+
id
|
|
13
|
+
title
|
|
14
|
+
description
|
|
15
|
+
status
|
|
16
|
+
businessValue
|
|
17
|
+
effortEstimate
|
|
18
|
+
priorityScore
|
|
19
|
+
voteCount
|
|
20
|
+
submittedBy
|
|
21
|
+
tags
|
|
22
|
+
createdAt
|
|
23
|
+
updatedAt
|
|
24
|
+
votes {
|
|
25
|
+
id
|
|
26
|
+
voterId
|
|
27
|
+
weight
|
|
28
|
+
comment
|
|
29
|
+
createdAt
|
|
30
|
+
}
|
|
31
|
+
competitors {
|
|
32
|
+
id
|
|
33
|
+
name
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
`, _ = c`
|
|
38
|
+
query ListAllFeaturesAnalytics($workspaceId: ID!, $pagination: PaginationInput) {
|
|
39
|
+
planmagnetFeatureRequests(workspaceId: $workspaceId, pagination: $pagination) {
|
|
40
|
+
items {
|
|
41
|
+
id
|
|
42
|
+
status
|
|
43
|
+
voteCount
|
|
44
|
+
businessValue
|
|
45
|
+
priorityScore
|
|
46
|
+
}
|
|
47
|
+
totalCount
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
`;
|
|
51
|
+
function v() {
|
|
52
|
+
let { workspaceId: c } = e(), v = s().id ?? "", { data: y, loading: b, error: x } = l(g, {
|
|
53
|
+
variables: { id: v },
|
|
54
|
+
skip: !v
|
|
55
|
+
}), { data: S } = l(_, {
|
|
56
|
+
variables: {
|
|
57
|
+
workspaceId: c,
|
|
58
|
+
pagination: { first: 100 }
|
|
59
|
+
},
|
|
60
|
+
skip: !c
|
|
61
|
+
});
|
|
62
|
+
if (b) return /* @__PURE__ */ u("div", {
|
|
63
|
+
className: "flex items-center justify-center p-12",
|
|
64
|
+
children: /* @__PURE__ */ u(n, { className: "h-8 w-8 animate-spin text-muted-foreground" })
|
|
65
|
+
});
|
|
66
|
+
if (x) return /* @__PURE__ */ d("div", {
|
|
67
|
+
className: "p-6 text-destructive",
|
|
68
|
+
children: ["Failed to load analytics: ", x.message]
|
|
69
|
+
});
|
|
70
|
+
let C = y?.planmagnetFeatureRequest;
|
|
71
|
+
if (!C) return /* @__PURE__ */ u("div", {
|
|
72
|
+
className: "p-6 text-muted-foreground",
|
|
73
|
+
children: "Feature not found."
|
|
74
|
+
});
|
|
75
|
+
let w = C.votes ?? [], T = C.competitors?.length ?? 0, E = S?.featureRequests?.items ?? [], D = {};
|
|
76
|
+
for (let e of w) D[e.weight] = (D[e.weight] || 0) + 1;
|
|
77
|
+
let O = Math.max(...Object.values(D), 1), k = [], A = {};
|
|
78
|
+
for (let e of w) {
|
|
79
|
+
let t = new Date(e.createdAt).toLocaleDateString();
|
|
80
|
+
A[t] = (A[t] || 0) + 1;
|
|
81
|
+
}
|
|
82
|
+
for (let [e, t] of Object.entries(A)) k.push({
|
|
83
|
+
date: e,
|
|
84
|
+
count: t
|
|
85
|
+
});
|
|
86
|
+
k.sort((e, t) => new Date(e.date).getTime() - new Date(t.date).getTime());
|
|
87
|
+
let j = Math.max(...k.map((e) => e.count), 1), M = {};
|
|
88
|
+
for (let e of E) M[e.status] = (M[e.status] || 0) + 1;
|
|
89
|
+
let N = E.slice().sort((e, t) => t.voteCount - e.voteCount).findIndex((e) => e.id === C.id) + 1;
|
|
90
|
+
return /* @__PURE__ */ d("div", {
|
|
91
|
+
className: "space-y-6 p-6",
|
|
92
|
+
children: [
|
|
93
|
+
/* @__PURE__ */ d("div", { children: [/* @__PURE__ */ u("h1", {
|
|
94
|
+
className: "text-2xl font-semibold",
|
|
95
|
+
children: "Feature Analytics"
|
|
96
|
+
}), /* @__PURE__ */ d("p", {
|
|
97
|
+
className: "text-sm text-muted-foreground",
|
|
98
|
+
children: [
|
|
99
|
+
C.title,
|
|
100
|
+
" - ",
|
|
101
|
+
C.status.toLowerCase().replace("_", " ")
|
|
102
|
+
]
|
|
103
|
+
})] }),
|
|
104
|
+
/* @__PURE__ */ d("div", {
|
|
105
|
+
className: "grid grid-cols-2 md:grid-cols-4 gap-4",
|
|
106
|
+
children: [
|
|
107
|
+
/* @__PURE__ */ u(f, { children: /* @__PURE__ */ d(p, {
|
|
108
|
+
className: "pt-4",
|
|
109
|
+
children: [/* @__PURE__ */ d("div", {
|
|
110
|
+
className: "flex items-center gap-2 text-muted-foreground text-xs",
|
|
111
|
+
children: [/* @__PURE__ */ u(r, { className: "h-4 w-4" }), "Priority Score"]
|
|
112
|
+
}), /* @__PURE__ */ u("p", {
|
|
113
|
+
className: "text-2xl font-bold mt-1",
|
|
114
|
+
children: C.priorityScore ?? 0
|
|
115
|
+
})]
|
|
116
|
+
}) }),
|
|
117
|
+
/* @__PURE__ */ u(f, { children: /* @__PURE__ */ d(p, {
|
|
118
|
+
className: "pt-4",
|
|
119
|
+
children: [
|
|
120
|
+
/* @__PURE__ */ d("div", {
|
|
121
|
+
className: "flex items-center gap-2 text-muted-foreground text-xs",
|
|
122
|
+
children: [/* @__PURE__ */ u(i, { className: "h-4 w-4" }), "Total Votes"]
|
|
123
|
+
}),
|
|
124
|
+
/* @__PURE__ */ u("p", {
|
|
125
|
+
className: "text-2xl font-bold mt-1",
|
|
126
|
+
children: C.voteCount
|
|
127
|
+
}),
|
|
128
|
+
/* @__PURE__ */ d("p", {
|
|
129
|
+
className: "text-xs text-green-600 mt-1",
|
|
130
|
+
children: [
|
|
131
|
+
"Rank #",
|
|
132
|
+
N || "N/A",
|
|
133
|
+
" of ",
|
|
134
|
+
E.length
|
|
135
|
+
]
|
|
136
|
+
})
|
|
137
|
+
]
|
|
138
|
+
}) }),
|
|
139
|
+
/* @__PURE__ */ u(f, { children: /* @__PURE__ */ d(p, {
|
|
140
|
+
className: "pt-4",
|
|
141
|
+
children: [/* @__PURE__ */ d("div", {
|
|
142
|
+
className: "flex items-center gap-2 text-muted-foreground text-xs",
|
|
143
|
+
children: [/* @__PURE__ */ u(o, { className: "h-4 w-4" }), "Competitors"]
|
|
144
|
+
}), /* @__PURE__ */ u("p", {
|
|
145
|
+
className: "text-2xl font-bold mt-1",
|
|
146
|
+
children: T
|
|
147
|
+
})]
|
|
148
|
+
}) }),
|
|
149
|
+
/* @__PURE__ */ u(f, { children: /* @__PURE__ */ d(p, {
|
|
150
|
+
className: "pt-4",
|
|
151
|
+
children: [/* @__PURE__ */ d("div", {
|
|
152
|
+
className: "flex items-center gap-2 text-muted-foreground text-xs",
|
|
153
|
+
children: [/* @__PURE__ */ u(a, { className: "h-4 w-4" }), "Business Value"]
|
|
154
|
+
}), /* @__PURE__ */ u("p", {
|
|
155
|
+
className: "text-2xl font-bold mt-1",
|
|
156
|
+
children: C.businessValue ?? 0
|
|
157
|
+
})]
|
|
158
|
+
}) })
|
|
159
|
+
]
|
|
160
|
+
}),
|
|
161
|
+
/* @__PURE__ */ d("div", {
|
|
162
|
+
className: "grid grid-cols-1 lg:grid-cols-2 gap-6",
|
|
163
|
+
children: [/* @__PURE__ */ d(f, { children: [/* @__PURE__ */ u(m, { children: /* @__PURE__ */ d(h, {
|
|
164
|
+
className: "flex items-center gap-2",
|
|
165
|
+
children: [/* @__PURE__ */ u(t, { className: "h-4 w-4" }), "Vote Timeline"]
|
|
166
|
+
}) }), /* @__PURE__ */ d(p, { children: [k.length === 0 ? /* @__PURE__ */ u("p", {
|
|
167
|
+
className: "text-sm text-muted-foreground text-center py-8",
|
|
168
|
+
children: "No vote data available"
|
|
169
|
+
}) : /* @__PURE__ */ u("div", {
|
|
170
|
+
className: "flex items-end gap-1 h-48",
|
|
171
|
+
children: k.map((e) => /* @__PURE__ */ d("div", {
|
|
172
|
+
className: "flex-1 flex flex-col items-center gap-1",
|
|
173
|
+
children: [/* @__PURE__ */ u("div", {
|
|
174
|
+
className: "w-full flex justify-center",
|
|
175
|
+
children: /* @__PURE__ */ u("div", {
|
|
176
|
+
className: "w-5 bg-primary rounded-t transition-all",
|
|
177
|
+
style: { height: `${e.count / j * 160}px` }
|
|
178
|
+
})
|
|
179
|
+
}), /* @__PURE__ */ u("span", {
|
|
180
|
+
className: "text-[10px] text-muted-foreground truncate max-w-[40px]",
|
|
181
|
+
children: e.date
|
|
182
|
+
})]
|
|
183
|
+
}, e.date))
|
|
184
|
+
}), /* @__PURE__ */ u("p", {
|
|
185
|
+
className: "text-xs text-muted-foreground text-center mt-2",
|
|
186
|
+
children: "Votes over time"
|
|
187
|
+
})] })] }), /* @__PURE__ */ d(f, { children: [/* @__PURE__ */ u(m, { children: /* @__PURE__ */ u(h, { children: "Vote Weight Distribution" }) }), /* @__PURE__ */ u(p, {
|
|
188
|
+
className: "space-y-4",
|
|
189
|
+
children: Object.entries(D).length === 0 ? /* @__PURE__ */ u("p", {
|
|
190
|
+
className: "text-sm text-muted-foreground text-center py-8",
|
|
191
|
+
children: "No votes recorded"
|
|
192
|
+
}) : Object.entries(D).sort(([e], [t]) => Number(e) - Number(t)).map(([e, t]) => /* @__PURE__ */ d("div", { children: [/* @__PURE__ */ d("div", {
|
|
193
|
+
className: "flex justify-between text-sm mb-1",
|
|
194
|
+
children: [/* @__PURE__ */ d("span", { children: ["Weight ", e] }), /* @__PURE__ */ d("span", {
|
|
195
|
+
className: "font-semibold",
|
|
196
|
+
children: [t, " votes"]
|
|
197
|
+
})]
|
|
198
|
+
}), /* @__PURE__ */ u("div", {
|
|
199
|
+
className: "w-full h-3 rounded-full bg-muted overflow-hidden",
|
|
200
|
+
children: /* @__PURE__ */ u("div", {
|
|
201
|
+
className: "h-full rounded-full bg-primary",
|
|
202
|
+
style: { width: `${t / O * 100}%` }
|
|
203
|
+
})
|
|
204
|
+
})] }, e))
|
|
205
|
+
})] })]
|
|
206
|
+
}),
|
|
207
|
+
/* @__PURE__ */ d("div", {
|
|
208
|
+
className: "grid grid-cols-1 lg:grid-cols-2 gap-6",
|
|
209
|
+
children: [/* @__PURE__ */ d(f, { children: [/* @__PURE__ */ u(m, { children: /* @__PURE__ */ u(h, { children: "All Features - Status Distribution" }) }), /* @__PURE__ */ u(p, {
|
|
210
|
+
className: "space-y-3",
|
|
211
|
+
children: Object.entries(M).map(([e, t]) => {
|
|
212
|
+
let n = E.length, r = n > 0 ? Math.round(t / n * 100) : 0;
|
|
213
|
+
return /* @__PURE__ */ d("div", { children: [/* @__PURE__ */ d("div", {
|
|
214
|
+
className: "flex justify-between text-sm mb-1",
|
|
215
|
+
children: [/* @__PURE__ */ u("span", {
|
|
216
|
+
className: "capitalize",
|
|
217
|
+
children: e.toLowerCase().replace("_", " ")
|
|
218
|
+
}), /* @__PURE__ */ d("span", {
|
|
219
|
+
className: "font-medium",
|
|
220
|
+
children: [
|
|
221
|
+
t,
|
|
222
|
+
" (",
|
|
223
|
+
r,
|
|
224
|
+
"%)"
|
|
225
|
+
]
|
|
226
|
+
})]
|
|
227
|
+
}), /* @__PURE__ */ u("div", {
|
|
228
|
+
className: "w-full h-2 rounded-full bg-muted overflow-hidden",
|
|
229
|
+
children: /* @__PURE__ */ u("div", {
|
|
230
|
+
className: `h-full rounded-full ${{
|
|
231
|
+
SUBMITTED: "bg-gray-400",
|
|
232
|
+
UNDER_REVIEW: "bg-yellow-400",
|
|
233
|
+
PLANNED: "bg-blue-400",
|
|
234
|
+
IN_PROGRESS: "bg-purple-400",
|
|
235
|
+
COMPLETED: "bg-green-400",
|
|
236
|
+
DECLINED: "bg-red-400",
|
|
237
|
+
DUPLICATE: "bg-orange-400"
|
|
238
|
+
}[e] ?? "bg-gray-300"}`,
|
|
239
|
+
style: { width: `${r}%` }
|
|
240
|
+
})
|
|
241
|
+
})] }, e);
|
|
242
|
+
})
|
|
243
|
+
})] }), /* @__PURE__ */ d(f, { children: [/* @__PURE__ */ u(m, { children: /* @__PURE__ */ u(h, { children: "Feature Impact" }) }), /* @__PURE__ */ d(p, {
|
|
244
|
+
className: "space-y-3",
|
|
245
|
+
children: [/* @__PURE__ */ d("div", {
|
|
246
|
+
className: "text-center p-4 bg-muted rounded-md",
|
|
247
|
+
children: [/* @__PURE__ */ u("p", {
|
|
248
|
+
className: "text-3xl font-bold text-primary",
|
|
249
|
+
children: C.voteCount
|
|
250
|
+
}), /* @__PURE__ */ u("p", {
|
|
251
|
+
className: "text-sm text-muted-foreground",
|
|
252
|
+
children: "total votes received"
|
|
253
|
+
})]
|
|
254
|
+
}), /* @__PURE__ */ d("div", {
|
|
255
|
+
className: "grid grid-cols-2 gap-2 text-center",
|
|
256
|
+
children: [/* @__PURE__ */ d("div", {
|
|
257
|
+
className: "p-3 border rounded-md",
|
|
258
|
+
children: [/* @__PURE__ */ u("p", {
|
|
259
|
+
className: "text-lg font-semibold",
|
|
260
|
+
children: C.businessValue ?? 0
|
|
261
|
+
}), /* @__PURE__ */ u("p", {
|
|
262
|
+
className: "text-xs text-muted-foreground",
|
|
263
|
+
children: "business value"
|
|
264
|
+
})]
|
|
265
|
+
}), /* @__PURE__ */ d("div", {
|
|
266
|
+
className: "p-3 border rounded-md",
|
|
267
|
+
children: [/* @__PURE__ */ u("p", {
|
|
268
|
+
className: "text-lg font-semibold",
|
|
269
|
+
children: C.priorityScore ?? 0
|
|
270
|
+
}), /* @__PURE__ */ u("p", {
|
|
271
|
+
className: "text-xs text-muted-foreground",
|
|
272
|
+
children: "priority score"
|
|
273
|
+
})]
|
|
274
|
+
})]
|
|
275
|
+
})]
|
|
276
|
+
})] })]
|
|
277
|
+
})
|
|
278
|
+
]
|
|
279
|
+
});
|
|
280
|
+
}
|
|
281
|
+
//#endregion
|
|
282
|
+
export { v as ProductsFeatureAnalyticsPagePage };
|
|
283
|
+
|
|
284
|
+
//# sourceMappingURL=ProductsFeatureAnalyticsPagePage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ProductsFeatureAnalyticsPagePage.js","names":[],"sources":["../../../src/planmagnet/pages/ProductsFeatureAnalyticsPagePage.tsx"],"sourcesContent":["// eslint-disable-next-line @typescript-eslint/ban-ts-comment\n// @ts-nocheck\nimport { gql } from '@apollo/client';\nimport { useQuery } from '@apollo/client/react';\nimport { Card, CardContent, CardHeader, CardTitle } from '@burdenoff/fe-libs/ui';\nimport { TrendingUp, ThumbsUp, Users, BarChart3, Target, Loader2 } from 'lucide-react';\nimport { usePlanMagnet } from '../providers/PlanMagnetProvider';\nimport { useParams } from 'react-router-dom';\n\nconst GET_FEATURE_REQUEST_ANALYTICS = gql`\n query GetFeatureRequestAnalytics($id: ID!) {\n planmagnetFeatureRequest(id: $id) {\n id\n title\n description\n status\n businessValue\n effortEstimate\n priorityScore\n voteCount\n submittedBy\n tags\n createdAt\n updatedAt\n votes {\n id\n voterId\n weight\n comment\n createdAt\n }\n competitors {\n id\n name\n }\n }\n }\n`;\n\nconst LIST_ALL_FEATURES_ANALYTICS = gql`\n query ListAllFeaturesAnalytics($workspaceId: ID!, $pagination: PaginationInput) {\n planmagnetFeatureRequests(workspaceId: $workspaceId, pagination: $pagination) {\n items {\n id\n status\n voteCount\n businessValue\n priorityScore\n }\n totalCount\n }\n }\n`;\n\ninterface VoteNode {\n id: string;\n voterId: string;\n weight: number;\n comment: string | null;\n createdAt: string;\n}\n\nexport function ProductsFeatureAnalyticsPagePage() {\n const { workspaceId } = usePlanMagnet();\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_ANALYTICS, {\n variables: { id: featureId },\n skip: !featureId,\n });\n\n const {\n data: allFeaturesData,\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_ALL_FEATURES_ANALYTICS, {\n variables: { workspaceId, pagination: { first: 100 } },\n skip: !workspaceId,\n });\n\n if (loading) {\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 analytics: {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: VoteNode[] = feature.votes ?? [];\n const competitorCount = feature.competitors?.length ?? 0;\n const allFeatures = allFeaturesData?.featureRequests?.items ?? [];\n\n // Vote distribution by weight\n const votesByWeight: Record<number, number> = {};\n for (const v of votes) {\n votesByWeight[v.weight] = (votesByWeight[v.weight] || 0) + 1;\n }\n const maxVoteWeight = Math.max(...Object.values(votesByWeight), 1);\n\n // Vote timeline - group by creation date\n const voteTimeline: { date: string; count: number }[] = [];\n const voteDateMap: Record<string, number> = {};\n for (const v of votes) {\n const date = new Date(v.createdAt).toLocaleDateString();\n voteDateMap[date] = (voteDateMap[date] || 0) + 1;\n }\n for (const [date, count] of Object.entries(voteDateMap)) {\n voteTimeline.push({ date, count });\n }\n voteTimeline.sort((a, b) => new Date(a.date).getTime() - new Date(b.date).getTime());\n const maxTimelineCount = Math.max(...voteTimeline.map((d) => d.count), 1);\n\n // Status distribution across all features\n const statusDistribution: Record<string, number> = {};\n for (const f of allFeatures) {\n statusDistribution[f.status] = (statusDistribution[f.status] || 0) + 1;\n }\n\n // Rank this feature among all features by vote count\n const rankByVotes =\n allFeatures\n .slice()\n .sort((a: { voteCount: number }, b: { voteCount: number }) => b.voteCount - a.voteCount)\n .findIndex((f: { id: string }) => f.id === feature.id) + 1;\n\n return (\n <div className=\"space-y-6 p-6\">\n <div>\n <h1 className=\"text-2xl font-semibold\">Feature Analytics</h1>\n <p className=\"text-sm text-muted-foreground\">\n {feature.title} - {feature.status.toLowerCase().replace('_', ' ')}\n </p>\n </div>\n\n <div className=\"grid grid-cols-2 md:grid-cols-4 gap-4\">\n <Card>\n <CardContent className=\"pt-4\">\n <div className=\"flex items-center gap-2 text-muted-foreground text-xs\">\n <Target className=\"h-4 w-4\" />\n Priority Score\n </div>\n <p className=\"text-2xl font-bold mt-1\">{feature.priorityScore ?? 0}</p>\n </CardContent>\n </Card>\n <Card>\n <CardContent className=\"pt-4\">\n <div className=\"flex items-center gap-2 text-muted-foreground text-xs\">\n <ThumbsUp className=\"h-4 w-4\" />\n Total Votes\n </div>\n <p className=\"text-2xl font-bold mt-1\">{feature.voteCount}</p>\n <p className=\"text-xs text-green-600 mt-1\">\n Rank #{rankByVotes || 'N/A'} of {allFeatures.length}\n </p>\n </CardContent>\n </Card>\n <Card>\n <CardContent className=\"pt-4\">\n <div className=\"flex items-center gap-2 text-muted-foreground text-xs\">\n <Users className=\"h-4 w-4\" />\n Competitors\n </div>\n <p className=\"text-2xl font-bold mt-1\">{competitorCount}</p>\n </CardContent>\n </Card>\n <Card>\n <CardContent className=\"pt-4\">\n <div className=\"flex items-center gap-2 text-muted-foreground text-xs\">\n <TrendingUp className=\"h-4 w-4\" />\n Business Value\n </div>\n <p className=\"text-2xl font-bold mt-1\">{feature.businessValue ?? 0}</p>\n </CardContent>\n </Card>\n </div>\n\n <div className=\"grid grid-cols-1 lg:grid-cols-2 gap-6\">\n <Card>\n <CardHeader>\n <CardTitle className=\"flex items-center gap-2\">\n <BarChart3 className=\"h-4 w-4\" />\n Vote Timeline\n </CardTitle>\n </CardHeader>\n <CardContent>\n {voteTimeline.length === 0 ? (\n <p className=\"text-sm text-muted-foreground text-center py-8\">\n No vote data available\n </p>\n ) : (\n <div className=\"flex items-end gap-1 h-48\">\n {voteTimeline.map((d) => (\n <div key={d.date} className=\"flex-1 flex flex-col items-center gap-1\">\n <div className=\"w-full flex justify-center\">\n <div\n className=\"w-5 bg-primary rounded-t transition-all\"\n style={{ height: `${(d.count / maxTimelineCount) * 160}px` }}\n />\n </div>\n <span className=\"text-[10px] text-muted-foreground truncate max-w-[40px]\">\n {d.date}\n </span>\n </div>\n ))}\n </div>\n )}\n <p className=\"text-xs text-muted-foreground text-center mt-2\">Votes over time</p>\n </CardContent>\n </Card>\n\n <Card>\n <CardHeader>\n <CardTitle>Vote Weight Distribution</CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-4\">\n {Object.entries(votesByWeight).length === 0 ? (\n <p className=\"text-sm text-muted-foreground text-center py-8\">No votes recorded</p>\n ) : (\n Object.entries(votesByWeight)\n .sort(([a], [b]) => Number(a) - Number(b))\n .map(([weight, count]) => (\n <div key={weight}>\n <div className=\"flex justify-between text-sm mb-1\">\n <span>Weight {weight}</span>\n <span className=\"font-semibold\">{count} votes</span>\n </div>\n <div className=\"w-full h-3 rounded-full bg-muted overflow-hidden\">\n <div\n className=\"h-full rounded-full bg-primary\"\n style={{ width: `${(count / maxVoteWeight) * 100}%` }}\n />\n </div>\n </div>\n ))\n )}\n </CardContent>\n </Card>\n </div>\n\n <div className=\"grid grid-cols-1 lg:grid-cols-2 gap-6\">\n <Card>\n <CardHeader>\n <CardTitle>All Features - Status Distribution</CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n {Object.entries(statusDistribution).map(([status, count]) => {\n const total = allFeatures.length;\n const pct = total > 0 ? Math.round((count / total) * 100) : 0;\n const colors: Record<string, string> = {\n SUBMITTED: 'bg-gray-400',\n UNDER_REVIEW: 'bg-yellow-400',\n PLANNED: 'bg-blue-400',\n IN_PROGRESS: 'bg-purple-400',\n COMPLETED: 'bg-green-400',\n DECLINED: 'bg-red-400',\n DUPLICATE: 'bg-orange-400',\n };\n return (\n <div key={status}>\n <div className=\"flex justify-between text-sm mb-1\">\n <span className=\"capitalize\">{status.toLowerCase().replace('_', ' ')}</span>\n <span className=\"font-medium\">\n {count} ({pct}%)\n </span>\n </div>\n <div className=\"w-full h-2 rounded-full bg-muted overflow-hidden\">\n <div\n className={`h-full rounded-full ${colors[status] ?? 'bg-gray-300'}`}\n style={{ width: `${pct}%` }}\n />\n </div>\n </div>\n );\n })}\n </CardContent>\n </Card>\n\n <Card>\n <CardHeader>\n <CardTitle>Feature Impact</CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n <div className=\"text-center p-4 bg-muted rounded-md\">\n <p className=\"text-3xl font-bold text-primary\">{feature.voteCount}</p>\n <p className=\"text-sm text-muted-foreground\">total votes received</p>\n </div>\n <div className=\"grid grid-cols-2 gap-2 text-center\">\n <div className=\"p-3 border rounded-md\">\n <p className=\"text-lg font-semibold\">{feature.businessValue ?? 0}</p>\n <p className=\"text-xs text-muted-foreground\">business value</p>\n </div>\n <div className=\"p-3 border rounded-md\">\n <p className=\"text-lg font-semibold\">{feature.priorityScore ?? 0}</p>\n <p className=\"text-xs text-muted-foreground\">priority score</p>\n </div>\n </div>\n </CardContent>\n </Card>\n </div>\n </div>\n );\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ProductsFeatureDetailPagePage.d.ts","sourceRoot":"","sources":["../../../src/planmagnet/pages/ProductsFeatureDetailPagePage.tsx"],"names":[],"mappings":"AA2DA,wBAAgB,6BAA6B,4CA8M5C"}
|