@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.
Files changed (66) hide show
  1. package/dist/planmagnet/controls/FeatureControls.d.ts +26 -0
  2. package/dist/planmagnet/controls/FeatureControls.d.ts.map +1 -0
  3. package/dist/planmagnet/controls/FeatureControls.js +318 -0
  4. package/dist/planmagnet/controls/FeatureControls.js.map +1 -0
  5. package/dist/planmagnet/controls/MilestoneControls.d.ts +17 -0
  6. package/dist/planmagnet/controls/MilestoneControls.d.ts.map +1 -0
  7. package/dist/planmagnet/controls/MilestoneControls.js +200 -0
  8. package/dist/planmagnet/controls/MilestoneControls.js.map +1 -0
  9. package/dist/planmagnet/controls/ObjectiveControls.d.ts +31 -0
  10. package/dist/planmagnet/controls/ObjectiveControls.d.ts.map +1 -0
  11. package/dist/planmagnet/controls/ObjectiveControls.js +296 -0
  12. package/dist/planmagnet/controls/ObjectiveControls.js.map +1 -0
  13. package/dist/planmagnet/controls/Pickers.d.ts +26 -0
  14. package/dist/planmagnet/controls/Pickers.d.ts.map +1 -0
  15. package/dist/planmagnet/controls/Pickers.js +171 -0
  16. package/dist/planmagnet/controls/Pickers.js.map +1 -0
  17. package/dist/planmagnet/controls/ProjectControls.js +7 -7
  18. package/dist/planmagnet/controls/ReleaseControls.d.ts +14 -0
  19. package/dist/planmagnet/controls/ReleaseControls.d.ts.map +1 -0
  20. package/dist/planmagnet/controls/ReleaseControls.js +108 -0
  21. package/dist/planmagnet/controls/ReleaseControls.js.map +1 -0
  22. package/dist/planmagnet/pages/DocsDocDetailPagePage.d.ts.map +1 -1
  23. package/dist/planmagnet/pages/DocsDocDetailPagePage.js +186 -152
  24. package/dist/planmagnet/pages/DocsDocDetailPagePage.js.map +1 -1
  25. package/dist/planmagnet/pages/GoalsCreateObjectivePagePage.d.ts.map +1 -1
  26. package/dist/planmagnet/pages/GoalsCreateObjectivePagePage.js +63 -56
  27. package/dist/planmagnet/pages/GoalsCreateObjectivePagePage.js.map +1 -1
  28. package/dist/planmagnet/pages/GoalsObjectiveDetailPagePage.d.ts.map +1 -1
  29. package/dist/planmagnet/pages/GoalsObjectiveDetailPagePage.js +229 -214
  30. package/dist/planmagnet/pages/GoalsObjectiveDetailPagePage.js.map +1 -1
  31. package/dist/planmagnet/pages/ProductsEditProductPagePage.d.ts.map +1 -1
  32. package/dist/planmagnet/pages/ProductsEditProductPagePage.js +142 -114
  33. package/dist/planmagnet/pages/ProductsEditProductPagePage.js.map +1 -1
  34. package/dist/planmagnet/pages/ProductsEditReleasePagePage.d.ts.map +1 -1
  35. package/dist/planmagnet/pages/ProductsEditReleasePagePage.js +134 -105
  36. package/dist/planmagnet/pages/ProductsEditReleasePagePage.js.map +1 -1
  37. package/dist/planmagnet/pages/ProductsFeatureDetailPagePage.d.ts.map +1 -1
  38. package/dist/planmagnet/pages/ProductsFeatureDetailPagePage.js +102 -108
  39. package/dist/planmagnet/pages/ProductsFeatureDetailPagePage.js.map +1 -1
  40. package/dist/planmagnet/pages/ProductsNewFeaturePagePage.d.ts.map +1 -1
  41. package/dist/planmagnet/pages/ProductsNewFeaturePagePage.js +119 -94
  42. package/dist/planmagnet/pages/ProductsNewFeaturePagePage.js.map +1 -1
  43. package/dist/planmagnet/pages/ProductsReleaseDetailPagePage.d.ts.map +1 -1
  44. package/dist/planmagnet/pages/ProductsReleaseDetailPagePage.js +107 -106
  45. package/dist/planmagnet/pages/ProductsReleaseDetailPagePage.js.map +1 -1
  46. package/dist/planmagnet/pages/ProductsReleasesPagePage.d.ts.map +1 -1
  47. package/dist/planmagnet/pages/ProductsReleasesPagePage.js +2 -0
  48. package/dist/planmagnet/pages/ProductsReleasesPagePage.js.map +1 -1
  49. package/dist/planmagnet/pages/ProjectsEditProjectPagePage.js +6 -6
  50. package/dist/planmagnet/pages/ProjectsMilestoneDetailPagePage.d.ts.map +1 -1
  51. package/dist/planmagnet/pages/ProjectsMilestoneDetailPagePage.js +55 -63
  52. package/dist/planmagnet/pages/ProjectsMilestoneDetailPagePage.js.map +1 -1
  53. package/dist/planmagnet/pages/ProjectsPlanningEditPagePage.js +4 -4
  54. package/dist/planmagnet/pages/TasksCreateTaskPagePage.js +123 -128
  55. package/dist/planmagnet/pages/TasksCreateTaskPagePage.js.map +1 -1
  56. package/dist/planmagnet/pages/TasksEditTaskPagePage.d.ts.map +1 -1
  57. package/dist/planmagnet/pages/TasksEditTaskPagePage.js +139 -107
  58. package/dist/planmagnet/pages/TasksEditTaskPagePage.js.map +1 -1
  59. package/dist/planmagnet/pages/TasksTaskDetailPagePage.d.ts.map +1 -1
  60. package/dist/planmagnet/pages/TasksTaskDetailPagePage.js +173 -126
  61. package/dist/planmagnet/pages/TasksTaskDetailPagePage.js.map +1 -1
  62. package/dist/planmagnet/pages/TasksTasksPagePage.d.ts.map +1 -1
  63. package/dist/planmagnet/pages/TasksTasksPagePage.js +1 -0
  64. package/dist/planmagnet/pages/TasksTasksPagePage.js.map +1 -1
  65. package/dist/planmagnet/roadmaps/RoadmapControls.js +23 -23
  66. 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 { ReleaseNotesCard as n } from "../releases/ReleaseNotesCard.js";
4
- import { ReleaseGatesCard as r } from "../releases/ReleaseGatesCard.js";
5
- import { ReleaseReadinessCard as i } from "../releases/ReleaseReadinessCard.js";
6
- import { ReleaseWorkItemsCard as a } from "../releases/ReleaseWorkItemsCard.js";
7
- import { Calendar as o, Clock as s, GitBranch as c, Loader2 as l } from "lucide-react";
8
- import { useParams as u } from "react-router";
9
- import { gql as d } from "@apollo/client";
10
- import { useQuery as f } from "@apollo/client/react";
11
- import { jsx as p, jsxs as m } from "react/jsx-runtime";
12
- import { Badge as h, Card as g, CardContent as _, CardHeader as v, CardTitle as y } from "@burdenoff/fe-libs/ui";
13
- import { Markdown as b } from "@burdenoff/fe-libs/shared/components";
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 x = d`
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
- `, S = {
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 C() {
52
- let { workspaceId: d } = e(), C = u().id ?? "", { data: w, loading: T, error: E } = f(x, {
53
- variables: { id: C },
54
- skip: !C
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 (T && !w) return /* @__PURE__ */ p("div", {
57
+ if (E && !T) return /* @__PURE__ */ m("div", {
57
58
  className: "flex items-center justify-center p-12",
58
- children: /* @__PURE__ */ p(l, { className: "h-8 w-8 animate-spin text-muted-foreground" })
59
+ children: /* @__PURE__ */ m(u, { className: "h-8 w-8 animate-spin text-muted-foreground" })
59
60
  });
60
- if (E) return /* @__PURE__ */ m("div", {
61
+ if (D) return /* @__PURE__ */ h("div", {
61
62
  className: "p-6 text-destructive",
62
- children: ["Failed to load release: ", E.message]
63
+ children: ["Failed to load release: ", D.message]
63
64
  });
64
- let D = w?.planmagnetRelease;
65
- if (!D) return /* @__PURE__ */ p("div", {
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 O = D.workItems ?? [], k = O.filter((e) => e.type === "STORY" || e.type === "FEATURE"), A = O.filter((e) => e.type === "BUG");
70
- return /* @__PURE__ */ m("div", {
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__ */ m("div", {
73
+ children: [/* @__PURE__ */ h("div", {
73
74
  className: "flex items-center justify-between",
74
- children: [/* @__PURE__ */ m("div", { children: [/* @__PURE__ */ m("div", {
75
+ children: [/* @__PURE__ */ h("div", { children: [/* @__PURE__ */ h("div", {
75
76
  className: "flex items-center gap-2",
76
77
  children: [
77
- /* @__PURE__ */ p(c, { className: "h-5 w-5 text-primary" }),
78
- /* @__PURE__ */ p("h1", {
78
+ /* @__PURE__ */ m(l, { className: "h-5 w-5 text-primary" }),
79
+ /* @__PURE__ */ m("h1", {
79
80
  className: "text-2xl font-semibold",
80
- children: D.version
81
+ children: O.version
81
82
  }),
82
- /* @__PURE__ */ p("span", {
83
- className: `text-xs px-2 py-0.5 rounded-full capitalize ${S[D.status] ?? "bg-gray-100"}`,
84
- children: D.status.toLowerCase().replace("_", " ")
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__ */ p("p", {
88
+ }), /* @__PURE__ */ m("p", {
88
89
  className: "text-sm text-muted-foreground mt-1",
89
- children: D.name
90
- })] }), /* @__PURE__ */ p(h, {
91
- variant: "outline",
92
- className: "capitalize",
93
- children: D.status.toLowerCase().replace("_", " ")
90
+ children: O.name
91
+ })] }), /* @__PURE__ */ m(n, {
92
+ releaseId: O.id,
93
+ version: O.version,
94
+ status: O.status
94
95
  })]
95
- }), /* @__PURE__ */ m("div", {
96
+ }), /* @__PURE__ */ h("div", {
96
97
  className: "grid grid-cols-1 lg:grid-cols-3 gap-6",
97
- children: [/* @__PURE__ */ m("div", {
98
+ children: [/* @__PURE__ */ h("div", {
98
99
  className: "lg:col-span-2 space-y-6",
99
100
  children: [
100
- /* @__PURE__ */ p(i, {
101
- releaseId: D.id,
102
- projectId: D.projectId || null,
103
- releaseStatus: D.status,
104
- plannedDate: D.plannedDate ?? null
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__ */ m(g, { children: [/* @__PURE__ */ p(v, { children: /* @__PURE__ */ p(y, { children: "Overview" }) }), /* @__PURE__ */ m(_, {
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__ */ p("div", {
109
+ children: [/* @__PURE__ */ m("div", {
109
110
  className: "text-sm prose prose-sm dark:prose-invert max-w-none",
110
- children: D.description ? /* @__PURE__ */ p(b, { children: D.description }) : /* @__PURE__ */ p("p", { children: "No description provided." })
111
- }), /* @__PURE__ */ m("div", {
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__ */ m("div", {
115
+ /* @__PURE__ */ h("div", {
115
116
  className: "text-center p-3 bg-muted rounded-md",
116
- children: [/* @__PURE__ */ p("p", {
117
+ children: [/* @__PURE__ */ m("p", {
117
118
  className: "text-lg font-semibold mt-1",
118
- children: k.length
119
- }), /* @__PURE__ */ p("p", {
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__ */ m("div", {
125
+ /* @__PURE__ */ h("div", {
125
126
  className: "text-center p-3 bg-muted rounded-md",
126
- children: [/* @__PURE__ */ p("p", {
127
+ children: [/* @__PURE__ */ m("p", {
127
128
  className: "text-lg font-semibold mt-1",
128
- children: A.length
129
- }), /* @__PURE__ */ p("p", {
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__ */ m("div", {
135
+ /* @__PURE__ */ h("div", {
135
136
  className: "text-center p-3 bg-muted rounded-md",
136
- children: [/* @__PURE__ */ p("p", {
137
+ children: [/* @__PURE__ */ m("p", {
137
138
  className: "text-lg font-semibold mt-1",
138
- children: O.length
139
- }), /* @__PURE__ */ p("p", {
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__ */ p(r, {
148
- releaseId: D.id,
149
- projectId: D.projectId ?? null,
150
- releaseStatus: D.status
148
+ /* @__PURE__ */ m(i, {
149
+ releaseId: O.id,
150
+ projectId: O.projectId ?? null,
151
+ releaseStatus: O.status
151
152
  }),
152
- /* @__PURE__ */ p(n, {
153
- releaseId: D.id,
154
- notes: D.releaseNotes ?? null
153
+ /* @__PURE__ */ m(r, {
154
+ releaseId: O.id,
155
+ notes: O.releaseNotes ?? null
155
156
  }),
156
- /* @__PURE__ */ p(a, {
157
- releaseId: D.id,
158
- projectId: D.projectId || null,
159
- items: O
157
+ /* @__PURE__ */ m(o, {
158
+ releaseId: O.id,
159
+ projectId: O.projectId || null,
160
+ items: k
160
161
  })
161
162
  ]
162
- }), /* @__PURE__ */ m("div", {
163
+ }), /* @__PURE__ */ h("div", {
163
164
  className: "space-y-6",
164
165
  children: [
165
- /* @__PURE__ */ m(g, { children: [/* @__PURE__ */ p(v, { children: /* @__PURE__ */ p(y, { children: "Timeline" }) }), /* @__PURE__ */ m(_, {
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__ */ m("div", {
168
+ children: [/* @__PURE__ */ h("div", {
168
169
  className: "flex items-center gap-2",
169
170
  children: [
170
- /* @__PURE__ */ p(o, { className: "h-4 w-4 text-muted-foreground" }),
171
- /* @__PURE__ */ p("span", {
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__ */ p("span", {
176
+ /* @__PURE__ */ m("span", {
176
177
  className: "font-medium",
177
- children: D.plannedDate ? new Date(D.plannedDate).toLocaleDateString() : "Not set"
178
+ children: O.plannedDate ? new Date(O.plannedDate).toLocaleDateString() : "Not set"
178
179
  })
179
180
  ]
180
- }), D.releasedAt && /* @__PURE__ */ m("div", {
181
+ }), O.releasedAt && /* @__PURE__ */ h("div", {
181
182
  className: "flex items-center gap-2",
182
183
  children: [
183
- /* @__PURE__ */ p(s, { className: "h-4 w-4 text-green-500" }),
184
- /* @__PURE__ */ p("span", {
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__ */ p("span", {
189
+ /* @__PURE__ */ m("span", {
189
190
  className: "font-medium",
190
- children: new Date(D.releasedAt).toLocaleDateString()
191
+ children: new Date(O.releasedAt).toLocaleDateString()
191
192
  })
192
193
  ]
193
194
  })]
194
195
  })] }),
195
- /* @__PURE__ */ m(g, { children: [/* @__PURE__ */ p(v, { children: /* @__PURE__ */ p(y, { children: "Details" }) }), /* @__PURE__ */ m(_, {
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__ */ m("div", {
199
+ /* @__PURE__ */ h("div", {
199
200
  className: "flex justify-between",
200
- children: [/* @__PURE__ */ p("span", {
201
+ children: [/* @__PURE__ */ m("span", {
201
202
  className: "text-muted-foreground",
202
203
  children: "Version"
203
- }), /* @__PURE__ */ p("span", {
204
+ }), /* @__PURE__ */ m("span", {
204
205
  className: "font-medium",
205
- children: D.version
206
+ children: O.version
206
207
  })]
207
208
  }),
208
- /* @__PURE__ */ m("div", {
209
+ /* @__PURE__ */ h("div", {
209
210
  className: "flex justify-between",
210
- children: [/* @__PURE__ */ p("span", {
211
+ children: [/* @__PURE__ */ m("span", {
211
212
  className: "text-muted-foreground",
212
213
  children: "Status"
213
- }), /* @__PURE__ */ p(h, {
214
+ }), /* @__PURE__ */ m(g, {
214
215
  variant: "outline",
215
216
  className: "text-xs capitalize",
216
- children: D.status.toLowerCase().replace("_", " ")
217
+ children: O.status.toLowerCase().replace("_", " ")
217
218
  })]
218
219
  }),
219
- /* @__PURE__ */ m("div", {
220
+ /* @__PURE__ */ h("div", {
220
221
  className: "flex justify-between",
221
- children: [/* @__PURE__ */ p("span", {
222
+ children: [/* @__PURE__ */ m("span", {
222
223
  className: "text-muted-foreground",
223
224
  children: "Owner"
224
- }), /* @__PURE__ */ p("span", { children: /* @__PURE__ */ p(t, { id: D.ownerId }) })]
225
+ }), /* @__PURE__ */ m("span", { children: /* @__PURE__ */ m(t, { id: O.ownerId }) })]
225
226
  }),
226
- /* @__PURE__ */ m("div", {
227
+ /* @__PURE__ */ h("div", {
227
228
  className: "flex justify-between",
228
- children: [/* @__PURE__ */ p("span", {
229
+ children: [/* @__PURE__ */ m("span", {
229
230
  className: "text-muted-foreground",
230
231
  children: "Created"
231
- }), /* @__PURE__ */ p("span", { children: new Date(D.createdAt).toLocaleDateString() })]
232
+ }), /* @__PURE__ */ m("span", { children: new Date(O.createdAt).toLocaleDateString() })]
232
233
  }),
233
- /* @__PURE__ */ m("div", {
234
+ /* @__PURE__ */ h("div", {
234
235
  className: "flex justify-between",
235
- children: [/* @__PURE__ */ p("span", {
236
+ children: [/* @__PURE__ */ m("span", {
236
237
  className: "text-muted-foreground",
237
238
  children: "Updated"
238
- }), /* @__PURE__ */ p("span", { children: new Date(D.updatedAt).toLocaleDateString() })]
239
+ }), /* @__PURE__ */ m("span", { children: new Date(O.updatedAt).toLocaleDateString() })]
239
240
  })
240
241
  ]
241
242
  })] }),
242
- D.tags?.length > 0 && /* @__PURE__ */ m(g, { children: [/* @__PURE__ */ p(v, { children: /* @__PURE__ */ p(y, { children: "Tags" }) }), /* @__PURE__ */ p(_, {
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: D.tags.map((e) => /* @__PURE__ */ p(h, {
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 { C as ProductsReleaseDetailPagePage };
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":";;;;;;;;;;;;;;AAeA,IAAM,IAAc,CAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCjB,IAAsC;CAC1C,OAAO;CACP,UAAU;CACV,aAAa;CACb,OAAO;CACP,UAAU;CACV,WAAW;CACX,aAAa;CACd;AAED,SAAgB,IAAgC;CAC9C,IAAM,EAAE,mBAAgB,GAAe,EAEjC,IADS,GAA2B,CACjB,MAAM,IAEzB,EACJ,SACA,YACA,aAGA,EAA8B,GAAa;EACzC,WAAW,EAAE,IAAI,GAAW;EAC5B,MAAM,CAAC;EACR,CAAC;AAMJ,KAAI,KAAW,CAAC,EACd,QACE,kBAAC,OAAD;EAAK,WAAU;YACb,kBAAC,GAAD,EAAS,WAAU,8CAA+C,CAAA;EAC9D,CAAA;AAIV,KAAI,EACF,QAAO,kBAAC,OAAD;EAAK,WAAU;YAAf,CAAsC,4BAAyB,EAAM,QAAc;;CAG5F,IAAM,IAAU,GAAM;AACtB,KAAI,CAAC,EAAS,QAAO,kBAAC,OAAD;EAAK,WAAU;YAA4B;EAAwB,CAAA;CAExF,IAAM,IAA+B,EAAQ,aAAa,EAAE,EACtD,IAAe,EAAU,QAAQ,MAAM,EAAE,SAAS,WAAW,EAAE,SAAS,UAAU,EAClF,IAAW,EAAU,QAAQ,MAAM,EAAE,SAAS,MAAM;AAE1D,QACE,kBAAC,OAAD;EAAK,WAAU;YAAf,CACE,kBAAC,OAAD;GAAK,WAAU;aAAf,CACE,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,OAAD;IAAK,WAAU;cAAf;KACE,kBAAC,GAAD,EAAW,WAAU,wBAAyB,CAAA;KAC9C,kBAAC,MAAD;MAAI,WAAU;gBAA0B,EAAQ;MAAa,CAAA;KAC7D,kBAAC,QAAD;MACE,WAAW,+CAA+C,EAAY,EAAQ,WAAW;gBAExF,EAAQ,OAAO,aAAa,CAAC,QAAQ,KAAK,IAAI;MAC1C,CAAA;KACH;OACN,kBAAC,KAAD;IAAG,WAAU;cAAsC,EAAQ;IAAS,CAAA,CAChE,EAAA,CAAA,EACN,kBAAC,GAAD;IAAO,SAAQ;IAAU,WAAU;cAChC,EAAQ,OAAO,aAAa,CAAC,QAAQ,KAAK,IAAI;IACzC,CAAA,CACJ;MAEN,kBAAC,OAAD;GAAK,WAAU;aAAf,CACE,kBAAC,OAAD;IAAK,WAAU;cAAf;KACE,kBAAC,GAAD;MACE,WAAW,EAAQ;MACnB,WAAW,EAAQ,aAAa;MAChC,eAAe,EAAQ;MACvB,aAAa,EAAQ,eAAe;MACpC,CAAA;KACF,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD,EAAA,UAAW,YAAoB,CAAA,EACpB,CAAA,EACb,kBAAC,GAAD;MAAa,WAAU;gBAAvB,CACE,kBAAC,OAAD;OAAK,WAAU;iBACZ,EAAQ,cACP,kBAAC,GAAD,EAAA,UAAW,EAAQ,aAAuB,CAAA,GAE1C,kBAAC,KAAD,EAAA,UAAG,4BAA4B,CAAA;OAE7B,CAAA,EACN,kBAAC,OAAD;OAAK,WAAU;iBAAf;QACE,kBAAC,OAAD;SAAK,WAAU;mBAAf,CACE,kBAAC,KAAD;UAAG,WAAU;oBAA8B,EAAa;UAAW,CAAA,EACnE,kBAAC,KAAD;UAAG,WAAU;oBAAgC;UAAY,CAAA,CACrD;;QACN,kBAAC,OAAD;SAAK,WAAU;mBAAf,CACE,kBAAC,KAAD;UAAG,WAAU;oBAA8B,EAAS;UAAW,CAAA,EAC/D,kBAAC,KAAD;UAAG,WAAU;oBAAgC;UAAa,CAAA,CACtD;;QACN,kBAAC,OAAD;SAAK,WAAU;mBAAf,CACE,kBAAC,KAAD;UAAG,WAAU;oBAA8B,EAAU;UAAW,CAAA,EAChE,kBAAC,KAAD;UAAG,WAAU;oBAAgC;UAAe,CAAA,CACxD;;QACF;SACM;QACT,EAAA,CAAA;KAEP,kBAAC,GAAD;MACE,WAAW,EAAQ;MACnB,WAAW,EAAQ,aAAa;MAChC,eAAe,EAAQ;MACvB,CAAA;KACF,kBAAC,GAAD;MAAkB,WAAW,EAAQ;MAAI,OAAO,EAAQ,gBAAgB;MAAQ,CAAA;KAEhF,kBAAC,GAAD;MACE,WAAW,EAAQ;MACnB,WAAW,EAAQ,aAAa;MAChC,OAAO;MACP,CAAA;KACE;OAEN,kBAAC,OAAD;IAAK,WAAU;cAAf;KACE,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD,EAAA,UAAW,YAAoB,CAAA,EACpB,CAAA,EACb,kBAAC,GAAD;MAAa,WAAU;gBAAvB,CACE,kBAAC,OAAD;OAAK,WAAU;iBAAf;QACE,kBAAC,GAAD,EAAU,WAAU,iCAAkC,CAAA;QACtD,kBAAC,QAAD;SAAM,WAAU;mBAAwB;SAAe,CAAA;QACvD,kBAAC,QAAD;SAAM,WAAU;mBACb,EAAQ,cACL,IAAI,KAAK,EAAQ,YAAY,CAAC,oBAAoB,GAClD;SACC,CAAA;QACH;UACL,EAAQ,cACP,kBAAC,OAAD;OAAK,WAAU;iBAAf;QACE,kBAAC,GAAD,EAAO,WAAU,0BAA2B,CAAA;QAC5C,kBAAC,QAAD;SAAM,WAAU;mBAAwB;SAAgB,CAAA;QACxD,kBAAC,QAAD;SAAM,WAAU;mBACb,IAAI,KAAK,EAAQ,WAAW,CAAC,oBAAoB;SAC7C,CAAA;QACH;SAEI;QACT,EAAA,CAAA;KAEP,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD,EAAA,UAAW,WAAmB,CAAA,EACnB,CAAA,EACb,kBAAC,GAAD;MAAa,WAAU;gBAAvB;OACE,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,QAAD;SAAM,WAAU;mBAAwB;SAAc,CAAA,EACtD,kBAAC,QAAD;SAAM,WAAU;mBAAe,EAAQ;SAAe,CAAA,CAClD;;OACN,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,QAAD;SAAM,WAAU;mBAAwB;SAAa,CAAA,EACrD,kBAAC,GAAD;SAAO,SAAQ;SAAU,WAAU;mBAChC,EAAQ,OAAO,aAAa,CAAC,QAAQ,KAAK,IAAI;SACzC,CAAA,CACJ;;OACN,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,QAAD;SAAM,WAAU;mBAAwB;SAAY,CAAA,EACpD,kBAAC,QAAD,EAAA,UACE,kBAAC,GAAD,EAAY,IAAI,EAAQ,SAAW,CAAA,EAC9B,CAAA,CACH;;OACN,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,QAAD;SAAM,WAAU;mBAAwB;SAAc,CAAA,EACtD,kBAAC,QAAD,EAAA,UAAO,IAAI,KAAK,EAAQ,UAAU,CAAC,oBAAoB,EAAQ,CAAA,CAC3D;;OACN,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,QAAD;SAAM,WAAU;mBAAwB;SAAc,CAAA,EACtD,kBAAC,QAAD,EAAA,UAAO,IAAI,KAAK,EAAQ,UAAU,CAAC,oBAAoB,EAAQ,CAAA,CAC3D;;OACM;QACT,EAAA,CAAA;KAEN,EAAQ,MAAM,SAAS,KACtB,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD,EAAA,UAAW,QAAgB,CAAA,EAChB,CAAA,EACb,kBAAC,GAAD;MAAa,WAAU;gBACpB,EAAQ,KAAK,KAAK,MACjB,kBAAC,GAAD;OAAiB,SAAQ;OAAU,WAAU;iBAC1C;OACK,EAFI,EAEJ,CACR;MACU,CAAA,CACT,EAAA,CAAA;KAEL;MACF;KACF"}
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":"AA0EA,wBAAgB,wBAAwB,4CAiIvC"}
1
+ {"version":3,"file":"ProductsReleasesPagePage.d.ts","sourceRoot":"","sources":["../../../src/planmagnet/pages/ProductsReleasesPagePage.tsx"],"names":[],"mappings":"AA6EA,wBAAgB,wBAAwB,4CAiIvC"}
@@ -41,7 +41,9 @@ var y = u`
41
41
  "PLANNING",
42
42
  "IN_PROGRESS",
43
43
  "READY",
44
+ "STAGING",
44
45
  "RELEASED",
46
+ "ROLLED_BACK",
45
47
  "CANCELLED"
46
48
  ], x = {
47
49
  DRAFT: "bg-gray-100 text-gray-800",
@@ -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":"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"}
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 { detailPath as n } from "../utils/rowNavigation.js";
4
- import { endBeforeStart as r } from "../utils/formValidation.js";
5
- import { enumLabel as i } from "../controls/WorkItemControls.js";
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 = r(P.startDate, P.endDate);
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(n("/projects/project-detail-page", d)),
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: i(e)
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":"AAuCA,wBAAgB,+BAA+B,4CAkJ9C"}
1
+ {"version":3,"file":"ProjectsMilestoneDetailPagePage.d.ts","sourceRoot":"","sources":["../../../src/planmagnet/pages/ProjectsMilestoneDetailPagePage.tsx"],"names":[],"mappings":"AAgCA,wBAAgB,+BAA+B,4CA+I9C"}