@burdenoff/microfe-planmagnet 2026.927.3 → 2026.927.4
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/planmagnet/controls/FeatureControls.d.ts +26 -0
- package/dist/planmagnet/controls/FeatureControls.d.ts.map +1 -0
- package/dist/planmagnet/controls/FeatureControls.js +318 -0
- package/dist/planmagnet/controls/FeatureControls.js.map +1 -0
- package/dist/planmagnet/controls/MilestoneControls.d.ts +17 -0
- package/dist/planmagnet/controls/MilestoneControls.d.ts.map +1 -0
- package/dist/planmagnet/controls/MilestoneControls.js +200 -0
- package/dist/planmagnet/controls/MilestoneControls.js.map +1 -0
- package/dist/planmagnet/controls/ObjectiveControls.d.ts +31 -0
- package/dist/planmagnet/controls/ObjectiveControls.d.ts.map +1 -0
- package/dist/planmagnet/controls/ObjectiveControls.js +296 -0
- package/dist/planmagnet/controls/ObjectiveControls.js.map +1 -0
- package/dist/planmagnet/controls/Pickers.d.ts +26 -0
- package/dist/planmagnet/controls/Pickers.d.ts.map +1 -0
- package/dist/planmagnet/controls/Pickers.js +171 -0
- package/dist/planmagnet/controls/Pickers.js.map +1 -0
- package/dist/planmagnet/controls/ProjectControls.js +7 -7
- package/dist/planmagnet/controls/ReleaseControls.d.ts +14 -0
- package/dist/planmagnet/controls/ReleaseControls.d.ts.map +1 -0
- package/dist/planmagnet/controls/ReleaseControls.js +108 -0
- package/dist/planmagnet/controls/ReleaseControls.js.map +1 -0
- package/dist/planmagnet/pages/DocsDocDetailPagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/DocsDocDetailPagePage.js +186 -152
- package/dist/planmagnet/pages/DocsDocDetailPagePage.js.map +1 -1
- package/dist/planmagnet/pages/GoalsCreateObjectivePagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/GoalsCreateObjectivePagePage.js +63 -56
- package/dist/planmagnet/pages/GoalsCreateObjectivePagePage.js.map +1 -1
- package/dist/planmagnet/pages/GoalsObjectiveDetailPagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/GoalsObjectiveDetailPagePage.js +229 -214
- package/dist/planmagnet/pages/GoalsObjectiveDetailPagePage.js.map +1 -1
- package/dist/planmagnet/pages/ProductsEditProductPagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/ProductsEditProductPagePage.js +142 -114
- package/dist/planmagnet/pages/ProductsEditProductPagePage.js.map +1 -1
- package/dist/planmagnet/pages/ProductsEditReleasePagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/ProductsEditReleasePagePage.js +134 -105
- package/dist/planmagnet/pages/ProductsEditReleasePagePage.js.map +1 -1
- package/dist/planmagnet/pages/ProductsFeatureDetailPagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/ProductsFeatureDetailPagePage.js +102 -108
- package/dist/planmagnet/pages/ProductsFeatureDetailPagePage.js.map +1 -1
- package/dist/planmagnet/pages/ProductsNewFeaturePagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/ProductsNewFeaturePagePage.js +119 -94
- package/dist/planmagnet/pages/ProductsNewFeaturePagePage.js.map +1 -1
- package/dist/planmagnet/pages/ProductsReleaseDetailPagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/ProductsReleaseDetailPagePage.js +107 -106
- package/dist/planmagnet/pages/ProductsReleaseDetailPagePage.js.map +1 -1
- package/dist/planmagnet/pages/ProductsReleasesPagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/ProductsReleasesPagePage.js +2 -0
- package/dist/planmagnet/pages/ProductsReleasesPagePage.js.map +1 -1
- package/dist/planmagnet/pages/ProjectsEditProjectPagePage.js +6 -6
- package/dist/planmagnet/pages/ProjectsMilestoneDetailPagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/ProjectsMilestoneDetailPagePage.js +55 -63
- package/dist/planmagnet/pages/ProjectsMilestoneDetailPagePage.js.map +1 -1
- package/dist/planmagnet/pages/ProjectsPlanningEditPagePage.js +4 -4
- package/dist/planmagnet/pages/TasksCreateTaskPagePage.js +123 -128
- 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 +139 -107
- 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 +173 -126
- package/dist/planmagnet/pages/TasksTaskDetailPagePage.js.map +1 -1
- package/dist/planmagnet/pages/TasksTasksPagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/TasksTasksPagePage.js +1 -0
- package/dist/planmagnet/pages/TasksTasksPagePage.js.map +1 -1
- package/dist/planmagnet/roadmaps/RoadmapControls.js +23 -23
- package/package.json +1 -1
|
@@ -1,18 +1,19 @@
|
|
|
1
1
|
import { usePlanMagnet as e } from "../providers/PlanMagnetProvider.js";
|
|
2
2
|
import { PersonName as t } from "../people/People.js";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
3
|
+
import { ReleaseHeaderActions as n } from "../controls/ReleaseControls.js";
|
|
4
|
+
import { ReleaseNotesCard as r } from "../releases/ReleaseNotesCard.js";
|
|
5
|
+
import { ReleaseGatesCard as i } from "../releases/ReleaseGatesCard.js";
|
|
6
|
+
import { ReleaseReadinessCard as a } from "../releases/ReleaseReadinessCard.js";
|
|
7
|
+
import { ReleaseWorkItemsCard as o } from "../releases/ReleaseWorkItemsCard.js";
|
|
8
|
+
import { Calendar as s, Clock as c, GitBranch as l, Loader2 as u } from "lucide-react";
|
|
9
|
+
import { useParams as d } from "react-router";
|
|
10
|
+
import { gql as f } from "@apollo/client";
|
|
11
|
+
import { useQuery as p } from "@apollo/client/react";
|
|
12
|
+
import { jsx as m, jsxs as h } from "react/jsx-runtime";
|
|
13
|
+
import { Badge as g, Card as _, CardContent as v, CardHeader as y, CardTitle as b } from "@burdenoff/fe-libs/ui";
|
|
14
|
+
import { Markdown as x } from "@burdenoff/fe-libs/shared/components";
|
|
14
15
|
//#region src/planmagnet/pages/ProductsReleaseDetailPagePage.tsx
|
|
15
|
-
var
|
|
16
|
+
var S = f`
|
|
16
17
|
query GetRelease($id: ID!) {
|
|
17
18
|
planmagnetRelease(id: $id) {
|
|
18
19
|
id
|
|
@@ -39,7 +40,7 @@ var x = d`
|
|
|
39
40
|
}
|
|
40
41
|
}
|
|
41
42
|
}
|
|
42
|
-
`,
|
|
43
|
+
`, C = {
|
|
43
44
|
DRAFT: "bg-gray-100 text-gray-800",
|
|
44
45
|
PLANNING: "bg-yellow-100 text-yellow-800",
|
|
45
46
|
IN_PROGRESS: "bg-blue-100 text-blue-800",
|
|
@@ -48,95 +49,95 @@ var x = d`
|
|
|
48
49
|
CANCELLED: "bg-red-100 text-red-800",
|
|
49
50
|
ROLLED_BACK: "bg-red-100 text-red-800"
|
|
50
51
|
};
|
|
51
|
-
function
|
|
52
|
-
let { workspaceId:
|
|
53
|
-
variables: { id:
|
|
54
|
-
skip: !
|
|
52
|
+
function w() {
|
|
53
|
+
let { workspaceId: f } = e(), w = d().id ?? "", { data: T, loading: E, error: D } = p(S, {
|
|
54
|
+
variables: { id: w },
|
|
55
|
+
skip: !w
|
|
55
56
|
});
|
|
56
|
-
if (
|
|
57
|
+
if (E && !T) return /* @__PURE__ */ m("div", {
|
|
57
58
|
className: "flex items-center justify-center p-12",
|
|
58
|
-
children: /* @__PURE__ */
|
|
59
|
+
children: /* @__PURE__ */ m(u, { className: "h-8 w-8 animate-spin text-muted-foreground" })
|
|
59
60
|
});
|
|
60
|
-
if (
|
|
61
|
+
if (D) return /* @__PURE__ */ h("div", {
|
|
61
62
|
className: "p-6 text-destructive",
|
|
62
|
-
children: ["Failed to load release: ",
|
|
63
|
+
children: ["Failed to load release: ", D.message]
|
|
63
64
|
});
|
|
64
|
-
let
|
|
65
|
-
if (!
|
|
65
|
+
let O = T?.planmagnetRelease;
|
|
66
|
+
if (!O) return /* @__PURE__ */ m("div", {
|
|
66
67
|
className: "p-6 text-muted-foreground",
|
|
67
68
|
children: "Release not found."
|
|
68
69
|
});
|
|
69
|
-
let
|
|
70
|
-
return /* @__PURE__ */
|
|
70
|
+
let k = O.workItems ?? [], A = k.filter((e) => e.type === "STORY" || e.type === "FEATURE"), j = k.filter((e) => e.type === "BUG");
|
|
71
|
+
return /* @__PURE__ */ h("div", {
|
|
71
72
|
className: "space-y-6 p-6",
|
|
72
|
-
children: [/* @__PURE__ */
|
|
73
|
+
children: [/* @__PURE__ */ h("div", {
|
|
73
74
|
className: "flex items-center justify-between",
|
|
74
|
-
children: [/* @__PURE__ */
|
|
75
|
+
children: [/* @__PURE__ */ h("div", { children: [/* @__PURE__ */ h("div", {
|
|
75
76
|
className: "flex items-center gap-2",
|
|
76
77
|
children: [
|
|
77
|
-
/* @__PURE__ */
|
|
78
|
-
/* @__PURE__ */
|
|
78
|
+
/* @__PURE__ */ m(l, { className: "h-5 w-5 text-primary" }),
|
|
79
|
+
/* @__PURE__ */ m("h1", {
|
|
79
80
|
className: "text-2xl font-semibold",
|
|
80
|
-
children:
|
|
81
|
+
children: O.version
|
|
81
82
|
}),
|
|
82
|
-
/* @__PURE__ */
|
|
83
|
-
className: `text-xs px-2 py-0.5 rounded-full capitalize ${
|
|
84
|
-
children:
|
|
83
|
+
/* @__PURE__ */ m("span", {
|
|
84
|
+
className: `text-xs px-2 py-0.5 rounded-full capitalize ${C[O.status] ?? "bg-gray-100"}`,
|
|
85
|
+
children: O.status.toLowerCase().replace("_", " ")
|
|
85
86
|
})
|
|
86
87
|
]
|
|
87
|
-
}), /* @__PURE__ */
|
|
88
|
+
}), /* @__PURE__ */ m("p", {
|
|
88
89
|
className: "text-sm text-muted-foreground mt-1",
|
|
89
|
-
children:
|
|
90
|
-
})] }), /* @__PURE__ */
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
90
|
+
children: O.name
|
|
91
|
+
})] }), /* @__PURE__ */ m(n, {
|
|
92
|
+
releaseId: O.id,
|
|
93
|
+
version: O.version,
|
|
94
|
+
status: O.status
|
|
94
95
|
})]
|
|
95
|
-
}), /* @__PURE__ */
|
|
96
|
+
}), /* @__PURE__ */ h("div", {
|
|
96
97
|
className: "grid grid-cols-1 lg:grid-cols-3 gap-6",
|
|
97
|
-
children: [/* @__PURE__ */
|
|
98
|
+
children: [/* @__PURE__ */ h("div", {
|
|
98
99
|
className: "lg:col-span-2 space-y-6",
|
|
99
100
|
children: [
|
|
100
|
-
/* @__PURE__ */
|
|
101
|
-
releaseId:
|
|
102
|
-
projectId:
|
|
103
|
-
releaseStatus:
|
|
104
|
-
plannedDate:
|
|
101
|
+
/* @__PURE__ */ m(a, {
|
|
102
|
+
releaseId: O.id,
|
|
103
|
+
projectId: O.projectId || null,
|
|
104
|
+
releaseStatus: O.status,
|
|
105
|
+
plannedDate: O.plannedDate ?? null
|
|
105
106
|
}),
|
|
106
|
-
/* @__PURE__ */
|
|
107
|
+
/* @__PURE__ */ h(_, { children: [/* @__PURE__ */ m(y, { children: /* @__PURE__ */ m(b, { children: "Overview" }) }), /* @__PURE__ */ h(v, {
|
|
107
108
|
className: "space-y-4",
|
|
108
|
-
children: [/* @__PURE__ */
|
|
109
|
+
children: [/* @__PURE__ */ m("div", {
|
|
109
110
|
className: "text-sm prose prose-sm dark:prose-invert max-w-none",
|
|
110
|
-
children:
|
|
111
|
-
}), /* @__PURE__ */
|
|
111
|
+
children: O.description ? /* @__PURE__ */ m(x, { children: O.description }) : /* @__PURE__ */ m("p", { children: "No description provided." })
|
|
112
|
+
}), /* @__PURE__ */ h("div", {
|
|
112
113
|
className: "grid grid-cols-3 gap-4",
|
|
113
114
|
children: [
|
|
114
|
-
/* @__PURE__ */
|
|
115
|
+
/* @__PURE__ */ h("div", {
|
|
115
116
|
className: "text-center p-3 bg-muted rounded-md",
|
|
116
|
-
children: [/* @__PURE__ */
|
|
117
|
+
children: [/* @__PURE__ */ m("p", {
|
|
117
118
|
className: "text-lg font-semibold mt-1",
|
|
118
|
-
children:
|
|
119
|
-
}), /* @__PURE__ */
|
|
119
|
+
children: A.length
|
|
120
|
+
}), /* @__PURE__ */ m("p", {
|
|
120
121
|
className: "text-xs text-muted-foreground",
|
|
121
122
|
children: "Features"
|
|
122
123
|
})]
|
|
123
124
|
}),
|
|
124
|
-
/* @__PURE__ */
|
|
125
|
+
/* @__PURE__ */ h("div", {
|
|
125
126
|
className: "text-center p-3 bg-muted rounded-md",
|
|
126
|
-
children: [/* @__PURE__ */
|
|
127
|
+
children: [/* @__PURE__ */ m("p", {
|
|
127
128
|
className: "text-lg font-semibold mt-1",
|
|
128
|
-
children:
|
|
129
|
-
}), /* @__PURE__ */
|
|
129
|
+
children: j.length
|
|
130
|
+
}), /* @__PURE__ */ m("p", {
|
|
130
131
|
className: "text-xs text-muted-foreground",
|
|
131
132
|
children: "Bug Fixes"
|
|
132
133
|
})]
|
|
133
134
|
}),
|
|
134
|
-
/* @__PURE__ */
|
|
135
|
+
/* @__PURE__ */ h("div", {
|
|
135
136
|
className: "text-center p-3 bg-muted rounded-md",
|
|
136
|
-
children: [/* @__PURE__ */
|
|
137
|
+
children: [/* @__PURE__ */ m("p", {
|
|
137
138
|
className: "text-lg font-semibold mt-1",
|
|
138
|
-
children:
|
|
139
|
-
}), /* @__PURE__ */
|
|
139
|
+
children: k.length
|
|
140
|
+
}), /* @__PURE__ */ m("p", {
|
|
140
141
|
className: "text-xs text-muted-foreground",
|
|
141
142
|
children: "Total Items"
|
|
142
143
|
})]
|
|
@@ -144,104 +145,104 @@ function C() {
|
|
|
144
145
|
]
|
|
145
146
|
})]
|
|
146
147
|
})] }),
|
|
147
|
-
/* @__PURE__ */
|
|
148
|
-
releaseId:
|
|
149
|
-
projectId:
|
|
150
|
-
releaseStatus:
|
|
148
|
+
/* @__PURE__ */ m(i, {
|
|
149
|
+
releaseId: O.id,
|
|
150
|
+
projectId: O.projectId ?? null,
|
|
151
|
+
releaseStatus: O.status
|
|
151
152
|
}),
|
|
152
|
-
/* @__PURE__ */
|
|
153
|
-
releaseId:
|
|
154
|
-
notes:
|
|
153
|
+
/* @__PURE__ */ m(r, {
|
|
154
|
+
releaseId: O.id,
|
|
155
|
+
notes: O.releaseNotes ?? null
|
|
155
156
|
}),
|
|
156
|
-
/* @__PURE__ */
|
|
157
|
-
releaseId:
|
|
158
|
-
projectId:
|
|
159
|
-
items:
|
|
157
|
+
/* @__PURE__ */ m(o, {
|
|
158
|
+
releaseId: O.id,
|
|
159
|
+
projectId: O.projectId || null,
|
|
160
|
+
items: k
|
|
160
161
|
})
|
|
161
162
|
]
|
|
162
|
-
}), /* @__PURE__ */
|
|
163
|
+
}), /* @__PURE__ */ h("div", {
|
|
163
164
|
className: "space-y-6",
|
|
164
165
|
children: [
|
|
165
|
-
/* @__PURE__ */
|
|
166
|
+
/* @__PURE__ */ h(_, { children: [/* @__PURE__ */ m(y, { children: /* @__PURE__ */ m(b, { children: "Timeline" }) }), /* @__PURE__ */ h(v, {
|
|
166
167
|
className: "space-y-3 text-sm",
|
|
167
|
-
children: [/* @__PURE__ */
|
|
168
|
+
children: [/* @__PURE__ */ h("div", {
|
|
168
169
|
className: "flex items-center gap-2",
|
|
169
170
|
children: [
|
|
170
|
-
/* @__PURE__ */
|
|
171
|
-
/* @__PURE__ */
|
|
171
|
+
/* @__PURE__ */ m(s, { className: "h-4 w-4 text-muted-foreground" }),
|
|
172
|
+
/* @__PURE__ */ m("span", {
|
|
172
173
|
className: "text-muted-foreground",
|
|
173
174
|
children: "Planned:"
|
|
174
175
|
}),
|
|
175
|
-
/* @__PURE__ */
|
|
176
|
+
/* @__PURE__ */ m("span", {
|
|
176
177
|
className: "font-medium",
|
|
177
|
-
children:
|
|
178
|
+
children: O.plannedDate ? new Date(O.plannedDate).toLocaleDateString() : "Not set"
|
|
178
179
|
})
|
|
179
180
|
]
|
|
180
|
-
}),
|
|
181
|
+
}), O.releasedAt && /* @__PURE__ */ h("div", {
|
|
181
182
|
className: "flex items-center gap-2",
|
|
182
183
|
children: [
|
|
183
|
-
/* @__PURE__ */
|
|
184
|
-
/* @__PURE__ */
|
|
184
|
+
/* @__PURE__ */ m(c, { className: "h-4 w-4 text-green-500" }),
|
|
185
|
+
/* @__PURE__ */ m("span", {
|
|
185
186
|
className: "text-muted-foreground",
|
|
186
187
|
children: "Released:"
|
|
187
188
|
}),
|
|
188
|
-
/* @__PURE__ */
|
|
189
|
+
/* @__PURE__ */ m("span", {
|
|
189
190
|
className: "font-medium",
|
|
190
|
-
children: new Date(
|
|
191
|
+
children: new Date(O.releasedAt).toLocaleDateString()
|
|
191
192
|
})
|
|
192
193
|
]
|
|
193
194
|
})]
|
|
194
195
|
})] }),
|
|
195
|
-
/* @__PURE__ */
|
|
196
|
+
/* @__PURE__ */ h(_, { children: [/* @__PURE__ */ m(y, { children: /* @__PURE__ */ m(b, { children: "Details" }) }), /* @__PURE__ */ h(v, {
|
|
196
197
|
className: "space-y-2 text-sm",
|
|
197
198
|
children: [
|
|
198
|
-
/* @__PURE__ */
|
|
199
|
+
/* @__PURE__ */ h("div", {
|
|
199
200
|
className: "flex justify-between",
|
|
200
|
-
children: [/* @__PURE__ */
|
|
201
|
+
children: [/* @__PURE__ */ m("span", {
|
|
201
202
|
className: "text-muted-foreground",
|
|
202
203
|
children: "Version"
|
|
203
|
-
}), /* @__PURE__ */
|
|
204
|
+
}), /* @__PURE__ */ m("span", {
|
|
204
205
|
className: "font-medium",
|
|
205
|
-
children:
|
|
206
|
+
children: O.version
|
|
206
207
|
})]
|
|
207
208
|
}),
|
|
208
|
-
/* @__PURE__ */
|
|
209
|
+
/* @__PURE__ */ h("div", {
|
|
209
210
|
className: "flex justify-between",
|
|
210
|
-
children: [/* @__PURE__ */
|
|
211
|
+
children: [/* @__PURE__ */ m("span", {
|
|
211
212
|
className: "text-muted-foreground",
|
|
212
213
|
children: "Status"
|
|
213
|
-
}), /* @__PURE__ */
|
|
214
|
+
}), /* @__PURE__ */ m(g, {
|
|
214
215
|
variant: "outline",
|
|
215
216
|
className: "text-xs capitalize",
|
|
216
|
-
children:
|
|
217
|
+
children: O.status.toLowerCase().replace("_", " ")
|
|
217
218
|
})]
|
|
218
219
|
}),
|
|
219
|
-
/* @__PURE__ */
|
|
220
|
+
/* @__PURE__ */ h("div", {
|
|
220
221
|
className: "flex justify-between",
|
|
221
|
-
children: [/* @__PURE__ */
|
|
222
|
+
children: [/* @__PURE__ */ m("span", {
|
|
222
223
|
className: "text-muted-foreground",
|
|
223
224
|
children: "Owner"
|
|
224
|
-
}), /* @__PURE__ */
|
|
225
|
+
}), /* @__PURE__ */ m("span", { children: /* @__PURE__ */ m(t, { id: O.ownerId }) })]
|
|
225
226
|
}),
|
|
226
|
-
/* @__PURE__ */
|
|
227
|
+
/* @__PURE__ */ h("div", {
|
|
227
228
|
className: "flex justify-between",
|
|
228
|
-
children: [/* @__PURE__ */
|
|
229
|
+
children: [/* @__PURE__ */ m("span", {
|
|
229
230
|
className: "text-muted-foreground",
|
|
230
231
|
children: "Created"
|
|
231
|
-
}), /* @__PURE__ */
|
|
232
|
+
}), /* @__PURE__ */ m("span", { children: new Date(O.createdAt).toLocaleDateString() })]
|
|
232
233
|
}),
|
|
233
|
-
/* @__PURE__ */
|
|
234
|
+
/* @__PURE__ */ h("div", {
|
|
234
235
|
className: "flex justify-between",
|
|
235
|
-
children: [/* @__PURE__ */
|
|
236
|
+
children: [/* @__PURE__ */ m("span", {
|
|
236
237
|
className: "text-muted-foreground",
|
|
237
238
|
children: "Updated"
|
|
238
|
-
}), /* @__PURE__ */
|
|
239
|
+
}), /* @__PURE__ */ m("span", { children: new Date(O.updatedAt).toLocaleDateString() })]
|
|
239
240
|
})
|
|
240
241
|
]
|
|
241
242
|
})] }),
|
|
242
|
-
|
|
243
|
+
O.tags?.length > 0 && /* @__PURE__ */ h(_, { children: [/* @__PURE__ */ m(y, { children: /* @__PURE__ */ m(b, { children: "Tags" }) }), /* @__PURE__ */ m(v, {
|
|
243
244
|
className: "flex flex-wrap gap-1",
|
|
244
|
-
children:
|
|
245
|
+
children: O.tags.map((e) => /* @__PURE__ */ m(g, {
|
|
245
246
|
variant: "outline",
|
|
246
247
|
className: "text-xs",
|
|
247
248
|
children: e
|
|
@@ -253,6 +254,6 @@ function C() {
|
|
|
253
254
|
});
|
|
254
255
|
}
|
|
255
256
|
//#endregion
|
|
256
|
-
export {
|
|
257
|
+
export { w as ProductsReleaseDetailPagePage };
|
|
257
258
|
|
|
258
259
|
//# sourceMappingURL=ProductsReleaseDetailPagePage.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ProductsReleaseDetailPagePage.js","names":[],"sources":["../../../src/planmagnet/pages/ProductsReleaseDetailPagePage.tsx"],"sourcesContent":["// eslint-disable-next-line @typescript-eslint/ban-ts-comment\n// @ts-nocheck\nimport { gql } from '@apollo/client';\nimport { useQuery } from '@apollo/client/react';\nimport { Card, CardContent, CardHeader, CardTitle, Badge } from '@burdenoff/fe-libs/ui';\nimport { Markdown } from '@burdenoff/fe-libs/shared/components';\nimport { GitBranch, Calendar, Clock, Server, Loader2 } from 'lucide-react';\nimport { usePlanMagnet } from '../providers/PlanMagnetProvider';\nimport { useParams } from 'react-router';\nimport { PersonName } from '../people/People';\nimport { ReleaseNotesCard } from '../releases/ReleaseNotesCard';\nimport { ReleaseGatesCard } from '../releases/ReleaseGatesCard';\nimport { ReleaseReadinessCard } from '../releases/ReleaseReadinessCard';\nimport { ReleaseWorkItemsCard } from '../releases/ReleaseWorkItemsCard';\n\nconst GET_RELEASE = gql`\n query GetRelease($id: ID!) {\n planmagnetRelease(id: $id) {\n id\n workspaceId\n projectId\n name\n description\n version\n status\n plannedDate\n releasedAt\n releaseNotes\n ownerId\n tags\n metadata\n createdAt\n updatedAt\n workItems {\n id\n title\n status\n type\n priority\n }\n }\n }\n`;\n\ninterface WorkItemSummary {\n id: string;\n title: string;\n status: string;\n type: string;\n priority: string;\n}\n\nconst statusColor: Record<string, string> = {\n DRAFT: 'bg-gray-100 text-gray-800',\n PLANNING: 'bg-yellow-100 text-yellow-800',\n IN_PROGRESS: 'bg-blue-100 text-blue-800',\n READY: 'bg-orange-100 text-orange-800',\n RELEASED: 'bg-green-100 text-green-800',\n CANCELLED: 'bg-red-100 text-red-800',\n ROLLED_BACK: 'bg-red-100 text-red-800',\n};\n\nexport function ProductsReleaseDetailPagePage() {\n const { workspaceId } = usePlanMagnet();\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 // 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 release: {error.message}</div>;\n }\n\n const release = data?.planmagnetRelease;\n if (!release) return <div className=\"p-6 text-muted-foreground\">Release not found.</div>;\n\n const workItems: WorkItemSummary[] = release.workItems ?? [];\n const featureItems = workItems.filter((w) => w.type === 'STORY' || w.type === 'FEATURE');\n const bugItems = workItems.filter((w) => w.type === 'BUG');\n\n return (\n <div className=\"space-y-6 p-6\">\n <div className=\"flex items-center justify-between\">\n <div>\n <div className=\"flex items-center gap-2\">\n <GitBranch className=\"h-5 w-5 text-primary\" />\n <h1 className=\"text-2xl font-semibold\">{release.version}</h1>\n <span\n className={`text-xs px-2 py-0.5 rounded-full capitalize ${statusColor[release.status] ?? 'bg-gray-100'}`}\n >\n {release.status.toLowerCase().replace('_', ' ')}\n </span>\n </div>\n <p className=\"text-sm text-muted-foreground mt-1\">{release.name}</p>\n </div>\n <Badge variant=\"outline\" className=\"capitalize\">\n {release.status.toLowerCase().replace('_', ' ')}\n </Badge>\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 <ReleaseReadinessCard\n releaseId={release.id}\n projectId={release.projectId || null}\n releaseStatus={release.status}\n plannedDate={release.plannedDate ?? null}\n />\n <Card>\n <CardHeader>\n <CardTitle>Overview</CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-4\">\n <div className=\"text-sm prose prose-sm dark:prose-invert max-w-none\">\n {release.description ? (\n <Markdown>{release.description}</Markdown>\n ) : (\n <p>No description provided.</p>\n )}\n </div>\n <div className=\"grid grid-cols-3 gap-4\">\n <div className=\"text-center p-3 bg-muted rounded-md\">\n <p className=\"text-lg font-semibold mt-1\">{featureItems.length}</p>\n <p className=\"text-xs text-muted-foreground\">Features</p>\n </div>\n <div className=\"text-center p-3 bg-muted rounded-md\">\n <p className=\"text-lg font-semibold mt-1\">{bugItems.length}</p>\n <p className=\"text-xs text-muted-foreground\">Bug Fixes</p>\n </div>\n <div className=\"text-center p-3 bg-muted rounded-md\">\n <p className=\"text-lg font-semibold mt-1\">{workItems.length}</p>\n <p className=\"text-xs text-muted-foreground\">Total Items</p>\n </div>\n </div>\n </CardContent>\n </Card>\n\n <ReleaseGatesCard\n releaseId={release.id}\n projectId={release.projectId ?? null}\n releaseStatus={release.status}\n />\n <ReleaseNotesCard releaseId={release.id} notes={release.releaseNotes ?? null} />\n\n <ReleaseWorkItemsCard\n releaseId={release.id}\n projectId={release.projectId || null}\n items={workItems}\n />\n </div>\n\n <div className=\"space-y-6\">\n <Card>\n <CardHeader>\n <CardTitle>Timeline</CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-3 text-sm\">\n <div className=\"flex items-center gap-2\">\n <Calendar className=\"h-4 w-4 text-muted-foreground\" />\n <span className=\"text-muted-foreground\">Planned:</span>\n <span className=\"font-medium\">\n {release.plannedDate\n ? new Date(release.plannedDate).toLocaleDateString()\n : 'Not set'}\n </span>\n </div>\n {release.releasedAt && (\n <div className=\"flex items-center gap-2\">\n <Clock className=\"h-4 w-4 text-green-500\" />\n <span className=\"text-muted-foreground\">Released:</span>\n <span className=\"font-medium\">\n {new Date(release.releasedAt).toLocaleDateString()}\n </span>\n </div>\n )}\n </CardContent>\n </Card>\n\n <Card>\n <CardHeader>\n <CardTitle>Details</CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-2 text-sm\">\n <div className=\"flex justify-between\">\n <span className=\"text-muted-foreground\">Version</span>\n <span className=\"font-medium\">{release.version}</span>\n </div>\n <div className=\"flex justify-between\">\n <span className=\"text-muted-foreground\">Status</span>\n <Badge variant=\"outline\" className=\"text-xs capitalize\">\n {release.status.toLowerCase().replace('_', ' ')}\n </Badge>\n </div>\n <div className=\"flex justify-between\">\n <span className=\"text-muted-foreground\">Owner</span>\n <span>\n <PersonName id={release.ownerId} />\n </span>\n </div>\n <div className=\"flex justify-between\">\n <span className=\"text-muted-foreground\">Created</span>\n <span>{new Date(release.createdAt).toLocaleDateString()}</span>\n </div>\n <div className=\"flex justify-between\">\n <span className=\"text-muted-foreground\">Updated</span>\n <span>{new Date(release.updatedAt).toLocaleDateString()}</span>\n </div>\n </CardContent>\n </Card>\n\n {release.tags?.length > 0 && (\n <Card>\n <CardHeader>\n <CardTitle>Tags</CardTitle>\n </CardHeader>\n <CardContent className=\"flex flex-wrap gap-1\">\n {release.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":"ProductsReleaseDetailPagePage.js","names":[],"sources":["../../../src/planmagnet/pages/ProductsReleaseDetailPagePage.tsx"],"sourcesContent":["// eslint-disable-next-line @typescript-eslint/ban-ts-comment\n// @ts-nocheck\nimport { gql } from '@apollo/client';\nimport { useQuery } from '@apollo/client/react';\nimport { Card, CardContent, CardHeader, CardTitle, Badge } from '@burdenoff/fe-libs/ui';\nimport { Markdown } from '@burdenoff/fe-libs/shared/components';\nimport { GitBranch, Calendar, Clock, Server, Loader2 } from 'lucide-react';\nimport { usePlanMagnet } from '../providers/PlanMagnetProvider';\nimport { useParams } from 'react-router';\nimport { PersonName } from '../people/People';\nimport { ReleaseNotesCard } from '../releases/ReleaseNotesCard';\nimport { ReleaseHeaderActions } from '../controls/ReleaseControls';\nimport { ReleaseGatesCard } from '../releases/ReleaseGatesCard';\nimport { ReleaseReadinessCard } from '../releases/ReleaseReadinessCard';\nimport { ReleaseWorkItemsCard } from '../releases/ReleaseWorkItemsCard';\n\nconst GET_RELEASE = gql`\n query GetRelease($id: ID!) {\n planmagnetRelease(id: $id) {\n id\n workspaceId\n projectId\n name\n description\n version\n status\n plannedDate\n releasedAt\n releaseNotes\n ownerId\n tags\n metadata\n createdAt\n updatedAt\n workItems {\n id\n title\n status\n type\n priority\n }\n }\n }\n`;\n\ninterface WorkItemSummary {\n id: string;\n title: string;\n status: string;\n type: string;\n priority: string;\n}\n\nconst statusColor: Record<string, string> = {\n DRAFT: 'bg-gray-100 text-gray-800',\n PLANNING: 'bg-yellow-100 text-yellow-800',\n IN_PROGRESS: 'bg-blue-100 text-blue-800',\n READY: 'bg-orange-100 text-orange-800',\n RELEASED: 'bg-green-100 text-green-800',\n CANCELLED: 'bg-red-100 text-red-800',\n ROLLED_BACK: 'bg-red-100 text-red-800',\n};\n\nexport function ProductsReleaseDetailPagePage() {\n const { workspaceId } = usePlanMagnet();\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 // 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 release: {error.message}</div>;\n }\n\n const release = data?.planmagnetRelease;\n if (!release) return <div className=\"p-6 text-muted-foreground\">Release not found.</div>;\n\n const workItems: WorkItemSummary[] = release.workItems ?? [];\n const featureItems = workItems.filter((w) => w.type === 'STORY' || w.type === 'FEATURE');\n const bugItems = workItems.filter((w) => w.type === 'BUG');\n\n return (\n <div className=\"space-y-6 p-6\">\n <div className=\"flex items-center justify-between\">\n <div>\n <div className=\"flex items-center gap-2\">\n <GitBranch className=\"h-5 w-5 text-primary\" />\n <h1 className=\"text-2xl font-semibold\">{release.version}</h1>\n <span\n className={`text-xs px-2 py-0.5 rounded-full capitalize ${statusColor[release.status] ?? 'bg-gray-100'}`}\n >\n {release.status.toLowerCase().replace('_', ' ')}\n </span>\n </div>\n <p className=\"text-sm text-muted-foreground mt-1\">{release.name}</p>\n </div>\n {/* Status, Edit and Delete (BOFF-7952): nothing could release, edit or delete a release. */}\n <ReleaseHeaderActions\n releaseId={release.id}\n version={release.version}\n status={release.status}\n />\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 <ReleaseReadinessCard\n releaseId={release.id}\n projectId={release.projectId || null}\n releaseStatus={release.status}\n plannedDate={release.plannedDate ?? null}\n />\n <Card>\n <CardHeader>\n <CardTitle>Overview</CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-4\">\n <div className=\"text-sm prose prose-sm dark:prose-invert max-w-none\">\n {release.description ? (\n <Markdown>{release.description}</Markdown>\n ) : (\n <p>No description provided.</p>\n )}\n </div>\n <div className=\"grid grid-cols-3 gap-4\">\n <div className=\"text-center p-3 bg-muted rounded-md\">\n <p className=\"text-lg font-semibold mt-1\">{featureItems.length}</p>\n <p className=\"text-xs text-muted-foreground\">Features</p>\n </div>\n <div className=\"text-center p-3 bg-muted rounded-md\">\n <p className=\"text-lg font-semibold mt-1\">{bugItems.length}</p>\n <p className=\"text-xs text-muted-foreground\">Bug Fixes</p>\n </div>\n <div className=\"text-center p-3 bg-muted rounded-md\">\n <p className=\"text-lg font-semibold mt-1\">{workItems.length}</p>\n <p className=\"text-xs text-muted-foreground\">Total Items</p>\n </div>\n </div>\n </CardContent>\n </Card>\n\n <ReleaseGatesCard\n releaseId={release.id}\n projectId={release.projectId ?? null}\n releaseStatus={release.status}\n />\n <ReleaseNotesCard releaseId={release.id} notes={release.releaseNotes ?? null} />\n\n <ReleaseWorkItemsCard\n releaseId={release.id}\n projectId={release.projectId || null}\n items={workItems}\n />\n </div>\n\n <div className=\"space-y-6\">\n <Card>\n <CardHeader>\n <CardTitle>Timeline</CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-3 text-sm\">\n <div className=\"flex items-center gap-2\">\n <Calendar className=\"h-4 w-4 text-muted-foreground\" />\n <span className=\"text-muted-foreground\">Planned:</span>\n <span className=\"font-medium\">\n {release.plannedDate\n ? new Date(release.plannedDate).toLocaleDateString()\n : 'Not set'}\n </span>\n </div>\n {release.releasedAt && (\n <div className=\"flex items-center gap-2\">\n <Clock className=\"h-4 w-4 text-green-500\" />\n <span className=\"text-muted-foreground\">Released:</span>\n <span className=\"font-medium\">\n {new Date(release.releasedAt).toLocaleDateString()}\n </span>\n </div>\n )}\n </CardContent>\n </Card>\n\n <Card>\n <CardHeader>\n <CardTitle>Details</CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-2 text-sm\">\n <div className=\"flex justify-between\">\n <span className=\"text-muted-foreground\">Version</span>\n <span className=\"font-medium\">{release.version}</span>\n </div>\n <div className=\"flex justify-between\">\n <span className=\"text-muted-foreground\">Status</span>\n <Badge variant=\"outline\" className=\"text-xs capitalize\">\n {release.status.toLowerCase().replace('_', ' ')}\n </Badge>\n </div>\n <div className=\"flex justify-between\">\n <span className=\"text-muted-foreground\">Owner</span>\n <span>\n <PersonName id={release.ownerId} />\n </span>\n </div>\n <div className=\"flex justify-between\">\n <span className=\"text-muted-foreground\">Created</span>\n <span>{new Date(release.createdAt).toLocaleDateString()}</span>\n </div>\n <div className=\"flex justify-between\">\n <span className=\"text-muted-foreground\">Updated</span>\n <span>{new Date(release.updatedAt).toLocaleDateString()}</span>\n </div>\n </CardContent>\n </Card>\n\n {release.tags?.length > 0 && (\n <Card>\n <CardHeader>\n <CardTitle>Tags</CardTitle>\n </CardHeader>\n <CardContent className=\"flex flex-wrap gap-1\">\n {release.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":"ProductsReleasesPagePage.d.ts","sourceRoot":"","sources":["../../../src/planmagnet/pages/ProductsReleasesPagePage.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ProductsReleasesPagePage.d.ts","sourceRoot":"","sources":["../../../src/planmagnet/pages/ProductsReleasesPagePage.tsx"],"names":[],"mappings":"AA6EA,wBAAgB,wBAAwB,4CAiIvC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ProductsReleasesPagePage.js","names":[],"sources":["../../../src/planmagnet/pages/ProductsReleasesPagePage.tsx"],"sourcesContent":["// eslint-disable-next-line @typescript-eslint/ban-ts-comment\n// @ts-nocheck\nimport { useState } from 'react';\nimport { gql } from '@apollo/client';\nimport { useQuery } from '@apollo/client/react';\nimport { Card, CardContent, CardHeader, CardTitle, Badge, Button } from '@burdenoff/fe-libs/ui';\nimport { Calendar, Package, Loader2 } from 'lucide-react';\nimport { usePlanMagnet, usePlanMagnetNavigate } from '../providers/PlanMagnetProvider';\nimport { rowLinkProps, detailPath } from '../utils/rowNavigation';\nimport { PersonName } from '../people/People';\nimport { NewReleaseDialog } from '../create/CreateDialogs';\n\nconst LIST_RELEASES = gql`\n query ListReleases(\n $workspaceId: ID!\n $filter: PlanmagnetReleaseFilter\n $pagination: PlanmagnetPaginationInput\n ) {\n planmagnetReleases(workspaceId: $workspaceId, filter: $filter, pagination: $pagination) {\n items {\n id\n workspaceId\n projectId\n name\n description\n version\n status\n plannedDate\n releasedAt\n releaseNotes\n ownerId\n tags\n createdAt\n updatedAt\n }\n totalCount\n }\n }\n`;\n\ninterface ReleaseNode {\n id: string;\n name: string;\n description: string | null;\n version: string;\n status: string;\n plannedDate: string | null;\n releasedAt: string | null;\n releaseNotes: string | null;\n ownerId: string;\n tags: string[];\n createdAt: string;\n updatedAt: string;\n}\n\nconst statusTabs = [\n 'all',\n 'DRAFT',\n 'PLANNING',\n 'IN_PROGRESS',\n 'READY',\n 'RELEASED',\n 'CANCELLED',\n] as const;\nconst statusColor: Record<string, string> = {\n DRAFT: 'bg-gray-100 text-gray-800',\n PLANNING: 'bg-yellow-100 text-yellow-800',\n IN_PROGRESS: 'bg-blue-100 text-blue-800',\n READY: 'bg-orange-100 text-orange-800',\n RELEASED: 'bg-green-100 text-green-800',\n CANCELLED: 'bg-red-100 text-red-800',\n ROLLED_BACK: 'bg-red-100 text-red-800',\n};\n\nexport function ProductsReleasesPagePage() {\n const { workspaceId } = usePlanMagnet();\n const navigate = usePlanMagnetNavigate();\n const [activeTab, setActiveTab] = useState<string>('all');\n\n const {\n data,\n loading,\n error,\n } = // eslint-disable-next-line @typescript-eslint/no-explicit-any\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n useQuery<Record<string, any>>(LIST_RELEASES, {\n variables: {\n workspaceId,\n filter: activeTab !== 'all' ? { status: activeTab } : undefined,\n pagination: { first: 50 },\n },\n skip: !workspaceId,\n });\n\n // Only before the first load: a refetch after a create must not blank the page.\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 releases: {error.message}</div>;\n }\n\n const releases: ReleaseNode[] = data?.planmagnetReleases?.items ?? [];\n const totalCount = data?.planmagnetReleases?.totalCount ?? 0;\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\">Releases</h1>\n <p className=\"text-sm text-muted-foreground\">{totalCount} releases across all products</p>\n </div>\n <NewReleaseDialog\n onCreated={(id) => navigate(detailPath('/products/release-detail-page', id))}\n />\n </div>\n\n <div className=\"flex gap-1 border-b pb-1\">\n {statusTabs.map((tab) => (\n <button\n key={tab}\n onClick={() => setActiveTab(tab)}\n className={`px-3 py-1.5 text-sm rounded-md capitalize ${activeTab === tab ? 'bg-primary text-primary-foreground' : 'text-muted-foreground hover:bg-muted'}`}\n >\n {tab === 'all' ? 'All' : tab.toLowerCase().replace('_', ' ')}\n </button>\n ))}\n </div>\n\n <div className=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\n {releases.map((release) => (\n <Card\n key={release.id}\n {...rowLinkProps(\n () => navigate(detailPath('/products/release-detail-page', release.id)),\n release.name\n )}\n >\n <CardHeader className=\"pb-2\">\n <div className=\"flex items-center justify-between\">\n <div className=\"flex items-center gap-2\">\n <span className=\"text-lg font-semibold\">{release.version}</span>\n </div>\n <span\n className={`text-xs px-2 py-0.5 rounded-full capitalize ${statusColor[release.status] ?? 'bg-gray-100'}`}\n >\n {release.status.toLowerCase().replace('_', ' ')}\n </span>\n </div>\n <CardTitle className=\"text-sm font-medium\">{release.name}</CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n <p className=\"text-sm text-muted-foreground\">\n {release.description ?? 'No description'}\n </p>\n\n <div className=\"flex items-center gap-4 text-sm\">\n <div className=\"flex items-center gap-1 text-muted-foreground\">\n <Package className=\"h-3.5 w-3.5\" />\n Owner: <PersonName id={release.ownerId} />\n </div>\n <div className=\"flex items-center gap-1 text-muted-foreground\">\n <Calendar className=\"h-3.5 w-3.5\" />\n {release.plannedDate\n ? new Date(release.plannedDate).toLocaleDateString()\n : 'No date'}\n </div>\n </div>\n\n {release.tags.length > 0 && (\n <div className=\"flex gap-1 flex-wrap\">\n {release.tags.map((tag) => (\n <Badge key={tag} variant=\"outline\" className=\"text-xs\">\n {tag}\n </Badge>\n ))}\n </div>\n )}\n\n {release.releaseNotes && (\n <div className=\"border-t pt-2\">\n <p className=\"text-xs font-medium text-muted-foreground mb-1\">\n Release Notes Preview\n </p>\n <p className=\"text-xs text-muted-foreground line-clamp-3\">\n {release.releaseNotes}\n </p>\n </div>\n )}\n </CardContent>\n </Card>\n ))}\n </div>\n {releases.length === 0 && (\n <p className=\"text-center text-muted-foreground py-8\">No releases match this filter.</p>\n )}\n </div>\n );\n}\n"],"mappings":";;;;;;;;;;;AAYA,IAAM,IAAgB,CAAG;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"ProductsReleasesPagePage.js","names":[],"sources":["../../../src/planmagnet/pages/ProductsReleasesPagePage.tsx"],"sourcesContent":["// eslint-disable-next-line @typescript-eslint/ban-ts-comment\n// @ts-nocheck\nimport { useState } from 'react';\nimport { gql } from '@apollo/client';\nimport { useQuery } from '@apollo/client/react';\nimport { Card, CardContent, CardHeader, CardTitle, Badge, Button } from '@burdenoff/fe-libs/ui';\nimport { Calendar, Package, Loader2 } from 'lucide-react';\nimport { usePlanMagnet, usePlanMagnetNavigate } from '../providers/PlanMagnetProvider';\nimport { rowLinkProps, detailPath } from '../utils/rowNavigation';\nimport { PersonName } from '../people/People';\nimport { NewReleaseDialog } from '../create/CreateDialogs';\n\nconst LIST_RELEASES = gql`\n query ListReleases(\n $workspaceId: ID!\n $filter: PlanmagnetReleaseFilter\n $pagination: PlanmagnetPaginationInput\n ) {\n planmagnetReleases(workspaceId: $workspaceId, filter: $filter, pagination: $pagination) {\n items {\n id\n workspaceId\n projectId\n name\n description\n version\n status\n plannedDate\n releasedAt\n releaseNotes\n ownerId\n tags\n createdAt\n updatedAt\n }\n totalCount\n }\n }\n`;\n\ninterface ReleaseNode {\n id: string;\n name: string;\n description: string | null;\n version: string;\n status: string;\n plannedDate: string | null;\n releasedAt: string | null;\n releaseNotes: string | null;\n ownerId: string;\n tags: string[];\n createdAt: string;\n updatedAt: string;\n}\n\n// Every ReleaseStatus: STAGING and ROLLED_BACK had no tab (BOFF-7985).\nconst statusTabs = [\n 'all',\n 'DRAFT',\n 'PLANNING',\n 'IN_PROGRESS',\n 'READY',\n 'STAGING',\n 'RELEASED',\n 'ROLLED_BACK',\n 'CANCELLED',\n] as const;\nconst statusColor: Record<string, string> = {\n DRAFT: 'bg-gray-100 text-gray-800',\n PLANNING: 'bg-yellow-100 text-yellow-800',\n IN_PROGRESS: 'bg-blue-100 text-blue-800',\n READY: 'bg-orange-100 text-orange-800',\n RELEASED: 'bg-green-100 text-green-800',\n CANCELLED: 'bg-red-100 text-red-800',\n ROLLED_BACK: 'bg-red-100 text-red-800',\n};\n\nexport function ProductsReleasesPagePage() {\n const { workspaceId } = usePlanMagnet();\n const navigate = usePlanMagnetNavigate();\n const [activeTab, setActiveTab] = useState<string>('all');\n\n const {\n data,\n loading,\n error,\n } = // eslint-disable-next-line @typescript-eslint/no-explicit-any\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n useQuery<Record<string, any>>(LIST_RELEASES, {\n variables: {\n workspaceId,\n filter: activeTab !== 'all' ? { status: activeTab } : undefined,\n pagination: { first: 50 },\n },\n skip: !workspaceId,\n });\n\n // Only before the first load: a refetch after a create must not blank the page.\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 releases: {error.message}</div>;\n }\n\n const releases: ReleaseNode[] = data?.planmagnetReleases?.items ?? [];\n const totalCount = data?.planmagnetReleases?.totalCount ?? 0;\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\">Releases</h1>\n <p className=\"text-sm text-muted-foreground\">{totalCount} releases across all products</p>\n </div>\n <NewReleaseDialog\n onCreated={(id) => navigate(detailPath('/products/release-detail-page', id))}\n />\n </div>\n\n <div className=\"flex gap-1 border-b pb-1\">\n {statusTabs.map((tab) => (\n <button\n key={tab}\n onClick={() => setActiveTab(tab)}\n className={`px-3 py-1.5 text-sm rounded-md capitalize ${activeTab === tab ? 'bg-primary text-primary-foreground' : 'text-muted-foreground hover:bg-muted'}`}\n >\n {tab === 'all' ? 'All' : tab.toLowerCase().replace('_', ' ')}\n </button>\n ))}\n </div>\n\n <div className=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\n {releases.map((release) => (\n <Card\n key={release.id}\n {...rowLinkProps(\n () => navigate(detailPath('/products/release-detail-page', release.id)),\n release.name\n )}\n >\n <CardHeader className=\"pb-2\">\n <div className=\"flex items-center justify-between\">\n <div className=\"flex items-center gap-2\">\n <span className=\"text-lg font-semibold\">{release.version}</span>\n </div>\n <span\n className={`text-xs px-2 py-0.5 rounded-full capitalize ${statusColor[release.status] ?? 'bg-gray-100'}`}\n >\n {release.status.toLowerCase().replace('_', ' ')}\n </span>\n </div>\n <CardTitle className=\"text-sm font-medium\">{release.name}</CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n <p className=\"text-sm text-muted-foreground\">\n {release.description ?? 'No description'}\n </p>\n\n <div className=\"flex items-center gap-4 text-sm\">\n <div className=\"flex items-center gap-1 text-muted-foreground\">\n <Package className=\"h-3.5 w-3.5\" />\n Owner: <PersonName id={release.ownerId} />\n </div>\n <div className=\"flex items-center gap-1 text-muted-foreground\">\n <Calendar className=\"h-3.5 w-3.5\" />\n {release.plannedDate\n ? new Date(release.plannedDate).toLocaleDateString()\n : 'No date'}\n </div>\n </div>\n\n {release.tags.length > 0 && (\n <div className=\"flex gap-1 flex-wrap\">\n {release.tags.map((tag) => (\n <Badge key={tag} variant=\"outline\" className=\"text-xs\">\n {tag}\n </Badge>\n ))}\n </div>\n )}\n\n {release.releaseNotes && (\n <div className=\"border-t pt-2\">\n <p className=\"text-xs font-medium text-muted-foreground mb-1\">\n Release Notes Preview\n </p>\n <p className=\"text-xs text-muted-foreground line-clamp-3\">\n {release.releaseNotes}\n </p>\n </div>\n )}\n </CardContent>\n </Card>\n ))}\n </div>\n {releases.length === 0 && (\n <p className=\"text-center text-muted-foreground py-8\">No releases match this filter.</p>\n )}\n </div>\n );\n}\n"],"mappings":"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"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { usePlanMagnetNavigate as e } from "../providers/PlanMagnetProvider.js";
|
|
2
2
|
import { throwOnError as t } from "../utils/mutationResult.js";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
3
|
+
import { endBeforeStart as n } from "../utils/formValidation.js";
|
|
4
|
+
import { enumLabel as r } from "../controls/WorkItemControls.js";
|
|
5
|
+
import { detailPath as i } from "../utils/rowNavigation.js";
|
|
6
6
|
import { useEntityId as a } from "../hooks/useEntityId.js";
|
|
7
7
|
import { PROJECT_STATUSES as o } from "../controls/ProjectControls.js";
|
|
8
8
|
import { useMemo as s, useState as c } from "react";
|
|
@@ -64,7 +64,7 @@ function w() {
|
|
|
64
64
|
"GetProjectsForEdit",
|
|
65
65
|
"GetProjectDetail",
|
|
66
66
|
"AdminPlanmagnetProjects"
|
|
67
|
-
] }), [R, z] = c(null), B =
|
|
67
|
+
] }), [R, z] = c(null), B = n(P.startDate, P.endDate);
|
|
68
68
|
return d ? E && !T ? /* @__PURE__ */ m("div", {
|
|
69
69
|
className: "flex items-center justify-center p-12",
|
|
70
70
|
children: /* @__PURE__ */ m("div", { className: "animate-spin h-8 w-8 border-2 border-primary border-t-transparent rounded-full" })
|
|
@@ -82,7 +82,7 @@ function w() {
|
|
|
82
82
|
variant: "ghost",
|
|
83
83
|
size: "sm",
|
|
84
84
|
"aria-label": "Back to the project",
|
|
85
|
-
onClick: () => w(
|
|
85
|
+
onClick: () => w(i("/projects/project-detail-page", d)),
|
|
86
86
|
children: /* @__PURE__ */ m(l, { className: "h-4 w-4" })
|
|
87
87
|
}), /* @__PURE__ */ h("div", { children: [/* @__PURE__ */ m("h1", {
|
|
88
88
|
className: "text-2xl font-semibold",
|
|
@@ -190,7 +190,7 @@ function w() {
|
|
|
190
190
|
}),
|
|
191
191
|
children: (o.includes(P.status) ? o : [P.status, ...o]).map((e) => /* @__PURE__ */ m("option", {
|
|
192
192
|
value: e,
|
|
193
|
-
children:
|
|
193
|
+
children: r(e)
|
|
194
194
|
}, e))
|
|
195
195
|
})] }),
|
|
196
196
|
/* @__PURE__ */ h("div", {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ProjectsMilestoneDetailPagePage.d.ts","sourceRoot":"","sources":["../../../src/planmagnet/pages/ProjectsMilestoneDetailPagePage.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ProjectsMilestoneDetailPagePage.d.ts","sourceRoot":"","sources":["../../../src/planmagnet/pages/ProjectsMilestoneDetailPagePage.tsx"],"names":[],"mappings":"AAgCA,wBAAgB,+BAA+B,4CA+I9C"}
|