@burdenoff/microfe-planmagnet 2026.1001.2 → 2026.1001.3
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/PlanMagnetRoot.d.ts.map +1 -1
- package/dist/planmagnet/PlanMagnetRoot.js +160 -153
- package/dist/planmagnet/PlanMagnetRoot.js.map +1 -1
- package/dist/planmagnet/PlanMagnetRoutes.d.ts.map +1 -1
- package/dist/planmagnet/PlanMagnetRoutes.js +121 -109
- package/dist/planmagnet/PlanMagnetRoutes.js.map +1 -1
- package/dist/planmagnet/controls/MilestoneControls.d.ts +2 -0
- package/dist/planmagnet/controls/MilestoneControls.d.ts.map +1 -1
- package/dist/planmagnet/controls/MilestoneControls.js +89 -72
- package/dist/planmagnet/controls/MilestoneControls.js.map +1 -1
- package/dist/planmagnet/meetings/MeetingActionItemsPanel.d.ts +17 -0
- package/dist/planmagnet/meetings/MeetingActionItemsPanel.d.ts.map +1 -0
- package/dist/planmagnet/meetings/MeetingActionItemsPanel.js +218 -0
- package/dist/planmagnet/meetings/MeetingActionItemsPanel.js.map +1 -0
- package/dist/planmagnet/meetings/MeetingsCard.d.ts +7 -0
- package/dist/planmagnet/meetings/MeetingsCard.d.ts.map +1 -0
- package/dist/planmagnet/meetings/MeetingsCard.js +108 -0
- package/dist/planmagnet/meetings/MeetingsCard.js.map +1 -0
- package/dist/planmagnet/meetings/ScheduleCeremoniesDialog.d.ts +9 -0
- package/dist/planmagnet/meetings/ScheduleCeremoniesDialog.d.ts.map +1 -0
- package/dist/planmagnet/meetings/ScheduleCeremoniesDialog.js +232 -0
- package/dist/planmagnet/meetings/ScheduleCeremoniesDialog.js.map +1 -0
- package/dist/planmagnet/meetings/ScheduleMeetingDialog.d.ts +19 -0
- package/dist/planmagnet/meetings/ScheduleMeetingDialog.d.ts.map +1 -0
- package/dist/planmagnet/meetings/ScheduleMeetingDialog.js +226 -0
- package/dist/planmagnet/meetings/ScheduleMeetingDialog.js.map +1 -0
- package/dist/planmagnet/meetings/UnlinkMeetingDialog.d.ts +14 -0
- package/dist/planmagnet/meetings/UnlinkMeetingDialog.d.ts.map +1 -0
- package/dist/planmagnet/meetings/UnlinkMeetingDialog.js +81 -0
- package/dist/planmagnet/meetings/UnlinkMeetingDialog.js.map +1 -0
- package/dist/planmagnet/meetings/meetingActions.d.ts +57 -0
- package/dist/planmagnet/meetings/meetingActions.d.ts.map +1 -0
- package/dist/planmagnet/meetings/meetingActions.js +51 -0
- package/dist/planmagnet/meetings/meetingActions.js.map +1 -0
- package/dist/planmagnet/meetings/meetingGraphql.d.ts +29 -0
- package/dist/planmagnet/meetings/meetingGraphql.d.ts.map +1 -0
- package/dist/planmagnet/meetings/meetingGraphql.js +166 -0
- package/dist/planmagnet/meetings/meetingGraphql.js.map +1 -0
- package/dist/planmagnet/meetings/meetingModel.d.ts +74 -0
- package/dist/planmagnet/meetings/meetingModel.d.ts.map +1 -0
- package/dist/planmagnet/meetings/meetingModel.js +88 -0
- package/dist/planmagnet/meetings/meetingModel.js.map +1 -0
- package/dist/planmagnet/pages/MeetingsMeetingDetailPagePage.d.ts +2 -0
- package/dist/planmagnet/pages/MeetingsMeetingDetailPagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/MeetingsMeetingDetailPagePage.js +197 -0
- package/dist/planmagnet/pages/MeetingsMeetingDetailPagePage.js.map +1 -0
- package/dist/planmagnet/pages/MeetingsMeetingsPagePage.d.ts +2 -0
- package/dist/planmagnet/pages/MeetingsMeetingsPagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/MeetingsMeetingsPagePage.js +173 -0
- package/dist/planmagnet/pages/MeetingsMeetingsPagePage.js.map +1 -0
- package/dist/planmagnet/pages/ProjectsMilestonesPagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/ProjectsMilestonesPagePage.js +73 -52
- package/dist/planmagnet/pages/ProjectsMilestonesPagePage.js.map +1 -1
- package/dist/planmagnet/pages/ProjectsPlanningDetailPagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/ProjectsPlanningDetailPagePage.js +205 -190
- package/dist/planmagnet/pages/ProjectsPlanningDetailPagePage.js.map +1 -1
- package/dist/planmagnet/pages/ProjectsProjectDetailPagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/ProjectsProjectDetailPagePage.js +192 -187
- package/dist/planmagnet/pages/ProjectsProjectDetailPagePage.js.map +1 -1
- package/dist/planmagnet/reports/ShareDialog.js +65 -65
- package/dist/planmagnet/reports/ShareDialog.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
import { usePlanMagnet as e, usePlanMagnetNavigate as t } from "../providers/PlanMagnetProvider.js";
|
|
2
2
|
import { PersonName as n } from "../people/People.js";
|
|
3
|
-
import { detailPath as r, rowLinkProps as i } from "../utils/rowNavigation.js";
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
3
|
+
import { detailPath as r, rowLinkProps as i, stopRowActivation as a } from "../utils/rowNavigation.js";
|
|
4
|
+
import { ScheduleMeetingDialog as o } from "../meetings/ScheduleMeetingDialog.js";
|
|
5
|
+
import { NewMilestoneDialog as s } from "../create/CreateDialogs.js";
|
|
6
|
+
import { MilestoneProgressBar as c } from "../milestones/MilestoneControls.js";
|
|
7
|
+
import { useState as l } from "react";
|
|
8
|
+
import { Calendar as u, Target as d, User as f } from "lucide-react";
|
|
9
|
+
import { gql as p } from "@apollo/client";
|
|
10
|
+
import { useQuery as m } from "@apollo/client/react";
|
|
11
|
+
import { jsx as h, jsxs as g } from "react/jsx-runtime";
|
|
12
|
+
import { Badge as _, Card as v, CardContent as y, CardHeader as b, CardTitle as x } from "@burdenoff/fe-libs/ui";
|
|
12
13
|
//#region src/planmagnet/pages/ProjectsMilestonesPagePage.tsx
|
|
13
|
-
var
|
|
14
|
+
var S = p`
|
|
14
15
|
query GetMilestones($workspaceId: ID!, $filter: PlanmagnetMilestoneFilter) {
|
|
15
16
|
planmagnetMilestones(workspaceId: $workspaceId, filter: $filter, pagination: { first: 100 }) {
|
|
16
17
|
items {
|
|
@@ -38,13 +39,13 @@ var b = d`
|
|
|
38
39
|
totalCount
|
|
39
40
|
}
|
|
40
41
|
}
|
|
41
|
-
`,
|
|
42
|
+
`, C = {
|
|
42
43
|
PENDING: "bg-gray-100 text-gray-800",
|
|
43
44
|
IN_PROGRESS: "bg-blue-100 text-blue-800",
|
|
44
45
|
COMPLETED: "bg-green-100 text-green-800",
|
|
45
46
|
MISSED: "bg-red-100 text-red-800",
|
|
46
47
|
CANCELLED: "bg-red-100 text-red-800"
|
|
47
|
-
},
|
|
48
|
+
}, w = [
|
|
48
49
|
"all",
|
|
49
50
|
"PENDING",
|
|
50
51
|
"IN_PROGRESS",
|
|
@@ -52,93 +53,113 @@ var b = d`
|
|
|
52
53
|
"MISSED",
|
|
53
54
|
"CANCELLED"
|
|
54
55
|
];
|
|
55
|
-
function
|
|
56
|
-
let { workspaceId:
|
|
57
|
-
workspaceId:
|
|
58
|
-
filter:
|
|
56
|
+
function T() {
|
|
57
|
+
let { workspaceId: p } = e(), T = t(), [E, D] = l("all"), { data: O, loading: k, error: A } = m(S, { variables: {
|
|
58
|
+
workspaceId: p ?? "default",
|
|
59
|
+
filter: E === "all" ? void 0 : { status: E }
|
|
59
60
|
} });
|
|
60
|
-
if (
|
|
61
|
+
if (k && !O) return /* @__PURE__ */ h("div", {
|
|
61
62
|
className: "flex items-center justify-center p-12",
|
|
62
|
-
children: /* @__PURE__ */
|
|
63
|
+
children: /* @__PURE__ */ h("div", { className: "animate-spin h-8 w-8 border-2 border-primary border-t-transparent rounded-full" })
|
|
63
64
|
});
|
|
64
|
-
let
|
|
65
|
-
return /* @__PURE__ */
|
|
65
|
+
let j = O?.planmagnetMilestones?.items ?? [], M = O?.planmagnetMilestones?.totalCount ?? 0;
|
|
66
|
+
return /* @__PURE__ */ g("div", {
|
|
66
67
|
className: "space-y-6 p-6",
|
|
67
68
|
children: [
|
|
68
|
-
/* @__PURE__ */
|
|
69
|
+
/* @__PURE__ */ g("div", {
|
|
69
70
|
className: "flex items-center justify-between",
|
|
70
|
-
children: [/* @__PURE__ */
|
|
71
|
+
children: [/* @__PURE__ */ g("div", { children: [/* @__PURE__ */ h("h1", {
|
|
71
72
|
className: "text-2xl font-semibold",
|
|
72
73
|
children: "Milestones"
|
|
73
|
-
}), /* @__PURE__ */
|
|
74
|
+
}), /* @__PURE__ */ h("p", {
|
|
74
75
|
className: "text-sm text-muted-foreground",
|
|
75
|
-
children:
|
|
76
|
-
})] }), /* @__PURE__ */
|
|
76
|
+
children: E === "all" ? `${M} milestones across all projects` : `${M} ${E.toLowerCase().replace("_", " ")} milestones`
|
|
77
|
+
})] }), /* @__PURE__ */ h(s, { onCreated: (e) => T(r("/projects/milestone-detail-page", e)) })]
|
|
77
78
|
}),
|
|
78
|
-
/* @__PURE__ */
|
|
79
|
+
/* @__PURE__ */ h("div", {
|
|
79
80
|
className: "flex gap-1",
|
|
80
|
-
children:
|
|
81
|
-
onClick: () =>
|
|
82
|
-
className: `px-3 py-1.5 text-sm rounded-md capitalize ${
|
|
81
|
+
children: w.map((e) => /* @__PURE__ */ h("button", {
|
|
82
|
+
onClick: () => D(e),
|
|
83
|
+
className: `px-3 py-1.5 text-sm rounded-md capitalize ${E === e ? "bg-primary text-primary-foreground" : "text-muted-foreground hover:bg-muted"}`,
|
|
83
84
|
children: e === "all" ? "All" : e.toLowerCase().replace("_", " ")
|
|
84
85
|
}, e))
|
|
85
86
|
}),
|
|
86
|
-
|
|
87
|
+
A && /* @__PURE__ */ g("div", {
|
|
87
88
|
role: "alert",
|
|
88
89
|
className: "rounded-md border border-destructive/40 p-4 text-sm text-destructive",
|
|
89
|
-
children: ["Milestones could not be loaded: ",
|
|
90
|
+
children: ["Milestones could not be loaded: ", A.message]
|
|
90
91
|
}),
|
|
91
|
-
/* @__PURE__ */
|
|
92
|
+
/* @__PURE__ */ h("div", {
|
|
92
93
|
className: "grid grid-cols-1 md:grid-cols-2 gap-4",
|
|
93
|
-
children:
|
|
94
|
-
...i(() =>
|
|
95
|
-
children: [/* @__PURE__ */
|
|
94
|
+
children: j.map((e) => /* @__PURE__ */ g(v, {
|
|
95
|
+
...i(() => T(r("/projects/milestone-detail-page", e.id)), e.name),
|
|
96
|
+
children: [/* @__PURE__ */ h(b, {
|
|
96
97
|
className: "pb-2",
|
|
97
|
-
children: /* @__PURE__ */
|
|
98
|
+
children: /* @__PURE__ */ g("div", {
|
|
98
99
|
className: "flex items-center justify-between",
|
|
99
|
-
children: [/* @__PURE__ */
|
|
100
|
+
children: [/* @__PURE__ */ g(x, {
|
|
100
101
|
className: "text-base flex items-center gap-2",
|
|
101
|
-
children: [/* @__PURE__ */
|
|
102
|
-
}), /* @__PURE__ */
|
|
103
|
-
className: `text-xs px-2 py-0.5 rounded-full capitalize ${
|
|
102
|
+
children: [/* @__PURE__ */ h(d, { className: "h-4 w-4 text-primary" }), e.name]
|
|
103
|
+
}), /* @__PURE__ */ h("span", {
|
|
104
|
+
className: `text-xs px-2 py-0.5 rounded-full capitalize ${C[e.status] ?? "bg-gray-100"}`,
|
|
104
105
|
children: e.status.toLowerCase().replace("_", " ")
|
|
105
106
|
})]
|
|
106
107
|
})
|
|
107
|
-
}), /* @__PURE__ */
|
|
108
|
+
}), /* @__PURE__ */ g(y, {
|
|
108
109
|
className: "space-y-3",
|
|
109
110
|
children: [
|
|
110
|
-
/* @__PURE__ */
|
|
111
|
+
/* @__PURE__ */ h("p", {
|
|
111
112
|
className: "text-sm text-muted-foreground",
|
|
112
113
|
children: e.description ?? "No description"
|
|
113
114
|
}),
|
|
114
|
-
e.workItemProgress && /* @__PURE__ */
|
|
115
|
-
/* @__PURE__ */
|
|
115
|
+
e.workItemProgress && /* @__PURE__ */ h(c, { progress: e.workItemProgress }),
|
|
116
|
+
/* @__PURE__ */ g("div", {
|
|
116
117
|
className: "flex gap-3 text-xs text-muted-foreground",
|
|
117
118
|
children: [
|
|
118
|
-
/* @__PURE__ */
|
|
119
|
+
/* @__PURE__ */ g("span", {
|
|
119
120
|
className: "flex items-center gap-1",
|
|
120
|
-
children: [/* @__PURE__ */
|
|
121
|
+
children: [/* @__PURE__ */ h(u, { className: "h-3 w-3" }), e.dueDate ? new Date(e.dueDate).toLocaleDateString() : "No due date"]
|
|
121
122
|
}),
|
|
122
|
-
e.isOverdue && /* @__PURE__ */
|
|
123
|
+
e.isOverdue && /* @__PURE__ */ h(_, {
|
|
123
124
|
variant: "destructive",
|
|
124
125
|
"data-testid": "milestone-overdue",
|
|
125
126
|
children: "Overdue"
|
|
126
127
|
}),
|
|
127
|
-
e.ownerId && /* @__PURE__ */
|
|
128
|
+
e.ownerId && /* @__PURE__ */ g("span", {
|
|
128
129
|
className: "flex items-center gap-1",
|
|
129
|
-
children: [/* @__PURE__ */
|
|
130
|
+
children: [/* @__PURE__ */ h(f, { className: "h-3 w-3" }), /* @__PURE__ */ h(n, { id: e.ownerId })]
|
|
130
131
|
})
|
|
131
132
|
]
|
|
132
133
|
}),
|
|
133
|
-
/* @__PURE__ */
|
|
134
|
+
/* @__PURE__ */ g("div", {
|
|
134
135
|
className: "text-xs text-muted-foreground",
|
|
135
136
|
children: ["Project: ", e.project?.name ?? "not available"]
|
|
137
|
+
}),
|
|
138
|
+
/* @__PURE__ */ g("div", {
|
|
139
|
+
className: "flex flex-wrap gap-2 border-t pt-2",
|
|
140
|
+
onClick: a,
|
|
141
|
+
"data-testid": "milestone-schedule-actions",
|
|
142
|
+
children: [/* @__PURE__ */ h(o, {
|
|
143
|
+
projectId: e.projectId,
|
|
144
|
+
milestoneId: e.id,
|
|
145
|
+
defaultKind: "MILESTONE_CELEBRATION",
|
|
146
|
+
lockKind: !0,
|
|
147
|
+
defaultTitle: `${e.name} celebration`,
|
|
148
|
+
triggerLabel: "Celebration"
|
|
149
|
+
}), /* @__PURE__ */ h(o, {
|
|
150
|
+
projectId: e.projectId,
|
|
151
|
+
milestoneId: e.id,
|
|
152
|
+
defaultKind: "DEMO",
|
|
153
|
+
lockKind: !0,
|
|
154
|
+
defaultTitle: `${e.name} demo`,
|
|
155
|
+
triggerLabel: "Demo"
|
|
156
|
+
})]
|
|
136
157
|
})
|
|
137
158
|
]
|
|
138
159
|
})]
|
|
139
160
|
}, e.id))
|
|
140
161
|
}),
|
|
141
|
-
!
|
|
162
|
+
!A && j.length === 0 && /* @__PURE__ */ h("p", {
|
|
142
163
|
className: "text-center text-muted-foreground py-8",
|
|
143
164
|
children: "No milestones found."
|
|
144
165
|
})
|
|
@@ -146,6 +167,6 @@ function C() {
|
|
|
146
167
|
});
|
|
147
168
|
}
|
|
148
169
|
//#endregion
|
|
149
|
-
export {
|
|
170
|
+
export { T as ProjectsMilestonesPagePage };
|
|
150
171
|
|
|
151
172
|
//# sourceMappingURL=ProjectsMilestonesPagePage.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ProjectsMilestonesPagePage.js","names":[],"sources":["../../../src/planmagnet/pages/ProjectsMilestonesPagePage.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 } from '@burdenoff/fe-libs/ui';\nimport { Target, Calendar, User } from 'lucide-react';\nimport { usePlanMagnet, usePlanMagnetNavigate } from '../providers/PlanMagnetProvider';\nimport { rowLinkProps, detailPath } from '../utils/rowNavigation';\nimport { PersonName } from '../people/People';\nimport { NewMilestoneDialog } from '../create/CreateDialogs';\nimport { type MilestoneProgress, MilestoneProgressBar } from '../milestones/MilestoneControls';\n\nconst GET_MILESTONES = gql`\n query GetMilestones($workspaceId: ID!, $filter: PlanmagnetMilestoneFilter) {\n planmagnetMilestones(workspaceId: $workspaceId, filter: $filter, pagination: { first: 100 }) {\n items {\n id\n name\n description\n projectId\n project {\n id\n name\n }\n status\n dueDate\n isOverdue\n ownerId\n createdAt\n workItemProgress {\n total\n done\n cancelled\n open\n percentComplete\n }\n }\n totalCount\n }\n }\n`;\n\nconst statusColor: Record<string, string> = {\n PENDING: 'bg-gray-100 text-gray-800',\n IN_PROGRESS: 'bg-blue-100 text-blue-800',\n COMPLETED: 'bg-green-100 text-green-800',\n MISSED: 'bg-red-100 text-red-800',\n CANCELLED: 'bg-red-100 text-red-800',\n};\n\nconst milestoneStatuses = [\n 'all',\n 'PENDING',\n 'IN_PROGRESS',\n 'COMPLETED',\n 'MISSED',\n 'CANCELLED',\n] as const;\n\nexport function ProjectsMilestonesPagePage() {\n const { workspaceId } = usePlanMagnet();\n const navigate = usePlanMagnetNavigate();\n const [filter, setFilter] = 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>>(GET_MILESTONES, {\n variables: {\n workspaceId: workspaceId ?? 'default',\n filter: filter !== 'all' ? { status: filter } : undefined,\n },\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 <div className=\"animate-spin h-8 w-8 border-2 border-primary border-t-transparent rounded-full\" />\n </div>\n );\n // A failed load is shown INSIDE the list area: an early return here replaced the whole page, so the status tabs\n // and New Milestone vanished and a failing tab could not be left (BOFF-7942).\n\n const milestones = data?.planmagnetMilestones?.items ?? [];\n const totalCount = data?.planmagnetMilestones?.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\">Milestones</h1>\n <p className=\"text-sm text-muted-foreground\">\n {/* The count follows the tab: it is the filtered total, so do not call it \"all\". */}\n {filter === 'all'\n ? `${totalCount} milestones across all projects`\n : `${totalCount} ${filter.toLowerCase().replace('_', ' ')} milestones`}\n </p>\n </div>\n <NewMilestoneDialog\n onCreated={(id) => navigate(detailPath('/projects/milestone-detail-page', id))}\n />\n </div>\n <div className=\"flex gap-1\">\n {milestoneStatuses.map((s) => (\n <button\n key={s}\n onClick={() => setFilter(s)}\n className={`px-3 py-1.5 text-sm rounded-md capitalize ${filter === s ? 'bg-primary text-primary-foreground' : 'text-muted-foreground hover:bg-muted'}`}\n >\n {s === 'all' ? 'All' : s.toLowerCase().replace('_', ' ')}\n </button>\n ))}\n </div>\n {error && (\n <div\n role=\"alert\"\n className=\"rounded-md border border-destructive/40 p-4 text-sm text-destructive\"\n >\n Milestones could not be loaded: {error.message}\n </div>\n )}\n <div className=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\n {milestones.map(\n (ms: {\n id: string;\n name: string;\n description: string | null;\n projectId: string;\n project: { id: string; name: string } | null;\n status: string;\n dueDate: string | null;\n isOverdue: boolean;\n ownerId: string | null;\n workItemProgress: MilestoneProgress | null;\n }) => (\n <Card\n key={ms.id}\n {...rowLinkProps(\n () => navigate(detailPath('/projects/milestone-detail-page', ms.id)),\n ms.name\n )}\n >\n <CardHeader className=\"pb-2\">\n <div className=\"flex items-center justify-between\">\n <CardTitle className=\"text-base flex items-center gap-2\">\n <Target className=\"h-4 w-4 text-primary\" />\n {ms.name}\n </CardTitle>\n <span\n className={`text-xs px-2 py-0.5 rounded-full capitalize ${statusColor[ms.status] ?? 'bg-gray-100'}`}\n >\n {ms.status.toLowerCase().replace('_', ' ')}\n </span>\n </div>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n <p className=\"text-sm text-muted-foreground\">\n {ms.description ?? 'No description'}\n </p>\n {ms.workItemProgress && <MilestoneProgressBar progress={ms.workItemProgress} />}\n <div className=\"flex gap-3 text-xs text-muted-foreground\">\n <span className=\"flex items-center gap-1\">\n <Calendar className=\"h-3 w-3\" />\n {ms.dueDate ? new Date(ms.dueDate).toLocaleDateString() : 'No due date'}\n </span>\n {ms.isOverdue && (\n <Badge variant=\"destructive\" data-testid=\"milestone-overdue\">\n Overdue\n </Badge>\n )}\n {ms.ownerId && (\n <span className=\"flex items-center gap-1\">\n <User className=\"h-3 w-3\" />\n <PersonName id={ms.ownerId} />\n </span>\n )}\n </div>\n <div className=\"text-xs text-muted-foreground\">\n Project: {ms.project?.name ?? 'not available'}\n </div>\n </CardContent>\n </Card>\n )\n )}\n </div>\n {!error && milestones.length === 0 && (\n <p className=\"text-center text-muted-foreground py-8\">No milestones found.</p>\n )}\n </div>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ProjectsMilestonesPagePage.js","names":[],"sources":["../../../src/planmagnet/pages/ProjectsMilestonesPagePage.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 } from '@burdenoff/fe-libs/ui';\nimport { Target, Calendar, User } from 'lucide-react';\nimport { usePlanMagnet, usePlanMagnetNavigate } from '../providers/PlanMagnetProvider';\nimport { rowLinkProps, detailPath, stopRowActivation } from '../utils/rowNavigation';\nimport { PersonName } from '../people/People';\nimport { NewMilestoneDialog } from '../create/CreateDialogs';\nimport { type MilestoneProgress, MilestoneProgressBar } from '../milestones/MilestoneControls';\nimport { ScheduleMeetingDialog } from '../meetings/ScheduleMeetingDialog';\n\nconst GET_MILESTONES = gql`\n query GetMilestones($workspaceId: ID!, $filter: PlanmagnetMilestoneFilter) {\n planmagnetMilestones(workspaceId: $workspaceId, filter: $filter, pagination: { first: 100 }) {\n items {\n id\n name\n description\n projectId\n project {\n id\n name\n }\n status\n dueDate\n isOverdue\n ownerId\n createdAt\n workItemProgress {\n total\n done\n cancelled\n open\n percentComplete\n }\n }\n totalCount\n }\n }\n`;\n\nconst statusColor: Record<string, string> = {\n PENDING: 'bg-gray-100 text-gray-800',\n IN_PROGRESS: 'bg-blue-100 text-blue-800',\n COMPLETED: 'bg-green-100 text-green-800',\n MISSED: 'bg-red-100 text-red-800',\n CANCELLED: 'bg-red-100 text-red-800',\n};\n\nconst milestoneStatuses = [\n 'all',\n 'PENDING',\n 'IN_PROGRESS',\n 'COMPLETED',\n 'MISSED',\n 'CANCELLED',\n] as const;\n\nexport function ProjectsMilestonesPagePage() {\n const { workspaceId } = usePlanMagnet();\n const navigate = usePlanMagnetNavigate();\n const [filter, setFilter] = 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>>(GET_MILESTONES, {\n variables: {\n workspaceId: workspaceId ?? 'default',\n filter: filter !== 'all' ? { status: filter } : undefined,\n },\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 <div className=\"animate-spin h-8 w-8 border-2 border-primary border-t-transparent rounded-full\" />\n </div>\n );\n // A failed load is shown INSIDE the list area: an early return here replaced the whole page, so the status tabs\n // and New Milestone vanished and a failing tab could not be left (BOFF-7942).\n\n const milestones = data?.planmagnetMilestones?.items ?? [];\n const totalCount = data?.planmagnetMilestones?.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\">Milestones</h1>\n <p className=\"text-sm text-muted-foreground\">\n {/* The count follows the tab: it is the filtered total, so do not call it \"all\". */}\n {filter === 'all'\n ? `${totalCount} milestones across all projects`\n : `${totalCount} ${filter.toLowerCase().replace('_', ' ')} milestones`}\n </p>\n </div>\n <NewMilestoneDialog\n onCreated={(id) => navigate(detailPath('/projects/milestone-detail-page', id))}\n />\n </div>\n <div className=\"flex gap-1\">\n {milestoneStatuses.map((s) => (\n <button\n key={s}\n onClick={() => setFilter(s)}\n className={`px-3 py-1.5 text-sm rounded-md capitalize ${filter === s ? 'bg-primary text-primary-foreground' : 'text-muted-foreground hover:bg-muted'}`}\n >\n {s === 'all' ? 'All' : s.toLowerCase().replace('_', ' ')}\n </button>\n ))}\n </div>\n {error && (\n <div\n role=\"alert\"\n className=\"rounded-md border border-destructive/40 p-4 text-sm text-destructive\"\n >\n Milestones could not be loaded: {error.message}\n </div>\n )}\n <div className=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\n {milestones.map(\n (ms: {\n id: string;\n name: string;\n description: string | null;\n projectId: string;\n project: { id: string; name: string } | null;\n status: string;\n dueDate: string | null;\n isOverdue: boolean;\n ownerId: string | null;\n workItemProgress: MilestoneProgress | null;\n }) => (\n <Card\n key={ms.id}\n {...rowLinkProps(\n () => navigate(detailPath('/projects/milestone-detail-page', ms.id)),\n ms.name\n )}\n >\n <CardHeader className=\"pb-2\">\n <div className=\"flex items-center justify-between\">\n <CardTitle className=\"text-base flex items-center gap-2\">\n <Target className=\"h-4 w-4 text-primary\" />\n {ms.name}\n </CardTitle>\n <span\n className={`text-xs px-2 py-0.5 rounded-full capitalize ${statusColor[ms.status] ?? 'bg-gray-100'}`}\n >\n {ms.status.toLowerCase().replace('_', ' ')}\n </span>\n </div>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n <p className=\"text-sm text-muted-foreground\">\n {ms.description ?? 'No description'}\n </p>\n {ms.workItemProgress && <MilestoneProgressBar progress={ms.workItemProgress} />}\n <div className=\"flex gap-3 text-xs text-muted-foreground\">\n <span className=\"flex items-center gap-1\">\n <Calendar className=\"h-3 w-3\" />\n {ms.dueDate ? new Date(ms.dueDate).toLocaleDateString() : 'No due date'}\n </span>\n {ms.isOverdue && (\n <Badge variant=\"destructive\" data-testid=\"milestone-overdue\">\n Overdue\n </Badge>\n )}\n {ms.ownerId && (\n <span className=\"flex items-center gap-1\">\n <User className=\"h-3 w-3\" />\n <PersonName id={ms.ownerId} />\n </span>\n )}\n </div>\n <div className=\"text-xs text-muted-foreground\">\n Project: {ms.project?.name ?? 'not available'}\n </div>\n <div\n className=\"flex flex-wrap gap-2 border-t pt-2\"\n onClick={stopRowActivation}\n data-testid=\"milestone-schedule-actions\"\n >\n <ScheduleMeetingDialog\n projectId={ms.projectId}\n milestoneId={ms.id}\n defaultKind=\"MILESTONE_CELEBRATION\"\n lockKind\n defaultTitle={`${ms.name} celebration`}\n triggerLabel=\"Celebration\"\n />\n <ScheduleMeetingDialog\n projectId={ms.projectId}\n milestoneId={ms.id}\n defaultKind=\"DEMO\"\n lockKind\n defaultTitle={`${ms.name} demo`}\n triggerLabel=\"Demo\"\n />\n </div>\n </CardContent>\n </Card>\n )\n )}\n </div>\n {!error && milestones.length === 0 && (\n <p className=\"text-center text-muted-foreground py-8\">No milestones found.</p>\n )}\n </div>\n );\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ProjectsPlanningDetailPagePage.d.ts","sourceRoot":"","sources":["../../../src/planmagnet/pages/ProjectsPlanningDetailPagePage.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ProjectsPlanningDetailPagePage.d.ts","sourceRoot":"","sources":["../../../src/planmagnet/pages/ProjectsPlanningDetailPagePage.tsx"],"names":[],"mappings":"AA8FA,wBAAgB,8BAA8B,4CA+V7C"}
|