@burdenoff/microfe-planmagnet 2026.925.11 → 2026.925.12

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.
@@ -1 +1 @@
1
- {"version":3,"file":"ProductsReleaseDetailPagePage.d.ts","sourceRoot":"","sources":["../../../src/planmagnet/pages/ProductsReleaseDetailPagePage.tsx"],"names":[],"mappings":"AA0DA,wBAAgB,6BAA6B,4CA2M5C"}
1
+ {"version":3,"file":"ProductsReleaseDetailPagePage.d.ts","sourceRoot":"","sources":["../../../src/planmagnet/pages/ProductsReleaseDetailPagePage.tsx"],"names":[],"mappings":"AA2DA,wBAAgB,6BAA6B,4CAgM5C"}
@@ -1,14 +1,15 @@
1
1
  import { usePlanMagnet as e } from "../providers/PlanMagnetProvider.js";
2
2
  import { PersonName as t } from "../people/People.js";
3
- import { Calendar as n, Clock as r, GitBranch as i, Loader2 as a } from "lucide-react";
4
- import { useParams as o } from "react-router";
5
- import { gql as s } from "@apollo/client";
6
- import { useQuery as c } from "@apollo/client/react";
7
- import { jsx as l, jsxs as u } from "react/jsx-runtime";
8
- import { Badge as d, Card as f, CardContent as p, CardHeader as m, CardTitle as h } from "@burdenoff/fe-libs/ui";
9
- import { Markdown as g } from "@burdenoff/fe-libs/shared/components";
3
+ import { ReleaseNotesCard as n } from "../releases/ReleaseNotesCard.js";
4
+ import { Calendar as r, Clock as i, GitBranch as a, Loader2 as o } from "lucide-react";
5
+ import { useParams as s } from "react-router";
6
+ import { gql as c } from "@apollo/client";
7
+ import { useQuery as l } from "@apollo/client/react";
8
+ import { jsx as u, jsxs as d } from "react/jsx-runtime";
9
+ import { Badge as f, Card as p, CardContent as m, CardHeader as h, CardTitle as g } from "@burdenoff/fe-libs/ui";
10
+ import { Markdown as _ } from "@burdenoff/fe-libs/shared/components";
10
11
  //#region src/planmagnet/pages/ProductsReleaseDetailPagePage.tsx
11
- var _ = s`
12
+ var v = c`
12
13
  query GetRelease($id: ID!) {
13
14
  planmagnetRelease(id: $id) {
14
15
  id
@@ -35,7 +36,7 @@ var _ = s`
35
36
  }
36
37
  }
37
38
  }
38
- `, v = {
39
+ `, y = {
39
40
  DRAFT: "bg-gray-100 text-gray-800",
40
41
  PLANNING: "bg-yellow-100 text-yellow-800",
41
42
  IN_PROGRESS: "bg-blue-100 text-blue-800",
@@ -44,89 +45,89 @@ var _ = s`
44
45
  CANCELLED: "bg-red-100 text-red-800",
45
46
  ROLLED_BACK: "bg-red-100 text-red-800"
46
47
  };
47
- function y() {
48
- let { workspaceId: s } = e(), y = o().id ?? "", { data: b, loading: x, error: S } = c(_, {
49
- variables: { id: y },
50
- skip: !y
48
+ function b() {
49
+ let { workspaceId: c } = e(), b = s().id ?? "", { data: x, loading: S, error: C } = l(v, {
50
+ variables: { id: b },
51
+ skip: !b
51
52
  });
52
- if (x) return /* @__PURE__ */ l("div", {
53
+ if (S) return /* @__PURE__ */ u("div", {
53
54
  className: "flex items-center justify-center p-12",
54
- children: /* @__PURE__ */ l(a, { className: "h-8 w-8 animate-spin text-muted-foreground" })
55
+ children: /* @__PURE__ */ u(o, { className: "h-8 w-8 animate-spin text-muted-foreground" })
55
56
  });
56
- if (S) return /* @__PURE__ */ u("div", {
57
+ if (C) return /* @__PURE__ */ d("div", {
57
58
  className: "p-6 text-destructive",
58
- children: ["Failed to load release: ", S.message]
59
+ children: ["Failed to load release: ", C.message]
59
60
  });
60
- let C = b?.planmagnetRelease;
61
- if (!C) return /* @__PURE__ */ l("div", {
61
+ let w = x?.planmagnetRelease;
62
+ if (!w) return /* @__PURE__ */ u("div", {
62
63
  className: "p-6 text-muted-foreground",
63
64
  children: "Release not found."
64
65
  });
65
- let w = C.workItems ?? [], T = w.filter((e) => e.type === "STORY" || e.type === "FEATURE"), E = w.filter((e) => e.type === "BUG");
66
- return /* @__PURE__ */ u("div", {
66
+ let T = w.workItems ?? [], E = T.filter((e) => e.type === "STORY" || e.type === "FEATURE"), D = T.filter((e) => e.type === "BUG");
67
+ return /* @__PURE__ */ d("div", {
67
68
  className: "space-y-6 p-6",
68
- children: [/* @__PURE__ */ u("div", {
69
+ children: [/* @__PURE__ */ d("div", {
69
70
  className: "flex items-center justify-between",
70
- children: [/* @__PURE__ */ u("div", { children: [/* @__PURE__ */ u("div", {
71
+ children: [/* @__PURE__ */ d("div", { children: [/* @__PURE__ */ d("div", {
71
72
  className: "flex items-center gap-2",
72
73
  children: [
73
- /* @__PURE__ */ l(i, { className: "h-5 w-5 text-primary" }),
74
- /* @__PURE__ */ l("h1", {
74
+ /* @__PURE__ */ u(a, { className: "h-5 w-5 text-primary" }),
75
+ /* @__PURE__ */ u("h1", {
75
76
  className: "text-2xl font-semibold",
76
- children: C.version
77
+ children: w.version
77
78
  }),
78
- /* @__PURE__ */ l("span", {
79
- className: `text-xs px-2 py-0.5 rounded-full capitalize ${v[C.status] ?? "bg-gray-100"}`,
80
- children: C.status.toLowerCase().replace("_", " ")
79
+ /* @__PURE__ */ u("span", {
80
+ className: `text-xs px-2 py-0.5 rounded-full capitalize ${y[w.status] ?? "bg-gray-100"}`,
81
+ children: w.status.toLowerCase().replace("_", " ")
81
82
  })
82
83
  ]
83
- }), /* @__PURE__ */ l("p", {
84
+ }), /* @__PURE__ */ u("p", {
84
85
  className: "text-sm text-muted-foreground mt-1",
85
- children: C.name
86
- })] }), /* @__PURE__ */ l(d, {
86
+ children: w.name
87
+ })] }), /* @__PURE__ */ u(f, {
87
88
  variant: "outline",
88
89
  className: "capitalize",
89
- children: C.status.toLowerCase().replace("_", " ")
90
+ children: w.status.toLowerCase().replace("_", " ")
90
91
  })]
91
- }), /* @__PURE__ */ u("div", {
92
+ }), /* @__PURE__ */ d("div", {
92
93
  className: "grid grid-cols-1 lg:grid-cols-3 gap-6",
93
- children: [/* @__PURE__ */ u("div", {
94
+ children: [/* @__PURE__ */ d("div", {
94
95
  className: "lg:col-span-2 space-y-6",
95
96
  children: [
96
- /* @__PURE__ */ u(f, { children: [/* @__PURE__ */ l(m, { children: /* @__PURE__ */ l(h, { children: "Overview" }) }), /* @__PURE__ */ u(p, {
97
+ /* @__PURE__ */ d(p, { children: [/* @__PURE__ */ u(h, { children: /* @__PURE__ */ u(g, { children: "Overview" }) }), /* @__PURE__ */ d(m, {
97
98
  className: "space-y-4",
98
- children: [/* @__PURE__ */ l("div", {
99
+ children: [/* @__PURE__ */ u("div", {
99
100
  className: "text-sm prose prose-sm dark:prose-invert max-w-none",
100
- children: C.description ? /* @__PURE__ */ l(g, { children: C.description }) : /* @__PURE__ */ l("p", { children: "No description provided." })
101
- }), /* @__PURE__ */ u("div", {
101
+ children: w.description ? /* @__PURE__ */ u(_, { children: w.description }) : /* @__PURE__ */ u("p", { children: "No description provided." })
102
+ }), /* @__PURE__ */ d("div", {
102
103
  className: "grid grid-cols-3 gap-4",
103
104
  children: [
104
- /* @__PURE__ */ u("div", {
105
+ /* @__PURE__ */ d("div", {
105
106
  className: "text-center p-3 bg-muted rounded-md",
106
- children: [/* @__PURE__ */ l("p", {
107
+ children: [/* @__PURE__ */ u("p", {
107
108
  className: "text-lg font-semibold mt-1",
108
- children: T.length
109
- }), /* @__PURE__ */ l("p", {
109
+ children: E.length
110
+ }), /* @__PURE__ */ u("p", {
110
111
  className: "text-xs text-muted-foreground",
111
112
  children: "Features"
112
113
  })]
113
114
  }),
114
- /* @__PURE__ */ u("div", {
115
+ /* @__PURE__ */ d("div", {
115
116
  className: "text-center p-3 bg-muted rounded-md",
116
- children: [/* @__PURE__ */ l("p", {
117
+ children: [/* @__PURE__ */ u("p", {
117
118
  className: "text-lg font-semibold mt-1",
118
- children: E.length
119
- }), /* @__PURE__ */ l("p", {
119
+ children: D.length
120
+ }), /* @__PURE__ */ u("p", {
120
121
  className: "text-xs text-muted-foreground",
121
122
  children: "Bug Fixes"
122
123
  })]
123
124
  }),
124
- /* @__PURE__ */ u("div", {
125
+ /* @__PURE__ */ d("div", {
125
126
  className: "text-center p-3 bg-muted rounded-md",
126
- children: [/* @__PURE__ */ l("p", {
127
+ children: [/* @__PURE__ */ u("p", {
127
128
  className: "text-lg font-semibold mt-1",
128
- children: w.length
129
- }), /* @__PURE__ */ l("p", {
129
+ children: T.length
130
+ }), /* @__PURE__ */ u("p", {
130
131
  className: "text-xs text-muted-foreground",
131
132
  children: "Total Items"
132
133
  })]
@@ -134,22 +135,22 @@ function y() {
134
135
  ]
135
136
  })]
136
137
  })] }),
137
- C.releaseNotes && /* @__PURE__ */ u(f, { children: [/* @__PURE__ */ l(m, { children: /* @__PURE__ */ l(h, { children: "Release Notes" }) }), /* @__PURE__ */ l(p, { children: /* @__PURE__ */ l("div", {
138
- className: "text-sm prose prose-sm dark:prose-invert max-w-none",
139
- children: /* @__PURE__ */ l(g, { children: C.releaseNotes })
140
- }) })] }),
141
- w.length > 0 && /* @__PURE__ */ u(f, { children: [/* @__PURE__ */ l(m, { children: /* @__PURE__ */ u(h, { children: [
138
+ /* @__PURE__ */ u(n, {
139
+ releaseId: w.id,
140
+ notes: w.releaseNotes ?? null
141
+ }),
142
+ T.length > 0 && /* @__PURE__ */ d(p, { children: [/* @__PURE__ */ u(h, { children: /* @__PURE__ */ d(g, { children: [
142
143
  "Work Items (",
143
- w.length,
144
+ T.length,
144
145
  ")"
145
- ] }) }), /* @__PURE__ */ l(p, {
146
+ ] }) }), /* @__PURE__ */ u(m, {
146
147
  className: "space-y-2",
147
- children: w.map((e) => /* @__PURE__ */ u("div", {
148
+ children: T.map((e) => /* @__PURE__ */ d("div", {
148
149
  className: "flex items-center justify-between border rounded-md p-3",
149
- children: [/* @__PURE__ */ u("div", { children: [/* @__PURE__ */ l("p", {
150
+ children: [/* @__PURE__ */ d("div", { children: [/* @__PURE__ */ u("p", {
150
151
  className: "text-sm font-medium",
151
152
  children: e.title
152
- }), /* @__PURE__ */ u("p", {
153
+ }), /* @__PURE__ */ d("p", {
153
154
  className: "text-xs text-muted-foreground capitalize",
154
155
  children: [
155
156
  e.type.toLowerCase(),
@@ -157,7 +158,7 @@ function y() {
157
158
  e.priority.toLowerCase(),
158
159
  " priority"
159
160
  ]
160
- })] }), /* @__PURE__ */ l(d, {
161
+ })] }), /* @__PURE__ */ u(f, {
161
162
  variant: "outline",
162
163
  className: "text-xs capitalize",
163
164
  children: e.status.toLowerCase().replace("_", " ")
@@ -165,89 +166,89 @@ function y() {
165
166
  }, e.id))
166
167
  })] })
167
168
  ]
168
- }), /* @__PURE__ */ u("div", {
169
+ }), /* @__PURE__ */ d("div", {
169
170
  className: "space-y-6",
170
171
  children: [
171
- /* @__PURE__ */ u(f, { children: [/* @__PURE__ */ l(m, { children: /* @__PURE__ */ l(h, { children: "Timeline" }) }), /* @__PURE__ */ u(p, {
172
+ /* @__PURE__ */ d(p, { children: [/* @__PURE__ */ u(h, { children: /* @__PURE__ */ u(g, { children: "Timeline" }) }), /* @__PURE__ */ d(m, {
172
173
  className: "space-y-3 text-sm",
173
- children: [/* @__PURE__ */ u("div", {
174
+ children: [/* @__PURE__ */ d("div", {
174
175
  className: "flex items-center gap-2",
175
176
  children: [
176
- /* @__PURE__ */ l(n, { className: "h-4 w-4 text-muted-foreground" }),
177
- /* @__PURE__ */ l("span", {
177
+ /* @__PURE__ */ u(r, { className: "h-4 w-4 text-muted-foreground" }),
178
+ /* @__PURE__ */ u("span", {
178
179
  className: "text-muted-foreground",
179
180
  children: "Planned:"
180
181
  }),
181
- /* @__PURE__ */ l("span", {
182
+ /* @__PURE__ */ u("span", {
182
183
  className: "font-medium",
183
- children: C.plannedDate ? new Date(C.plannedDate).toLocaleDateString() : "Not set"
184
+ children: w.plannedDate ? new Date(w.plannedDate).toLocaleDateString() : "Not set"
184
185
  })
185
186
  ]
186
- }), C.releasedAt && /* @__PURE__ */ u("div", {
187
+ }), w.releasedAt && /* @__PURE__ */ d("div", {
187
188
  className: "flex items-center gap-2",
188
189
  children: [
189
- /* @__PURE__ */ l(r, { className: "h-4 w-4 text-green-500" }),
190
- /* @__PURE__ */ l("span", {
190
+ /* @__PURE__ */ u(i, { className: "h-4 w-4 text-green-500" }),
191
+ /* @__PURE__ */ u("span", {
191
192
  className: "text-muted-foreground",
192
193
  children: "Released:"
193
194
  }),
194
- /* @__PURE__ */ l("span", {
195
+ /* @__PURE__ */ u("span", {
195
196
  className: "font-medium",
196
- children: new Date(C.releasedAt).toLocaleDateString()
197
+ children: new Date(w.releasedAt).toLocaleDateString()
197
198
  })
198
199
  ]
199
200
  })]
200
201
  })] }),
201
- /* @__PURE__ */ u(f, { children: [/* @__PURE__ */ l(m, { children: /* @__PURE__ */ l(h, { children: "Details" }) }), /* @__PURE__ */ u(p, {
202
+ /* @__PURE__ */ d(p, { children: [/* @__PURE__ */ u(h, { children: /* @__PURE__ */ u(g, { children: "Details" }) }), /* @__PURE__ */ d(m, {
202
203
  className: "space-y-2 text-sm",
203
204
  children: [
204
- /* @__PURE__ */ u("div", {
205
+ /* @__PURE__ */ d("div", {
205
206
  className: "flex justify-between",
206
- children: [/* @__PURE__ */ l("span", {
207
+ children: [/* @__PURE__ */ u("span", {
207
208
  className: "text-muted-foreground",
208
209
  children: "Version"
209
- }), /* @__PURE__ */ l("span", {
210
+ }), /* @__PURE__ */ u("span", {
210
211
  className: "font-medium",
211
- children: C.version
212
+ children: w.version
212
213
  })]
213
214
  }),
214
- /* @__PURE__ */ u("div", {
215
+ /* @__PURE__ */ d("div", {
215
216
  className: "flex justify-between",
216
- children: [/* @__PURE__ */ l("span", {
217
+ children: [/* @__PURE__ */ u("span", {
217
218
  className: "text-muted-foreground",
218
219
  children: "Status"
219
- }), /* @__PURE__ */ l(d, {
220
+ }), /* @__PURE__ */ u(f, {
220
221
  variant: "outline",
221
222
  className: "text-xs capitalize",
222
- children: C.status.toLowerCase().replace("_", " ")
223
+ children: w.status.toLowerCase().replace("_", " ")
223
224
  })]
224
225
  }),
225
- /* @__PURE__ */ u("div", {
226
+ /* @__PURE__ */ d("div", {
226
227
  className: "flex justify-between",
227
- children: [/* @__PURE__ */ l("span", {
228
+ children: [/* @__PURE__ */ u("span", {
228
229
  className: "text-muted-foreground",
229
230
  children: "Owner"
230
- }), /* @__PURE__ */ l("span", { children: /* @__PURE__ */ l(t, { id: C.ownerId }) })]
231
+ }), /* @__PURE__ */ u("span", { children: /* @__PURE__ */ u(t, { id: w.ownerId }) })]
231
232
  }),
232
- /* @__PURE__ */ u("div", {
233
+ /* @__PURE__ */ d("div", {
233
234
  className: "flex justify-between",
234
- children: [/* @__PURE__ */ l("span", {
235
+ children: [/* @__PURE__ */ u("span", {
235
236
  className: "text-muted-foreground",
236
237
  children: "Created"
237
- }), /* @__PURE__ */ l("span", { children: new Date(C.createdAt).toLocaleDateString() })]
238
+ }), /* @__PURE__ */ u("span", { children: new Date(w.createdAt).toLocaleDateString() })]
238
239
  }),
239
- /* @__PURE__ */ u("div", {
240
+ /* @__PURE__ */ d("div", {
240
241
  className: "flex justify-between",
241
- children: [/* @__PURE__ */ l("span", {
242
+ children: [/* @__PURE__ */ u("span", {
242
243
  className: "text-muted-foreground",
243
244
  children: "Updated"
244
- }), /* @__PURE__ */ l("span", { children: new Date(C.updatedAt).toLocaleDateString() })]
245
+ }), /* @__PURE__ */ u("span", { children: new Date(w.updatedAt).toLocaleDateString() })]
245
246
  })
246
247
  ]
247
248
  })] }),
248
- C.tags?.length > 0 && /* @__PURE__ */ u(f, { children: [/* @__PURE__ */ l(m, { children: /* @__PURE__ */ l(h, { children: "Tags" }) }), /* @__PURE__ */ l(p, {
249
+ w.tags?.length > 0 && /* @__PURE__ */ d(p, { children: [/* @__PURE__ */ u(h, { children: /* @__PURE__ */ u(g, { children: "Tags" }) }), /* @__PURE__ */ u(m, {
249
250
  className: "flex flex-wrap gap-1",
250
- children: C.tags.map((e) => /* @__PURE__ */ l(d, {
251
+ children: w.tags.map((e) => /* @__PURE__ */ u(f, {
251
252
  variant: "outline",
252
253
  className: "text-xs",
253
254
  children: e
@@ -259,6 +260,6 @@ function y() {
259
260
  });
260
261
  }
261
262
  //#endregion
262
- export { y as ProductsReleaseDetailPagePage };
263
+ export { b as ProductsReleaseDetailPagePage };
263
264
 
264
265
  //# 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';\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 if (loading) {\n return (\n <div className=\"flex items-center justify-center p-12\">\n <Loader2 className=\"h-8 w-8 animate-spin text-muted-foreground\" />\n </div>\n );\n }\n\n if (error) {\n return <div className=\"p-6 text-destructive\">Failed to load release: {error.message}</div>;\n }\n\n 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 <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 {release.releaseNotes && (\n <Card>\n <CardHeader>\n <CardTitle>Release Notes</CardTitle>\n </CardHeader>\n <CardContent>\n <div className=\"text-sm prose prose-sm dark:prose-invert max-w-none\">\n <Markdown>{release.releaseNotes}</Markdown>\n </div>\n </CardContent>\n </Card>\n )}\n\n {workItems.length > 0 && (\n <Card>\n <CardHeader>\n <CardTitle>Work Items ({workItems.length})</CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-2\">\n {workItems.map((item) => (\n <div\n key={item.id}\n className=\"flex items-center justify-between border rounded-md p-3\"\n >\n <div>\n <p className=\"text-sm font-medium\">{item.title}</p>\n <p className=\"text-xs text-muted-foreground capitalize\">\n {item.type.toLowerCase()} &middot; {item.priority.toLowerCase()} priority\n </p>\n </div>\n <Badge variant=\"outline\" className=\"text-xs capitalize\">\n {item.status.toLowerCase().replace('_', ' ')}\n </Badge>\n </div>\n ))}\n </CardContent>\n </Card>\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';\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 if (loading) {\n return (\n <div className=\"flex items-center justify-center p-12\">\n <Loader2 className=\"h-8 w-8 animate-spin text-muted-foreground\" />\n </div>\n );\n }\n\n if (error) {\n return <div className=\"p-6 text-destructive\">Failed to load release: {error.message}</div>;\n }\n\n 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 <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 <ReleaseNotesCard releaseId={release.id} notes={release.releaseNotes ?? null} />\n\n {workItems.length > 0 && (\n <Card>\n <CardHeader>\n <CardTitle>Work Items ({workItems.length})</CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-2\">\n {workItems.map((item) => (\n <div\n key={item.id}\n className=\"flex items-center justify-between border rounded-md p-3\"\n >\n <div>\n <p className=\"text-sm font-medium\">{item.title}</p>\n <p className=\"text-xs text-muted-foreground capitalize\">\n {item.type.toLowerCase()} &middot; {item.priority.toLowerCase()} priority\n </p>\n </div>\n <Badge variant=\"outline\" className=\"text-xs capitalize\">\n {item.status.toLowerCase().replace('_', ' ')}\n </Badge>\n </div>\n ))}\n </CardContent>\n </Card>\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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"}
@@ -0,0 +1,5 @@
1
+ export declare function ReleaseNotesCard({ releaseId, notes, }: {
2
+ releaseId: string;
3
+ notes: string | null;
4
+ }): import("react/jsx-runtime").JSX.Element;
5
+ //# sourceMappingURL=ReleaseNotesCard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ReleaseNotesCard.d.ts","sourceRoot":"","sources":["../../../src/planmagnet/releases/ReleaseNotesCard.tsx"],"names":[],"mappings":"AAqDA,wBAAgB,gBAAgB,CAAC,EAC/B,SAAS,EACT,KAAK,GACN,EAAE;IACD,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB,2CA6EA"}
@@ -0,0 +1,101 @@
1
+ import { throwOnError as e } from "../utils/mutationResult.js";
2
+ import { useState as t } from "react";
3
+ import { FileText as n } from "lucide-react";
4
+ import { gql as r } from "@apollo/client";
5
+ import { useMutation as i } from "@apollo/client/react";
6
+ import { jsx as a, jsxs as o } from "react/jsx-runtime";
7
+ import { AlertDialog as s, AlertDialogAction as c, AlertDialogCancel as l, AlertDialogContent as u, AlertDialogDescription as d, AlertDialogFooter as f, AlertDialogHeader as p, AlertDialogTitle as m, AlertDialogTrigger as h, Button as g, Card as _, CardContent as v, CardHeader as y, CardTitle as b } from "@burdenoff/fe-libs/ui";
8
+ import { Markdown as x } from "@burdenoff/fe-libs/shared/components";
9
+ //#region src/planmagnet/releases/ReleaseNotesCard.tsx
10
+ var S = r`
11
+ mutation ReleaseNotesGenerate($id: ID!) {
12
+ planmagnetGenerateReleaseNotes(id: $id, persist: true) {
13
+ markdown
14
+ counts {
15
+ total
16
+ features
17
+ bugFixes
18
+ improvements
19
+ other
20
+ }
21
+ }
22
+ }
23
+ `;
24
+ function C({ releaseId: r, notes: C }) {
25
+ let [w, T] = t(null), [E, D] = t(null), [O, { loading: k }] = i(S, {
26
+ refetchQueries: ["GetRelease"],
27
+ awaitRefetchQueries: !0
28
+ }), A = async () => {
29
+ T(null);
30
+ try {
31
+ D((await e(O({ variables: { id: r } }))).data?.planmagnetGenerateReleaseNotes.counts ?? null);
32
+ } catch (e) {
33
+ T(e instanceof Error ? e.message : "The release notes could not be generated.");
34
+ }
35
+ };
36
+ return /* @__PURE__ */ o(_, {
37
+ "data-testid": "release-notes",
38
+ children: [/* @__PURE__ */ o(y, {
39
+ className: "flex flex-row items-center justify-between space-y-0",
40
+ children: [/* @__PURE__ */ a(b, { children: "Release Notes" }), C ? /* @__PURE__ */ o(s, { children: [/* @__PURE__ */ a(h, {
41
+ asChild: !0,
42
+ children: /* @__PURE__ */ a(g, {
43
+ size: "sm",
44
+ variant: "outline",
45
+ disabled: k,
46
+ children: k ? "Generating…" : "Regenerate"
47
+ })
48
+ }), /* @__PURE__ */ o(u, { children: [/* @__PURE__ */ o(p, { children: [/* @__PURE__ */ a(m, { children: "Replace the release notes?" }), /* @__PURE__ */ a(d, { children: "The current notes are replaced by notes generated from the release's completed work items. Hand edits are lost." })] }), /* @__PURE__ */ o(f, { children: [/* @__PURE__ */ a(l, { children: "Keep them" }), /* @__PURE__ */ a(c, {
49
+ onClick: A,
50
+ children: "Regenerate"
51
+ })] })] })] }) : /* @__PURE__ */ o(g, {
52
+ size: "sm",
53
+ onClick: A,
54
+ disabled: k,
55
+ "data-testid": "release-notes-generate",
56
+ children: [/* @__PURE__ */ a(n, { className: "mr-1 h-4 w-4" }), k ? "Generating…" : "Generate release notes"]
57
+ })]
58
+ }), /* @__PURE__ */ o(v, {
59
+ className: "space-y-3",
60
+ children: [
61
+ w && /* @__PURE__ */ a("p", {
62
+ role: "alert",
63
+ className: "text-sm text-destructive",
64
+ children: w
65
+ }),
66
+ E && /* @__PURE__ */ o("p", {
67
+ className: "text-xs text-muted-foreground",
68
+ "data-testid": "release-notes-counts",
69
+ children: [
70
+ "Generated from ",
71
+ E.total,
72
+ " completed work item",
73
+ E.total === 1 ? "" : "s",
74
+ ":",
75
+ " ",
76
+ E.features,
77
+ " features, ",
78
+ E.bugFixes,
79
+ " bug fixes, ",
80
+ E.improvements,
81
+ " ",
82
+ "improvements, ",
83
+ E.other,
84
+ " other."
85
+ ]
86
+ }),
87
+ C ? /* @__PURE__ */ a("div", {
88
+ className: "text-sm prose prose-sm dark:prose-invert max-w-none",
89
+ children: /* @__PURE__ */ a(x, { children: C })
90
+ }) : /* @__PURE__ */ a("p", {
91
+ className: "text-sm text-muted-foreground",
92
+ children: "No release notes yet. Generate them from this release's completed work items."
93
+ })
94
+ ]
95
+ })]
96
+ });
97
+ }
98
+ //#endregion
99
+ export { C as ReleaseNotesCard };
100
+
101
+ //# sourceMappingURL=ReleaseNotesCard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ReleaseNotesCard.js","names":[],"sources":["../../../src/planmagnet/releases/ReleaseNotesCard.tsx"],"sourcesContent":["import { useState } from 'react';\nimport { gql } from '@apollo/client';\nimport { useMutation } from '@apollo/client/react';\nimport {\n AlertDialog,\n AlertDialogAction,\n AlertDialogCancel,\n AlertDialogContent,\n AlertDialogDescription,\n AlertDialogFooter,\n AlertDialogHeader,\n AlertDialogTitle,\n AlertDialogTrigger,\n Button,\n Card,\n CardContent,\n CardHeader,\n CardTitle,\n} from '@burdenoff/fe-libs/ui';\nimport { Markdown } from '@burdenoff/fe-libs/shared/components';\nimport { FileText } from 'lucide-react';\nimport { throwOnError } from '../utils/mutationResult';\n\n/**\n * Release notes (P1.4). planmagnetGenerateReleaseNotes was verified to be real\n * generation (the release's closed work items, grouped) but no UI invoked it,\n * and this card only appeared once notes already existed, so there was nothing\n * to click on a new release.\n */\n\nconst GENERATE = gql`\n mutation ReleaseNotesGenerate($id: ID!) {\n planmagnetGenerateReleaseNotes(id: $id, persist: true) {\n markdown\n counts {\n total\n features\n bugFixes\n improvements\n other\n }\n }\n }\n`;\n\ninterface Counts {\n total: number;\n features: number;\n bugFixes: number;\n improvements: number;\n other: number;\n}\n\nexport function ReleaseNotesCard({\n releaseId,\n notes,\n}: {\n releaseId: string;\n notes: string | null;\n}) {\n const [error, setError] = useState<string | null>(null);\n const [counts, setCounts] = useState<Counts | null>(null);\n const [generate, { loading }] = useMutation<{\n planmagnetGenerateReleaseNotes: { markdown: string; counts: Counts };\n }>(GENERATE, { refetchQueries: ['GetRelease'], awaitRefetchQueries: true });\n\n const run = async () => {\n setError(null);\n try {\n const result = await throwOnError(generate({ variables: { id: releaseId } }));\n setCounts(result.data?.planmagnetGenerateReleaseNotes.counts ?? null);\n } catch (e) {\n setError(e instanceof Error ? e.message : 'The release notes could not be generated.');\n }\n };\n\n const action = notes ? (\n // Regenerating replaces the saved notes, including any hand edits.\n <AlertDialog>\n <AlertDialogTrigger asChild>\n <Button size=\"sm\" variant=\"outline\" disabled={loading}>\n {loading ? 'Generating…' : 'Regenerate'}\n </Button>\n </AlertDialogTrigger>\n <AlertDialogContent>\n <AlertDialogHeader>\n <AlertDialogTitle>Replace the release notes?</AlertDialogTitle>\n <AlertDialogDescription>\n The current notes are replaced by notes generated from the release&apos;s completed work\n items. Hand edits are lost.\n </AlertDialogDescription>\n </AlertDialogHeader>\n <AlertDialogFooter>\n <AlertDialogCancel>Keep them</AlertDialogCancel>\n <AlertDialogAction onClick={run}>Regenerate</AlertDialogAction>\n </AlertDialogFooter>\n </AlertDialogContent>\n </AlertDialog>\n ) : (\n <Button size=\"sm\" onClick={run} disabled={loading} data-testid=\"release-notes-generate\">\n <FileText className=\"mr-1 h-4 w-4\" />\n {loading ? 'Generating…' : 'Generate release notes'}\n </Button>\n );\n\n return (\n <Card data-testid=\"release-notes\">\n <CardHeader className=\"flex flex-row items-center justify-between space-y-0\">\n <CardTitle>Release Notes</CardTitle>\n {action}\n </CardHeader>\n <CardContent className=\"space-y-3\">\n {error && (\n <p role=\"alert\" className=\"text-sm text-destructive\">\n {error}\n </p>\n )}\n {counts && (\n <p className=\"text-xs text-muted-foreground\" data-testid=\"release-notes-counts\">\n Generated from {counts.total} completed work item{counts.total === 1 ? '' : 's'}:{' '}\n {counts.features} features, {counts.bugFixes} bug fixes, {counts.improvements}{' '}\n improvements, {counts.other} other.\n </p>\n )}\n {notes ? (\n <div className=\"text-sm prose prose-sm dark:prose-invert max-w-none\">\n <Markdown>{notes}</Markdown>\n </div>\n ) : (\n <p className=\"text-sm text-muted-foreground\">\n No release notes yet. Generate them from this release&apos;s completed work items.\n </p>\n )}\n </CardContent>\n </Card>\n );\n}\n"],"mappings":";;;;;;;;;AA8BA,IAAM,IAAW,CAAG;;;;;;;;;;;;;;AAuBpB,SAAgB,EAAiB,EAC/B,cACA,YAIC;CACD,IAAM,CAAC,GAAO,KAAY,EAAwB,KAAK,EACjD,CAAC,GAAQ,KAAa,EAAwB,KAAK,EACnD,CAAC,GAAU,EAAE,gBAAa,EAE7B,GAAU;EAAE,gBAAgB,CAAC,aAAa;EAAE,qBAAqB;EAAM,CAAC,EAErE,IAAM,YAAY;AACtB,IAAS,KAAK;AACd,MAAI;AAEF,MADe,MAAM,EAAa,EAAS,EAAE,WAAW,EAAE,IAAI,GAAW,EAAE,CAAC,CAAC,EAC5D,MAAM,+BAA+B,UAAU,KAAK;WAC9D,GAAG;AACV,KAAS,aAAa,QAAQ,EAAE,UAAU,4CAA4C;;;AAiC1F,QACE,kBAAC,GAAD;EAAM,eAAY;YAAlB,CACE,kBAAC,GAAD;GAAY,WAAU;aAAtB,CACE,kBAAC,GAAD,EAAA,UAAW,iBAAyB,CAAA,EAhC3B,IAEb,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD;IAAoB,SAAA;cAClB,kBAAC,GAAD;KAAQ,MAAK;KAAK,SAAQ;KAAU,UAAU;eAC3C,IAAU,gBAAgB;KACpB,CAAA;IACU,CAAA,EACrB,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD,EAAA,UAAkB,8BAA6C,CAAA,EAC/D,kBAAC,GAAD,EAAA,UAAwB,mHAGC,CAAA,CACP,EAAA,CAAA,EACpB,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD,EAAA,UAAmB,aAA6B,CAAA,EAChD,kBAAC,GAAD;IAAmB,SAAS;cAAK;IAA8B,CAAA,CAC7C,EAAA,CAAA,CACD,EAAA,CAAA,CACT,EAAA,CAAA,GAEd,kBAAC,GAAD;IAAQ,MAAK;IAAK,SAAS;IAAK,UAAU;IAAS,eAAY;cAA/D,CACE,kBAAC,GAAD,EAAU,WAAU,gBAAiB,CAAA,EACpC,IAAU,gBAAgB,yBACpB;MAQM;MACb,kBAAC,GAAD;GAAa,WAAU;aAAvB;IACG,KACC,kBAAC,KAAD;KAAG,MAAK;KAAQ,WAAU;eACvB;KACC,CAAA;IAEL,KACC,kBAAC,KAAD;KAAG,WAAU;KAAgC,eAAY;eAAzD;MAAgF;MAC9D,EAAO;MAAM;MAAqB,EAAO,UAAU,IAAI,KAAK;MAAI;MAAE;MACjF,EAAO;MAAS;MAAY,EAAO;MAAS;MAAa,EAAO;MAAc;MAAI;MACpE,EAAO;MAAM;MAC1B;;IAEL,IACC,kBAAC,OAAD;KAAK,WAAU;eACb,kBAAC,GAAD,EAAA,UAAW,GAAiB,CAAA;KACxB,CAAA,GAEN,kBAAC,KAAD;KAAG,WAAU;eAAgC;KAEzC,CAAA;IAEM;KACT"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@burdenoff/microfe-planmagnet",
3
- "version": "2026.925.11",
3
+ "version": "2026.925.12",
4
4
  "description": "Burdenoff PlanMagnet Microfrontend",
5
5
  "type": "module",
6
6
  "files": [