@burdenoff/microfe-planmagnet 2026.927.4 → 2026.927.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (141) hide show
  1. package/dist/generated/global-types.d.ts +9 -1
  2. package/dist/generated/global-types.d.ts.map +1 -1
  3. package/dist/generated/wspace-operations.d.ts +0 -12
  4. package/dist/generated/wspace-operations.d.ts.map +1 -1
  5. package/dist/planmagnet/PlanMagnetRoutes.d.ts.map +1 -1
  6. package/dist/planmagnet/PlanMagnetRoutes.js +14 -10
  7. package/dist/planmagnet/PlanMagnetRoutes.js.map +1 -1
  8. package/dist/planmagnet/admin/PlanMagnetAdminRoot.d.ts.map +1 -1
  9. package/dist/planmagnet/admin/PlanMagnetAdminRoot.js +149 -127
  10. package/dist/planmagnet/admin/PlanMagnetAdminRoot.js.map +1 -1
  11. package/dist/planmagnet/board/ProjectBoard.d.ts +2 -0
  12. package/dist/planmagnet/board/ProjectBoard.d.ts.map +1 -1
  13. package/dist/planmagnet/board/ProjectBoard.js +492 -225
  14. package/dist/planmagnet/board/ProjectBoard.js.map +1 -1
  15. package/dist/planmagnet/controls/FeatureControls.d.ts.map +1 -1
  16. package/dist/planmagnet/controls/FeatureControls.js +142 -139
  17. package/dist/planmagnet/controls/FeatureControls.js.map +1 -1
  18. package/dist/planmagnet/controls/FeatureTriage.d.ts +21 -0
  19. package/dist/planmagnet/controls/FeatureTriage.d.ts.map +1 -0
  20. package/dist/planmagnet/controls/FeatureTriage.js +398 -0
  21. package/dist/planmagnet/controls/FeatureTriage.js.map +1 -0
  22. package/dist/planmagnet/controls/MilestoneControls.d.ts.map +1 -1
  23. package/dist/planmagnet/controls/MilestoneControls.js +76 -73
  24. package/dist/planmagnet/controls/MilestoneControls.js.map +1 -1
  25. package/dist/planmagnet/controls/ProjectControls.d.ts.map +1 -1
  26. package/dist/planmagnet/controls/ProjectControls.js +47 -44
  27. package/dist/planmagnet/controls/ProjectControls.js.map +1 -1
  28. package/dist/planmagnet/controls/ReleaseControls.d.ts.map +1 -1
  29. package/dist/planmagnet/controls/ReleaseControls.js +47 -44
  30. package/dist/planmagnet/controls/ReleaseControls.js.map +1 -1
  31. package/dist/planmagnet/controls/WorkItemControls.d.ts.map +1 -1
  32. package/dist/planmagnet/controls/WorkItemControls.js +68 -65
  33. package/dist/planmagnet/controls/WorkItemControls.js.map +1 -1
  34. package/dist/planmagnet/hooks/useCounts.d.ts +39 -0
  35. package/dist/planmagnet/hooks/useCounts.d.ts.map +1 -0
  36. package/dist/planmagnet/hooks/useCounts.js +209 -0
  37. package/dist/planmagnet/hooks/useCounts.js.map +1 -0
  38. package/dist/planmagnet/import/exportColumns.d.ts +52 -0
  39. package/dist/planmagnet/import/exportColumns.d.ts.map +1 -0
  40. package/dist/planmagnet/import/exportColumns.js +81 -0
  41. package/dist/planmagnet/import/exportColumns.js.map +1 -0
  42. package/dist/planmagnet/pages/AnalyticsAnalyticsPagePage.d.ts.map +1 -1
  43. package/dist/planmagnet/pages/AnalyticsAnalyticsPagePage.js +255 -242
  44. package/dist/planmagnet/pages/AnalyticsAnalyticsPagePage.js.map +1 -1
  45. package/dist/planmagnet/pages/DashboardDashboardPagePage.d.ts.map +1 -1
  46. package/dist/planmagnet/pages/DashboardDashboardPagePage.js +199 -160
  47. package/dist/planmagnet/pages/DashboardDashboardPagePage.js.map +1 -1
  48. package/dist/planmagnet/pages/DocsDocDetailPagePage.d.ts.map +1 -1
  49. package/dist/planmagnet/pages/DocsDocDetailPagePage.js +147 -144
  50. package/dist/planmagnet/pages/DocsDocDetailPagePage.js.map +1 -1
  51. package/dist/planmagnet/pages/GoalsGoalsPagePage.d.ts.map +1 -1
  52. package/dist/planmagnet/pages/GoalsGoalsPagePage.js +2 -7
  53. package/dist/planmagnet/pages/GoalsGoalsPagePage.js.map +1 -1
  54. package/dist/planmagnet/pages/GoalsObjectiveDetailPagePage.d.ts.map +1 -1
  55. package/dist/planmagnet/pages/GoalsObjectiveDetailPagePage.js +173 -173
  56. package/dist/planmagnet/pages/GoalsObjectiveDetailPagePage.js.map +1 -1
  57. package/dist/planmagnet/pages/ProductsEditProductPagePage.d.ts.map +1 -1
  58. package/dist/planmagnet/pages/ProductsEditProductPagePage.js +120 -117
  59. package/dist/planmagnet/pages/ProductsEditProductPagePage.js.map +1 -1
  60. package/dist/planmagnet/pages/ProductsFeatureAnalyticsPagePage.d.ts.map +1 -1
  61. package/dist/planmagnet/pages/ProductsFeatureAnalyticsPagePage.js +97 -117
  62. package/dist/planmagnet/pages/ProductsFeatureAnalyticsPagePage.js.map +1 -1
  63. package/dist/planmagnet/pages/ProductsFeatureDetailPagePage.d.ts.map +1 -1
  64. package/dist/planmagnet/pages/ProductsFeatureDetailPagePage.js +168 -103
  65. package/dist/planmagnet/pages/ProductsFeatureDetailPagePage.js.map +1 -1
  66. package/dist/planmagnet/pages/ProductsFeaturesPagePage.d.ts.map +1 -1
  67. package/dist/planmagnet/pages/ProductsFeaturesPagePage.js +117 -103
  68. package/dist/planmagnet/pages/ProductsFeaturesPagePage.js.map +1 -1
  69. package/dist/planmagnet/pages/ProductsProductDetailPagePage.d.ts.map +1 -1
  70. package/dist/planmagnet/pages/ProductsProductDetailPagePage.js +4 -8
  71. package/dist/planmagnet/pages/ProductsProductDetailPagePage.js.map +1 -1
  72. package/dist/planmagnet/pages/ProductsProductsPagePage.d.ts.map +1 -1
  73. package/dist/planmagnet/pages/ProductsProductsPagePage.js +85 -90
  74. package/dist/planmagnet/pages/ProductsProductsPagePage.js.map +1 -1
  75. package/dist/planmagnet/pages/ProductsReleaseDetailPagePage.d.ts.map +1 -1
  76. package/dist/planmagnet/pages/ProductsReleaseDetailPagePage.js +12 -2
  77. package/dist/planmagnet/pages/ProductsReleaseDetailPagePage.js.map +1 -1
  78. package/dist/planmagnet/pages/ProductsReleasesPagePage.d.ts.map +1 -1
  79. package/dist/planmagnet/pages/ProductsReleasesPagePage.js +2 -2
  80. package/dist/planmagnet/pages/ProductsReleasesPagePage.js.map +1 -1
  81. package/dist/planmagnet/pages/ProductsRoadmapAnalyticsPagePage.d.ts.map +1 -1
  82. package/dist/planmagnet/pages/ProductsRoadmapAnalyticsPagePage.js +48 -71
  83. package/dist/planmagnet/pages/ProductsRoadmapAnalyticsPagePage.js.map +1 -1
  84. package/dist/planmagnet/pages/ProductsRoadmapsPagePage.d.ts.map +1 -1
  85. package/dist/planmagnet/pages/ProductsRoadmapsPagePage.js +17 -13
  86. package/dist/planmagnet/pages/ProductsRoadmapsPagePage.js.map +1 -1
  87. package/dist/planmagnet/pages/ProjectsActiveProjectsPagePage.d.ts.map +1 -1
  88. package/dist/planmagnet/pages/ProjectsActiveProjectsPagePage.js +1 -1
  89. package/dist/planmagnet/pages/ProjectsActiveProjectsPagePage.js.map +1 -1
  90. package/dist/planmagnet/pages/ProjectsEditProjectPagePage.js +6 -6
  91. package/dist/planmagnet/pages/ProjectsPlanningDetailPagePage.d.ts.map +1 -1
  92. package/dist/planmagnet/pages/ProjectsPlanningDetailPagePage.js +11 -8
  93. package/dist/planmagnet/pages/ProjectsPlanningDetailPagePage.js.map +1 -1
  94. package/dist/planmagnet/pages/ProjectsPlanningEditPagePage.js +4 -4
  95. package/dist/planmagnet/pages/ProjectsPlanningPagePage.d.ts.map +1 -1
  96. package/dist/planmagnet/pages/ProjectsPlanningPagePage.js +1 -1
  97. package/dist/planmagnet/pages/ProjectsPlanningPagePage.js.map +1 -1
  98. package/dist/planmagnet/pages/ProjectsProjectDetailPagePage.d.ts.map +1 -1
  99. package/dist/planmagnet/pages/ProjectsProjectDetailPagePage.js +152 -139
  100. package/dist/planmagnet/pages/ProjectsProjectDetailPagePage.js.map +1 -1
  101. package/dist/planmagnet/pages/ProjectsProjectsPagePage.d.ts.map +1 -1
  102. package/dist/planmagnet/pages/ProjectsProjectsPagePage.js +75 -74
  103. package/dist/planmagnet/pages/ProjectsProjectsPagePage.js.map +1 -1
  104. package/dist/planmagnet/pages/ReportsReportsPagePage.d.ts +7 -0
  105. package/dist/planmagnet/pages/ReportsReportsPagePage.d.ts.map +1 -1
  106. package/dist/planmagnet/pages/ReportsReportsPagePage.js +39 -201
  107. package/dist/planmagnet/pages/ReportsReportsPagePage.js.map +1 -1
  108. package/dist/planmagnet/pages/SprintsStartSprintPagePage.d.ts.map +1 -1
  109. package/dist/planmagnet/pages/SprintsStartSprintPagePage.js +118 -99
  110. package/dist/planmagnet/pages/SprintsStartSprintPagePage.js.map +1 -1
  111. package/dist/planmagnet/pages/TasksImportPagePage.d.ts +2 -0
  112. package/dist/planmagnet/pages/TasksImportPagePage.d.ts.map +1 -0
  113. package/dist/planmagnet/pages/TasksImportPagePage.js +309 -0
  114. package/dist/planmagnet/pages/TasksImportPagePage.js.map +1 -0
  115. package/dist/planmagnet/pages/TasksTasksPagePage.d.ts.map +1 -1
  116. package/dist/planmagnet/pages/TasksTasksPagePage.js +110 -104
  117. package/dist/planmagnet/pages/TasksTasksPagePage.js.map +1 -1
  118. package/dist/planmagnet/pages/TeamTeamPagePage.d.ts.map +1 -1
  119. package/dist/planmagnet/pages/TeamTeamPagePage.js +99 -177
  120. package/dist/planmagnet/pages/TeamTeamPagePage.js.map +1 -1
  121. package/dist/planmagnet/pages/analytics/DeliveryHealthCards.d.ts.map +1 -1
  122. package/dist/planmagnet/pages/analytics/DeliveryHealthCards.js +8 -4
  123. package/dist/planmagnet/pages/analytics/DeliveryHealthCards.js.map +1 -1
  124. package/dist/planmagnet/releases/ReleaseWorkItemsCard.d.ts.map +1 -1
  125. package/dist/planmagnet/releases/ReleaseWorkItemsCard.js +10 -4
  126. package/dist/planmagnet/releases/ReleaseWorkItemsCard.js.map +1 -1
  127. package/dist/planmagnet/roadmaps/RoadmapControls.d.ts.map +1 -1
  128. package/dist/planmagnet/roadmaps/RoadmapControls.js +151 -138
  129. package/dist/planmagnet/roadmaps/RoadmapControls.js.map +1 -1
  130. package/dist/planmagnet/sprints/SprintControls.d.ts.map +1 -1
  131. package/dist/planmagnet/sprints/SprintControls.js +32 -30
  132. package/dist/planmagnet/sprints/SprintControls.js.map +1 -1
  133. package/dist/planmagnet/utils/mutationResult.d.ts +10 -0
  134. package/dist/planmagnet/utils/mutationResult.d.ts.map +1 -1
  135. package/dist/planmagnet/utils/mutationResult.js +2 -1
  136. package/dist/planmagnet/utils/mutationResult.js.map +1 -1
  137. package/dist/planmagnet/utils/rowNavigation.d.ts +2 -0
  138. package/dist/planmagnet/utils/rowNavigation.d.ts.map +1 -1
  139. package/dist/planmagnet/utils/rowNavigation.js +9 -8
  140. package/dist/planmagnet/utils/rowNavigation.js.map +1 -1
  141. package/package.json +1 -1
@@ -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
- import { detailPath as r, rowLinkProps as i } from "../utils/rowNavigation.js";
4
- import { CheckSquare as a, FolderKanban as o, Plus as s, TrendingUp as c, Users as l } from "lucide-react";
5
- import { gql as u } from "@apollo/client";
6
- import { useQuery as d } from "@apollo/client/react";
7
- import { jsx as f, jsxs as p } from "react/jsx-runtime";
8
- import { useI18n as m } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
9
- import { Badge as h, Button as g, Card as _, CardContent as v, CardHeader as y, CardTitle as b } from "@burdenoff/fe-libs/ui";
3
+ import { countLabel as r, useProjectCounts as i } from "../hooks/useCounts.js";
4
+ import { detailPath as a, rowLinkProps as o } from "../utils/rowNavigation.js";
5
+ import { CheckSquare as s, FolderKanban as c, Plus as l, TrendingUp as u, Users as d } from "lucide-react";
6
+ import { gql as f } from "@apollo/client";
7
+ import { useQuery as p } from "@apollo/client/react";
8
+ import { jsx as m, jsxs as h } from "react/jsx-runtime";
9
+ import { useI18n as g } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
10
+ import { Badge as _, Button as v, Card as y, CardContent as b, CardHeader as x, CardTitle as S } from "@burdenoff/fe-libs/ui";
10
11
  //#region src/planmagnet/pages/ProjectsProjectsPagePage.tsx
11
- var x = u`
12
+ var C = f`
12
13
  query GetProjects($workspaceId: ID!) {
13
14
  planmagnetProjects(workspaceId: $workspaceId, pagination: { first: 100 }) {
14
15
  items {
@@ -27,139 +28,139 @@ var x = u`
27
28
  totalCount
28
29
  }
29
30
  }
30
- `, S = {
31
+ `, w = {
31
32
  SCRUM: "bg-blue-100 text-blue-800",
32
33
  KANBAN: "bg-purple-100 text-purple-800",
33
34
  WATERFALL: "bg-gray-100 text-gray-800",
34
35
  HYBRID: "bg-teal-100 text-teal-800",
35
36
  AGILE: "bg-indigo-100 text-indigo-800",
36
37
  CUSTOM: "bg-amber-100 text-amber-800"
37
- }, C = (e) => e === "ACTIVE" ? "default" : "secondary";
38
- function w() {
39
- let u = t(), { workspaceId: w } = e(), { t: T } = m(), { data: E, loading: D, error: O } = d(x, { variables: { workspaceId: w ?? "default" } });
40
- if (D && !E) return /* @__PURE__ */ f("div", {
38
+ }, T = (e) => e === "ACTIVE" ? "default" : "secondary";
39
+ function E() {
40
+ let f = t(), { workspaceId: E } = e(), { t: D } = g(), { data: O, loading: k, error: A } = p(C, { variables: { workspaceId: E ?? "default" } }), j = i();
41
+ if (k && !O) return /* @__PURE__ */ m("div", {
41
42
  className: "flex items-center justify-center p-12",
42
- children: /* @__PURE__ */ f("div", { className: "animate-spin h-8 w-8 border-2 border-primary border-t-transparent rounded-full" })
43
+ children: /* @__PURE__ */ m("div", { className: "animate-spin h-8 w-8 border-2 border-primary border-t-transparent rounded-full" })
43
44
  });
44
- if (O) return /* @__PURE__ */ p("div", {
45
+ if (A) return /* @__PURE__ */ h("div", {
45
46
  className: "p-6 text-red-500",
46
47
  children: [
47
- T("planmagnet.projects.errorLoading", "Error loading projects"),
48
+ D("planmagnet.projects.errorLoading", "Error loading projects"),
48
49
  ": ",
49
- O.message
50
+ A.message
50
51
  ]
51
52
  });
52
- let k = E?.planmagnetProjects?.items ?? [], A = {
53
- total: k.length,
54
- active: k.filter((e) => e.status === "ACTIVE").length,
55
- completed: k.filter((e) => e.status === "COMPLETED").length,
56
- onHold: k.filter((e) => e.status === "ON_HOLD").length
53
+ let M = O?.planmagnetProjects?.items ?? [], N = {
54
+ total: r(j?.all),
55
+ active: r(j?.active),
56
+ completed: r(j?.completed),
57
+ onHold: r(j?.onHold)
57
58
  };
58
- return /* @__PURE__ */ p("div", {
59
+ return /* @__PURE__ */ h("div", {
59
60
  className: "space-y-6 p-6",
60
61
  children: [
61
- /* @__PURE__ */ p("div", {
62
+ /* @__PURE__ */ h("div", {
62
63
  className: "flex items-center justify-between",
63
- children: [/* @__PURE__ */ p("div", { children: [/* @__PURE__ */ f("h1", {
64
+ children: [/* @__PURE__ */ h("div", { children: [/* @__PURE__ */ m("h1", {
64
65
  className: "text-2xl font-semibold",
65
- children: T("planmagnet.projects.title", "All Projects")
66
- }), /* @__PURE__ */ f("p", {
66
+ children: D("planmagnet.projects.title", "All Projects")
67
+ }), /* @__PURE__ */ m("p", {
67
68
  className: "text-sm text-muted-foreground",
68
- children: T("planmagnet.projects.subtitle", "Manage and track all projects across teams")
69
- })] }), /* @__PURE__ */ p(g, {
69
+ children: D("planmagnet.projects.subtitle", "Manage and track all projects across teams")
70
+ })] }), /* @__PURE__ */ h(v, {
70
71
  size: "sm",
71
- onClick: () => u("/projects/create-project-page"),
72
- children: [/* @__PURE__ */ f(s, { className: "mr-1 h-4 w-4" }), T("planmagnet.projects.actions.newProject", "New Project")]
72
+ onClick: () => f("/projects/create-project-page"),
73
+ children: [/* @__PURE__ */ m(l, { className: "mr-1 h-4 w-4" }), D("planmagnet.projects.actions.newProject", "New Project")]
73
74
  })]
74
75
  }),
75
- /* @__PURE__ */ f("div", {
76
+ /* @__PURE__ */ m("div", {
76
77
  className: "grid grid-cols-2 md:grid-cols-4 gap-4",
77
78
  children: [
78
79
  {
79
- label: T("planmagnet.projects.metrics.totalProjects", "Total Projects"),
80
- value: A.total,
81
- icon: o
80
+ label: D("planmagnet.projects.metrics.totalProjects", "Total Projects"),
81
+ value: N.total,
82
+ icon: c
82
83
  },
83
84
  {
84
- label: T("planmagnet.projects.metrics.active", "Active"),
85
- value: A.active,
86
- icon: c
85
+ label: D("planmagnet.projects.metrics.active", "Active"),
86
+ value: N.active,
87
+ icon: u
87
88
  },
88
89
  {
89
- label: T("planmagnet.projects.metrics.completed", "Completed"),
90
- value: A.completed,
91
- icon: a
90
+ label: D("planmagnet.projects.metrics.completed", "Completed"),
91
+ value: N.completed,
92
+ icon: s
92
93
  },
93
94
  {
94
- label: T("planmagnet.projects.metrics.onHold", "On Hold"),
95
- value: A.onHold,
96
- icon: c
95
+ label: D("planmagnet.projects.metrics.onHold", "On Hold"),
96
+ value: N.onHold,
97
+ icon: u
97
98
  }
98
- ].map((e) => /* @__PURE__ */ f(_, { children: /* @__PURE__ */ p(v, {
99
+ ].map((e) => /* @__PURE__ */ m(y, { children: /* @__PURE__ */ h(b, {
99
100
  className: "pt-4",
100
- children: [/* @__PURE__ */ p("div", {
101
+ children: [/* @__PURE__ */ h("div", {
101
102
  className: "flex items-center gap-2 text-muted-foreground text-sm",
102
- children: [/* @__PURE__ */ f(e.icon, { className: "h-4 w-4" }), e.label]
103
- }), /* @__PURE__ */ f("p", {
103
+ children: [/* @__PURE__ */ m(e.icon, { className: "h-4 w-4" }), e.label]
104
+ }), /* @__PURE__ */ m("p", {
104
105
  className: "text-xl font-semibold mt-1",
105
106
  children: e.value
106
107
  })]
107
108
  }) }, e.label))
108
109
  }),
109
- /* @__PURE__ */ f("div", {
110
+ /* @__PURE__ */ m("div", {
110
111
  className: "grid grid-cols-1 md:grid-cols-2 gap-4",
111
- children: k.map((e) => /* @__PURE__ */ p(_, {
112
- ...i(() => u(r("/projects/project-detail-page", e.id)), e.name),
113
- children: [/* @__PURE__ */ f(y, {
112
+ children: M.map((e) => /* @__PURE__ */ h(y, {
113
+ ...o(() => f(a("/projects/project-detail-page", e.id)), e.name),
114
+ children: [/* @__PURE__ */ m(x, {
114
115
  className: "pb-2",
115
- children: /* @__PURE__ */ p("div", {
116
+ children: /* @__PURE__ */ h("div", {
116
117
  className: "flex items-center justify-between",
117
- children: [/* @__PURE__ */ f(b, {
118
+ children: [/* @__PURE__ */ m(S, {
118
119
  className: "text-base",
119
120
  children: e.name
120
- }), /* @__PURE__ */ f("span", {
121
+ }), /* @__PURE__ */ m("span", {
121
122
  className: "text-xs text-muted-foreground font-mono",
122
123
  children: e.key
123
124
  })]
124
125
  })
125
- }), /* @__PURE__ */ p(v, {
126
+ }), /* @__PURE__ */ h(b, {
126
127
  className: "space-y-3",
127
128
  children: [
128
- /* @__PURE__ */ f("p", {
129
+ /* @__PURE__ */ m("p", {
129
130
  className: "text-sm text-muted-foreground",
130
- children: e.description ?? T("planmagnet.projects.shared.noDescription", "No description")
131
+ children: e.description ?? D("planmagnet.projects.shared.noDescription", "No description")
131
132
  }),
132
- /* @__PURE__ */ p("div", {
133
+ /* @__PURE__ */ h("div", {
133
134
  className: "flex gap-2",
134
- children: [/* @__PURE__ */ f(h, {
135
- variant: C(e.status),
135
+ children: [/* @__PURE__ */ m(_, {
136
+ variant: T(e.status),
136
137
  className: "capitalize",
137
138
  children: e.status.toLowerCase().replace("_", " ")
138
- }), /* @__PURE__ */ f("span", {
139
- className: `text-xs px-2 py-0.5 rounded-full capitalize ${S[e.methodology] ?? "bg-gray-100"}`,
139
+ }), /* @__PURE__ */ m("span", {
140
+ className: `text-xs px-2 py-0.5 rounded-full capitalize ${w[e.methodology] ?? "bg-gray-100"}`,
140
141
  children: e.methodology.toLowerCase()
141
142
  })]
142
143
  }),
143
- e.tags.length > 0 && /* @__PURE__ */ f("div", {
144
+ e.tags.length > 0 && /* @__PURE__ */ m("div", {
144
145
  className: "flex gap-1 flex-wrap",
145
- children: e.tags.map((e) => /* @__PURE__ */ f(h, {
146
+ children: e.tags.map((e) => /* @__PURE__ */ m(_, {
146
147
  variant: "outline",
147
148
  className: "text-xs",
148
149
  children: e
149
150
  }, e))
150
151
  }),
151
- /* @__PURE__ */ p("div", {
152
+ /* @__PURE__ */ h("div", {
152
153
  className: "flex justify-between text-xs text-muted-foreground border-t pt-2",
153
- children: [/* @__PURE__ */ p("span", {
154
+ children: [/* @__PURE__ */ h("span", {
154
155
  className: "flex items-center gap-1",
155
156
  children: [
156
- /* @__PURE__ */ f(l, { className: "h-3 w-3" }),
157
- T("planmagnet.projects.shared.owner", "Owner"),
157
+ /* @__PURE__ */ m(d, { className: "h-3 w-3" }),
158
+ D("planmagnet.projects.shared.owner", "Owner"),
158
159
  ":",
159
160
  " ",
160
- /* @__PURE__ */ f(n, { id: e.ownerId })
161
+ /* @__PURE__ */ m(n, { id: e.ownerId })
161
162
  ]
162
- }), /* @__PURE__ */ p("span", { children: [
163
+ }), /* @__PURE__ */ h("span", { children: [
163
164
  e.startDate ? new Date(e.startDate).toLocaleDateString() : "—",
164
165
  " -",
165
166
  " ",
@@ -170,14 +171,14 @@ function w() {
170
171
  })]
171
172
  }, e.id))
172
173
  }),
173
- k.length === 0 && /* @__PURE__ */ f("p", {
174
+ M.length === 0 && /* @__PURE__ */ m("p", {
174
175
  className: "text-center text-muted-foreground py-8",
175
- children: T("planmagnet.projects.empty", "No projects found.")
176
+ children: D("planmagnet.projects.empty", "No projects found.")
176
177
  })
177
178
  ]
178
179
  });
179
180
  }
180
181
  //#endregion
181
- export { w as ProjectsProjectsPagePage };
182
+ export { E as ProjectsProjectsPagePage };
182
183
 
183
184
  //# sourceMappingURL=ProjectsProjectsPagePage.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ProjectsProjectsPagePage.js","names":[],"sources":["../../../src/planmagnet/pages/ProjectsProjectsPagePage.tsx"],"sourcesContent":["// eslint-disable-next-line @typescript-eslint/ban-ts-comment\n// @ts-nocheck\nimport { gql } from '@apollo/client';\nimport { useQuery } from '@apollo/client/react';\nimport { Card, CardContent, CardHeader, CardTitle, Badge, Button } from '@burdenoff/fe-libs/ui';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { FolderKanban, Plus, Users, CheckSquare, TrendingUp } from 'lucide-react';\nimport { usePlanMagnet, usePlanMagnetNavigate } from '../providers/PlanMagnetProvider';\nimport { rowLinkProps, detailPath } from '../utils/rowNavigation';\nimport { PersonName } from '../people/People';\n\nconst GET_PROJECTS = gql`\n query GetProjects($workspaceId: ID!) {\n planmagnetProjects(workspaceId: $workspaceId, pagination: { first: 100 }) {\n items {\n id\n name\n key\n description\n status\n methodology\n ownerId\n startDate\n endDate\n tags\n createdAt\n }\n totalCount\n }\n }\n`;\n\nconst methodColor: Record<string, string> = {\n SCRUM: 'bg-blue-100 text-blue-800',\n KANBAN: 'bg-purple-100 text-purple-800',\n WATERFALL: 'bg-gray-100 text-gray-800',\n HYBRID: 'bg-teal-100 text-teal-800',\n AGILE: 'bg-indigo-100 text-indigo-800',\n CUSTOM: 'bg-amber-100 text-amber-800',\n};\n\nconst statusVariant = (status: string) => (status === 'ACTIVE' ? 'default' : 'secondary');\n\nexport function ProjectsProjectsPagePage() {\n const navigate = usePlanMagnetNavigate();\n const { workspaceId } = usePlanMagnet();\n const { t } = useI18n();\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_PROJECTS, {\n variables: { workspaceId: workspaceId ?? 'default' },\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 if (error)\n return (\n <div className=\"p-6 text-red-500\">\n {t('planmagnet.projects.errorLoading', 'Error loading projects')}: {error.message}\n </div>\n );\n\n const projects = data?.planmagnetProjects?.items ?? [];\n\n const stats = {\n total: projects.length,\n active: projects.filter((p: { status: string }) => p.status === 'ACTIVE').length,\n completed: projects.filter((p: { status: string }) => p.status === 'COMPLETED').length,\n onHold: projects.filter((p: { status: string }) => p.status === 'ON_HOLD').length,\n };\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\">\n {t('planmagnet.projects.title', 'All Projects')}\n </h1>\n <p className=\"text-sm text-muted-foreground\">\n {t('planmagnet.projects.subtitle', 'Manage and track all projects across teams')}\n </p>\n </div>\n <Button size=\"sm\" onClick={() => navigate('/projects/create-project-page')}>\n <Plus className=\"mr-1 h-4 w-4\" />\n {t('planmagnet.projects.actions.newProject', 'New Project')}\n </Button>\n </div>\n\n <div className=\"grid grid-cols-2 md:grid-cols-4 gap-4\">\n {[\n {\n label: t('planmagnet.projects.metrics.totalProjects', 'Total Projects'),\n value: stats.total,\n icon: FolderKanban,\n },\n {\n label: t('planmagnet.projects.metrics.active', 'Active'),\n value: stats.active,\n icon: TrendingUp,\n },\n {\n label: t('planmagnet.projects.metrics.completed', 'Completed'),\n value: stats.completed,\n icon: CheckSquare,\n },\n {\n label: t('planmagnet.projects.metrics.onHold', 'On Hold'),\n value: stats.onHold,\n icon: TrendingUp,\n },\n ].map((s) => (\n <Card key={s.label}>\n <CardContent className=\"pt-4\">\n <div className=\"flex items-center gap-2 text-muted-foreground text-sm\">\n <s.icon className=\"h-4 w-4\" />\n {s.label}\n </div>\n <p className=\"text-xl font-semibold mt-1\">{s.value}</p>\n </CardContent>\n </Card>\n ))}\n </div>\n\n <div className=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\n {projects.map(\n (project: {\n id: string;\n name: string;\n key: string;\n description: string | null;\n status: string;\n methodology: string;\n ownerId: string;\n startDate: string | null;\n endDate: string | null;\n tags: string[];\n }) => {\n return (\n <Card\n key={project.id}\n {...rowLinkProps(\n () => navigate(detailPath('/projects/project-detail-page', project.id)),\n project.name\n )}\n >\n <CardHeader className=\"pb-2\">\n <div className=\"flex items-center justify-between\">\n <CardTitle className=\"text-base\">{project.name}</CardTitle>\n <span className=\"text-xs text-muted-foreground font-mono\">{project.key}</span>\n </div>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n <p className=\"text-sm text-muted-foreground\">\n {project.description ??\n t('planmagnet.projects.shared.noDescription', 'No description')}\n </p>\n <div className=\"flex gap-2\">\n <Badge variant={statusVariant(project.status)} className=\"capitalize\">\n {project.status.toLowerCase().replace('_', ' ')}\n </Badge>\n <span\n className={`text-xs px-2 py-0.5 rounded-full capitalize ${methodColor[project.methodology] ?? 'bg-gray-100'}`}\n >\n {project.methodology.toLowerCase()}\n </span>\n </div>\n {project.tags.length > 0 && (\n <div className=\"flex gap-1 flex-wrap\">\n {project.tags.map((tag: string) => (\n <Badge key={tag} variant=\"outline\" className=\"text-xs\">\n {tag}\n </Badge>\n ))}\n </div>\n )}\n <div className=\"flex justify-between text-xs text-muted-foreground border-t pt-2\">\n <span className=\"flex items-center gap-1\">\n <Users className=\"h-3 w-3\" />\n {t('planmagnet.projects.shared.owner', 'Owner')}:{' '}\n <PersonName id={project.ownerId} />\n </span>\n <span>\n {project.startDate ? new Date(project.startDate).toLocaleDateString() : '—'} -{' '}\n {project.endDate ? new Date(project.endDate).toLocaleDateString() : '—'}\n </span>\n </div>\n </CardContent>\n </Card>\n );\n }\n )}\n </div>\n {projects.length === 0 && (\n <p className=\"text-center text-muted-foreground py-8\">\n {t('planmagnet.projects.empty', 'No projects found.')}\n </p>\n )}\n </div>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"ProjectsProjectsPagePage.js","names":[],"sources":["../../../src/planmagnet/pages/ProjectsProjectsPagePage.tsx"],"sourcesContent":["// eslint-disable-next-line @typescript-eslint/ban-ts-comment\n// @ts-nocheck\nimport { gql } from '@apollo/client';\nimport { useQuery } from '@apollo/client/react';\nimport { Card, CardContent, CardHeader, CardTitle, Badge, Button } from '@burdenoff/fe-libs/ui';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { FolderKanban, Plus, Users, CheckSquare, TrendingUp } from 'lucide-react';\nimport { countLabel, useProjectCounts } from '../hooks/useCounts';\nimport { usePlanMagnet, usePlanMagnetNavigate } from '../providers/PlanMagnetProvider';\nimport { rowLinkProps, detailPath } from '../utils/rowNavigation';\nimport { PersonName } from '../people/People';\n\nconst GET_PROJECTS = gql`\n query GetProjects($workspaceId: ID!) {\n planmagnetProjects(workspaceId: $workspaceId, pagination: { first: 100 }) {\n items {\n id\n name\n key\n description\n status\n methodology\n ownerId\n startDate\n endDate\n tags\n createdAt\n }\n totalCount\n }\n }\n`;\n\nconst methodColor: Record<string, string> = {\n SCRUM: 'bg-blue-100 text-blue-800',\n KANBAN: 'bg-purple-100 text-purple-800',\n WATERFALL: 'bg-gray-100 text-gray-800',\n HYBRID: 'bg-teal-100 text-teal-800',\n AGILE: 'bg-indigo-100 text-indigo-800',\n CUSTOM: 'bg-amber-100 text-amber-800',\n};\n\nconst statusVariant = (status: string) => (status === 'ACTIVE' ? 'default' : 'secondary');\n\nexport function ProjectsProjectsPagePage() {\n const navigate = usePlanMagnetNavigate();\n const { workspaceId } = usePlanMagnet();\n const { t } = useI18n();\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_PROJECTS, {\n variables: { workspaceId: workspaceId ?? 'default' },\n });\n // Server counts (BOFF-7969): these tiles counted the rows of one 100-row page.\n const counts = useProjectCounts();\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 if (error)\n return (\n <div className=\"p-6 text-red-500\">\n {t('planmagnet.projects.errorLoading', 'Error loading projects')}: {error.message}\n </div>\n );\n\n const projects = data?.planmagnetProjects?.items ?? [];\n\n const stats = {\n total: countLabel(counts?.all),\n active: countLabel(counts?.active),\n completed: countLabel(counts?.completed),\n onHold: countLabel(counts?.onHold),\n };\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\">\n {t('planmagnet.projects.title', 'All Projects')}\n </h1>\n <p className=\"text-sm text-muted-foreground\">\n {t('planmagnet.projects.subtitle', 'Manage and track all projects across teams')}\n </p>\n </div>\n <Button size=\"sm\" onClick={() => navigate('/projects/create-project-page')}>\n <Plus className=\"mr-1 h-4 w-4\" />\n {t('planmagnet.projects.actions.newProject', 'New Project')}\n </Button>\n </div>\n\n <div className=\"grid grid-cols-2 md:grid-cols-4 gap-4\">\n {[\n {\n label: t('planmagnet.projects.metrics.totalProjects', 'Total Projects'),\n value: stats.total,\n icon: FolderKanban,\n },\n {\n label: t('planmagnet.projects.metrics.active', 'Active'),\n value: stats.active,\n icon: TrendingUp,\n },\n {\n label: t('planmagnet.projects.metrics.completed', 'Completed'),\n value: stats.completed,\n icon: CheckSquare,\n },\n {\n label: t('planmagnet.projects.metrics.onHold', 'On Hold'),\n value: stats.onHold,\n icon: TrendingUp,\n },\n ].map((s) => (\n <Card key={s.label}>\n <CardContent className=\"pt-4\">\n <div className=\"flex items-center gap-2 text-muted-foreground text-sm\">\n <s.icon className=\"h-4 w-4\" />\n {s.label}\n </div>\n <p className=\"text-xl font-semibold mt-1\">{s.value}</p>\n </CardContent>\n </Card>\n ))}\n </div>\n\n <div className=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\n {projects.map(\n (project: {\n id: string;\n name: string;\n key: string;\n description: string | null;\n status: string;\n methodology: string;\n ownerId: string;\n startDate: string | null;\n endDate: string | null;\n tags: string[];\n }) => {\n return (\n <Card\n key={project.id}\n {...rowLinkProps(\n () => navigate(detailPath('/projects/project-detail-page', project.id)),\n project.name\n )}\n >\n <CardHeader className=\"pb-2\">\n <div className=\"flex items-center justify-between\">\n <CardTitle className=\"text-base\">{project.name}</CardTitle>\n <span className=\"text-xs text-muted-foreground font-mono\">{project.key}</span>\n </div>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n <p className=\"text-sm text-muted-foreground\">\n {project.description ??\n t('planmagnet.projects.shared.noDescription', 'No description')}\n </p>\n <div className=\"flex gap-2\">\n <Badge variant={statusVariant(project.status)} className=\"capitalize\">\n {project.status.toLowerCase().replace('_', ' ')}\n </Badge>\n <span\n className={`text-xs px-2 py-0.5 rounded-full capitalize ${methodColor[project.methodology] ?? 'bg-gray-100'}`}\n >\n {project.methodology.toLowerCase()}\n </span>\n </div>\n {project.tags.length > 0 && (\n <div className=\"flex gap-1 flex-wrap\">\n {project.tags.map((tag: string) => (\n <Badge key={tag} variant=\"outline\" className=\"text-xs\">\n {tag}\n </Badge>\n ))}\n </div>\n )}\n <div className=\"flex justify-between text-xs text-muted-foreground border-t pt-2\">\n <span className=\"flex items-center gap-1\">\n <Users className=\"h-3 w-3\" />\n {t('planmagnet.projects.shared.owner', 'Owner')}:{' '}\n <PersonName id={project.ownerId} />\n </span>\n <span>\n {project.startDate ? new Date(project.startDate).toLocaleDateString() : '—'} -{' '}\n {project.endDate ? new Date(project.endDate).toLocaleDateString() : '—'}\n </span>\n </div>\n </CardContent>\n </Card>\n );\n }\n )}\n </div>\n {projects.length === 0 && (\n <p className=\"text-center text-muted-foreground py-8\">\n {t('planmagnet.projects.empty', 'No projects found.')}\n </p>\n )}\n </div>\n );\n}\n"],"mappings":"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"}
@@ -1,2 +1,9 @@
1
+ /**
2
+ * Reports (BOFF-7967). There is no saved-report model and no report runner yet, so there are no reports to list.
3
+ * This page used to invent them — one "Velocity Report" per completed sprint, one "Burndown" per active sprint, one
4
+ * "Status Report" per active project — with made-up schedules, "Run Today" counts for reports that never ran, and
5
+ * the viewer named as their creator. It now says so, and points to where the same analysis lives, computed on the
6
+ * server from real data.
7
+ */
1
8
  export declare function ReportsReportsPagePage(): import("react/jsx-runtime").JSX.Element;
2
9
  //# sourceMappingURL=ReportsReportsPagePage.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ReportsReportsPagePage.d.ts","sourceRoot":"","sources":["../../../src/planmagnet/pages/ReportsReportsPagePage.tsx"],"names":[],"mappings":"AA6FA,wBAAgB,sBAAsB,4CAqKrC"}
1
+ {"version":3,"file":"ReportsReportsPagePage.d.ts","sourceRoot":"","sources":["../../../src/planmagnet/pages/ReportsReportsPagePage.tsx"],"names":[],"mappings":"AAIA;;;;;;GAMG;AACH,wBAAgB,sBAAsB,4CA+CrC"}
@@ -1,211 +1,49 @@
1
- import { usePlanMagnet as e, usePlanMagnetNavigate as t } from "../providers/PlanMagnetProvider.js";
2
- import { useState as n } from "react";
3
- import { BarChart3 as r, Calendar as i, Clock as a, Plus as o } from "lucide-react";
4
- import { gql as s } from "@apollo/client";
5
- import { useQuery as c } from "@apollo/client/react";
6
- import { jsx as l, jsxs as u } from "react/jsx-runtime";
7
- import { Button as d, Card as f, CardContent as p, CardHeader as m, CardTitle as h } from "@burdenoff/fe-libs/ui";
1
+ import { usePlanMagnetNavigate as e } from "../providers/PlanMagnetProvider.js";
2
+ import { BarChart3 as t, FileSpreadsheet as n, LineChart as r } from "lucide-react";
3
+ import { jsx as i, jsxs as a } from "react/jsx-runtime";
4
+ import { Button as o, Card as s, CardContent as c, CardHeader as l, CardTitle as u } from "@burdenoff/fe-libs/ui";
8
5
  //#region src/planmagnet/pages/ReportsReportsPagePage.tsx
9
- var g = s`
10
- query GetReportsData(
11
- $workspaceId: ID!
12
- $projectPagination: PlanmagnetPaginationInput
13
- $sprintPagination: PlanmagnetPaginationInput
14
- $workItemPagination: PlanmagnetPaginationInput
15
- ) {
16
- planmagnetProjects(workspaceId: $workspaceId, pagination: $projectPagination) {
17
- items {
18
- id
19
- name
20
- key
21
- status
22
- methodology
23
- startDate
24
- endDate
25
- }
26
- totalCount
27
- }
28
- planmagnetSprints(workspaceId: $workspaceId, pagination: $sprintPagination) {
29
- items {
30
- id
31
- name
32
- status
33
- velocity
34
- startDate
35
- endDate
36
- }
37
- totalCount
38
- }
39
- planmagnetWorkItems(workspaceId: $workspaceId, pagination: $workItemPagination) {
40
- items {
41
- id
42
- status
43
- storyPoints
44
- createdAt
45
- }
46
- totalCount
47
- }
48
- }
49
- `, _ = {
50
- velocity: "bg-blue-100 text-blue-800",
51
- burndown: "bg-orange-100 text-orange-800",
52
- burnup: "bg-green-100 text-green-800",
53
- cumulative_flow: "bg-purple-100 text-purple-800",
54
- cycle_time: "bg-yellow-100 text-yellow-800",
55
- lead_time: "bg-pink-100 text-pink-800",
56
- project_status: "bg-gray-100 text-gray-800"
57
- };
58
- function v() {
59
- let { workspaceId: s } = e(), v = t(), [y, b] = n("all"), { data: x, loading: S, error: C } = c(g, {
60
- variables: {
61
- workspaceId: s,
62
- projectPagination: { first: 100 },
63
- sprintPagination: { first: 100 },
64
- workItemPagination: { first: 500 }
65
- },
66
- skip: !s
67
- });
68
- if (S && !x) return /* @__PURE__ */ l("div", {
69
- className: "flex items-center justify-center p-12",
70
- children: /* @__PURE__ */ l("div", { className: "animate-spin h-8 w-8 border-2 border-primary border-t-transparent rounded-full" })
71
- });
72
- if (C) return /* @__PURE__ */ u("div", {
73
- className: "p-6 text-red-500",
74
- children: ["Error: ", C.message]
75
- });
76
- let w = x?.planmagnetProjects?.items ?? [], T = x?.planmagnetSprints?.items ?? [];
77
- x?.planmagnetWorkItems?.items;
78
- let E = T.filter((e) => e.status === "COMPLETED"), D = T.filter((e) => e.status === "ACTIVE"), O = [
79
- ...E.map((e) => ({
80
- id: `velocity-${e.id}`,
81
- name: `${e.name} Velocity Report`,
82
- description: `Velocity analysis for ${e.name} (${e.velocity ?? 0} pts)`,
83
- type: "velocity",
84
- lastRun: e.endDate ?? "",
85
- schedule: null
86
- })),
87
- ...D.map((e) => ({
88
- id: `burndown-${e.id}`,
89
- name: `${e.name} Burndown`,
90
- description: `Active burndown tracking for ${e.name}`,
91
- type: "burndown",
92
- lastRun: (/* @__PURE__ */ new Date()).toISOString().split("T")[0],
93
- schedule: "daily"
94
- })),
95
- ...w.filter((e) => e.status === "ACTIVE").map((e) => ({
96
- id: `status-${e.id}`,
97
- name: `${e.name} Status Report`,
98
- description: `Project status overview for ${e.key}`,
99
- type: "project_status",
100
- lastRun: (/* @__PURE__ */ new Date()).toISOString().split("T")[0],
101
- schedule: "weekly"
102
- }))
103
- ], k = ["all", ...new Set(O.map((e) => e.type))], A = y === "all" ? O : O.filter((e) => e.type === y), j = O.filter((e) => e.schedule).length, M = (/* @__PURE__ */ new Date()).toISOString().split("T")[0], N = O.filter((e) => e.lastRun === M).length;
104
- return /* @__PURE__ */ u("div", {
6
+ function d() {
7
+ let d = e();
8
+ return /* @__PURE__ */ a("div", {
105
9
  className: "space-y-6 p-6",
106
- children: [
107
- /* @__PURE__ */ u("div", {
108
- className: "flex items-center justify-between",
109
- children: [/* @__PURE__ */ u("div", { children: [/* @__PURE__ */ l("h1", {
110
- className: "text-2xl font-semibold",
111
- children: "Reports"
112
- }), /* @__PURE__ */ u("p", {
10
+ children: [/* @__PURE__ */ a("div", { children: [/* @__PURE__ */ a("h1", {
11
+ className: "text-2xl font-semibold flex items-center gap-2",
12
+ children: [/* @__PURE__ */ i(t, { className: "h-6 w-6" }), "Reports"]
13
+ }), /* @__PURE__ */ i("p", {
14
+ className: "text-sm text-muted-foreground",
15
+ children: "Saved and scheduled reports are not available yet — there are none to show."
16
+ })] }), /* @__PURE__ */ i("div", {
17
+ className: "grid gap-4 md:grid-cols-2",
18
+ children: [{
19
+ title: "Analytics",
20
+ body: "Sprint burndown, velocity, cumulative flow, cycle time and delivery health for any project.",
21
+ icon: r,
22
+ to: "/analytics/analytics-page"
23
+ }, {
24
+ title: "Task Board export",
25
+ body: "Download every work item that matches the board’s filters as CSV.",
26
+ icon: n,
27
+ to: "/tasks/tasks-page"
28
+ }].map((e) => /* @__PURE__ */ a(s, { children: [/* @__PURE__ */ i(l, { children: /* @__PURE__ */ a(u, {
29
+ className: "flex items-center gap-2 text-base",
30
+ children: [/* @__PURE__ */ i(e.icon, { className: "h-5 w-5 text-primary" }), e.title]
31
+ }) }), /* @__PURE__ */ a(c, {
32
+ className: "space-y-3",
33
+ children: [/* @__PURE__ */ i("p", {
113
34
  className: "text-sm text-muted-foreground",
114
- children: [O.length, " reports configured"]
115
- })] }), /* @__PURE__ */ u(d, {
35
+ children: e.body
36
+ }), /* @__PURE__ */ a(o, {
116
37
  size: "sm",
117
- onClick: () => v("/reports/create-report-page"),
118
- children: [/* @__PURE__ */ l(o, { className: "mr-1 h-4 w-4" }), "New Report"]
119
- })]
120
- }),
121
- /* @__PURE__ */ u("div", {
122
- className: "grid grid-cols-3 gap-4",
123
- children: [
124
- /* @__PURE__ */ l(f, { children: /* @__PURE__ */ u(p, {
125
- className: "pt-4",
126
- children: [/* @__PURE__ */ l("p", {
127
- className: "text-xs text-muted-foreground",
128
- children: "Total Reports"
129
- }), /* @__PURE__ */ l("p", {
130
- className: "text-xl font-bold",
131
- children: O.length
132
- })]
133
- }) }),
134
- /* @__PURE__ */ l(f, { children: /* @__PURE__ */ u(p, {
135
- className: "pt-4",
136
- children: [/* @__PURE__ */ l("p", {
137
- className: "text-xs text-muted-foreground",
138
- children: "Scheduled"
139
- }), /* @__PURE__ */ l("p", {
140
- className: "text-xl font-bold",
141
- children: j
142
- })]
143
- }) }),
144
- /* @__PURE__ */ l(f, { children: /* @__PURE__ */ u(p, {
145
- className: "pt-4",
146
- children: [/* @__PURE__ */ l("p", {
147
- className: "text-xs text-muted-foreground",
148
- children: "Run Today"
149
- }), /* @__PURE__ */ l("p", {
150
- className: "text-xl font-bold",
151
- children: N
152
- })]
153
- }) })
154
- ]
155
- }),
156
- /* @__PURE__ */ l("div", {
157
- className: "flex gap-1",
158
- children: k.map((e) => /* @__PURE__ */ l("button", {
159
- onClick: () => b(e),
160
- className: `px-3 py-1.5 text-sm rounded-md capitalize ${y === e ? "bg-primary text-primary-foreground" : "text-muted-foreground hover:bg-muted"}`,
161
- children: e === "all" ? "All" : e.replace("_", " ")
162
- }, e))
163
- }),
164
- /* @__PURE__ */ u("div", {
165
- className: "grid grid-cols-1 md:grid-cols-2 gap-4",
166
- children: [A.map((e) => /* @__PURE__ */ u(f, { children: [/* @__PURE__ */ l(m, {
167
- className: "pb-2",
168
- children: /* @__PURE__ */ u("div", {
169
- className: "flex items-center justify-between",
170
- children: [/* @__PURE__ */ u(h, {
171
- className: "text-base flex items-center gap-2",
172
- children: [/* @__PURE__ */ l(r, { className: "h-4 w-4 text-primary" }), e.name]
173
- }), /* @__PURE__ */ l("span", {
174
- className: `text-xs px-2 py-0.5 rounded-full capitalize ${_[e.type] ?? "bg-gray-100"}`,
175
- children: e.type.replace("_", " ")
176
- })]
177
- })
178
- }), /* @__PURE__ */ u(p, {
179
- className: "space-y-2",
180
- children: [/* @__PURE__ */ l("p", {
181
- className: "text-sm text-muted-foreground",
182
- children: e.description
183
- }), /* @__PURE__ */ u("div", {
184
- className: "flex gap-3 text-xs text-muted-foreground",
185
- children: [e.schedule && /* @__PURE__ */ u("span", {
186
- className: "flex items-center gap-1",
187
- children: [/* @__PURE__ */ l(a, { className: "h-3 w-3" }), e.schedule]
188
- }), e.lastRun && /* @__PURE__ */ u("span", {
189
- className: "flex items-center gap-1",
190
- children: [
191
- /* @__PURE__ */ l(i, { className: "h-3 w-3" }),
192
- "Last: ",
193
- e.lastRun
194
- ]
195
- })]
196
- })]
197
- })] }, e.id)), A.length === 0 && /* @__PURE__ */ u("div", {
198
- className: "col-span-2 text-center py-12",
199
- children: [/* @__PURE__ */ l(r, { className: "h-12 w-12 text-muted-foreground mx-auto mb-3" }), /* @__PURE__ */ l("p", {
200
- className: "text-sm text-muted-foreground",
201
- children: "No reports found for the selected filter."
202
- })]
38
+ variant: "outline",
39
+ onClick: () => d(e.to),
40
+ children: ["Open ", e.title]
203
41
  })]
204
- })
205
- ]
42
+ })] }, e.title))
43
+ })]
206
44
  });
207
45
  }
208
46
  //#endregion
209
- export { v as ReportsReportsPagePage };
47
+ export { d as ReportsReportsPagePage };
210
48
 
211
49
  //# sourceMappingURL=ReportsReportsPagePage.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ReportsReportsPagePage.js","names":[],"sources":["../../../src/planmagnet/pages/ReportsReportsPagePage.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 } from '@burdenoff/fe-libs/ui';\nimport { BarChart3, Plus, Clock, Calendar } from 'lucide-react';\nimport { usePlanMagnet, usePlanMagnetNavigate } from '../providers/PlanMagnetProvider';\n\nconst GET_REPORTS_DATA = gql`\n query GetReportsData(\n $workspaceId: ID!\n $projectPagination: PlanmagnetPaginationInput\n $sprintPagination: PlanmagnetPaginationInput\n $workItemPagination: PlanmagnetPaginationInput\n ) {\n planmagnetProjects(workspaceId: $workspaceId, pagination: $projectPagination) {\n items {\n id\n name\n key\n status\n methodology\n startDate\n endDate\n }\n totalCount\n }\n planmagnetSprints(workspaceId: $workspaceId, pagination: $sprintPagination) {\n items {\n id\n name\n status\n velocity\n startDate\n endDate\n }\n totalCount\n }\n planmagnetWorkItems(workspaceId: $workspaceId, pagination: $workItemPagination) {\n items {\n id\n status\n storyPoints\n createdAt\n }\n totalCount\n }\n }\n`;\n\ninterface ProjectNode {\n id: string;\n name: string;\n key: string;\n status: string;\n methodology: string | null;\n startDate: string | null;\n endDate: string | null;\n}\n\ninterface SprintNode {\n id: string;\n name: string;\n status: string;\n velocity: number | null;\n startDate: string | null;\n endDate: string | null;\n}\n\ninterface WorkItemNode {\n id: string;\n status: string;\n storyPoints: number | null;\n createdAt: string;\n}\n\ninterface ReportsData {\n projects: { items: ProjectNode[]; totalCount: number };\n sprints: { items: SprintNode[]; totalCount: number };\n workItems: { items: WorkItemNode[]; totalCount: number };\n}\n\nconst typeColor: Record<string, string> = {\n velocity: 'bg-blue-100 text-blue-800',\n burndown: 'bg-orange-100 text-orange-800',\n burnup: 'bg-green-100 text-green-800',\n cumulative_flow: 'bg-purple-100 text-purple-800',\n cycle_time: 'bg-yellow-100 text-yellow-800',\n lead_time: 'bg-pink-100 text-pink-800',\n project_status: 'bg-gray-100 text-gray-800',\n};\n\nexport function ReportsReportsPagePage() {\n const { workspaceId } = usePlanMagnet();\n const navigate = usePlanMagnetNavigate();\n const [typeFilter, setTypeFilter] = useState<string>('all');\n\n const { data, loading, error } = useQuery<ReportsData>(GET_REPORTS_DATA, {\n variables: {\n workspaceId,\n projectPagination: { first: 100 },\n sprintPagination: { first: 100 },\n workItemPagination: { first: 500 },\n },\n skip: !workspaceId,\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-red-500\">Error: {error.message}</div>;\n }\n\n const projects = data?.planmagnetProjects?.items ?? [];\n const sprints = data?.planmagnetSprints?.items ?? [];\n const workItems = data?.planmagnetWorkItems?.items ?? [];\n\n const completedSprints = sprints.filter((s) => s.status === 'COMPLETED');\n const activeSprints = sprints.filter((s) => s.status === 'ACTIVE');\n\n const reports = [\n ...completedSprints.map((sprint) => ({\n id: `velocity-${sprint.id}`,\n name: `${sprint.name} Velocity Report`,\n description: `Velocity analysis for ${sprint.name} (${sprint.velocity ?? 0} pts)`,\n type: 'velocity',\n lastRun: sprint.endDate ?? '',\n schedule: null as string | null,\n })),\n ...activeSprints.map((sprint) => ({\n id: `burndown-${sprint.id}`,\n name: `${sprint.name} Burndown`,\n description: `Active burndown tracking for ${sprint.name}`,\n type: 'burndown',\n lastRun: new Date().toISOString().split('T')[0],\n schedule: 'daily' as string | null,\n })),\n ...projects\n .filter((p) => p.status === 'ACTIVE')\n .map((project) => ({\n id: `status-${project.id}`,\n name: `${project.name} Status Report`,\n description: `Project status overview for ${project.key}`,\n type: 'project_status',\n lastRun: new Date().toISOString().split('T')[0],\n schedule: 'weekly' as string | null,\n })),\n ];\n\n const types = ['all', ...new Set(reports.map((r) => r.type))];\n const filtered = typeFilter === 'all' ? reports : reports.filter((r) => r.type === typeFilter);\n\n const scheduledCount = reports.filter((r) => r.schedule).length;\n const todayStr = new Date().toISOString().split('T')[0];\n const runTodayCount = reports.filter((r) => r.lastRun === todayStr).length;\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\">Reports</h1>\n <p className=\"text-sm text-muted-foreground\">{reports.length} reports configured</p>\n </div>\n {/* The route is `reports/create-report-page`; `/reports/create` has never\n existed, so this button navigated into the catch-all. */}\n <Button size=\"sm\" onClick={() => navigate('/reports/create-report-page')}>\n <Plus className=\"mr-1 h-4 w-4\" />\n New Report\n </Button>\n </div>\n <div className=\"grid grid-cols-3 gap-4\">\n <Card>\n <CardContent className=\"pt-4\">\n <p className=\"text-xs text-muted-foreground\">Total Reports</p>\n <p className=\"text-xl font-bold\">{reports.length}</p>\n </CardContent>\n </Card>\n <Card>\n <CardContent className=\"pt-4\">\n <p className=\"text-xs text-muted-foreground\">Scheduled</p>\n <p className=\"text-xl font-bold\">{scheduledCount}</p>\n </CardContent>\n </Card>\n <Card>\n <CardContent className=\"pt-4\">\n <p className=\"text-xs text-muted-foreground\">Run Today</p>\n <p className=\"text-xl font-bold\">{runTodayCount}</p>\n </CardContent>\n </Card>\n </div>\n <div className=\"flex gap-1\">\n {types.map((t) => (\n <button\n key={t}\n onClick={() => setTypeFilter(t)}\n className={`px-3 py-1.5 text-sm rounded-md capitalize ${typeFilter === t ? 'bg-primary text-primary-foreground' : 'text-muted-foreground hover:bg-muted'}`}\n >\n {t === 'all' ? 'All' : t.replace('_', ' ')}\n </button>\n ))}\n </div>\n <div className=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\n {filtered.map((report) => (\n <Card key={report.id}>\n <CardHeader className=\"pb-2\">\n <div className=\"flex items-center justify-between\">\n <CardTitle className=\"text-base flex items-center gap-2\">\n <BarChart3 className=\"h-4 w-4 text-primary\" />\n {report.name}\n </CardTitle>\n <span\n className={`text-xs px-2 py-0.5 rounded-full capitalize ${typeColor[report.type] ?? 'bg-gray-100'}`}\n >\n {report.type.replace('_', ' ')}\n </span>\n </div>\n </CardHeader>\n <CardContent className=\"space-y-2\">\n <p className=\"text-sm text-muted-foreground\">{report.description}</p>\n <div className=\"flex gap-3 text-xs text-muted-foreground\">\n {report.schedule && (\n <span className=\"flex items-center gap-1\">\n <Clock className=\"h-3 w-3\" />\n {report.schedule}\n </span>\n )}\n {report.lastRun && (\n <span className=\"flex items-center gap-1\">\n <Calendar className=\"h-3 w-3\" />\n Last: {report.lastRun}\n </span>\n )}\n </div>\n </CardContent>\n </Card>\n ))}\n {filtered.length === 0 && (\n <div className=\"col-span-2 text-center py-12\">\n <BarChart3 className=\"h-12 w-12 text-muted-foreground mx-auto mb-3\" />\n <p className=\"text-sm text-muted-foreground\">\n No reports found for the selected filter.\n </p>\n </div>\n )}\n </div>\n </div>\n );\n}\n"],"mappings":";;;;;;;;AASA,IAAM,IAAmB,CAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0EtB,IAAoC;CACxC,UAAU;CACV,UAAU;CACV,QAAQ;CACR,iBAAiB;CACjB,YAAY;CACZ,WAAW;CACX,gBAAgB;CACjB;AAED,SAAgB,IAAyB;CACvC,IAAM,EAAE,mBAAgB,GAAe,EACjC,IAAW,GAAuB,EAClC,CAAC,GAAY,KAAiB,EAAiB,MAAM,EAErD,EAAE,SAAM,YAAS,aAAU,EAAsB,GAAkB;EACvE,WAAW;GACT;GACA,mBAAmB,EAAE,OAAO,KAAK;GACjC,kBAAkB,EAAE,OAAO,KAAK;GAChC,oBAAoB,EAAE,OAAO,KAAK;GACnC;EACD,MAAM,CAAC;EACR,CAAC;AAMF,KAAI,KAAW,CAAC,EACd,QACE,kBAAC,OAAD;EAAK,WAAU;YACb,kBAAC,OAAD,EAAK,WAAU,kFAAmF,CAAA;EAC9F,CAAA;AAIV,KAAI,EACF,QAAO,kBAAC,OAAD;EAAK,WAAU;YAAf,CAAkC,WAAQ,EAAM,QAAc;;CAGvE,IAAM,IAAW,GAAM,oBAAoB,SAAS,EAAE,EAChD,IAAU,GAAM,mBAAmB,SAAS,EAAE;AAClC,IAAM,qBAAqB;CAE7C,IAAM,IAAmB,EAAQ,QAAQ,MAAM,EAAE,WAAW,YAAY,EAClE,IAAgB,EAAQ,QAAQ,MAAM,EAAE,WAAW,SAAS,EAE5D,IAAU;EACd,GAAG,EAAiB,KAAK,OAAY;GACnC,IAAI,YAAY,EAAO;GACvB,MAAM,GAAG,EAAO,KAAK;GACrB,aAAa,yBAAyB,EAAO,KAAK,IAAI,EAAO,YAAY,EAAE;GAC3E,MAAM;GACN,SAAS,EAAO,WAAW;GAC3B,UAAU;GACX,EAAE;EACH,GAAG,EAAc,KAAK,OAAY;GAChC,IAAI,YAAY,EAAO;GACvB,MAAM,GAAG,EAAO,KAAK;GACrB,aAAa,gCAAgC,EAAO;GACpD,MAAM;GACN,0BAAS,IAAI,MAAM,EAAC,aAAa,CAAC,MAAM,IAAI,CAAC;GAC7C,UAAU;GACX,EAAE;EACH,GAAG,EACA,QAAQ,MAAM,EAAE,WAAW,SAAS,CACpC,KAAK,OAAa;GACjB,IAAI,UAAU,EAAQ;GACtB,MAAM,GAAG,EAAQ,KAAK;GACtB,aAAa,+BAA+B,EAAQ;GACpD,MAAM;GACN,0BAAS,IAAI,MAAM,EAAC,aAAa,CAAC,MAAM,IAAI,CAAC;GAC7C,UAAU;GACX,EAAE;EACN,EAEK,IAAQ,CAAC,OAAO,GAAG,IAAI,IAAI,EAAQ,KAAK,MAAM,EAAE,KAAK,CAAC,CAAC,EACvD,IAAW,MAAe,QAAQ,IAAU,EAAQ,QAAQ,MAAM,EAAE,SAAS,EAAW,EAExF,IAAiB,EAAQ,QAAQ,MAAM,EAAE,SAAS,CAAC,QACnD,qBAAW,IAAI,MAAM,EAAC,aAAa,CAAC,MAAM,IAAI,CAAC,IAC/C,IAAgB,EAAQ,QAAQ,MAAM,EAAE,YAAY,EAAS,CAAC;AAEpE,QACE,kBAAC,OAAD;EAAK,WAAU;YAAf;GACE,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,MAAD;KAAI,WAAU;eAAyB;KAAY,CAAA,EACnD,kBAAC,KAAD;KAAG,WAAU;eAAb,CAA8C,EAAQ,QAAO,sBAAuB;OAChF,EAAA,CAAA,EAGN,kBAAC,GAAD;KAAQ,MAAK;KAAK,eAAe,EAAS,8BAA8B;eAAxE,CACE,kBAAC,GAAD,EAAM,WAAU,gBAAiB,CAAA,EAAA,aAE1B;OACL;;GACN,kBAAC,OAAD;IAAK,WAAU;cAAf;KACE,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD;MAAa,WAAU;gBAAvB,CACE,kBAAC,KAAD;OAAG,WAAU;iBAAgC;OAAiB,CAAA,EAC9D,kBAAC,KAAD;OAAG,WAAU;iBAAqB,EAAQ;OAAW,CAAA,CACzC;SACT,CAAA;KACP,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD;MAAa,WAAU;gBAAvB,CACE,kBAAC,KAAD;OAAG,WAAU;iBAAgC;OAAa,CAAA,EAC1D,kBAAC,KAAD;OAAG,WAAU;iBAAqB;OAAmB,CAAA,CACzC;SACT,CAAA;KACP,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD;MAAa,WAAU;gBAAvB,CACE,kBAAC,KAAD;OAAG,WAAU;iBAAgC;OAAa,CAAA,EAC1D,kBAAC,KAAD;OAAG,WAAU;iBAAqB;OAAkB,CAAA,CACxC;SACT,CAAA;KACH;;GACN,kBAAC,OAAD;IAAK,WAAU;cACZ,EAAM,KAAK,MACV,kBAAC,UAAD;KAEE,eAAe,EAAc,EAAE;KAC/B,WAAW,6CAA6C,MAAe,IAAI,uCAAuC;eAEjH,MAAM,QAAQ,QAAQ,EAAE,QAAQ,KAAK,IAAI;KACnC,EALF,EAKE,CACT;IACE,CAAA;GACN,kBAAC,OAAD;IAAK,WAAU;cAAf,CACG,EAAS,KAAK,MACb,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD;KAAY,WAAU;eACpB,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,kBAAC,GAAD;OAAW,WAAU;iBAArB,CACE,kBAAC,GAAD,EAAW,WAAU,wBAAyB,CAAA,EAC7C,EAAO,KACE;UACZ,kBAAC,QAAD;OACE,WAAW,+CAA+C,EAAU,EAAO,SAAS;iBAEnF,EAAO,KAAK,QAAQ,KAAK,IAAI;OACzB,CAAA,CACH;;KACK,CAAA,EACb,kBAAC,GAAD;KAAa,WAAU;eAAvB,CACE,kBAAC,KAAD;MAAG,WAAU;gBAAiC,EAAO;MAAgB,CAAA,EACrE,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACG,EAAO,YACN,kBAAC,QAAD;OAAM,WAAU;iBAAhB,CACE,kBAAC,GAAD,EAAO,WAAU,WAAY,CAAA,EAC5B,EAAO,SACH;UAER,EAAO,WACN,kBAAC,QAAD;OAAM,WAAU;iBAAhB;QACE,kBAAC,GAAD,EAAU,WAAU,WAAY,CAAA;;QACzB,EAAO;QACT;SAEL;QACM;OACT,EAAA,EA/BI,EAAO,GA+BX,CACP,EACD,EAAS,WAAW,KACnB,kBAAC,OAAD;KAAK,WAAU;eAAf,CACE,kBAAC,GAAD,EAAW,WAAU,gDAAiD,CAAA,EACtE,kBAAC,KAAD;MAAG,WAAU;gBAAgC;MAEzC,CAAA,CACA;OAEJ;;GACF"}
1
+ {"version":3,"file":"ReportsReportsPagePage.js","names":[],"sources":["../../../src/planmagnet/pages/ReportsReportsPagePage.tsx"],"sourcesContent":["import { Card, CardContent, CardHeader, CardTitle, Button } from '@burdenoff/fe-libs/ui';\nimport { BarChart3, FileSpreadsheet, LineChart } from 'lucide-react';\nimport { usePlanMagnetNavigate } from '../providers/PlanMagnetProvider';\n\n/**\n * Reports (BOFF-7967). There is no saved-report model and no report runner yet, so there are no reports to list.\n * This page used to invent them — one \"Velocity Report\" per completed sprint, one \"Burndown\" per active sprint, one\n * \"Status Report\" per active project — with made-up schedules, \"Run Today\" counts for reports that never ran, and\n * the viewer named as their creator. It now says so, and points to where the same analysis lives, computed on the\n * server from real data.\n */\nexport function ReportsReportsPagePage() {\n const navigate = usePlanMagnetNavigate();\n const places = [\n {\n title: 'Analytics',\n body: 'Sprint burndown, velocity, cumulative flow, cycle time and delivery health for any project.',\n icon: LineChart,\n to: '/analytics/analytics-page',\n },\n {\n title: 'Task Board export',\n body: 'Download every work item that matches the board’s filters as CSV.',\n icon: FileSpreadsheet,\n to: '/tasks/tasks-page',\n },\n ];\n return (\n <div className=\"space-y-6 p-6\">\n <div>\n <h1 className=\"text-2xl font-semibold flex items-center gap-2\">\n <BarChart3 className=\"h-6 w-6\" />\n Reports\n </h1>\n <p className=\"text-sm text-muted-foreground\">\n Saved and scheduled reports are not available yet — there are none to show.\n </p>\n </div>\n <div className=\"grid gap-4 md:grid-cols-2\">\n {places.map((p) => (\n <Card key={p.title}>\n <CardHeader>\n <CardTitle className=\"flex items-center gap-2 text-base\">\n <p.icon className=\"h-5 w-5 text-primary\" />\n {p.title}\n </CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n <p className=\"text-sm text-muted-foreground\">{p.body}</p>\n <Button size=\"sm\" variant=\"outline\" onClick={() => navigate(p.to)}>\n Open {p.title}\n </Button>\n </CardContent>\n </Card>\n ))}\n </div>\n </div>\n );\n}\n"],"mappings":";;;;;AAWA,SAAgB,IAAyB;CACvC,IAAM,IAAW,GAAuB;AAexC,QACE,kBAAC,OAAD;EAAK,WAAU;YAAf,CACE,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,MAAD;GAAI,WAAU;aAAd,CACE,kBAAC,GAAD,EAAW,WAAU,WAAY,CAAA,EAAA,UAE9B;MACL,kBAAC,KAAD;GAAG,WAAU;aAAgC;GAEzC,CAAA,CACA,EAAA,CAAA,EACN,kBAAC,OAAD;GAAK,WAAU;aAzBJ,CACb;IACE,OAAO;IACP,MAAM;IACN,MAAM;IACN,IAAI;IACL,EACD;IACE,OAAO;IACP,MAAM;IACN,MAAM;IACN,IAAI;IACL,CACF,CAaa,KAAK,MACX,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD;IAAW,WAAU;cAArB,CACE,kBAAC,EAAE,MAAH,EAAQ,WAAU,wBAAyB,CAAA,EAC1C,EAAE,MACO;OACD,CAAA,EACb,kBAAC,GAAD;IAAa,WAAU;cAAvB,CACE,kBAAC,KAAD;KAAG,WAAU;eAAiC,EAAE;KAAS,CAAA,EACzD,kBAAC,GAAD;KAAQ,MAAK;KAAK,SAAQ;KAAU,eAAe,EAAS,EAAE,GAAG;eAAjE,CAAmE,SAC3D,EAAE,MACD;OACG;MACT,EAAA,EAbI,EAAE,MAaN,CACP;GACE,CAAA,CACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"SprintsStartSprintPagePage.d.ts","sourceRoot":"","sources":["../../../src/planmagnet/pages/SprintsStartSprintPagePage.tsx"],"names":[],"mappings":"AAsGA,wBAAgB,0BAA0B,4CAkQzC"}
1
+ {"version":3,"file":"SprintsStartSprintPagePage.d.ts","sourceRoot":"","sources":["../../../src/planmagnet/pages/SprintsStartSprintPagePage.tsx"],"names":[],"mappings":"AAuGA,wBAAgB,0BAA0B,4CAoRzC"}