@burdenoff/microfe-planmagnet 2026.927.2 → 2026.927.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/planmagnet/admin/PlanMagnetAdminRoot.d.ts.map +1 -1
- package/dist/planmagnet/admin/PlanMagnetAdminRoot.js +128 -124
- package/dist/planmagnet/admin/PlanMagnetAdminRoot.js.map +1 -1
- package/dist/planmagnet/controls/ConfirmButton.d.ts +25 -0
- package/dist/planmagnet/controls/ConfirmButton.d.ts.map +1 -0
- package/dist/planmagnet/controls/ConfirmButton.js +30 -0
- package/dist/planmagnet/controls/ConfirmButton.js.map +1 -0
- package/dist/planmagnet/controls/FeatureControls.d.ts +26 -0
- package/dist/planmagnet/controls/FeatureControls.d.ts.map +1 -0
- package/dist/planmagnet/controls/FeatureControls.js +318 -0
- package/dist/planmagnet/controls/FeatureControls.js.map +1 -0
- package/dist/planmagnet/controls/MilestoneControls.d.ts +17 -0
- package/dist/planmagnet/controls/MilestoneControls.d.ts.map +1 -0
- package/dist/planmagnet/controls/MilestoneControls.js +200 -0
- package/dist/planmagnet/controls/MilestoneControls.js.map +1 -0
- package/dist/planmagnet/controls/ObjectiveControls.d.ts +31 -0
- package/dist/planmagnet/controls/ObjectiveControls.d.ts.map +1 -0
- package/dist/planmagnet/controls/ObjectiveControls.js +296 -0
- package/dist/planmagnet/controls/ObjectiveControls.js.map +1 -0
- package/dist/planmagnet/controls/Pickers.d.ts +26 -0
- package/dist/planmagnet/controls/Pickers.d.ts.map +1 -0
- package/dist/planmagnet/controls/Pickers.js +171 -0
- package/dist/planmagnet/controls/Pickers.js.map +1 -0
- package/dist/planmagnet/controls/ProjectControls.d.ts +13 -0
- package/dist/planmagnet/controls/ProjectControls.d.ts.map +1 -0
- package/dist/planmagnet/controls/ProjectControls.js +104 -0
- package/dist/planmagnet/controls/ProjectControls.js.map +1 -0
- package/dist/planmagnet/controls/ReleaseControls.d.ts +14 -0
- package/dist/planmagnet/controls/ReleaseControls.d.ts.map +1 -0
- package/dist/planmagnet/controls/ReleaseControls.js +108 -0
- package/dist/planmagnet/controls/ReleaseControls.js.map +1 -0
- package/dist/planmagnet/controls/WorkItemControls.d.ts +52 -0
- package/dist/planmagnet/controls/WorkItemControls.d.ts.map +1 -0
- package/dist/planmagnet/controls/WorkItemControls.js +198 -0
- package/dist/planmagnet/controls/WorkItemControls.js.map +1 -0
- package/dist/planmagnet/pages/DocsDocDetailPagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/DocsDocDetailPagePage.js +188 -154
- package/dist/planmagnet/pages/DocsDocDetailPagePage.js.map +1 -1
- package/dist/planmagnet/pages/DocsDocsPagePage.js +4 -4
- package/dist/planmagnet/pages/GoalsCreateObjectivePagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/GoalsCreateObjectivePagePage.js +63 -56
- package/dist/planmagnet/pages/GoalsCreateObjectivePagePage.js.map +1 -1
- package/dist/planmagnet/pages/GoalsObjectiveDetailPagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/GoalsObjectiveDetailPagePage.js +229 -214
- package/dist/planmagnet/pages/GoalsObjectiveDetailPagePage.js.map +1 -1
- package/dist/planmagnet/pages/ProductsEditProductPagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/ProductsEditProductPagePage.js +142 -114
- package/dist/planmagnet/pages/ProductsEditProductPagePage.js.map +1 -1
- package/dist/planmagnet/pages/ProductsEditReleasePagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/ProductsEditReleasePagePage.js +134 -105
- package/dist/planmagnet/pages/ProductsEditReleasePagePage.js.map +1 -1
- package/dist/planmagnet/pages/ProductsFeatureDetailPagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/ProductsFeatureDetailPagePage.js +102 -108
- package/dist/planmagnet/pages/ProductsFeatureDetailPagePage.js.map +1 -1
- package/dist/planmagnet/pages/ProductsNewFeaturePagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/ProductsNewFeaturePagePage.js +119 -94
- package/dist/planmagnet/pages/ProductsNewFeaturePagePage.js.map +1 -1
- package/dist/planmagnet/pages/ProductsProductDetailPagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/ProductsProductDetailPagePage.js +97 -90
- package/dist/planmagnet/pages/ProductsProductDetailPagePage.js.map +1 -1
- package/dist/planmagnet/pages/ProductsReleaseDetailPagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/ProductsReleaseDetailPagePage.js +107 -106
- package/dist/planmagnet/pages/ProductsReleaseDetailPagePage.js.map +1 -1
- package/dist/planmagnet/pages/ProductsReleasesPagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/ProductsReleasesPagePage.js +2 -0
- package/dist/planmagnet/pages/ProductsReleasesPagePage.js.map +1 -1
- package/dist/planmagnet/pages/ProductsRoadmapDetailPagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/ProductsRoadmapDetailPagePage.js +150 -111
- package/dist/planmagnet/pages/ProductsRoadmapDetailPagePage.js.map +1 -1
- package/dist/planmagnet/pages/ProjectsEditProjectPagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/ProjectsEditProjectPagePage.js +116 -93
- package/dist/planmagnet/pages/ProjectsEditProjectPagePage.js.map +1 -1
- package/dist/planmagnet/pages/ProjectsMilestoneDetailPagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/ProjectsMilestoneDetailPagePage.js +55 -63
- package/dist/planmagnet/pages/ProjectsMilestoneDetailPagePage.js.map +1 -1
- package/dist/planmagnet/pages/ProjectsPlanningEditPagePage.js +4 -4
- package/dist/planmagnet/pages/ProjectsProjectDetailPagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/ProjectsProjectDetailPagePage.js +134 -132
- package/dist/planmagnet/pages/ProjectsProjectDetailPagePage.js.map +1 -1
- package/dist/planmagnet/pages/SprintsStartSprintPagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/SprintsStartSprintPagePage.js +6 -5
- package/dist/planmagnet/pages/SprintsStartSprintPagePage.js.map +1 -1
- package/dist/planmagnet/pages/TasksCreateTaskPagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/TasksCreateTaskPagePage.js +167 -116
- package/dist/planmagnet/pages/TasksCreateTaskPagePage.js.map +1 -1
- package/dist/planmagnet/pages/TasksEditTaskPagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/TasksEditTaskPagePage.js +139 -107
- package/dist/planmagnet/pages/TasksEditTaskPagePage.js.map +1 -1
- package/dist/planmagnet/pages/TasksTaskDetailPagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/TasksTaskDetailPagePage.js +205 -158
- package/dist/planmagnet/pages/TasksTaskDetailPagePage.js.map +1 -1
- package/dist/planmagnet/pages/TasksTasksPagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/TasksTasksPagePage.js +1 -0
- package/dist/planmagnet/pages/TasksTasksPagePage.js.map +1 -1
- package/dist/planmagnet/pages/TeamTeamPagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/TeamTeamPagePage.js +1 -1
- package/dist/planmagnet/pages/TeamTeamPagePage.js.map +1 -1
- package/dist/planmagnet/people/People.js +1 -1
- package/dist/planmagnet/roadmaps/RoadmapControls.d.ts +34 -0
- package/dist/planmagnet/roadmaps/RoadmapControls.d.ts.map +1 -0
- package/dist/planmagnet/roadmaps/RoadmapControls.js +301 -0
- package/dist/planmagnet/roadmaps/RoadmapControls.js.map +1 -0
- package/dist/planmagnet/sprints/SprintControls.d.ts.map +1 -1
- package/dist/planmagnet/sprints/SprintControls.js +194 -215
- package/dist/planmagnet/sprints/SprintControls.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
import { usePlanMagnet as e, usePlanMagnetNavigate as t } from "../providers/PlanMagnetProvider.js";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
2
|
+
import { throwOnError as n } from "../utils/mutationResult.js";
|
|
3
|
+
import { parseIntField as r } from "../utils/formValidation.js";
|
|
4
|
+
import { WORK_ITEM_PRIORITIES as i } from "../controls/WorkItemControls.js";
|
|
5
|
+
import { useMemo as a, useState as o } from "react";
|
|
6
|
+
import { ArrowLeft as s, Save as c } from "lucide-react";
|
|
7
|
+
import { gql as l } from "@apollo/client";
|
|
8
|
+
import { useMutation as u, useQuery as d } from "@apollo/client/react";
|
|
9
|
+
import { jsx as f, jsxs as p } from "react/jsx-runtime";
|
|
10
|
+
import { Button as m, Card as h, CardContent as g, CardHeader as _, CardTitle as v, Input as y } from "@burdenoff/fe-libs/ui";
|
|
9
11
|
//#region src/planmagnet/pages/TasksEditTaskPagePage.tsx
|
|
10
|
-
var
|
|
12
|
+
var b = l`
|
|
11
13
|
query GetWorkItem($workItemId: ID!) {
|
|
12
14
|
planmagnetWorkItem(id: $workItemId) {
|
|
13
15
|
id
|
|
@@ -25,7 +27,7 @@ var v = s`
|
|
|
25
27
|
updatedAt
|
|
26
28
|
}
|
|
27
29
|
}
|
|
28
|
-
`,
|
|
30
|
+
`, x = l`
|
|
29
31
|
mutation UpdateWorkItem($workItemId: ID!, $input: PlanmagnetUpdateWorkItemInput!) {
|
|
30
32
|
planmagnetUpdateWorkItem(id: $workItemId, input: $input) {
|
|
31
33
|
id
|
|
@@ -41,136 +43,166 @@ var v = s`
|
|
|
41
43
|
}
|
|
42
44
|
}
|
|
43
45
|
`;
|
|
44
|
-
function
|
|
45
|
-
let { workspaceId:
|
|
46
|
-
variables: { workItemId:
|
|
47
|
-
skip: !
|
|
48
|
-
}), [
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
}), [
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
46
|
+
function S() {
|
|
47
|
+
let { workspaceId: l } = e(), S = new URLSearchParams(window.location.search).get("taskId") ?? "", C = t(), { data: w, loading: T, error: E } = d(b, {
|
|
48
|
+
variables: { workItemId: S },
|
|
49
|
+
skip: !l || !S
|
|
50
|
+
}), [D, { loading: O }] = u(x, {
|
|
51
|
+
refetchQueries: [
|
|
52
|
+
"GetWorkItems",
|
|
53
|
+
"GetWorkItemDetail",
|
|
54
|
+
"GetWorkItemCounts",
|
|
55
|
+
"ProjectBoard"
|
|
56
|
+
],
|
|
57
|
+
awaitRefetchQueries: !0
|
|
58
|
+
}), [k, A] = o(null), [j, M] = o(!1), N = w?.planmagnetWorkItem, P = a(() => ({
|
|
59
|
+
title: N?.title ?? "",
|
|
60
|
+
description: N?.description ?? "",
|
|
61
|
+
priority: N?.priority ?? "MEDIUM",
|
|
62
|
+
type: N?.type ?? "STORY",
|
|
63
|
+
storyPoints: N?.storyPoints?.toString() ?? "",
|
|
64
|
+
labels: (N?.labels ?? []).join(", "),
|
|
65
|
+
dueDate: N?.dueDate ? String(N.dueDate).slice(0, 10) : ""
|
|
66
|
+
}), [N]), [F, I] = o({}), L = {
|
|
67
|
+
...P,
|
|
68
|
+
...F
|
|
69
|
+
}, R = (e) => I(e), z = r(L.storyPoints, { min: 0 }), B = async () => {
|
|
70
|
+
if (!l || !S || z.invalid) return;
|
|
71
|
+
if (!L.title.trim()) {
|
|
72
|
+
A("A task needs a title.");
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
let e = (e) => e.split(",").map((e) => e.trim()).filter(Boolean), t = {
|
|
76
|
+
title: L.title.trim(),
|
|
77
|
+
description: L.description.trim() || null,
|
|
78
|
+
priority: L.priority,
|
|
79
|
+
type: L.type,
|
|
80
|
+
storyPoints: z.value ?? null,
|
|
81
|
+
labels: e(L.labels),
|
|
82
|
+
dueDate: L.dueDate || null
|
|
83
|
+
}, r = {
|
|
84
|
+
title: P.title,
|
|
85
|
+
description: P.description.trim() || null,
|
|
86
|
+
priority: P.priority,
|
|
87
|
+
type: P.type,
|
|
88
|
+
storyPoints: P.storyPoints === "" ? null : Number(P.storyPoints),
|
|
89
|
+
labels: e(P.labels),
|
|
90
|
+
dueDate: P.dueDate || null
|
|
91
|
+
}, i = Object.fromEntries(Object.entries(t).filter(([e, t]) => JSON.stringify(t) !== JSON.stringify(r[e])));
|
|
92
|
+
if (A(null), M(!1), Object.keys(i).length === 0) {
|
|
93
|
+
M(!0);
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
try {
|
|
97
|
+
await n(D({ variables: {
|
|
98
|
+
workItemId: S,
|
|
99
|
+
input: i
|
|
100
|
+
} })), M(!0);
|
|
101
|
+
} catch (e) {
|
|
102
|
+
A(e instanceof Error ? e.message : "The task could not be saved.");
|
|
103
|
+
}
|
|
72
104
|
};
|
|
73
|
-
if (
|
|
105
|
+
if (T && !w) return /* @__PURE__ */ f("div", {
|
|
74
106
|
className: "flex items-center justify-center p-12",
|
|
75
|
-
children: /* @__PURE__ */
|
|
107
|
+
children: /* @__PURE__ */ f("div", { className: "animate-spin h-8 w-8 border-2 border-primary border-t-transparent rounded-full" })
|
|
76
108
|
});
|
|
77
|
-
if (
|
|
109
|
+
if (E) return /* @__PURE__ */ p("div", {
|
|
78
110
|
className: "p-6 text-destructive",
|
|
79
|
-
children: ["Error: ",
|
|
111
|
+
children: ["Error: ", E.message]
|
|
80
112
|
});
|
|
81
|
-
if (!
|
|
113
|
+
if (!w?.planmagnetWorkItem) return /* @__PURE__ */ f("div", {
|
|
82
114
|
className: "p-6 text-muted-foreground",
|
|
83
115
|
children: "Task not found."
|
|
84
116
|
});
|
|
85
|
-
let
|
|
86
|
-
return /* @__PURE__ */
|
|
117
|
+
let V = w.planmagnetWorkItem;
|
|
118
|
+
return /* @__PURE__ */ p("div", {
|
|
87
119
|
className: "space-y-6 p-6 max-w-4xl",
|
|
88
120
|
children: [
|
|
89
|
-
/* @__PURE__ */
|
|
121
|
+
/* @__PURE__ */ p("div", {
|
|
90
122
|
className: "flex items-center justify-between",
|
|
91
|
-
children: [/* @__PURE__ */
|
|
123
|
+
children: [/* @__PURE__ */ p("div", {
|
|
92
124
|
className: "flex items-center gap-3",
|
|
93
|
-
children: [/* @__PURE__ */
|
|
125
|
+
children: [/* @__PURE__ */ f(m, {
|
|
94
126
|
variant: "ghost",
|
|
95
127
|
size: "sm",
|
|
96
128
|
"aria-label": "Back to the task",
|
|
97
|
-
onClick: () =>
|
|
98
|
-
children: /* @__PURE__ */
|
|
99
|
-
}), /* @__PURE__ */
|
|
129
|
+
onClick: () => C(`/tasks/task-detail-page?taskId=${encodeURIComponent(S)}`),
|
|
130
|
+
children: /* @__PURE__ */ f(s, { className: "h-4 w-4" })
|
|
131
|
+
}), /* @__PURE__ */ p("div", { children: [/* @__PURE__ */ f("h1", {
|
|
100
132
|
className: "text-2xl font-semibold",
|
|
101
133
|
children: "Edit Task"
|
|
102
|
-
}), /* @__PURE__ */
|
|
134
|
+
}), /* @__PURE__ */ f("p", {
|
|
103
135
|
className: "text-sm text-muted-foreground",
|
|
104
|
-
children:
|
|
136
|
+
children: V.title
|
|
105
137
|
})] })]
|
|
106
|
-
}), /* @__PURE__ */
|
|
138
|
+
}), /* @__PURE__ */ p(m, {
|
|
107
139
|
size: "sm",
|
|
108
|
-
onClick:
|
|
109
|
-
disabled:
|
|
110
|
-
children: [/* @__PURE__ */
|
|
140
|
+
onClick: B,
|
|
141
|
+
disabled: O || z.invalid,
|
|
142
|
+
children: [/* @__PURE__ */ f(c, { className: "mr-1 h-4 w-4" }), O ? "Saving..." : "Save Changes"]
|
|
111
143
|
})]
|
|
112
144
|
}),
|
|
113
|
-
|
|
145
|
+
j && /* @__PURE__ */ f("div", {
|
|
146
|
+
role: "status",
|
|
147
|
+
className: "p-3 bg-muted text-status-success-text rounded-md text-sm",
|
|
148
|
+
children: "Changes saved."
|
|
149
|
+
}),
|
|
150
|
+
k && /* @__PURE__ */ f("div", {
|
|
114
151
|
role: "alert",
|
|
115
152
|
className: "p-3 bg-destructive/10 text-destructive rounded-md text-sm",
|
|
116
|
-
children:
|
|
153
|
+
children: k
|
|
117
154
|
}),
|
|
118
|
-
/* @__PURE__ */
|
|
155
|
+
/* @__PURE__ */ p(h, { children: [/* @__PURE__ */ f(_, { children: /* @__PURE__ */ f(v, { children: "Task Details" }) }), /* @__PURE__ */ p(g, {
|
|
119
156
|
className: "space-y-4",
|
|
120
157
|
children: [
|
|
121
|
-
/* @__PURE__ */
|
|
158
|
+
/* @__PURE__ */ p("div", { children: [/* @__PURE__ */ f("label", {
|
|
122
159
|
className: "text-sm font-medium",
|
|
123
160
|
children: "Title"
|
|
124
|
-
}), /* @__PURE__ */
|
|
125
|
-
value:
|
|
126
|
-
onChange: (e) =>
|
|
127
|
-
...
|
|
161
|
+
}), /* @__PURE__ */ f(y, {
|
|
162
|
+
value: L.title,
|
|
163
|
+
onChange: (e) => R({
|
|
164
|
+
...L,
|
|
128
165
|
title: e.target.value
|
|
129
166
|
}),
|
|
130
167
|
className: "mt-1"
|
|
131
168
|
})] }),
|
|
132
|
-
/* @__PURE__ */
|
|
169
|
+
/* @__PURE__ */ p("div", { children: [/* @__PURE__ */ f("label", {
|
|
133
170
|
className: "text-sm font-medium",
|
|
134
171
|
children: "Description"
|
|
135
|
-
}), /* @__PURE__ */
|
|
172
|
+
}), /* @__PURE__ */ f("textarea", {
|
|
136
173
|
className: "mt-1 w-full rounded-md border border-input bg-background px-3 py-2 text-sm min-h-[100px]",
|
|
137
|
-
value:
|
|
138
|
-
onChange: (e) =>
|
|
139
|
-
...
|
|
174
|
+
value: L.description,
|
|
175
|
+
onChange: (e) => R({
|
|
176
|
+
...L,
|
|
140
177
|
description: e.target.value
|
|
141
178
|
})
|
|
142
179
|
})] }),
|
|
143
|
-
/* @__PURE__ */
|
|
180
|
+
/* @__PURE__ */ p("div", {
|
|
144
181
|
className: "grid grid-cols-3 gap-4",
|
|
145
182
|
children: [
|
|
146
|
-
/* @__PURE__ */
|
|
183
|
+
/* @__PURE__ */ p("div", { children: [/* @__PURE__ */ f("label", {
|
|
147
184
|
className: "text-sm font-medium",
|
|
148
185
|
children: "Priority"
|
|
149
|
-
}), /* @__PURE__ */
|
|
186
|
+
}), /* @__PURE__ */ f("select", {
|
|
150
187
|
className: "mt-1 w-full rounded-md border border-input bg-background px-3 py-2 text-sm",
|
|
151
|
-
value:
|
|
152
|
-
onChange: (e) =>
|
|
153
|
-
...
|
|
188
|
+
value: L.priority,
|
|
189
|
+
onChange: (e) => R({
|
|
190
|
+
...L,
|
|
154
191
|
priority: e.target.value
|
|
155
192
|
}),
|
|
156
|
-
children:
|
|
157
|
-
"LOW",
|
|
158
|
-
"MEDIUM",
|
|
159
|
-
"HIGH",
|
|
160
|
-
"CRITICAL"
|
|
161
|
-
].map((e) => /* @__PURE__ */ u("option", {
|
|
193
|
+
children: i.map((e) => /* @__PURE__ */ f("option", {
|
|
162
194
|
value: e,
|
|
163
195
|
children: e.toLowerCase()
|
|
164
196
|
}, e))
|
|
165
197
|
})] }),
|
|
166
|
-
/* @__PURE__ */
|
|
198
|
+
/* @__PURE__ */ p("div", { children: [/* @__PURE__ */ f("label", {
|
|
167
199
|
className: "text-sm font-medium",
|
|
168
200
|
children: "Type"
|
|
169
|
-
}), /* @__PURE__ */
|
|
201
|
+
}), /* @__PURE__ */ f("select", {
|
|
170
202
|
className: "mt-1 w-full rounded-md border border-input bg-background px-3 py-2 text-sm",
|
|
171
|
-
value:
|
|
172
|
-
onChange: (e) =>
|
|
173
|
-
...
|
|
203
|
+
value: L.type,
|
|
204
|
+
onChange: (e) => R({
|
|
205
|
+
...L,
|
|
174
206
|
type: e.target.value
|
|
175
207
|
}),
|
|
176
208
|
children: [
|
|
@@ -179,31 +211,31 @@ function b() {
|
|
|
179
211
|
"TASK",
|
|
180
212
|
"EPIC",
|
|
181
213
|
"SUB_TASK"
|
|
182
|
-
].map((e) => /* @__PURE__ */
|
|
214
|
+
].map((e) => /* @__PURE__ */ f("option", {
|
|
183
215
|
value: e,
|
|
184
216
|
children: e.toLowerCase().replace("_", " ")
|
|
185
217
|
}, e))
|
|
186
218
|
})] }),
|
|
187
|
-
/* @__PURE__ */
|
|
188
|
-
/* @__PURE__ */
|
|
219
|
+
/* @__PURE__ */ p("div", { children: [
|
|
220
|
+
/* @__PURE__ */ f("label", {
|
|
189
221
|
htmlFor: "task-story-points",
|
|
190
222
|
className: "text-sm font-medium",
|
|
191
223
|
children: "Story Points"
|
|
192
224
|
}),
|
|
193
|
-
/* @__PURE__ */
|
|
225
|
+
/* @__PURE__ */ f(y, {
|
|
194
226
|
id: "task-story-points",
|
|
195
227
|
type: "number",
|
|
196
228
|
min: 0,
|
|
197
229
|
step: 1,
|
|
198
|
-
value:
|
|
199
|
-
onChange: (e) =>
|
|
200
|
-
...
|
|
230
|
+
value: L.storyPoints,
|
|
231
|
+
onChange: (e) => R({
|
|
232
|
+
...L,
|
|
201
233
|
storyPoints: e.target.value
|
|
202
234
|
}),
|
|
203
|
-
"aria-invalid":
|
|
235
|
+
"aria-invalid": z.invalid,
|
|
204
236
|
className: "mt-1"
|
|
205
237
|
}),
|
|
206
|
-
|
|
238
|
+
z.invalid && /* @__PURE__ */ f("p", {
|
|
207
239
|
role: "alert",
|
|
208
240
|
className: "mt-1 text-xs text-destructive",
|
|
209
241
|
children: "Story points must be a whole number, 0 or more."
|
|
@@ -211,26 +243,26 @@ function b() {
|
|
|
211
243
|
] })
|
|
212
244
|
]
|
|
213
245
|
}),
|
|
214
|
-
/* @__PURE__ */
|
|
246
|
+
/* @__PURE__ */ p("div", {
|
|
215
247
|
className: "grid grid-cols-2 gap-4",
|
|
216
|
-
children: [/* @__PURE__ */
|
|
248
|
+
children: [/* @__PURE__ */ p("div", { children: [/* @__PURE__ */ f("label", {
|
|
217
249
|
className: "text-sm font-medium",
|
|
218
250
|
children: "Due Date"
|
|
219
|
-
}), /* @__PURE__ */
|
|
251
|
+
}), /* @__PURE__ */ f(y, {
|
|
220
252
|
type: "date",
|
|
221
|
-
value:
|
|
222
|
-
onChange: (e) =>
|
|
223
|
-
...
|
|
253
|
+
value: L.dueDate,
|
|
254
|
+
onChange: (e) => R({
|
|
255
|
+
...L,
|
|
224
256
|
dueDate: e.target.value
|
|
225
257
|
}),
|
|
226
258
|
className: "mt-1"
|
|
227
|
-
})] }), /* @__PURE__ */
|
|
259
|
+
})] }), /* @__PURE__ */ p("div", { children: [/* @__PURE__ */ f("label", {
|
|
228
260
|
className: "text-sm font-medium",
|
|
229
261
|
children: "Labels"
|
|
230
|
-
}), /* @__PURE__ */
|
|
231
|
-
value:
|
|
232
|
-
onChange: (e) =>
|
|
233
|
-
...
|
|
262
|
+
}), /* @__PURE__ */ f(y, {
|
|
263
|
+
value: L.labels,
|
|
264
|
+
onChange: (e) => R({
|
|
265
|
+
...L,
|
|
234
266
|
labels: e.target.value
|
|
235
267
|
}),
|
|
236
268
|
className: "mt-1"
|
|
@@ -242,6 +274,6 @@ function b() {
|
|
|
242
274
|
});
|
|
243
275
|
}
|
|
244
276
|
//#endregion
|
|
245
|
-
export {
|
|
277
|
+
export { S as TasksEditTaskPagePage };
|
|
246
278
|
|
|
247
279
|
//# sourceMappingURL=TasksEditTaskPagePage.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TasksEditTaskPagePage.js","names":[],"sources":["../../../src/planmagnet/pages/TasksEditTaskPagePage.tsx"],"sourcesContent":["// eslint-disable-next-line @typescript-eslint/ban-ts-comment\n// @ts-nocheck\nimport { useState, useMemo } from 'react';\nimport { gql } from '@apollo/client';\nimport { useQuery, useMutation } from '@apollo/client/react';\nimport { Card, CardContent, CardHeader, CardTitle, Button, Input } from '@burdenoff/fe-libs/ui';\nimport { Save, ArrowLeft } from 'lucide-react';\nimport { usePlanMagnet, usePlanMagnetNavigate } from '../providers/PlanMagnetProvider';\nimport { parseIntField } from '../utils/formValidation';\n\nconst GET_WORK_ITEM = gql`\n query GetWorkItem($workItemId: ID!) {\n planmagnetWorkItem(id: $workItemId) {\n id\n title\n description\n type\n status\n priority\n key\n storyPoints\n dueDate\n labels\n tags\n createdAt\n updatedAt\n }\n }\n`;\n\nconst UPDATE_WORK_ITEM = gql`\n mutation UpdateWorkItem($workItemId: ID!, $input: PlanmagnetUpdateWorkItemInput!) {\n planmagnetUpdateWorkItem(id: $workItemId, input: $input) {\n id\n title\n description\n type\n status\n priority\n storyPoints\n dueDate\n labels\n updatedAt\n }\n }\n`;\n\ninterface WorkItemNode {\n id: string;\n title: string;\n description: string | null;\n type: string;\n status: string;\n priority: string;\n key: string;\n storyPoints: number | null;\n dueDate: string | null;\n labels: string[];\n tags: string[];\n createdAt: string;\n updatedAt: string;\n}\n\nexport function TasksEditTaskPagePage() {\n const { workspaceId } = usePlanMagnet();\n\n // In a real app, workItemId comes from the route params.\n // For now we use a placeholder that the host shell should provide.\n const workItemId = new URLSearchParams(window.location.search).get('taskId') ?? '';\n const navigate = usePlanMagnetNavigate();\n\n const { data, loading, error } = useQuery<{\n planmagnetWorkItem: WorkItemNode;\n }>(GET_WORK_ITEM, {\n variables: { workItemId },\n skip: !workspaceId || !workItemId,\n });\n\n const [updateWorkItem, { loading: saving, error: saveError }] = useMutation(UPDATE_WORK_ITEM, {\n refetchQueries: ['GetWorkItems', 'GetWorkItem'],\n });\n\n const workItem = data?.planmagnetWorkItem;\n\n const defaultForm = useMemo(\n () => ({\n title: workItem?.title ?? '',\n description: workItem?.description ?? '',\n priority: workItem?.priority ?? 'MEDIUM',\n type: workItem?.type ?? 'STORY',\n storyPoints: workItem?.storyPoints?.toString() ?? '0',\n labels: (workItem?.labels ?? []).join(', '),\n dueDate: workItem?.dueDate ?? '',\n }),\n [workItem]\n );\n\n const [formOverrides, setFormOverrides] = useState<Record<string, string>>({});\n const form = { ...defaultForm, ...formOverrides };\n const setForm = (updates: Record<string, string>) => setFormOverrides(updates);\n\n // Story points are a whole number, 0 or more (BOFF-7833); the service refuses anything else.\n const storyPoints = parseIntField(form.storyPoints, { min: 0 });\n\n const handleSave = async () => {\n if (!workspaceId || !workItemId || storyPoints.invalid) return;\n // mutation-error: shown from the hook's `error`; nothing runs on failure.\n await updateWorkItem({\n variables: {\n workItemId,\n input: {\n title: form.title,\n description: form.description || undefined,\n priority: form.priority,\n type: form.type,\n storyPoints: storyPoints.value,\n labels: form.labels\n ? form.labels\n .split(',')\n .map((l) => l.trim())\n .filter(Boolean)\n : undefined,\n dueDate: form.dueDate || undefined,\n },\n },\n });\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 <div className=\"animate-spin h-8 w-8 border-2 border-primary border-t-transparent rounded-full\" />\n </div>\n );\n }\n\n if (error) {\n return <div className=\"p-6 text-destructive\">Error: {error.message}</div>;\n }\n\n if (!data?.planmagnetWorkItem) {\n return <div className=\"p-6 text-muted-foreground\">Task not found.</div>;\n }\n\n const task = data.planmagnetWorkItem;\n\n return (\n <div className=\"space-y-6 p-6 max-w-4xl\">\n <div className=\"flex items-center justify-between\">\n <div className=\"flex items-center gap-3\">\n <Button\n variant=\"ghost\"\n size=\"sm\"\n aria-label=\"Back to the task\"\n onClick={() =>\n navigate(`/tasks/task-detail-page?taskId=${encodeURIComponent(workItemId)}`)\n }\n >\n <ArrowLeft className=\"h-4 w-4\" />\n </Button>\n <div>\n <h1 className=\"text-2xl font-semibold\">Edit Task</h1>\n <p className=\"text-sm text-muted-foreground\">{task.title}</p>\n </div>\n </div>\n <Button size=\"sm\" onClick={handleSave} disabled={saving || storyPoints.invalid}>\n <Save className=\"mr-1 h-4 w-4\" />\n {saving ? 'Saving...' : 'Save Changes'}\n </Button>\n </div>\n {saveError && (\n <div role=\"alert\" className=\"p-3 bg-destructive/10 text-destructive rounded-md text-sm\">\n {saveError.message}\n </div>\n )}\n <Card>\n <CardHeader>\n <CardTitle>Task Details</CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-4\">\n <div>\n <label className=\"text-sm font-medium\">Title</label>\n <Input\n value={form.title}\n onChange={(e) => setForm({ ...form, title: e.target.value })}\n className=\"mt-1\"\n />\n </div>\n <div>\n <label className=\"text-sm font-medium\">Description</label>\n <textarea\n className=\"mt-1 w-full rounded-md border border-input bg-background px-3 py-2 text-sm min-h-[100px]\"\n value={form.description}\n onChange={(e) => setForm({ ...form, description: e.target.value })}\n />\n </div>\n <div className=\"grid grid-cols-3 gap-4\">\n <div>\n <label className=\"text-sm font-medium\">Priority</label>\n <select\n className=\"mt-1 w-full rounded-md border border-input bg-background px-3 py-2 text-sm\"\n value={form.priority}\n onChange={(e) => setForm({ ...form, priority: e.target.value })}\n >\n {['LOW', 'MEDIUM', 'HIGH', 'CRITICAL'].map((p) => (\n <option key={p} value={p}>\n {p.toLowerCase()}\n </option>\n ))}\n </select>\n </div>\n <div>\n <label className=\"text-sm font-medium\">Type</label>\n <select\n className=\"mt-1 w-full rounded-md border border-input bg-background px-3 py-2 text-sm\"\n value={form.type}\n onChange={(e) => setForm({ ...form, type: e.target.value })}\n >\n {['STORY', 'BUG', 'TASK', 'EPIC', 'SUB_TASK'].map((t) => (\n <option key={t} value={t}>\n {t.toLowerCase().replace('_', ' ')}\n </option>\n ))}\n </select>\n </div>\n <div>\n <label htmlFor=\"task-story-points\" className=\"text-sm font-medium\">\n Story Points\n </label>\n <Input\n id=\"task-story-points\"\n type=\"number\"\n min={0}\n step={1}\n value={form.storyPoints}\n onChange={(e) => setForm({ ...form, storyPoints: e.target.value })}\n aria-invalid={storyPoints.invalid}\n className=\"mt-1\"\n />\n {storyPoints.invalid && (\n <p role=\"alert\" className=\"mt-1 text-xs text-destructive\">\n Story points must be a whole number, 0 or more.\n </p>\n )}\n </div>\n </div>\n <div className=\"grid grid-cols-2 gap-4\">\n <div>\n <label className=\"text-sm font-medium\">Due Date</label>\n <Input\n type=\"date\"\n value={form.dueDate}\n onChange={(e) => setForm({ ...form, dueDate: e.target.value })}\n className=\"mt-1\"\n />\n </div>\n <div>\n <label className=\"text-sm font-medium\">Labels</label>\n <Input\n value={form.labels}\n onChange={(e) => setForm({ ...form, labels: e.target.value })}\n className=\"mt-1\"\n />\n </div>\n </div>\n </CardContent>\n </Card>\n </div>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"TasksEditTaskPagePage.js","names":[],"sources":["../../../src/planmagnet/pages/TasksEditTaskPagePage.tsx"],"sourcesContent":["// eslint-disable-next-line @typescript-eslint/ban-ts-comment\n// @ts-nocheck\nimport { useState, useMemo } from 'react';\nimport { gql } from '@apollo/client';\nimport { useQuery, useMutation } from '@apollo/client/react';\nimport { Card, CardContent, CardHeader, CardTitle, Button, Input } from '@burdenoff/fe-libs/ui';\nimport { Save, ArrowLeft } from 'lucide-react';\nimport { usePlanMagnet, usePlanMagnetNavigate } from '../providers/PlanMagnetProvider';\nimport { parseIntField } from '../utils/formValidation';\nimport { throwOnError } from '../utils/mutationResult';\nimport { WORK_ITEM_PRIORITIES } from '../controls/WorkItemControls';\n\nconst GET_WORK_ITEM = gql`\n query GetWorkItem($workItemId: ID!) {\n planmagnetWorkItem(id: $workItemId) {\n id\n title\n description\n type\n status\n priority\n key\n storyPoints\n dueDate\n labels\n tags\n createdAt\n updatedAt\n }\n }\n`;\n\nconst UPDATE_WORK_ITEM = gql`\n mutation UpdateWorkItem($workItemId: ID!, $input: PlanmagnetUpdateWorkItemInput!) {\n planmagnetUpdateWorkItem(id: $workItemId, input: $input) {\n id\n title\n description\n type\n status\n priority\n storyPoints\n dueDate\n labels\n updatedAt\n }\n }\n`;\n\ninterface WorkItemNode {\n id: string;\n title: string;\n description: string | null;\n type: string;\n status: string;\n priority: string;\n key: string;\n storyPoints: number | null;\n dueDate: string | null;\n labels: string[];\n tags: string[];\n createdAt: string;\n updatedAt: string;\n}\n\nexport function TasksEditTaskPagePage() {\n const { workspaceId } = usePlanMagnet();\n\n // In a real app, workItemId comes from the route params.\n // For now we use a placeholder that the host shell should provide.\n const workItemId = new URLSearchParams(window.location.search).get('taskId') ?? '';\n const navigate = usePlanMagnetNavigate();\n\n const { data, loading, error } = useQuery<{\n planmagnetWorkItem: WorkItemNode;\n }>(GET_WORK_ITEM, {\n variables: { workItemId },\n skip: !workspaceId || !workItemId,\n });\n\n const [updateWorkItem, { loading: saving }] = useMutation(UPDATE_WORK_ITEM, {\n refetchQueries: ['GetWorkItems', 'GetWorkItemDetail', 'GetWorkItemCounts', 'ProjectBoard'],\n awaitRefetchQueries: true,\n });\n const [saveError, setSaveError] = useState<string | null>(null);\n const [saved, setSaved] = useState(false);\n\n const workItem = data?.planmagnetWorkItem;\n\n const defaultForm = useMemo(\n () => ({\n title: workItem?.title ?? '',\n description: workItem?.description ?? '',\n priority: workItem?.priority ?? 'MEDIUM',\n type: workItem?.type ?? 'STORY',\n storyPoints: workItem?.storyPoints?.toString() ?? '',\n labels: (workItem?.labels ?? []).join(', '),\n // A date input needs YYYY-MM-DD; the API returns a full ISO timestamp.\n dueDate: workItem?.dueDate ? String(workItem.dueDate).slice(0, 10) : '',\n }),\n [workItem]\n );\n\n const [formOverrides, setFormOverrides] = useState<Record<string, string>>({});\n const form = { ...defaultForm, ...formOverrides };\n const setForm = (updates: Record<string, string>) => setFormOverrides(updates);\n\n // Story points are a whole number, 0 or more (BOFF-7833); the service refuses anything else.\n const storyPoints = parseIntField(form.storyPoints, { min: 0 });\n\n // BOFF-7979: only changed fields are sent; an emptied field is cleared (it used to be omitted, so the old value\n // stayed); success is confirmed (there was no message at all).\n const handleSave = async () => {\n if (!workspaceId || !workItemId || storyPoints.invalid) return;\n if (!form.title.trim()) {\n setSaveError('A task needs a title.');\n return;\n }\n const labelList = (v: string) =>\n v\n .split(',')\n .map((l) => l.trim())\n .filter(Boolean);\n const next: Record<string, unknown> = {\n title: form.title.trim(),\n description: form.description.trim() || null,\n priority: form.priority,\n type: form.type,\n storyPoints: storyPoints.value ?? null,\n labels: labelList(form.labels),\n dueDate: form.dueDate || null,\n };\n const before: Record<string, unknown> = {\n title: defaultForm.title,\n description: defaultForm.description.trim() || null,\n priority: defaultForm.priority,\n type: defaultForm.type,\n storyPoints: defaultForm.storyPoints === '' ? null : Number(defaultForm.storyPoints),\n labels: labelList(defaultForm.labels),\n dueDate: defaultForm.dueDate || null,\n };\n const input = Object.fromEntries(\n Object.entries(next).filter(([k, v]) => JSON.stringify(v) !== JSON.stringify(before[k]))\n );\n setSaveError(null);\n setSaved(false);\n if (Object.keys(input).length === 0) {\n setSaved(true);\n return;\n }\n try {\n await throwOnError(updateWorkItem({ variables: { workItemId, input } }));\n setSaved(true);\n } catch (e) {\n setSaveError(e instanceof Error ? e.message : 'The task could not be saved.');\n }\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 <div className=\"animate-spin h-8 w-8 border-2 border-primary border-t-transparent rounded-full\" />\n </div>\n );\n }\n\n if (error) {\n return <div className=\"p-6 text-destructive\">Error: {error.message}</div>;\n }\n\n if (!data?.planmagnetWorkItem) {\n return <div className=\"p-6 text-muted-foreground\">Task not found.</div>;\n }\n\n const task = data.planmagnetWorkItem;\n\n return (\n <div className=\"space-y-6 p-6 max-w-4xl\">\n <div className=\"flex items-center justify-between\">\n <div className=\"flex items-center gap-3\">\n <Button\n variant=\"ghost\"\n size=\"sm\"\n aria-label=\"Back to the task\"\n onClick={() =>\n navigate(`/tasks/task-detail-page?taskId=${encodeURIComponent(workItemId)}`)\n }\n >\n <ArrowLeft className=\"h-4 w-4\" />\n </Button>\n <div>\n <h1 className=\"text-2xl font-semibold\">Edit Task</h1>\n <p className=\"text-sm text-muted-foreground\">{task.title}</p>\n </div>\n </div>\n <Button size=\"sm\" onClick={handleSave} disabled={saving || storyPoints.invalid}>\n <Save className=\"mr-1 h-4 w-4\" />\n {saving ? 'Saving...' : 'Save Changes'}\n </Button>\n </div>\n {saved && (\n <div role=\"status\" className=\"p-3 bg-muted text-status-success-text rounded-md text-sm\">\n Changes saved.\n </div>\n )}\n {saveError && (\n <div role=\"alert\" className=\"p-3 bg-destructive/10 text-destructive rounded-md text-sm\">\n {saveError}\n </div>\n )}\n <Card>\n <CardHeader>\n <CardTitle>Task Details</CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-4\">\n <div>\n <label className=\"text-sm font-medium\">Title</label>\n <Input\n value={form.title}\n onChange={(e) => setForm({ ...form, title: e.target.value })}\n className=\"mt-1\"\n />\n </div>\n <div>\n <label className=\"text-sm font-medium\">Description</label>\n <textarea\n className=\"mt-1 w-full rounded-md border border-input bg-background px-3 py-2 text-sm min-h-[100px]\"\n value={form.description}\n onChange={(e) => setForm({ ...form, description: e.target.value })}\n />\n </div>\n <div className=\"grid grid-cols-3 gap-4\">\n <div>\n <label className=\"text-sm font-medium\">Priority</label>\n <select\n className=\"mt-1 w-full rounded-md border border-input bg-background px-3 py-2 text-sm\"\n value={form.priority}\n onChange={(e) => setForm({ ...form, priority: e.target.value })}\n >\n {/* Every WorkItemPriority: NONE was missing, so a NONE task showed as \"low\" (BOFF-7985). */}\n {WORK_ITEM_PRIORITIES.map((p) => (\n <option key={p} value={p}>\n {p.toLowerCase()}\n </option>\n ))}\n </select>\n </div>\n <div>\n <label className=\"text-sm font-medium\">Type</label>\n <select\n className=\"mt-1 w-full rounded-md border border-input bg-background px-3 py-2 text-sm\"\n value={form.type}\n onChange={(e) => setForm({ ...form, type: e.target.value })}\n >\n {['STORY', 'BUG', 'TASK', 'EPIC', 'SUB_TASK'].map((t) => (\n <option key={t} value={t}>\n {t.toLowerCase().replace('_', ' ')}\n </option>\n ))}\n </select>\n </div>\n <div>\n <label htmlFor=\"task-story-points\" className=\"text-sm font-medium\">\n Story Points\n </label>\n <Input\n id=\"task-story-points\"\n type=\"number\"\n min={0}\n step={1}\n value={form.storyPoints}\n onChange={(e) => setForm({ ...form, storyPoints: e.target.value })}\n aria-invalid={storyPoints.invalid}\n className=\"mt-1\"\n />\n {storyPoints.invalid && (\n <p role=\"alert\" className=\"mt-1 text-xs text-destructive\">\n Story points must be a whole number, 0 or more.\n </p>\n )}\n </div>\n </div>\n <div className=\"grid grid-cols-2 gap-4\">\n <div>\n <label className=\"text-sm font-medium\">Due Date</label>\n <Input\n type=\"date\"\n value={form.dueDate}\n onChange={(e) => setForm({ ...form, dueDate: e.target.value })}\n className=\"mt-1\"\n />\n </div>\n <div>\n <label className=\"text-sm font-medium\">Labels</label>\n <Input\n value={form.labels}\n onChange={(e) => setForm({ ...form, labels: e.target.value })}\n className=\"mt-1\"\n />\n </div>\n </div>\n </CardContent>\n </Card>\n </div>\n );\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TasksTaskDetailPagePage.d.ts","sourceRoot":"","sources":["../../../src/planmagnet/pages/TasksTaskDetailPagePage.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"TasksTaskDetailPagePage.d.ts","sourceRoot":"","sources":["../../../src/planmagnet/pages/TasksTaskDetailPagePage.tsx"],"names":[],"mappings":"AA+UA,wBAAgB,uBAAuB,4CAuItC"}
|