@burdenoff/microfe-planmagnet 2026.925.3 → 2026.925.5
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.js +2 -2
- package/dist/planmagnet/admin/PlanMagnetAdminRoot.js.map +1 -1
- package/dist/planmagnet/create/CreateDialogs.d.ts +7 -0
- package/dist/planmagnet/create/CreateDialogs.d.ts.map +1 -0
- package/dist/planmagnet/create/CreateDialogs.js +282 -0
- package/dist/planmagnet/create/CreateDialogs.js.map +1 -0
- package/dist/planmagnet/pages/ProductsCreateProductPagePage.js +2 -2
- package/dist/planmagnet/pages/ProductsCreateProductPagePage.js.map +1 -1
- package/dist/planmagnet/pages/ProductsCreateRoadmapPagePage.js +2 -2
- package/dist/planmagnet/pages/ProductsCreateRoadmapPagePage.js.map +1 -1
- package/dist/planmagnet/pages/ProductsEditProductPagePage.js +2 -2
- package/dist/planmagnet/pages/ProductsEditProductPagePage.js.map +1 -1
- package/dist/planmagnet/pages/ProductsEditReleasePagePage.js +1 -1
- package/dist/planmagnet/pages/ProductsEditReleasePagePage.js.map +1 -1
- package/dist/planmagnet/pages/ProductsNewFeaturePagePage.js +2 -2
- package/dist/planmagnet/pages/ProductsNewFeaturePagePage.js.map +1 -1
- package/dist/planmagnet/pages/ProductsReleasesPagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/ProductsReleasesPagePage.js +28 -30
- package/dist/planmagnet/pages/ProductsReleasesPagePage.js.map +1 -1
- package/dist/planmagnet/pages/ProjectsMilestonesPagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/ProjectsMilestonesPagePage.js +53 -49
- package/dist/planmagnet/pages/ProjectsMilestonesPagePage.js.map +1 -1
- package/dist/planmagnet/pages/ReportsCreateReportPagePage.js +1 -1
- package/dist/planmagnet/pages/ReportsCreateReportPagePage.js.map +1 -1
- package/dist/planmagnet/pages/TeamCreateTeamPagePage.js +1 -1
- package/dist/planmagnet/pages/TeamCreateTeamPagePage.js.map +1 -1
- package/dist/planmagnet/pages/TeamInviteMemberPagePage.js +1 -1
- package/dist/planmagnet/pages/TeamInviteMemberPagePage.js.map +1 -1
- package/package.json +3 -2
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
import { usePlanMagnet as e, usePlanMagnetNavigate as t } from "../providers/PlanMagnetProvider.js";
|
|
2
2
|
import { PersonName as n } from "../people/People.js";
|
|
3
3
|
import { detailPath as r, rowLinkProps as i } from "../utils/rowNavigation.js";
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
4
|
+
import { NewMilestoneDialog as a } from "../create/CreateDialogs.js";
|
|
5
|
+
import { useState as o } from "react";
|
|
6
|
+
import { Calendar as s, Target as c, User as l } from "lucide-react";
|
|
7
|
+
import { gql as u } from "@apollo/client";
|
|
8
|
+
import { useQuery as d } from "@apollo/client/react";
|
|
9
|
+
import { jsx as f, jsxs as p } from "react/jsx-runtime";
|
|
10
|
+
import { Card as m, CardContent as h, CardHeader as g, CardTitle as _ } from "@burdenoff/fe-libs/ui";
|
|
10
11
|
//#region src/planmagnet/pages/ProjectsMilestonesPagePage.tsx
|
|
11
|
-
var
|
|
12
|
+
var v = u`
|
|
12
13
|
query GetMilestones($workspaceId: ID!, $filter: PlanmagnetMilestoneFilter) {
|
|
13
14
|
planmagnetMilestones(workspaceId: $workspaceId, filter: $filter, pagination: { first: 100 }) {
|
|
14
15
|
items {
|
|
@@ -24,13 +25,13 @@ var _ = l`
|
|
|
24
25
|
totalCount
|
|
25
26
|
}
|
|
26
27
|
}
|
|
27
|
-
`,
|
|
28
|
+
`, y = {
|
|
28
29
|
PENDING: "bg-gray-100 text-gray-800",
|
|
29
30
|
IN_PROGRESS: "bg-blue-100 text-blue-800",
|
|
30
31
|
COMPLETED: "bg-green-100 text-green-800",
|
|
31
32
|
MISSED: "bg-red-100 text-red-800",
|
|
32
33
|
CANCELLED: "bg-red-100 text-red-800"
|
|
33
|
-
},
|
|
34
|
+
}, b = [
|
|
34
35
|
"all",
|
|
35
36
|
"PENDING",
|
|
36
37
|
"IN_PROGRESS",
|
|
@@ -38,72 +39,75 @@ var _ = l`
|
|
|
38
39
|
"MISSED",
|
|
39
40
|
"CANCELLED"
|
|
40
41
|
];
|
|
41
|
-
function
|
|
42
|
-
let { workspaceId:
|
|
43
|
-
workspaceId:
|
|
44
|
-
filter:
|
|
42
|
+
function x() {
|
|
43
|
+
let { workspaceId: u } = e(), x = t(), [S, C] = o("all"), { data: w, loading: T, error: E } = d(v, { variables: {
|
|
44
|
+
workspaceId: u ?? "default",
|
|
45
|
+
filter: S === "all" ? void 0 : { status: S }
|
|
45
46
|
} });
|
|
46
|
-
if (w) return /* @__PURE__ */
|
|
47
|
+
if (T && !w) return /* @__PURE__ */ f("div", {
|
|
47
48
|
className: "flex items-center justify-center p-12",
|
|
48
|
-
children: /* @__PURE__ */
|
|
49
|
+
children: /* @__PURE__ */ f("div", { className: "animate-spin h-8 w-8 border-2 border-primary border-t-transparent rounded-full" })
|
|
49
50
|
});
|
|
50
|
-
if (
|
|
51
|
+
if (E) return /* @__PURE__ */ p("div", {
|
|
51
52
|
className: "p-6 text-red-500",
|
|
52
|
-
children: ["Error loading milestones: ",
|
|
53
|
+
children: ["Error loading milestones: ", E.message]
|
|
53
54
|
});
|
|
54
|
-
let
|
|
55
|
-
return /* @__PURE__ */
|
|
55
|
+
let D = w?.planmagnetMilestones?.items ?? [], O = w?.planmagnetMilestones?.totalCount ?? 0;
|
|
56
|
+
return /* @__PURE__ */ p("div", {
|
|
56
57
|
className: "space-y-6 p-6",
|
|
57
58
|
children: [
|
|
58
|
-
/* @__PURE__ */
|
|
59
|
-
className: "
|
|
60
|
-
children: "
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
59
|
+
/* @__PURE__ */ p("div", {
|
|
60
|
+
className: "flex items-center justify-between",
|
|
61
|
+
children: [/* @__PURE__ */ p("div", { children: [/* @__PURE__ */ f("h1", {
|
|
62
|
+
className: "text-2xl font-semibold",
|
|
63
|
+
children: "Milestones"
|
|
64
|
+
}), /* @__PURE__ */ p("p", {
|
|
65
|
+
className: "text-sm text-muted-foreground",
|
|
66
|
+
children: [O, " milestones across all projects"]
|
|
67
|
+
})] }), /* @__PURE__ */ f(a, { onCreated: (e) => x(r("/projects/milestone-detail-page", e)) })]
|
|
68
|
+
}),
|
|
69
|
+
/* @__PURE__ */ f("div", {
|
|
66
70
|
className: "flex gap-1",
|
|
67
|
-
children:
|
|
68
|
-
onClick: () =>
|
|
69
|
-
className: `px-3 py-1.5 text-sm rounded-md capitalize ${
|
|
71
|
+
children: b.map((e) => /* @__PURE__ */ f("button", {
|
|
72
|
+
onClick: () => C(e),
|
|
73
|
+
className: `px-3 py-1.5 text-sm rounded-md capitalize ${S === e ? "bg-primary text-primary-foreground" : "text-muted-foreground hover:bg-muted"}`,
|
|
70
74
|
children: e === "all" ? "All" : e.toLowerCase().replace("_", " ")
|
|
71
75
|
}, e))
|
|
72
76
|
}),
|
|
73
|
-
/* @__PURE__ */
|
|
77
|
+
/* @__PURE__ */ f("div", {
|
|
74
78
|
className: "grid grid-cols-1 md:grid-cols-2 gap-4",
|
|
75
|
-
children:
|
|
76
|
-
...i(() =>
|
|
77
|
-
children: [/* @__PURE__ */
|
|
79
|
+
children: D.map((e) => /* @__PURE__ */ p(m, {
|
|
80
|
+
...i(() => x(r("/projects/milestone-detail-page", e.id)), e.name),
|
|
81
|
+
children: [/* @__PURE__ */ f(g, {
|
|
78
82
|
className: "pb-2",
|
|
79
|
-
children: /* @__PURE__ */
|
|
83
|
+
children: /* @__PURE__ */ p("div", {
|
|
80
84
|
className: "flex items-center justify-between",
|
|
81
|
-
children: [/* @__PURE__ */
|
|
85
|
+
children: [/* @__PURE__ */ p(_, {
|
|
82
86
|
className: "text-base flex items-center gap-2",
|
|
83
|
-
children: [/* @__PURE__ */
|
|
84
|
-
}), /* @__PURE__ */
|
|
85
|
-
className: `text-xs px-2 py-0.5 rounded-full capitalize ${
|
|
87
|
+
children: [/* @__PURE__ */ f(c, { className: "h-4 w-4 text-primary" }), e.name]
|
|
88
|
+
}), /* @__PURE__ */ f("span", {
|
|
89
|
+
className: `text-xs px-2 py-0.5 rounded-full capitalize ${y[e.status] ?? "bg-gray-100"}`,
|
|
86
90
|
children: e.status.toLowerCase().replace("_", " ")
|
|
87
91
|
})]
|
|
88
92
|
})
|
|
89
|
-
}), /* @__PURE__ */
|
|
93
|
+
}), /* @__PURE__ */ p(h, {
|
|
90
94
|
className: "space-y-3",
|
|
91
95
|
children: [
|
|
92
|
-
/* @__PURE__ */
|
|
96
|
+
/* @__PURE__ */ f("p", {
|
|
93
97
|
className: "text-sm text-muted-foreground",
|
|
94
98
|
children: e.description ?? "No description"
|
|
95
99
|
}),
|
|
96
|
-
/* @__PURE__ */
|
|
100
|
+
/* @__PURE__ */ p("div", {
|
|
97
101
|
className: "flex gap-3 text-xs text-muted-foreground",
|
|
98
|
-
children: [/* @__PURE__ */
|
|
102
|
+
children: [/* @__PURE__ */ p("span", {
|
|
99
103
|
className: "flex items-center gap-1",
|
|
100
|
-
children: [/* @__PURE__ */
|
|
101
|
-
}), e.ownerId && /* @__PURE__ */
|
|
104
|
+
children: [/* @__PURE__ */ f(s, { className: "h-3 w-3" }), e.dueDate ? new Date(e.dueDate).toLocaleDateString() : "No due date"]
|
|
105
|
+
}), e.ownerId && /* @__PURE__ */ p("span", {
|
|
102
106
|
className: "flex items-center gap-1",
|
|
103
|
-
children: [/* @__PURE__ */
|
|
107
|
+
children: [/* @__PURE__ */ f(l, { className: "h-3 w-3" }), /* @__PURE__ */ f(n, { id: e.ownerId })]
|
|
104
108
|
})]
|
|
105
109
|
}),
|
|
106
|
-
/* @__PURE__ */
|
|
110
|
+
/* @__PURE__ */ p("div", {
|
|
107
111
|
className: "text-xs text-muted-foreground",
|
|
108
112
|
children: ["Project: ", e.projectId]
|
|
109
113
|
})
|
|
@@ -111,7 +115,7 @@ function b() {
|
|
|
111
115
|
})]
|
|
112
116
|
}, e.id))
|
|
113
117
|
}),
|
|
114
|
-
|
|
118
|
+
D.length === 0 && /* @__PURE__ */ f("p", {
|
|
115
119
|
className: "text-center text-muted-foreground py-8",
|
|
116
120
|
children: "No milestones found."
|
|
117
121
|
})
|
|
@@ -119,6 +123,6 @@ function b() {
|
|
|
119
123
|
});
|
|
120
124
|
}
|
|
121
125
|
//#endregion
|
|
122
|
-
export {
|
|
126
|
+
export { x as ProjectsMilestonesPagePage };
|
|
123
127
|
|
|
124
128
|
//# 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';\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 status\n dueDate\n ownerId\n createdAt\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 if (loading)\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 if (error)\n return <div className=\"p-6 text-red-500\">Error loading milestones: {error.message}</div>;\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>\n <h1 className=\"text-2xl font-semibold\">Milestones</h1>\n
|
|
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';\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 status\n dueDate\n ownerId\n createdAt\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 if (error)\n return <div className=\"p-6 text-red-500\">Error loading milestones: {error.message}</div>;\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 {totalCount} milestones across all projects\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 <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 status: string;\n dueDate: string | null;\n ownerId: string | 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 <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.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\">Project: {ms.projectId}</div>\n </CardContent>\n </Card>\n )\n )}\n </div>\n {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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"}
|
|
@@ -66,7 +66,7 @@ function _() {
|
|
|
66
66
|
children: [/* @__PURE__ */ l(u, {
|
|
67
67
|
variant: "outline",
|
|
68
68
|
size: "sm",
|
|
69
|
-
onClick: () => _("/reports"),
|
|
69
|
+
onClick: () => _("/reports/reports-page"),
|
|
70
70
|
children: [/* @__PURE__ */ c(a, { className: "mr-1 h-4 w-4" }), "Cancel"]
|
|
71
71
|
}), /* @__PURE__ */ l(u, {
|
|
72
72
|
size: "sm",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ReportsCreateReportPagePage.js","names":[],"sources":["../../../src/planmagnet/pages/ReportsCreateReportPagePage.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, Button, Input } from '@burdenoff/fe-libs/ui';\nimport { Save, X, BarChart3 } from 'lucide-react';\nimport { usePlanMagnet, usePlanMagnetNavigate } from '../providers/PlanMagnetProvider';\n\nconst GET_PROJECTS_FOR_REPORT = gql`\n query GetProjectsForReport($workspaceId: ID!, $pagination: PlanmagnetPaginationInput) {\n planmagnetProjects(workspaceId: $workspaceId, pagination: $pagination) {\n items {\n id\n name\n key\n }\n totalCount\n }\n }\n`;\n\ninterface ProjectNode {\n id: string;\n name: string;\n key: string;\n}\n\ninterface ProjectsData {\n projects: { items: ProjectNode[]; totalCount: number };\n}\n\nexport function ReportsCreateReportPagePage() {\n const { workspaceId } = usePlanMagnet();\n const navigate = usePlanMagnetNavigate();\n\n const { data, loading, error } = useQuery<ProjectsData>(GET_PROJECTS_FOR_REPORT, {\n variables: {\n workspaceId,\n pagination: { first: 100 },\n },\n skip: !workspaceId,\n });\n\n const [form, setForm] = useState({\n name: '',\n description: '',\n type: 'velocity',\n projectId: '',\n schedule: 'weekly',\n });\n const types = [\n 'velocity',\n 'burndown',\n 'burnup',\n 'cumulative_flow',\n 'cycle_time',\n 'lead_time',\n 'custom',\n ] as const;\n const schedules = ['daily', 'weekly', 'monthly'] as const;\n\n const projects = data?.planmagnetProjects?.items ?? [];\n\n // NOTE: there is no Report model in wspace-planmagnet-svc, so this form has nothing\n // to save to. It previously had a handler that navigated to '/reports' on submit,\n // which read as a successful save — the user filled the form, was redirected, and\n // nothing was persisted. The submit control is disabled until the model exists\n // (BOFF-7822); the notice above the form says so.\n\n if (loading) {\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-red-500\">Error: {error.message}</div>;\n }\n\n return (\n <div className=\"space-y-6 p-6 max-w-4xl\">\n <div className=\"flex items-center justify-between\">\n <div>\n <h1 className=\"text-2xl font-semibold\">Create Report</h1>\n <p className=\"text-sm text-muted-foreground\">Configure a new automated report.</p>\n </div>\n <div className=\"flex gap-2\">\n <Button variant=\"outline\" size=\"sm\" onClick={() => navigate('/reports')}>\n <X className=\"mr-1 h-4 w-4\" />\n Cancel\n </Button>\n <Button size=\"sm\" disabled title=\"Not available yet — see the notice below\">\n <Save className=\"mr-1 h-4 w-4\" />\n Create Report\n </Button>\n </div>\n </div>\n <div className=\"rounded-md border border-border bg-muted p-4 text-sm text-muted-foreground\">\n <strong className=\"text-foreground\">Not available yet.</strong> Reports cannot be saved —\n there is no report model behind this form. It is shown so the fields and options are\n visible, but nothing entered here is stored. This page previously returned you to the list\n on submit, which looked like it had saved.\n </div>\n <Card>\n <CardHeader>\n <CardTitle className=\"flex items-center gap-2\">\n <BarChart3 className=\"h-4 w-4\" />\n Report Configuration\n </CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-4\">\n <div>\n <label className=\"text-sm font-medium\">Report Name</label>\n <Input\n value={form.name}\n onChange={(e) => setForm({ ...form, name: e.target.value })}\n className=\"mt-1\"\n placeholder=\"e.g. Sprint Velocity Report\"\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-[80px]\"\n value={form.description}\n onChange={(e) => setForm({ ...form, description: e.target.value })}\n placeholder=\"What does this report track?\"\n />\n </div>\n <div className=\"grid grid-cols-3 gap-4\">\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 {types.map((t) => (\n <option key={t} value={t}>\n {t.replace('_', ' ')}\n </option>\n ))}\n </select>\n </div>\n <div>\n <label className=\"text-sm font-medium\">Project (optional)</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.projectId}\n onChange={(e) => setForm({ ...form, projectId: e.target.value })}\n >\n <option value=\"\">All projects</option>\n {projects.map((p) => (\n <option key={p.id} value={p.id}>\n {p.name} ({p.key})\n </option>\n ))}\n </select>\n </div>\n <div>\n <label className=\"text-sm font-medium\">Schedule</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.schedule}\n onChange={(e) => setForm({ ...form, schedule: e.target.value })}\n >\n {schedules.map((s) => (\n <option key={s} value={s}>\n {s}\n </option>\n ))}\n </select>\n </div>\n </div>\n </CardContent>\n </Card>\n </div>\n );\n}\n"],"mappings":";;;;;;;;AASA,IAAM,IAA0B,CAAG;;;;;;;;;;;;AAuBnC,SAAgB,IAA8B;CAC5C,IAAM,EAAE,mBAAgB,GAAe,EACjC,IAAW,GAAuB,EAElC,EAAE,SAAM,YAAS,aAAU,EAAuB,GAAyB;EAC/E,WAAW;GACT;GACA,YAAY,EAAE,OAAO,KAAK;GAC3B;EACD,MAAM,CAAC;EACR,CAAC,EAEI,CAAC,GAAM,KAAW,EAAS;EAC/B,MAAM;EACN,aAAa;EACb,MAAM;EACN,WAAW;EACX,UAAU;EACX,CAAC,EACI,IAAQ;EACZ;EACA;EACA;EACA;EACA;EACA;EACA;EACD,EACK,IAAY;EAAC;EAAS;EAAU;EAAU,EAE1C,IAAW,GAAM,oBAAoB,SAAS,EAAE;AAoBtD,QAZI,IAEA,kBAAC,OAAD;EAAK,WAAU;YACb,kBAAC,OAAD,EAAK,WAAU,kFAAmF,CAAA;EAC9F,CAAA,GAIN,IACK,kBAAC,OAAD;EAAK,WAAU;YAAf,CAAkC,WAAQ,EAAM,QAAc;MAIrE,kBAAC,OAAD;EAAK,WAAU;YAAf;GACE,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,MAAD;KAAI,WAAU;eAAyB;KAAkB,CAAA,EACzD,kBAAC,KAAD;KAAG,WAAU;eAAgC;KAAqC,CAAA,CAC9E,EAAA,CAAA,EACN,kBAAC,OAAD;KAAK,WAAU;eAAf,CACE,kBAAC,GAAD;MAAQ,SAAQ;MAAU,MAAK;MAAK,eAAe,EAAS,
|
|
1
|
+
{"version":3,"file":"ReportsCreateReportPagePage.js","names":[],"sources":["../../../src/planmagnet/pages/ReportsCreateReportPagePage.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, Button, Input } from '@burdenoff/fe-libs/ui';\nimport { Save, X, BarChart3 } from 'lucide-react';\nimport { usePlanMagnet, usePlanMagnetNavigate } from '../providers/PlanMagnetProvider';\n\nconst GET_PROJECTS_FOR_REPORT = gql`\n query GetProjectsForReport($workspaceId: ID!, $pagination: PlanmagnetPaginationInput) {\n planmagnetProjects(workspaceId: $workspaceId, pagination: $pagination) {\n items {\n id\n name\n key\n }\n totalCount\n }\n }\n`;\n\ninterface ProjectNode {\n id: string;\n name: string;\n key: string;\n}\n\ninterface ProjectsData {\n projects: { items: ProjectNode[]; totalCount: number };\n}\n\nexport function ReportsCreateReportPagePage() {\n const { workspaceId } = usePlanMagnet();\n const navigate = usePlanMagnetNavigate();\n\n const { data, loading, error } = useQuery<ProjectsData>(GET_PROJECTS_FOR_REPORT, {\n variables: {\n workspaceId,\n pagination: { first: 100 },\n },\n skip: !workspaceId,\n });\n\n const [form, setForm] = useState({\n name: '',\n description: '',\n type: 'velocity',\n projectId: '',\n schedule: 'weekly',\n });\n const types = [\n 'velocity',\n 'burndown',\n 'burnup',\n 'cumulative_flow',\n 'cycle_time',\n 'lead_time',\n 'custom',\n ] as const;\n const schedules = ['daily', 'weekly', 'monthly'] as const;\n\n const projects = data?.planmagnetProjects?.items ?? [];\n\n // NOTE: there is no Report model in wspace-planmagnet-svc, so this form has nothing\n // to save to. It previously had a handler that navigated to '/reports' on submit,\n // which read as a successful save — the user filled the form, was redirected, and\n // nothing was persisted. The submit control is disabled until the model exists\n // (BOFF-7822); the notice above the form says so.\n\n if (loading) {\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-red-500\">Error: {error.message}</div>;\n }\n\n return (\n <div className=\"space-y-6 p-6 max-w-4xl\">\n <div className=\"flex items-center justify-between\">\n <div>\n <h1 className=\"text-2xl font-semibold\">Create Report</h1>\n <p className=\"text-sm text-muted-foreground\">Configure a new automated report.</p>\n </div>\n <div className=\"flex gap-2\">\n <Button variant=\"outline\" size=\"sm\" onClick={() => navigate('/reports/reports-page')}>\n <X className=\"mr-1 h-4 w-4\" />\n Cancel\n </Button>\n <Button size=\"sm\" disabled title=\"Not available yet — see the notice below\">\n <Save className=\"mr-1 h-4 w-4\" />\n Create Report\n </Button>\n </div>\n </div>\n <div className=\"rounded-md border border-border bg-muted p-4 text-sm text-muted-foreground\">\n <strong className=\"text-foreground\">Not available yet.</strong> Reports cannot be saved —\n there is no report model behind this form. It is shown so the fields and options are\n visible, but nothing entered here is stored. This page previously returned you to the list\n on submit, which looked like it had saved.\n </div>\n <Card>\n <CardHeader>\n <CardTitle className=\"flex items-center gap-2\">\n <BarChart3 className=\"h-4 w-4\" />\n Report Configuration\n </CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-4\">\n <div>\n <label className=\"text-sm font-medium\">Report Name</label>\n <Input\n value={form.name}\n onChange={(e) => setForm({ ...form, name: e.target.value })}\n className=\"mt-1\"\n placeholder=\"e.g. Sprint Velocity Report\"\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-[80px]\"\n value={form.description}\n onChange={(e) => setForm({ ...form, description: e.target.value })}\n placeholder=\"What does this report track?\"\n />\n </div>\n <div className=\"grid grid-cols-3 gap-4\">\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 {types.map((t) => (\n <option key={t} value={t}>\n {t.replace('_', ' ')}\n </option>\n ))}\n </select>\n </div>\n <div>\n <label className=\"text-sm font-medium\">Project (optional)</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.projectId}\n onChange={(e) => setForm({ ...form, projectId: e.target.value })}\n >\n <option value=\"\">All projects</option>\n {projects.map((p) => (\n <option key={p.id} value={p.id}>\n {p.name} ({p.key})\n </option>\n ))}\n </select>\n </div>\n <div>\n <label className=\"text-sm font-medium\">Schedule</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.schedule}\n onChange={(e) => setForm({ ...form, schedule: e.target.value })}\n >\n {schedules.map((s) => (\n <option key={s} value={s}>\n {s}\n </option>\n ))}\n </select>\n </div>\n </div>\n </CardContent>\n </Card>\n </div>\n );\n}\n"],"mappings":"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"}
|
|
@@ -54,7 +54,7 @@ function _() {
|
|
|
54
54
|
children: [/* @__PURE__ */ l(u, {
|
|
55
55
|
variant: "outline",
|
|
56
56
|
size: "sm",
|
|
57
|
-
onClick: () => _("/team"),
|
|
57
|
+
onClick: () => _("/team/team-page"),
|
|
58
58
|
children: [/* @__PURE__ */ c(a, { className: "mr-1 h-4 w-4" }), "Cancel"]
|
|
59
59
|
}), /* @__PURE__ */ l(u, {
|
|
60
60
|
size: "sm",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TeamCreateTeamPagePage.js","names":[],"sources":["../../../src/planmagnet/pages/TeamCreateTeamPagePage.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, Button, Input } from '@burdenoff/fe-libs/ui';\nimport { Save, X, Users } from 'lucide-react';\nimport { usePlanMagnet, usePlanMagnetNavigate } from '../providers/PlanMagnetProvider';\n\nconst GET_PROJECTS_FOR_TEAM = gql`\n query GetProjectsForTeamCreation($workspaceId: ID!, $pagination: PlanmagnetPaginationInput) {\n planmagnetProjects(workspaceId: $workspaceId, pagination: $pagination) {\n items {\n id\n name\n key\n ownerId\n }\n totalCount\n }\n }\n`;\n\ninterface ProjectNode {\n id: string;\n name: string;\n key: string;\n ownerId: string | null;\n}\n\ninterface ProjectsData {\n projects: { items: ProjectNode[]; totalCount: number };\n}\n\nexport function TeamCreateTeamPagePage() {\n const { workspaceId } = usePlanMagnet();\n const navigate = usePlanMagnetNavigate();\n const [form, setForm] = useState({ name: '', description: '', lead: '', projectId: '' });\n\n const { data, loading, error } = useQuery<ProjectsData>(GET_PROJECTS_FOR_TEAM, {\n variables: {\n workspaceId,\n pagination: { first: 100 },\n },\n skip: !workspaceId,\n });\n\n const projects = data?.planmagnetProjects?.items ?? [];\n\n // NOTE: there is no Team model in wspace-planmagnet-svc, so this form has nothing\n // to save to. It previously had a handler that navigated to '/team' on submit,\n // which read as a successful save — the user filled the form, was redirected, and\n // nothing was persisted. The submit control is disabled until the model exists\n // (BOFF-7822); the notice above the form says so.\n\n if (loading) {\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-red-500\">Error: {error.message}</div>;\n }\n\n return (\n <div className=\"space-y-6 p-6 max-w-4xl\">\n <div className=\"flex items-center justify-between\">\n <div>\n <h1 className=\"text-2xl font-semibold\">Create Team</h1>\n <p className=\"text-sm text-muted-foreground\">\n Set up a new team with members and a lead.\n </p>\n </div>\n <div className=\"flex gap-2\">\n <Button variant=\"outline\" size=\"sm\" onClick={() => navigate('/team')}>\n <X className=\"mr-1 h-4 w-4\" />\n Cancel\n </Button>\n <Button size=\"sm\" disabled title=\"Not available yet — see the notice below\">\n <Save className=\"mr-1 h-4 w-4\" />\n Create Team\n </Button>\n </div>\n </div>\n <div className=\"rounded-md border border-border bg-muted p-4 text-sm text-muted-foreground\">\n <strong className=\"text-foreground\">Not available yet.</strong> Teams cannot be saved —\n there is no team model behind this form. It is shown so the fields and options are visible,\n but nothing entered here is stored. This page previously returned you to the list on submit,\n which looked like it had saved.\n </div>\n <Card>\n <CardHeader>\n <CardTitle className=\"flex items-center gap-2\">\n <Users className=\"h-4 w-4\" />\n Team Details\n </CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-4\">\n <div>\n <label className=\"text-sm font-medium\">Team Name</label>\n <Input\n value={form.name}\n onChange={(e) => setForm({ ...form, name: e.target.value })}\n className=\"mt-1\"\n placeholder=\"e.g. Platform Engineering\"\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-[80px]\"\n value={form.description}\n onChange={(e) => setForm({ ...form, description: e.target.value })}\n placeholder=\"Describe the team's mission and responsibilities...\"\n />\n </div>\n <div>\n <label className=\"text-sm font-medium\">Team Lead</label>\n <Input\n value={form.lead}\n onChange={(e) => setForm({ ...form, lead: e.target.value })}\n className=\"mt-1\"\n placeholder=\"Team lead name or email\"\n />\n </div>\n <div>\n <label className=\"text-sm font-medium\">Associated Project (optional)</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.projectId}\n onChange={(e) => setForm({ ...form, projectId: e.target.value })}\n >\n <option value=\"\">No project</option>\n {projects.map((p) => (\n <option key={p.id} value={p.id}>\n {p.name} ({p.key})\n </option>\n ))}\n </select>\n </div>\n </CardContent>\n </Card>\n </div>\n );\n}\n"],"mappings":";;;;;;;;AASA,IAAM,IAAwB,CAAG;;;;;;;;;;;;;AAyBjC,SAAgB,IAAyB;CACvC,IAAM,EAAE,mBAAgB,GAAe,EACjC,IAAW,GAAuB,EAClC,CAAC,GAAM,KAAW,EAAS;EAAE,MAAM;EAAI,aAAa;EAAI,MAAM;EAAI,WAAW;EAAI,CAAC,EAElF,EAAE,SAAM,YAAS,aAAU,EAAuB,GAAuB;EAC7E,WAAW;GACT;GACA,YAAY,EAAE,OAAO,KAAK;GAC3B;EACD,MAAM,CAAC;EACR,CAAC,EAEI,IAAW,GAAM,oBAAoB,SAAS,EAAE;AAoBtD,QAZI,IAEA,kBAAC,OAAD;EAAK,WAAU;YACb,kBAAC,OAAD,EAAK,WAAU,kFAAmF,CAAA;EAC9F,CAAA,GAIN,IACK,kBAAC,OAAD;EAAK,WAAU;YAAf,CAAkC,WAAQ,EAAM,QAAc;MAIrE,kBAAC,OAAD;EAAK,WAAU;YAAf;GACE,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,MAAD;KAAI,WAAU;eAAyB;KAAgB,CAAA,EACvD,kBAAC,KAAD;KAAG,WAAU;eAAgC;KAEzC,CAAA,CACA,EAAA,CAAA,EACN,kBAAC,OAAD;KAAK,WAAU;eAAf,CACE,kBAAC,GAAD;MAAQ,SAAQ;MAAU,MAAK;MAAK,eAAe,EAAS,
|
|
1
|
+
{"version":3,"file":"TeamCreateTeamPagePage.js","names":[],"sources":["../../../src/planmagnet/pages/TeamCreateTeamPagePage.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, Button, Input } from '@burdenoff/fe-libs/ui';\nimport { Save, X, Users } from 'lucide-react';\nimport { usePlanMagnet, usePlanMagnetNavigate } from '../providers/PlanMagnetProvider';\n\nconst GET_PROJECTS_FOR_TEAM = gql`\n query GetProjectsForTeamCreation($workspaceId: ID!, $pagination: PlanmagnetPaginationInput) {\n planmagnetProjects(workspaceId: $workspaceId, pagination: $pagination) {\n items {\n id\n name\n key\n ownerId\n }\n totalCount\n }\n }\n`;\n\ninterface ProjectNode {\n id: string;\n name: string;\n key: string;\n ownerId: string | null;\n}\n\ninterface ProjectsData {\n projects: { items: ProjectNode[]; totalCount: number };\n}\n\nexport function TeamCreateTeamPagePage() {\n const { workspaceId } = usePlanMagnet();\n const navigate = usePlanMagnetNavigate();\n const [form, setForm] = useState({ name: '', description: '', lead: '', projectId: '' });\n\n const { data, loading, error } = useQuery<ProjectsData>(GET_PROJECTS_FOR_TEAM, {\n variables: {\n workspaceId,\n pagination: { first: 100 },\n },\n skip: !workspaceId,\n });\n\n const projects = data?.planmagnetProjects?.items ?? [];\n\n // NOTE: there is no Team model in wspace-planmagnet-svc, so this form has nothing\n // to save to. It previously had a handler that navigated to '/team' on submit,\n // which read as a successful save — the user filled the form, was redirected, and\n // nothing was persisted. The submit control is disabled until the model exists\n // (BOFF-7822); the notice above the form says so.\n\n if (loading) {\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-red-500\">Error: {error.message}</div>;\n }\n\n return (\n <div className=\"space-y-6 p-6 max-w-4xl\">\n <div className=\"flex items-center justify-between\">\n <div>\n <h1 className=\"text-2xl font-semibold\">Create Team</h1>\n <p className=\"text-sm text-muted-foreground\">\n Set up a new team with members and a lead.\n </p>\n </div>\n <div className=\"flex gap-2\">\n <Button variant=\"outline\" size=\"sm\" onClick={() => navigate('/team/team-page')}>\n <X className=\"mr-1 h-4 w-4\" />\n Cancel\n </Button>\n <Button size=\"sm\" disabled title=\"Not available yet — see the notice below\">\n <Save className=\"mr-1 h-4 w-4\" />\n Create Team\n </Button>\n </div>\n </div>\n <div className=\"rounded-md border border-border bg-muted p-4 text-sm text-muted-foreground\">\n <strong className=\"text-foreground\">Not available yet.</strong> Teams cannot be saved —\n there is no team model behind this form. It is shown so the fields and options are visible,\n but nothing entered here is stored. This page previously returned you to the list on submit,\n which looked like it had saved.\n </div>\n <Card>\n <CardHeader>\n <CardTitle className=\"flex items-center gap-2\">\n <Users className=\"h-4 w-4\" />\n Team Details\n </CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-4\">\n <div>\n <label className=\"text-sm font-medium\">Team Name</label>\n <Input\n value={form.name}\n onChange={(e) => setForm({ ...form, name: e.target.value })}\n className=\"mt-1\"\n placeholder=\"e.g. Platform Engineering\"\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-[80px]\"\n value={form.description}\n onChange={(e) => setForm({ ...form, description: e.target.value })}\n placeholder=\"Describe the team's mission and responsibilities...\"\n />\n </div>\n <div>\n <label className=\"text-sm font-medium\">Team Lead</label>\n <Input\n value={form.lead}\n onChange={(e) => setForm({ ...form, lead: e.target.value })}\n className=\"mt-1\"\n placeholder=\"Team lead name or email\"\n />\n </div>\n <div>\n <label className=\"text-sm font-medium\">Associated Project (optional)</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.projectId}\n onChange={(e) => setForm({ ...form, projectId: e.target.value })}\n >\n <option value=\"\">No project</option>\n {projects.map((p) => (\n <option key={p.id} value={p.id}>\n {p.name} ({p.key})\n </option>\n ))}\n </select>\n </div>\n </CardContent>\n </Card>\n </div>\n );\n}\n"],"mappings":"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"}
|
|
@@ -73,7 +73,7 @@ function _() {
|
|
|
73
73
|
children: [/* @__PURE__ */ l(u, {
|
|
74
74
|
variant: "outline",
|
|
75
75
|
size: "sm",
|
|
76
|
-
onClick: () => _("/team"),
|
|
76
|
+
onClick: () => _("/team/team-page"),
|
|
77
77
|
children: [/* @__PURE__ */ c(a, { className: "mr-1 h-4 w-4" }), "Cancel"]
|
|
78
78
|
}), /* @__PURE__ */ l(u, {
|
|
79
79
|
size: "sm",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TeamInviteMemberPagePage.js","names":[],"sources":["../../../src/planmagnet/pages/TeamInviteMemberPagePage.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, Button, Input } from '@burdenoff/fe-libs/ui';\nimport { Save, X, UserPlus } from 'lucide-react';\nimport { usePlanMagnet, usePlanMagnetNavigate } from '../providers/PlanMagnetProvider';\n\nconst GET_PROJECTS_FOR_INVITE = gql`\n query GetProjectsForInvite($workspaceId: ID!, $pagination: PlanmagnetPaginationInput) {\n planmagnetProjects(workspaceId: $workspaceId, pagination: $pagination) {\n items {\n id\n name\n key\n methodology\n }\n totalCount\n }\n }\n`;\n\ninterface ProjectNode {\n id: string;\n name: string;\n key: string;\n methodology: string | null;\n}\n\ninterface ProjectsData {\n projects: { items: ProjectNode[]; totalCount: number };\n}\n\nexport function TeamInviteMemberPagePage() {\n const { workspaceId } = usePlanMagnet();\n const navigate = usePlanMagnetNavigate();\n\n const { data, loading, error } = useQuery<ProjectsData>(GET_PROJECTS_FOR_INVITE, {\n variables: {\n workspaceId,\n pagination: { first: 100 },\n },\n skip: !workspaceId,\n });\n\n const [form, setForm] = useState({\n email: '',\n role: 'developer',\n projectId: '',\n department: 'Engineering',\n });\n const roles = [\n 'developer',\n 'designer',\n 'product manager',\n 'qa engineer',\n 'engineering manager',\n 'data engineer',\n ] as const;\n const departments = ['Engineering', 'Product', 'Design', 'Quality', 'Data'] as const;\n\n const projects = data?.planmagnetProjects?.items ?? [];\n\n const teams = projects.reduce(\n (acc, p) => {\n const method = p.methodology ?? 'general';\n if (!acc.some((t) => t.id === method)) {\n acc.push({\n id: method,\n name: `${method.charAt(0).toUpperCase()}${method.slice(1)} Team`,\n });\n }\n return acc;\n },\n [] as Array<{ id: string; name: string }>\n );\n\n // NOTE: nothing here can send an invitation. wspace-planmagnet-svc has no Team or\n // membership model, and this MFE only talks to the workspaces gateway, which exposes\n // no invite mutation — the \"teams\" on the Team page are derived from project\n // methodologies, not real teams. The previous handler only called navigate('/team'),\n // so a user filled in an email, clicked Send Invite, was redirected, and no invitation\n // existed — indistinguishable from success. The submit control is disabled until there\n // is something to invite into (BOFF-7822); the notice above the form says so.\n\n if (loading) {\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-red-500\">Error: {error.message}</div>;\n }\n\n return (\n <div className=\"space-y-6 p-6 max-w-4xl\">\n <div className=\"flex items-center justify-between\">\n <div>\n <h1 className=\"text-2xl font-semibold\">Invite Team Member</h1>\n <p className=\"text-sm text-muted-foreground\">Add a new member to your workspace.</p>\n </div>\n <div className=\"flex gap-2\">\n <Button variant=\"outline\" size=\"sm\" onClick={() => navigate('/team')}>\n <X className=\"mr-1 h-4 w-4\" />\n Cancel\n </Button>\n <Button size=\"sm\" disabled title=\"Not available yet — see the notice below\">\n <Save className=\"mr-1 h-4 w-4\" />\n Send Invite\n </Button>\n </div>\n </div>\n <div className=\"rounded-md border border-border bg-muted p-4 text-sm text-muted-foreground\">\n <strong className=\"text-foreground\">Not available yet.</strong> Invitations cannot be sent —\n there is no team or membership model behind this form, so nothing entered here is stored and\n no email is sent. The form is shown so the fields and options are visible.\n </div>\n <Card>\n <CardHeader>\n <CardTitle className=\"flex items-center gap-2\">\n <UserPlus className=\"h-4 w-4\" />\n Invitation Details\n </CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-4\">\n <div>\n <label className=\"text-sm font-medium\">Email Address</label>\n <Input\n type=\"email\"\n value={form.email}\n onChange={(e) => setForm({ ...form, email: e.target.value })}\n className=\"mt-1\"\n placeholder=\"colleague@company.com\"\n />\n </div>\n <div className=\"grid grid-cols-3 gap-4\">\n <div>\n <label className=\"text-sm font-medium\">Role</label>\n <select\n className=\"mt-1 w-full rounded-md border border-input bg-background px-3 py-2 text-sm capitalize\"\n value={form.role}\n onChange={(e) => setForm({ ...form, role: e.target.value })}\n >\n {roles.map((r) => (\n <option key={r} value={r}>\n {r}\n </option>\n ))}\n </select>\n </div>\n <div>\n <label className=\"text-sm font-medium\">Department</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.department}\n onChange={(e) => setForm({ ...form, department: e.target.value })}\n >\n {departments.map((d) => (\n <option key={d} value={d}>\n {d}\n </option>\n ))}\n </select>\n </div>\n <div>\n <label className=\"text-sm font-medium\">Team</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.projectId}\n onChange={(e) => setForm({ ...form, projectId: e.target.value })}\n >\n <option value=\"\">No team</option>\n {teams.map((t) => (\n <option key={t.id} value={t.id}>\n {t.name}\n </option>\n ))}\n </select>\n </div>\n </div>\n </CardContent>\n </Card>\n </div>\n );\n}\n"],"mappings":";;;;;;;;AASA,IAAM,IAA0B,CAAG;;;;;;;;;;;;;AAyBnC,SAAgB,IAA2B;CACzC,IAAM,EAAE,mBAAgB,GAAe,EACjC,IAAW,GAAuB,EAElC,EAAE,SAAM,YAAS,aAAU,EAAuB,GAAyB;EAC/E,WAAW;GACT;GACA,YAAY,EAAE,OAAO,KAAK;GAC3B;EACD,MAAM,CAAC;EACR,CAAC,EAEI,CAAC,GAAM,KAAW,EAAS;EAC/B,OAAO;EACP,MAAM;EACN,WAAW;EACX,YAAY;EACb,CAAC,EACI,IAAQ;EACZ;EACA;EACA;EACA;EACA;EACA;EACD,EACK,IAAc;EAAC;EAAe;EAAW;EAAU;EAAW;EAAO,EAIrE,KAFW,GAAM,oBAAoB,SAAS,EAAE,EAE/B,QACpB,GAAK,MAAM;EACV,IAAM,IAAS,EAAE,eAAe;AAOhC,SANK,EAAI,MAAM,MAAM,EAAE,OAAO,EAAO,IACnC,EAAI,KAAK;GACP,IAAI;GACJ,MAAM,GAAG,EAAO,OAAO,EAAE,CAAC,aAAa,GAAG,EAAO,MAAM,EAAE,CAAC;GAC3D,CAAC,EAEG;IAET,EAAE,CACH;AAsBD,QAZI,IAEA,kBAAC,OAAD;EAAK,WAAU;YACb,kBAAC,OAAD,EAAK,WAAU,kFAAmF,CAAA;EAC9F,CAAA,GAIN,IACK,kBAAC,OAAD;EAAK,WAAU;YAAf,CAAkC,WAAQ,EAAM,QAAc;MAIrE,kBAAC,OAAD;EAAK,WAAU;YAAf;GACE,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,MAAD;KAAI,WAAU;eAAyB;KAAuB,CAAA,EAC9D,kBAAC,KAAD;KAAG,WAAU;eAAgC;KAAuC,CAAA,CAChF,EAAA,CAAA,EACN,kBAAC,OAAD;KAAK,WAAU;eAAf,CACE,kBAAC,GAAD;MAAQ,SAAQ;MAAU,MAAK;MAAK,eAAe,EAAS,
|
|
1
|
+
{"version":3,"file":"TeamInviteMemberPagePage.js","names":[],"sources":["../../../src/planmagnet/pages/TeamInviteMemberPagePage.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, Button, Input } from '@burdenoff/fe-libs/ui';\nimport { Save, X, UserPlus } from 'lucide-react';\nimport { usePlanMagnet, usePlanMagnetNavigate } from '../providers/PlanMagnetProvider';\n\nconst GET_PROJECTS_FOR_INVITE = gql`\n query GetProjectsForInvite($workspaceId: ID!, $pagination: PlanmagnetPaginationInput) {\n planmagnetProjects(workspaceId: $workspaceId, pagination: $pagination) {\n items {\n id\n name\n key\n methodology\n }\n totalCount\n }\n }\n`;\n\ninterface ProjectNode {\n id: string;\n name: string;\n key: string;\n methodology: string | null;\n}\n\ninterface ProjectsData {\n projects: { items: ProjectNode[]; totalCount: number };\n}\n\nexport function TeamInviteMemberPagePage() {\n const { workspaceId } = usePlanMagnet();\n const navigate = usePlanMagnetNavigate();\n\n const { data, loading, error } = useQuery<ProjectsData>(GET_PROJECTS_FOR_INVITE, {\n variables: {\n workspaceId,\n pagination: { first: 100 },\n },\n skip: !workspaceId,\n });\n\n const [form, setForm] = useState({\n email: '',\n role: 'developer',\n projectId: '',\n department: 'Engineering',\n });\n const roles = [\n 'developer',\n 'designer',\n 'product manager',\n 'qa engineer',\n 'engineering manager',\n 'data engineer',\n ] as const;\n const departments = ['Engineering', 'Product', 'Design', 'Quality', 'Data'] as const;\n\n const projects = data?.planmagnetProjects?.items ?? [];\n\n const teams = projects.reduce(\n (acc, p) => {\n const method = p.methodology ?? 'general';\n if (!acc.some((t) => t.id === method)) {\n acc.push({\n id: method,\n name: `${method.charAt(0).toUpperCase()}${method.slice(1)} Team`,\n });\n }\n return acc;\n },\n [] as Array<{ id: string; name: string }>\n );\n\n // NOTE: nothing here can send an invitation. wspace-planmagnet-svc has no Team or\n // membership model, and this MFE only talks to the workspaces gateway, which exposes\n // no invite mutation — the \"teams\" on the Team page are derived from project\n // methodologies, not real teams. The previous handler only called navigate('/team/team-page'),\n // so a user filled in an email, clicked Send Invite, was redirected, and no invitation\n // existed — indistinguishable from success. The submit control is disabled until there\n // is something to invite into (BOFF-7822); the notice above the form says so.\n\n if (loading) {\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-red-500\">Error: {error.message}</div>;\n }\n\n return (\n <div className=\"space-y-6 p-6 max-w-4xl\">\n <div className=\"flex items-center justify-between\">\n <div>\n <h1 className=\"text-2xl font-semibold\">Invite Team Member</h1>\n <p className=\"text-sm text-muted-foreground\">Add a new member to your workspace.</p>\n </div>\n <div className=\"flex gap-2\">\n <Button variant=\"outline\" size=\"sm\" onClick={() => navigate('/team/team-page')}>\n <X className=\"mr-1 h-4 w-4\" />\n Cancel\n </Button>\n <Button size=\"sm\" disabled title=\"Not available yet — see the notice below\">\n <Save className=\"mr-1 h-4 w-4\" />\n Send Invite\n </Button>\n </div>\n </div>\n <div className=\"rounded-md border border-border bg-muted p-4 text-sm text-muted-foreground\">\n <strong className=\"text-foreground\">Not available yet.</strong> Invitations cannot be sent —\n there is no team or membership model behind this form, so nothing entered here is stored and\n no email is sent. The form is shown so the fields and options are visible.\n </div>\n <Card>\n <CardHeader>\n <CardTitle className=\"flex items-center gap-2\">\n <UserPlus className=\"h-4 w-4\" />\n Invitation Details\n </CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-4\">\n <div>\n <label className=\"text-sm font-medium\">Email Address</label>\n <Input\n type=\"email\"\n value={form.email}\n onChange={(e) => setForm({ ...form, email: e.target.value })}\n className=\"mt-1\"\n placeholder=\"colleague@company.com\"\n />\n </div>\n <div className=\"grid grid-cols-3 gap-4\">\n <div>\n <label className=\"text-sm font-medium\">Role</label>\n <select\n className=\"mt-1 w-full rounded-md border border-input bg-background px-3 py-2 text-sm capitalize\"\n value={form.role}\n onChange={(e) => setForm({ ...form, role: e.target.value })}\n >\n {roles.map((r) => (\n <option key={r} value={r}>\n {r}\n </option>\n ))}\n </select>\n </div>\n <div>\n <label className=\"text-sm font-medium\">Department</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.department}\n onChange={(e) => setForm({ ...form, department: e.target.value })}\n >\n {departments.map((d) => (\n <option key={d} value={d}>\n {d}\n </option>\n ))}\n </select>\n </div>\n <div>\n <label className=\"text-sm font-medium\">Team</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.projectId}\n onChange={(e) => setForm({ ...form, projectId: e.target.value })}\n >\n <option value=\"\">No team</option>\n {teams.map((t) => (\n <option key={t.id} value={t.id}>\n {t.name}\n </option>\n ))}\n </select>\n </div>\n </div>\n </CardContent>\n </Card>\n </div>\n );\n}\n"],"mappings":";;;;;;;;AASA,IAAM,IAA0B,CAAG;;;;;;;;;;;;;AAyBnC,SAAgB,IAA2B;CACzC,IAAM,EAAE,mBAAgB,GAAe,EACjC,IAAW,GAAuB,EAElC,EAAE,SAAM,YAAS,aAAU,EAAuB,GAAyB;EAC/E,WAAW;GACT;GACA,YAAY,EAAE,OAAO,KAAK;GAC3B;EACD,MAAM,CAAC;EACR,CAAC,EAEI,CAAC,GAAM,KAAW,EAAS;EAC/B,OAAO;EACP,MAAM;EACN,WAAW;EACX,YAAY;EACb,CAAC,EACI,IAAQ;EACZ;EACA;EACA;EACA;EACA;EACA;EACD,EACK,IAAc;EAAC;EAAe;EAAW;EAAU;EAAW;EAAO,EAIrE,KAFW,GAAM,oBAAoB,SAAS,EAAE,EAE/B,QACpB,GAAK,MAAM;EACV,IAAM,IAAS,EAAE,eAAe;AAOhC,SANK,EAAI,MAAM,MAAM,EAAE,OAAO,EAAO,IACnC,EAAI,KAAK;GACP,IAAI;GACJ,MAAM,GAAG,EAAO,OAAO,EAAE,CAAC,aAAa,GAAG,EAAO,MAAM,EAAE,CAAC;GAC3D,CAAC,EAEG;IAET,EAAE,CACH;AAsBD,QAZI,IAEA,kBAAC,OAAD;EAAK,WAAU;YACb,kBAAC,OAAD,EAAK,WAAU,kFAAmF,CAAA;EAC9F,CAAA,GAIN,IACK,kBAAC,OAAD;EAAK,WAAU;YAAf,CAAkC,WAAQ,EAAM,QAAc;MAIrE,kBAAC,OAAD;EAAK,WAAU;YAAf;GACE,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,MAAD;KAAI,WAAU;eAAyB;KAAuB,CAAA,EAC9D,kBAAC,KAAD;KAAG,WAAU;eAAgC;KAAuC,CAAA,CAChF,EAAA,CAAA,EACN,kBAAC,OAAD;KAAK,WAAU;eAAf,CACE,kBAAC,GAAD;MAAQ,SAAQ;MAAU,MAAK;MAAK,eAAe,EAAS,kBAAkB;gBAA9E,CACE,kBAAC,GAAD,EAAG,WAAU,gBAAiB,CAAA,EAAA,SAEvB;SACT,kBAAC,GAAD;MAAQ,MAAK;MAAK,UAAA;MAAS,OAAM;gBAAjC,CACE,kBAAC,GAAD,EAAM,WAAU,gBAAiB,CAAA,EAAA,cAE1B;QACL;OACF;;GACN,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,UAAD;KAAQ,WAAU;eAAkB;KAA2B,CAAA,EAAA,wMAG3D;;GACN,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD;IAAW,WAAU;cAArB,CACE,kBAAC,GAAD,EAAU,WAAU,WAAY,CAAA,EAAA,qBAEtB;OACD,CAAA,EACb,kBAAC,GAAD;IAAa,WAAU;cAAvB,CACE,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,SAAD;KAAO,WAAU;eAAsB;KAAqB,CAAA,EAC5D,kBAAC,GAAD;KACE,MAAK;KACL,OAAO,EAAK;KACZ,WAAW,MAAM,EAAQ;MAAE,GAAG;MAAM,OAAO,EAAE,OAAO;MAAO,CAAC;KAC5D,WAAU;KACV,aAAY;KACZ,CAAA,CACE,EAAA,CAAA,EACN,kBAAC,OAAD;KAAK,WAAU;eAAf;MACE,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,SAAD;OAAO,WAAU;iBAAsB;OAAY,CAAA,EACnD,kBAAC,UAAD;OACE,WAAU;OACV,OAAO,EAAK;OACZ,WAAW,MAAM,EAAQ;QAAE,GAAG;QAAM,MAAM,EAAE,OAAO;QAAO,CAAC;iBAE1D,EAAM,KAAK,MACV,kBAAC,UAAD;QAAgB,OAAO;kBACpB;QACM,EAFI,EAEJ,CACT;OACK,CAAA,CACL,EAAA,CAAA;MACN,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,SAAD;OAAO,WAAU;iBAAsB;OAAkB,CAAA,EACzD,kBAAC,UAAD;OACE,WAAU;OACV,OAAO,EAAK;OACZ,WAAW,MAAM,EAAQ;QAAE,GAAG;QAAM,YAAY,EAAE,OAAO;QAAO,CAAC;iBAEhE,EAAY,KAAK,MAChB,kBAAC,UAAD;QAAgB,OAAO;kBACpB;QACM,EAFI,EAEJ,CACT;OACK,CAAA,CACL,EAAA,CAAA;MACN,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,SAAD;OAAO,WAAU;iBAAsB;OAAY,CAAA,EACnD,kBAAC,UAAD;OACE,WAAU;OACV,OAAO,EAAK;OACZ,WAAW,MAAM,EAAQ;QAAE,GAAG;QAAM,WAAW,EAAE,OAAO;QAAO,CAAC;iBAHlE,CAKE,kBAAC,UAAD;QAAQ,OAAM;kBAAG;QAAgB,CAAA,EAChC,EAAM,KAAK,MACV,kBAAC,UAAD;QAAmB,OAAO,EAAE;kBACzB,EAAE;QACI,EAFI,EAAE,GAEN,CACT,CACK;SACL,EAAA,CAAA;MACF;OACM;MACT,EAAA,CAAA;GACH"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@burdenoff/microfe-planmagnet",
|
|
3
|
-
"version": "2026.925.
|
|
3
|
+
"version": "2026.925.5",
|
|
4
4
|
"description": "Burdenoff PlanMagnet Microfrontend",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"files": [
|
|
@@ -26,8 +26,9 @@
|
|
|
26
26
|
"lint": "eslint .",
|
|
27
27
|
"format": "prettier --write \"src/**/*.{ts,tsx}\"",
|
|
28
28
|
"type:check": "bash scripts/build-limits.sh tsc --noEmit",
|
|
29
|
-
"sanity": "bash scripts/build-limits.sh --gate bash -c 'bun run codegen && bun run validate:schema && bun run lint && bun run format && bun run type:check && bun run build && bun run build-storybook'",
|
|
29
|
+
"sanity": "bash scripts/build-limits.sh --gate bash -c 'bun run codegen && bun run validate:schema && bun run check:nav && bun run lint && bun run format && bun run type:check && bun run build && bun run build-storybook'",
|
|
30
30
|
"validate:schema": "graphql-schema-drift",
|
|
31
|
+
"check:nav": "bun scripts/check-nav-targets.ts",
|
|
31
32
|
"schema:pull": "graphql-codegen --project schema-wspace && graphql-codegen --project schema-global && bun run schema:roots",
|
|
32
33
|
"schema:roots": "bun scripts/gen-gateway-roots.mjs",
|
|
33
34
|
"codegen": "graphql-codegen --project wspace && graphql-codegen --project global",
|