@burdenoff/microfe-planmagnet 2026.928.3 → 2026.928.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.
Files changed (245) hide show
  1. package/dist/planmagnet/PlanMagnetRoot.d.ts.map +1 -1
  2. package/dist/planmagnet/PlanMagnetRoot.js +126 -84
  3. package/dist/planmagnet/PlanMagnetRoot.js.map +1 -1
  4. package/dist/planmagnet/PlanMagnetRoutes.d.ts.map +1 -1
  5. package/dist/planmagnet/PlanMagnetRoutes.js +192 -64
  6. package/dist/planmagnet/PlanMagnetRoutes.js.map +1 -1
  7. package/dist/planmagnet/automation/AutomationExecutionsPanel.d.ts +5 -0
  8. package/dist/planmagnet/automation/AutomationExecutionsPanel.d.ts.map +1 -0
  9. package/dist/planmagnet/automation/AutomationExecutionsPanel.js +107 -0
  10. package/dist/planmagnet/automation/AutomationExecutionsPanel.js.map +1 -0
  11. package/dist/planmagnet/automation/AutomationRuleFields.d.ts +29 -0
  12. package/dist/planmagnet/automation/AutomationRuleFields.d.ts.map +1 -0
  13. package/dist/planmagnet/automation/AutomationRuleFields.js +308 -0
  14. package/dist/planmagnet/automation/AutomationRuleFields.js.map +1 -0
  15. package/dist/planmagnet/automation/automationRuleTypes.d.ts +60 -0
  16. package/dist/planmagnet/automation/automationRuleTypes.d.ts.map +1 -0
  17. package/dist/planmagnet/automation/automationRuleTypes.js +113 -0
  18. package/dist/planmagnet/automation/automationRuleTypes.js.map +1 -0
  19. package/dist/planmagnet/board/BulkActions.d.ts +11 -0
  20. package/dist/planmagnet/board/BulkActions.d.ts.map +1 -0
  21. package/dist/planmagnet/board/BulkActions.js +182 -0
  22. package/dist/planmagnet/board/BulkActions.js.map +1 -0
  23. package/dist/planmagnet/board/ProjectBoard.d.ts.map +1 -1
  24. package/dist/planmagnet/board/ProjectBoard.js +289 -254
  25. package/dist/planmagnet/board/ProjectBoard.js.map +1 -1
  26. package/dist/planmagnet/budgets/BudgetControls.d.ts +30 -0
  27. package/dist/planmagnet/budgets/BudgetControls.d.ts.map +1 -0
  28. package/dist/planmagnet/budgets/BudgetControls.js +470 -0
  29. package/dist/planmagnet/budgets/BudgetControls.js.map +1 -0
  30. package/dist/planmagnet/budgets/ExpenseControls.d.ts +27 -0
  31. package/dist/planmagnet/budgets/ExpenseControls.d.ts.map +1 -0
  32. package/dist/planmagnet/budgets/ExpenseControls.js +366 -0
  33. package/dist/planmagnet/budgets/ExpenseControls.js.map +1 -0
  34. package/dist/planmagnet/budgets/ProjectBudgetsSummary.d.ts +5 -0
  35. package/dist/planmagnet/budgets/ProjectBudgetsSummary.d.ts.map +1 -0
  36. package/dist/planmagnet/budgets/ProjectBudgetsSummary.js +112 -0
  37. package/dist/planmagnet/budgets/ProjectBudgetsSummary.js.map +1 -0
  38. package/dist/planmagnet/budgets/budgetMath.d.ts +26 -0
  39. package/dist/planmagnet/budgets/budgetMath.d.ts.map +1 -0
  40. package/dist/planmagnet/budgets/budgetMath.js +49 -0
  41. package/dist/planmagnet/budgets/budgetMath.js.map +1 -0
  42. package/dist/planmagnet/controls/AutomationRuleControls.d.ts +23 -0
  43. package/dist/planmagnet/controls/AutomationRuleControls.d.ts.map +1 -0
  44. package/dist/planmagnet/controls/AutomationRuleControls.js +172 -0
  45. package/dist/planmagnet/controls/AutomationRuleControls.js.map +1 -0
  46. package/dist/planmagnet/controls/CompetitorControls.d.ts +20 -0
  47. package/dist/planmagnet/controls/CompetitorControls.d.ts.map +1 -0
  48. package/dist/planmagnet/controls/CompetitorControls.js +172 -0
  49. package/dist/planmagnet/controls/CompetitorControls.js.map +1 -0
  50. package/dist/planmagnet/controls/CustomFieldControls.d.ts +42 -0
  51. package/dist/planmagnet/controls/CustomFieldControls.d.ts.map +1 -0
  52. package/dist/planmagnet/controls/CustomFieldControls.js +84 -0
  53. package/dist/planmagnet/controls/CustomFieldControls.js.map +1 -0
  54. package/dist/planmagnet/controls/CustomFieldValuesPanel.d.ts +8 -0
  55. package/dist/planmagnet/controls/CustomFieldValuesPanel.d.ts.map +1 -0
  56. package/dist/planmagnet/controls/CustomFieldValuesPanel.js +315 -0
  57. package/dist/planmagnet/controls/CustomFieldValuesPanel.js.map +1 -0
  58. package/dist/planmagnet/controls/FeatureControls.js +53 -53
  59. package/dist/planmagnet/controls/FeatureTriage.js +11 -11
  60. package/dist/planmagnet/controls/ObjectiveControls.js +37 -37
  61. package/dist/planmagnet/controls/Pickers.d.ts +17 -2
  62. package/dist/planmagnet/controls/Pickers.d.ts.map +1 -1
  63. package/dist/planmagnet/controls/Pickers.js +100 -9
  64. package/dist/planmagnet/controls/Pickers.js.map +1 -1
  65. package/dist/planmagnet/controls/PortfolioControls.d.ts +13 -0
  66. package/dist/planmagnet/controls/PortfolioControls.d.ts.map +1 -0
  67. package/dist/planmagnet/controls/PortfolioControls.js +114 -0
  68. package/dist/planmagnet/controls/PortfolioControls.js.map +1 -0
  69. package/dist/planmagnet/controls/ProgramControls.d.ts +25 -0
  70. package/dist/planmagnet/controls/ProgramControls.d.ts.map +1 -0
  71. package/dist/planmagnet/controls/ProgramControls.js +187 -0
  72. package/dist/planmagnet/controls/ProgramControls.js.map +1 -0
  73. package/dist/planmagnet/controls/ProjectControls.d.ts.map +1 -1
  74. package/dist/planmagnet/controls/ProjectControls.js +54 -47
  75. package/dist/planmagnet/controls/ProjectControls.js.map +1 -1
  76. package/dist/planmagnet/controls/ReleaseControls.js +7 -7
  77. package/dist/planmagnet/controls/RiskControls.d.ts +27 -0
  78. package/dist/planmagnet/controls/RiskControls.d.ts.map +1 -0
  79. package/dist/planmagnet/controls/RiskControls.js +346 -0
  80. package/dist/planmagnet/controls/RiskControls.js.map +1 -0
  81. package/dist/planmagnet/controls/TemplateControls.d.ts +15 -0
  82. package/dist/planmagnet/controls/TemplateControls.d.ts.map +1 -0
  83. package/dist/planmagnet/controls/TemplateControls.js +55 -0
  84. package/dist/planmagnet/controls/TemplateControls.js.map +1 -0
  85. package/dist/planmagnet/controls/WorkItemControls.js +1 -1
  86. package/dist/planmagnet/create/CreateDialogs.d.ts +20 -0
  87. package/dist/planmagnet/create/CreateDialogs.d.ts.map +1 -1
  88. package/dist/planmagnet/create/CreateDialogs.js +455 -116
  89. package/dist/planmagnet/create/CreateDialogs.js.map +1 -1
  90. package/dist/planmagnet/dependency/DependencyPanel.d.ts +6 -0
  91. package/dist/planmagnet/dependency/DependencyPanel.d.ts.map +1 -0
  92. package/dist/planmagnet/dependency/DependencyPanel.js +310 -0
  93. package/dist/planmagnet/dependency/DependencyPanel.js.map +1 -0
  94. package/dist/planmagnet/pages/AutomationAutomationRuleDetailPagePage.d.ts +2 -0
  95. package/dist/planmagnet/pages/AutomationAutomationRuleDetailPagePage.d.ts.map +1 -0
  96. package/dist/planmagnet/pages/AutomationAutomationRuleDetailPagePage.js +171 -0
  97. package/dist/planmagnet/pages/AutomationAutomationRuleDetailPagePage.js.map +1 -0
  98. package/dist/planmagnet/pages/AutomationAutomationRulesPagePage.d.ts +2 -0
  99. package/dist/planmagnet/pages/AutomationAutomationRulesPagePage.d.ts.map +1 -0
  100. package/dist/planmagnet/pages/AutomationAutomationRulesPagePage.js +232 -0
  101. package/dist/planmagnet/pages/AutomationAutomationRulesPagePage.js.map +1 -0
  102. package/dist/planmagnet/pages/AutomationCreateAutomationRulePagePage.d.ts +2 -0
  103. package/dist/planmagnet/pages/AutomationCreateAutomationRulePagePage.d.ts.map +1 -0
  104. package/dist/planmagnet/pages/AutomationCreateAutomationRulePagePage.js +93 -0
  105. package/dist/planmagnet/pages/AutomationCreateAutomationRulePagePage.js.map +1 -0
  106. package/dist/planmagnet/pages/CompetitorsCompetitorDetailPagePage.d.ts +2 -0
  107. package/dist/planmagnet/pages/CompetitorsCompetitorDetailPagePage.d.ts.map +1 -0
  108. package/dist/planmagnet/pages/CompetitorsCompetitorDetailPagePage.js +127 -0
  109. package/dist/planmagnet/pages/CompetitorsCompetitorDetailPagePage.js.map +1 -0
  110. package/dist/planmagnet/pages/CompetitorsCompetitorsPagePage.d.ts +2 -0
  111. package/dist/planmagnet/pages/CompetitorsCompetitorsPagePage.d.ts.map +1 -0
  112. package/dist/planmagnet/pages/CompetitorsCompetitorsPagePage.js +129 -0
  113. package/dist/planmagnet/pages/CompetitorsCompetitorsPagePage.js.map +1 -0
  114. package/dist/planmagnet/pages/CompetitorsCreateCompetitorPagePage.d.ts +2 -0
  115. package/dist/planmagnet/pages/CompetitorsCreateCompetitorPagePage.d.ts.map +1 -0
  116. package/dist/planmagnet/pages/CompetitorsCreateCompetitorPagePage.js +132 -0
  117. package/dist/planmagnet/pages/CompetitorsCreateCompetitorPagePage.js.map +1 -0
  118. package/dist/planmagnet/pages/CompetitorsEditCompetitorPagePage.d.ts +2 -0
  119. package/dist/planmagnet/pages/CompetitorsEditCompetitorPagePage.d.ts.map +1 -0
  120. package/dist/planmagnet/pages/CompetitorsEditCompetitorPagePage.js +181 -0
  121. package/dist/planmagnet/pages/CompetitorsEditCompetitorPagePage.js.map +1 -0
  122. package/dist/planmagnet/pages/PortfoliosCreatePortfolioPagePage.d.ts +2 -0
  123. package/dist/planmagnet/pages/PortfoliosCreatePortfolioPagePage.d.ts.map +1 -0
  124. package/dist/planmagnet/pages/PortfoliosCreatePortfolioPagePage.js +242 -0
  125. package/dist/planmagnet/pages/PortfoliosCreatePortfolioPagePage.js.map +1 -0
  126. package/dist/planmagnet/pages/PortfoliosEditPortfolioPagePage.d.ts +2 -0
  127. package/dist/planmagnet/pages/PortfoliosEditPortfolioPagePage.d.ts.map +1 -0
  128. package/dist/planmagnet/pages/PortfoliosEditPortfolioPagePage.js +302 -0
  129. package/dist/planmagnet/pages/PortfoliosEditPortfolioPagePage.js.map +1 -0
  130. package/dist/planmagnet/pages/PortfoliosPortfolioDetailPagePage.d.ts +2 -0
  131. package/dist/planmagnet/pages/PortfoliosPortfolioDetailPagePage.d.ts.map +1 -0
  132. package/dist/planmagnet/pages/PortfoliosPortfolioDetailPagePage.js +335 -0
  133. package/dist/planmagnet/pages/PortfoliosPortfolioDetailPagePage.js.map +1 -0
  134. package/dist/planmagnet/pages/PortfoliosPortfoliosPagePage.d.ts +2 -0
  135. package/dist/planmagnet/pages/PortfoliosPortfoliosPagePage.d.ts.map +1 -0
  136. package/dist/planmagnet/pages/PortfoliosPortfoliosPagePage.js +154 -0
  137. package/dist/planmagnet/pages/PortfoliosPortfoliosPagePage.js.map +1 -0
  138. package/dist/planmagnet/pages/ProductsFeatureDetailPagePage.d.ts.map +1 -1
  139. package/dist/planmagnet/pages/ProductsFeatureDetailPagePage.js +124 -138
  140. package/dist/planmagnet/pages/ProductsFeatureDetailPagePage.js.map +1 -1
  141. package/dist/planmagnet/pages/ProgramsCreateProgramPagePage.d.ts +2 -0
  142. package/dist/planmagnet/pages/ProgramsCreateProgramPagePage.d.ts.map +1 -0
  143. package/dist/planmagnet/pages/ProgramsCreateProgramPagePage.js +221 -0
  144. package/dist/planmagnet/pages/ProgramsCreateProgramPagePage.js.map +1 -0
  145. package/dist/planmagnet/pages/ProgramsEditProgramPagePage.d.ts +2 -0
  146. package/dist/planmagnet/pages/ProgramsEditProgramPagePage.d.ts.map +1 -0
  147. package/dist/planmagnet/pages/ProgramsEditProgramPagePage.js +279 -0
  148. package/dist/planmagnet/pages/ProgramsEditProgramPagePage.js.map +1 -0
  149. package/dist/planmagnet/pages/ProgramsProgramDetailPagePage.d.ts +2 -0
  150. package/dist/planmagnet/pages/ProgramsProgramDetailPagePage.d.ts.map +1 -0
  151. package/dist/planmagnet/pages/ProgramsProgramDetailPagePage.js +178 -0
  152. package/dist/planmagnet/pages/ProgramsProgramDetailPagePage.js.map +1 -0
  153. package/dist/planmagnet/pages/ProgramsProgramsPagePage.d.ts +2 -0
  154. package/dist/planmagnet/pages/ProgramsProgramsPagePage.d.ts.map +1 -0
  155. package/dist/planmagnet/pages/ProgramsProgramsPagePage.js +157 -0
  156. package/dist/planmagnet/pages/ProgramsProgramsPagePage.js.map +1 -0
  157. package/dist/planmagnet/pages/ProjectsBudgetDetailPagePage.d.ts +2 -0
  158. package/dist/planmagnet/pages/ProjectsBudgetDetailPagePage.d.ts.map +1 -0
  159. package/dist/planmagnet/pages/ProjectsBudgetDetailPagePage.js +315 -0
  160. package/dist/planmagnet/pages/ProjectsBudgetDetailPagePage.js.map +1 -0
  161. package/dist/planmagnet/pages/ProjectsBudgetsPagePage.d.ts +2 -0
  162. package/dist/planmagnet/pages/ProjectsBudgetsPagePage.d.ts.map +1 -0
  163. package/dist/planmagnet/pages/ProjectsBudgetsPagePage.js +186 -0
  164. package/dist/planmagnet/pages/ProjectsBudgetsPagePage.js.map +1 -0
  165. package/dist/planmagnet/pages/ProjectsCriticalPathPagePage.d.ts +2 -0
  166. package/dist/planmagnet/pages/ProjectsCriticalPathPagePage.d.ts.map +1 -0
  167. package/dist/planmagnet/pages/ProjectsCriticalPathPagePage.js +164 -0
  168. package/dist/planmagnet/pages/ProjectsCriticalPathPagePage.js.map +1 -0
  169. package/dist/planmagnet/pages/ProjectsCustomFieldsPagePage.d.ts +2 -0
  170. package/dist/planmagnet/pages/ProjectsCustomFieldsPagePage.d.ts.map +1 -0
  171. package/dist/planmagnet/pages/ProjectsCustomFieldsPagePage.js +348 -0
  172. package/dist/planmagnet/pages/ProjectsCustomFieldsPagePage.js.map +1 -0
  173. package/dist/planmagnet/pages/ProjectsEditProjectPagePage.d.ts.map +1 -1
  174. package/dist/planmagnet/pages/ProjectsEditProjectPagePage.js +130 -103
  175. package/dist/planmagnet/pages/ProjectsEditProjectPagePage.js.map +1 -1
  176. package/dist/planmagnet/pages/ProjectsMilestoneDetailPagePage.js +4 -4
  177. package/dist/planmagnet/pages/ProjectsPlanningDetailPagePage.js +4 -4
  178. package/dist/planmagnet/pages/ProjectsPlanningEditPagePage.js +6 -6
  179. package/dist/planmagnet/pages/ProjectsProjectDetailPagePage.d.ts.map +1 -1
  180. package/dist/planmagnet/pages/ProjectsProjectDetailPagePage.js +325 -189
  181. package/dist/planmagnet/pages/ProjectsProjectDetailPagePage.js.map +1 -1
  182. package/dist/planmagnet/pages/ProjectsProjectsPagePage.d.ts.map +1 -1
  183. package/dist/planmagnet/pages/ProjectsProjectsPagePage.js +81 -72
  184. package/dist/planmagnet/pages/ProjectsProjectsPagePage.js.map +1 -1
  185. package/dist/planmagnet/pages/RisksRiskDetailPagePage.d.ts +2 -0
  186. package/dist/planmagnet/pages/RisksRiskDetailPagePage.d.ts.map +1 -0
  187. package/dist/planmagnet/pages/RisksRiskDetailPagePage.js +278 -0
  188. package/dist/planmagnet/pages/RisksRiskDetailPagePage.js.map +1 -0
  189. package/dist/planmagnet/pages/RisksRiskRegisterPagePage.d.ts +2 -0
  190. package/dist/planmagnet/pages/RisksRiskRegisterPagePage.d.ts.map +1 -0
  191. package/dist/planmagnet/pages/RisksRiskRegisterPagePage.js +191 -0
  192. package/dist/planmagnet/pages/RisksRiskRegisterPagePage.js.map +1 -0
  193. package/dist/planmagnet/pages/TasksCreateTaskPagePage.js +5 -5
  194. package/dist/planmagnet/pages/TasksEditTaskPagePage.js +4 -4
  195. package/dist/planmagnet/pages/TasksImportPagePage.js +5 -5
  196. package/dist/planmagnet/pages/TasksTaskDetailPagePage.d.ts.map +1 -1
  197. package/dist/planmagnet/pages/TasksTaskDetailPagePage.js +161 -137
  198. package/dist/planmagnet/pages/TasksTaskDetailPagePage.js.map +1 -1
  199. package/dist/planmagnet/pages/TasksTasksPagePage.d.ts.map +1 -1
  200. package/dist/planmagnet/pages/TasksTasksPagePage.js +124 -113
  201. package/dist/planmagnet/pages/TasksTasksPagePage.js.map +1 -1
  202. package/dist/planmagnet/pages/TasksTimeEntriesPagePage.d.ts +2 -0
  203. package/dist/planmagnet/pages/TasksTimeEntriesPagePage.d.ts.map +1 -0
  204. package/dist/planmagnet/pages/TasksTimeEntriesPagePage.js +263 -0
  205. package/dist/planmagnet/pages/TasksTimeEntriesPagePage.js.map +1 -0
  206. package/dist/planmagnet/pages/TasksTimesheetDetailPagePage.d.ts +2 -0
  207. package/dist/planmagnet/pages/TasksTimesheetDetailPagePage.d.ts.map +1 -0
  208. package/dist/planmagnet/pages/TasksTimesheetDetailPagePage.js +254 -0
  209. package/dist/planmagnet/pages/TasksTimesheetDetailPagePage.js.map +1 -0
  210. package/dist/planmagnet/pages/TasksTimesheetsPagePage.d.ts +2 -0
  211. package/dist/planmagnet/pages/TasksTimesheetsPagePage.d.ts.map +1 -0
  212. package/dist/planmagnet/pages/TasksTimesheetsPagePage.js +165 -0
  213. package/dist/planmagnet/pages/TasksTimesheetsPagePage.js.map +1 -0
  214. package/dist/planmagnet/pages/TemplatesEditTemplatePagePage.d.ts +2 -0
  215. package/dist/planmagnet/pages/TemplatesEditTemplatePagePage.d.ts.map +1 -0
  216. package/dist/planmagnet/pages/TemplatesEditTemplatePagePage.js +316 -0
  217. package/dist/planmagnet/pages/TemplatesEditTemplatePagePage.js.map +1 -0
  218. package/dist/planmagnet/pages/TemplatesTemplatesPagePage.d.ts +2 -0
  219. package/dist/planmagnet/pages/TemplatesTemplatesPagePage.d.ts.map +1 -0
  220. package/dist/planmagnet/pages/TemplatesTemplatesPagePage.js +208 -0
  221. package/dist/planmagnet/pages/TemplatesTemplatesPagePage.js.map +1 -0
  222. package/dist/planmagnet/pages/analytics/DeliveryHealthCards.d.ts +0 -5
  223. package/dist/planmagnet/pages/analytics/DeliveryHealthCards.d.ts.map +1 -1
  224. package/dist/planmagnet/pages/analytics/DeliveryHealthCards.js +47 -89
  225. package/dist/planmagnet/pages/analytics/DeliveryHealthCards.js.map +1 -1
  226. package/dist/planmagnet/roadmaps/RoadmapControls.js +24 -24
  227. package/dist/planmagnet/time/TaskTimePanel.d.ts +7 -0
  228. package/dist/planmagnet/time/TaskTimePanel.d.ts.map +1 -0
  229. package/dist/planmagnet/time/TaskTimePanel.js +104 -0
  230. package/dist/planmagnet/time/TaskTimePanel.js.map +1 -0
  231. package/dist/planmagnet/time/TimeEntryControls.d.ts +37 -0
  232. package/dist/planmagnet/time/TimeEntryControls.d.ts.map +1 -0
  233. package/dist/planmagnet/time/TimeEntryControls.js +338 -0
  234. package/dist/planmagnet/time/TimeEntryControls.js.map +1 -0
  235. package/dist/planmagnet/time/TimesheetControls.d.ts +18 -0
  236. package/dist/planmagnet/time/TimesheetControls.d.ts.map +1 -0
  237. package/dist/planmagnet/time/TimesheetControls.js +244 -0
  238. package/dist/planmagnet/time/TimesheetControls.js.map +1 -0
  239. package/dist/planmagnet/time/timeShared.d.ts +29 -0
  240. package/dist/planmagnet/time/timeShared.d.ts.map +1 -0
  241. package/dist/planmagnet/time/timeShared.js +34 -0
  242. package/dist/planmagnet/time/timeShared.js.map +1 -0
  243. package/dist/planmagnet/utils/rowNavigation.js +5 -2
  244. package/dist/planmagnet/utils/rowNavigation.js.map +1 -1
  245. package/package.json +1 -1
@@ -0,0 +1,113 @@
1
+ //#region src/planmagnet/automation/automationRuleTypes.ts
2
+ var e = new Set(["WORK_ITEM_CREATED", "WORK_ITEM_STATUS_CHANGED"]), t = [
3
+ "WORK_ITEM_CREATED",
4
+ "WORK_ITEM_STATUS_CHANGED",
5
+ "WORK_ITEM_UPDATED",
6
+ "WORK_ITEM_ASSIGNED",
7
+ "SPRINT_STARTED",
8
+ "SPRINT_COMPLETED",
9
+ "MILESTONE_DUE",
10
+ "SCHEDULE",
11
+ "WEBHOOK",
12
+ "MANUAL"
13
+ ], n = {
14
+ WORK_ITEM_CREATED: "Work item created",
15
+ WORK_ITEM_STATUS_CHANGED: "Work item status changed",
16
+ WORK_ITEM_UPDATED: "Work item updated",
17
+ WORK_ITEM_ASSIGNED: "Work item assigned",
18
+ SPRINT_STARTED: "Sprint started",
19
+ SPRINT_COMPLETED: "Sprint completed",
20
+ MILESTONE_DUE: "Milestone due",
21
+ SCHEDULE: "Schedule",
22
+ WEBHOOK: "Webhook",
23
+ MANUAL: "Manual only"
24
+ };
25
+ function r(e) {
26
+ return n[e] ?? e;
27
+ }
28
+ var i = [
29
+ "ACTIVE",
30
+ "PAUSED",
31
+ "DISABLED",
32
+ "ERROR"
33
+ ], a = [
34
+ "ASSIGN_TO_USER",
35
+ "ADD_LABEL",
36
+ "SET_STATUS",
37
+ "SET_PRIORITY"
38
+ ], o = {
39
+ ASSIGN_TO_USER: "Assign to user",
40
+ ADD_LABEL: "Add label",
41
+ SET_STATUS: "Set status",
42
+ SET_PRIORITY: "Set priority"
43
+ }, s = [
44
+ "eq",
45
+ "neq",
46
+ "in",
47
+ "notIn",
48
+ "contains",
49
+ "gt",
50
+ "gte",
51
+ "lt",
52
+ "lte",
53
+ "exists"
54
+ ], c = {
55
+ eq: "is",
56
+ neq: "is not",
57
+ in: "is one of",
58
+ notIn: "is not one of",
59
+ contains: "contains",
60
+ gt: ">",
61
+ gte: ">=",
62
+ lt: "<",
63
+ lte: "<=",
64
+ exists: "is set"
65
+ }, l = [
66
+ "status",
67
+ "previousStatus",
68
+ "priority",
69
+ "type",
70
+ "assigneeId",
71
+ "title",
72
+ "labels",
73
+ "sprintId",
74
+ "projectId"
75
+ ];
76
+ function u(e) {
77
+ return e.filter((e) => e.value.trim() !== "").map((e) => ({
78
+ type: e.type,
79
+ value: e.value.trim()
80
+ }));
81
+ }
82
+ function d(e) {
83
+ let t = e.filter((e) => e.field.trim() !== "");
84
+ if (t.length !== 0) return t.map((e) => e.operator === "exists" ? {
85
+ field: e.field.trim(),
86
+ operator: e.operator
87
+ } : e.operator === "in" || e.operator === "notIn" ? {
88
+ field: e.field.trim(),
89
+ operator: e.operator,
90
+ value: e.value.split(",").map((e) => e.trim()).filter(Boolean)
91
+ } : {
92
+ field: e.field.trim(),
93
+ operator: e.operator,
94
+ value: e.value
95
+ });
96
+ }
97
+ function f(e) {
98
+ return Array.isArray(e) ? e.filter((e) => !!e && typeof e == "object" && typeof e.field == "string").map((e) => ({
99
+ field: e.field,
100
+ operator: s.includes(e.operator) ? e.operator : "eq",
101
+ value: Array.isArray(e.value) ? e.value.join(", ") : e.value == null ? "" : String(e.value)
102
+ })) : [];
103
+ }
104
+ function p(e) {
105
+ return Array.isArray(e) ? e.filter((e) => !!e && typeof e == "object" && typeof e.type == "string").map((e) => ({
106
+ type: e.type,
107
+ value: e.value == null ? "" : String(e.value)
108
+ })) : [];
109
+ }
110
+ //#endregion
111
+ export { a as ACTION_TYPES, o as ACTION_TYPE_LABEL, e as AUTOMATIC_TRIGGER_TYPES, l as CONDITION_FIELDS, s as CONDITION_OPERATORS, c as CONDITION_OPERATOR_LABEL, i as RULE_STATUSES, t as TRIGGER_TYPES, n as TRIGGER_TYPE_LABEL, p as actionsFromApi, u as actionsToApi, f as conditionsFromApi, d as conditionsToApi, r as triggerTypeLabel };
112
+
113
+ //# sourceMappingURL=automationRuleTypes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"automationRuleTypes.js","names":[],"sources":["../../../src/planmagnet/automation/automationRuleTypes.ts"],"sourcesContent":["/**\n * Automation rules (BOFF-8047). Shared trigger/condition/action vocabulary, kept in one place so the create\n * page, the edit page and the list's summaries can never drift from each other or from the engine.\n *\n * Scope note (from `automation-engine.ts`, the source of truth): only two triggers fire automatically today —\n * `WORK_ITEM_CREATED` and `WORK_ITEM_STATUS_CHANGED` — and only four action types can be dispatched —\n * `ASSIGN_TO_USER`, `ADD_LABEL`, `SET_STATUS`, `SET_PRIORITY`. The other five trigger types are real schema\n * values the service accepts and stores (so a rule can be prepared ahead of a future engine change), but they\n * never fire on their own; \"Run now\" (`planmagnetExecuteAutomationRule`) works for a rule of ANY trigger type,\n * including `MANUAL`, because it targets one named work item directly rather than listening for an event.\n *\n * The actions builder below offers ONLY the four dispatchable types: offering the others would create a rule\n * whose own execution log immediately reports \"declared action(s) are not supported\" — a UI that can build a\n * rule the backend documents as silently dropping is worse than not offering the option.\n */\n\nexport const AUTOMATIC_TRIGGER_TYPES = new Set(['WORK_ITEM_CREATED', 'WORK_ITEM_STATUS_CHANGED']);\n\nexport const TRIGGER_TYPES = [\n 'WORK_ITEM_CREATED',\n 'WORK_ITEM_STATUS_CHANGED',\n 'WORK_ITEM_UPDATED',\n 'WORK_ITEM_ASSIGNED',\n 'SPRINT_STARTED',\n 'SPRINT_COMPLETED',\n 'MILESTONE_DUE',\n 'SCHEDULE',\n 'WEBHOOK',\n 'MANUAL',\n] as const;\nexport type TriggerType = (typeof TRIGGER_TYPES)[number];\n\nexport const TRIGGER_TYPE_LABEL: Record<TriggerType, string> = {\n WORK_ITEM_CREATED: 'Work item created',\n WORK_ITEM_STATUS_CHANGED: 'Work item status changed',\n WORK_ITEM_UPDATED: 'Work item updated',\n WORK_ITEM_ASSIGNED: 'Work item assigned',\n SPRINT_STARTED: 'Sprint started',\n SPRINT_COMPLETED: 'Sprint completed',\n MILESTONE_DUE: 'Milestone due',\n SCHEDULE: 'Schedule',\n WEBHOOK: 'Webhook',\n MANUAL: 'Manual only',\n};\n\n/** Looks up a trigger type's label; falls back to the raw value for one this UI does not yet know (forward\n * compatible with a value the service adds later). Cast: `TRIGGER_TYPE_LABEL` is keyed by the known union, but\n * a value read back from the API is a plain string. */\nexport function triggerTypeLabel(value: string): string {\n return (TRIGGER_TYPE_LABEL as Record<string, string>)[value] ?? value;\n}\n\nexport const RULE_STATUSES = ['ACTIVE', 'PAUSED', 'DISABLED', 'ERROR'] as const;\nexport type RuleStatus = (typeof RULE_STATUSES)[number];\n\nexport const ACTION_TYPES = ['ASSIGN_TO_USER', 'ADD_LABEL', 'SET_STATUS', 'SET_PRIORITY'] as const;\nexport type ActionType = (typeof ACTION_TYPES)[number];\n\nexport const ACTION_TYPE_LABEL: Record<ActionType, string> = {\n ASSIGN_TO_USER: 'Assign to user',\n ADD_LABEL: 'Add label',\n SET_STATUS: 'Set status',\n SET_PRIORITY: 'Set priority',\n};\n\nexport interface RuleAction {\n type: ActionType;\n value: string;\n}\n\nexport const CONDITION_OPERATORS = [\n 'eq',\n 'neq',\n 'in',\n 'notIn',\n 'contains',\n 'gt',\n 'gte',\n 'lt',\n 'lte',\n 'exists',\n] as const;\nexport type ConditionOperator = (typeof CONDITION_OPERATORS)[number];\n\nexport const CONDITION_OPERATOR_LABEL: Record<ConditionOperator, string> = {\n eq: 'is',\n neq: 'is not',\n in: 'is one of',\n notIn: 'is not one of',\n contains: 'contains',\n gt: '>',\n gte: '>=',\n lt: '<',\n lte: '<=',\n exists: 'is set',\n};\n\n/** Fields present on every automatic trigger's snapshot (`TriggerData` in automation-engine.ts). */\nexport const CONDITION_FIELDS = [\n 'status',\n 'previousStatus',\n 'priority',\n 'type',\n 'assigneeId',\n 'title',\n 'labels',\n 'sprintId',\n 'projectId',\n] as const;\n\nexport interface RuleCondition {\n field: string;\n operator: ConditionOperator;\n /** Raw editor value; for `in`/`notIn` this is a comma-separated list, converted to an array on submit. */\n value: string;\n}\n\n/** actions[] (form shape) -> actions JSON the API accepts. */\nexport function actionsToApi(actions: RuleAction[]): { type: ActionType; value: string }[] {\n return actions\n .filter((a) => a.value.trim() !== '')\n .map((a) => ({ type: a.type, value: a.value.trim() }));\n}\n\n/** conditions[] (form shape) -> conditions JSON the API accepts, or undefined when there are none. */\nexport function conditionsToApi(\n conditions: RuleCondition[]\n): { field: string; operator: ConditionOperator; value?: unknown }[] | undefined {\n const usable = conditions.filter((c) => c.field.trim() !== '');\n if (usable.length === 0) return undefined;\n return usable.map((c) => {\n if (c.operator === 'exists') return { field: c.field.trim(), operator: c.operator };\n if (c.operator === 'in' || c.operator === 'notIn') {\n return {\n field: c.field.trim(),\n operator: c.operator,\n value: c.value\n .split(',')\n .map((v) => v.trim())\n .filter(Boolean),\n };\n }\n return { field: c.field.trim(), operator: c.operator, value: c.value };\n });\n}\n\n/** API conditions JSON -> form shape, for the edit page. Unrecognised shapes are dropped rather than crashing the form. */\nexport function conditionsFromApi(raw: unknown): RuleCondition[] {\n if (!Array.isArray(raw)) return [];\n return raw\n .filter(\n (v): v is { field: string; operator: string; value?: unknown } =>\n !!v && typeof v === 'object' && typeof (v as { field?: unknown }).field === 'string'\n )\n .map((c) => ({\n field: c.field,\n operator: (CONDITION_OPERATORS as readonly string[]).includes(c.operator)\n ? (c.operator as ConditionOperator)\n : 'eq',\n value: Array.isArray(c.value) ? c.value.join(', ') : c.value == null ? '' : String(c.value),\n }));\n}\n\n/** API actions JSON -> form shape, for the edit page. Action types this builder does not offer are kept (so an\n * existing rule's own configuration is never silently dropped by opening the edit page) but shown as read-only. */\nexport function actionsFromApi(raw: unknown): RuleAction[] {\n if (!Array.isArray(raw)) return [];\n return raw\n .filter(\n (v): v is { type: string; value?: unknown } =>\n !!v && typeof v === 'object' && typeof (v as { type?: unknown }).type === 'string'\n )\n .map((a) => ({ type: a.type as ActionType, value: a.value == null ? '' : String(a.value) }));\n}\n"],"mappings":";AAgBA,IAAa,IAA0B,IAAI,IAAI,CAAC,qBAAqB,2BAA2B,CAAC,EAEpF,IAAgB;CAC3B;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD,EAGY,IAAkD;CAC7D,mBAAmB;CACnB,0BAA0B;CAC1B,mBAAmB;CACnB,oBAAoB;CACpB,gBAAgB;CAChB,kBAAkB;CAClB,eAAe;CACf,UAAU;CACV,SAAS;CACT,QAAQ;CACT;AAKD,SAAgB,EAAiB,GAAuB;AACtD,QAAQ,EAA8C,MAAU;;AAGlE,IAAa,IAAgB;CAAC;CAAU;CAAU;CAAY;CAAQ,EAGzD,IAAe;CAAC;CAAkB;CAAa;CAAc;CAAe,EAG5E,IAAgD;CAC3D,gBAAgB;CAChB,WAAW;CACX,YAAY;CACZ,cAAc;CACf,EAOY,IAAsB;CACjC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD,EAGY,IAA8D;CACzE,IAAI;CACJ,KAAK;CACL,IAAI;CACJ,OAAO;CACP,UAAU;CACV,IAAI;CACJ,KAAK;CACL,IAAI;CACJ,KAAK;CACL,QAAQ;CACT,EAGY,IAAmB;CAC9B;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD;AAUD,SAAgB,EAAa,GAA8D;AACzF,QAAO,EACJ,QAAQ,MAAM,EAAE,MAAM,MAAM,KAAK,GAAG,CACpC,KAAK,OAAO;EAAE,MAAM,EAAE;EAAM,OAAO,EAAE,MAAM,MAAM;EAAE,EAAE;;AAI1D,SAAgB,EACd,GAC+E;CAC/E,IAAM,IAAS,EAAW,QAAQ,MAAM,EAAE,MAAM,MAAM,KAAK,GAAG;AAC1D,OAAO,WAAW,EACtB,QAAO,EAAO,KAAK,MACb,EAAE,aAAa,WAAiB;EAAE,OAAO,EAAE,MAAM,MAAM;EAAE,UAAU,EAAE;EAAU,GAC/E,EAAE,aAAa,QAAQ,EAAE,aAAa,UACjC;EACL,OAAO,EAAE,MAAM,MAAM;EACrB,UAAU,EAAE;EACZ,OAAO,EAAE,MACN,MAAM,IAAI,CACV,KAAK,MAAM,EAAE,MAAM,CAAC,CACpB,OAAO,QAAQ;EACnB,GAEI;EAAE,OAAO,EAAE,MAAM,MAAM;EAAE,UAAU,EAAE;EAAU,OAAO,EAAE;EAAO,CACtE;;AAIJ,SAAgB,EAAkB,GAA+B;AAE/D,QADK,MAAM,QAAQ,EAAI,GAChB,EACJ,QACE,MACC,CAAC,CAAC,KAAK,OAAO,KAAM,YAAY,OAAQ,EAA0B,SAAU,SAC/E,CACA,KAAK,OAAO;EACX,OAAO,EAAE;EACT,UAAW,EAA0C,SAAS,EAAE,SAAS,GACpE,EAAE,WACH;EACJ,OAAO,MAAM,QAAQ,EAAE,MAAM,GAAG,EAAE,MAAM,KAAK,KAAK,GAAG,EAAE,SAAS,OAAO,KAAK,OAAO,EAAE,MAAM;EAC5F,EAAE,GAZ2B,EAAE;;AAiBpC,SAAgB,EAAe,GAA4B;AAEzD,QADK,MAAM,QAAQ,EAAI,GAChB,EACJ,QACE,MACC,CAAC,CAAC,KAAK,OAAO,KAAM,YAAY,OAAQ,EAAyB,QAAS,SAC7E,CACA,KAAK,OAAO;EAAE,MAAM,EAAE;EAAoB,OAAO,EAAE,SAAS,OAAO,KAAK,OAAO,EAAE,MAAM;EAAE,EAAE,GAN9D,EAAE"}
@@ -0,0 +1,11 @@
1
+ import { ProjectWorkflow } from '../hooks/useProjectWorkflow';
2
+
3
+ /** Every query whose numbers a bulk change can move — the same list ProjectBoard's own mutations refetch. */
4
+ export declare const BULK_REFETCH: string[];
5
+ export declare function BulkActionsBar({ projectId, selectedIds, workflow, onDone, }: {
6
+ projectId: string;
7
+ selectedIds: string[];
8
+ workflow: ProjectWorkflow | null;
9
+ onDone: () => void;
10
+ }): import("react/jsx-runtime").JSX.Element;
11
+ //# sourceMappingURL=BulkActions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BulkActions.d.ts","sourceRoot":"","sources":["../../../src/planmagnet/board/BulkActions.tsx"],"names":[],"mappings":"AASA,OAAO,EAAE,KAAK,eAAe,EAAiB,MAAM,6BAA6B,CAAC;AA6ClF,6GAA6G;AAC7G,eAAO,MAAM,YAAY,UAMxB,CAAC;AAEF,wBAAgB,cAAc,CAAC,EAC7B,SAAS,EACT,WAAW,EACX,QAAQ,EACR,MAAM,GACP,EAAE;IACD,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,QAAQ,EAAE,eAAe,GAAG,IAAI,CAAC;IACjC,MAAM,EAAE,MAAM,IAAI,CAAC;CACpB,2CAkKA"}
@@ -0,0 +1,182 @@
1
+ import { usePlanMagnet as e } from "../providers/PlanMagnetProvider.js";
2
+ import { throwOnError as t } from "../utils/mutationResult.js";
3
+ import { ErrorLine as n } from "../controls/ConfirmButton.js";
4
+ import { workflowLabel as r } from "../hooks/useProjectWorkflow.js";
5
+ import { WORK_ITEM_PRIORITIES as i, enumLabel as a, useAssigneeOptions as o } from "../controls/WorkItemControls.js";
6
+ import { useState as s } from "react";
7
+ import { X as c } from "lucide-react";
8
+ import { gql as l } from "@apollo/client";
9
+ import { useMutation as u, useQuery as d } from "@apollo/client/react";
10
+ import { jsx as f, jsxs as p } from "react/jsx-runtime";
11
+ import { Button as m } from "@burdenoff/fe-libs/ui";
12
+ //#region src/planmagnet/board/BulkActions.tsx
13
+ var h = "", g = "__unassign__", _ = "__no_sprint__", v = new Set([
14
+ "PLANNING",
15
+ "ACTIVE",
16
+ "REVIEW"
17
+ ]), y = l`
18
+ mutation ProjectBoardBulkUpdate($input: PlanmagnetBulkUpdateWorkItemsInput!) {
19
+ planmagnetBulkUpdateWorkItems(input: $input) {
20
+ id
21
+ status
22
+ priority
23
+ assigneeId
24
+ sprintId
25
+ }
26
+ }
27
+ `, b = l`
28
+ query BulkActionsProjectSprints($workspaceId: ID!, $projectId: String) {
29
+ planmagnetSprints(
30
+ workspaceId: $workspaceId
31
+ filter: { projectId: $projectId }
32
+ pagination: { first: 100 }
33
+ ) {
34
+ items {
35
+ id
36
+ name
37
+ status
38
+ }
39
+ }
40
+ }
41
+ `, x = [
42
+ "ProjectBoard",
43
+ "ProjectBoards",
44
+ "GetWorkItems",
45
+ "GetWorkItemCounts",
46
+ "GetDashboardData"
47
+ ];
48
+ function S({ projectId: l, selectedIds: S, workflow: C, onDone: w }) {
49
+ let { workspaceId: T } = e(), [E, D] = s(h), [O, k] = s(h), [A, j] = s(h), [M, N] = s(h), [P, F] = s(null), [I, L] = s(null), { options: R } = o(null), { data: z } = d(b, {
50
+ variables: {
51
+ workspaceId: T ?? "",
52
+ projectId: l
53
+ },
54
+ skip: !T
55
+ }), B = (z?.planmagnetSprints?.items ?? []).filter((e) => v.has(e.status)), [V, H] = u(y, {
56
+ refetchQueries: x,
57
+ awaitRefetchQueries: !0
58
+ }), U = (C?.statuses ?? []).filter((e) => !e.hidden), W = E !== h || O !== h || A !== h || M !== h, G = () => {
59
+ D(h), k(h), j(h), N(h);
60
+ }, K = async () => {
61
+ F(null), L(null);
62
+ let e = { ids: S };
63
+ E !== h && (e.status = E), O !== h && (e.priority = O), A !== h && (e.assigneeId = A === g ? null : A), M !== h && (e.sprintId = M === _ ? null : M);
64
+ try {
65
+ L((await t(V({ variables: { input: e } }))).data?.planmagnetBulkUpdateWorkItems.length ?? S.length), G();
66
+ } catch (e) {
67
+ F(e instanceof Error ? e.message : "The selected tasks could not be updated.");
68
+ }
69
+ }, q = (e) => (t) => {
70
+ L(null), F(null), e(t);
71
+ };
72
+ return /* @__PURE__ */ p("div", {
73
+ className: "flex flex-wrap items-center gap-2 rounded-md border bg-muted/40 p-2",
74
+ "data-testid": "board-bulk-actions",
75
+ children: [
76
+ /* @__PURE__ */ p("span", {
77
+ className: "text-sm font-medium",
78
+ "data-testid": "board-bulk-count",
79
+ children: [S.length, " selected"]
80
+ }),
81
+ /* @__PURE__ */ p("select", {
82
+ "aria-label": "Bulk: set status",
83
+ className: "rounded-md border border-input bg-background px-2 py-1 text-sm",
84
+ value: E,
85
+ disabled: H.loading,
86
+ onChange: (e) => q(D)(e.target.value),
87
+ children: [/* @__PURE__ */ f("option", {
88
+ value: h,
89
+ children: "Status: no change"
90
+ }), U.map((e) => /* @__PURE__ */ p("option", {
91
+ value: e.status,
92
+ children: ["Status: ", r(C, e.status)]
93
+ }, e.status))]
94
+ }),
95
+ /* @__PURE__ */ p("select", {
96
+ "aria-label": "Bulk: set priority",
97
+ className: "rounded-md border border-input bg-background px-2 py-1 text-sm",
98
+ value: O,
99
+ disabled: H.loading,
100
+ onChange: (e) => q(k)(e.target.value),
101
+ children: [/* @__PURE__ */ f("option", {
102
+ value: h,
103
+ children: "Priority: no change"
104
+ }), i.map((e) => /* @__PURE__ */ p("option", {
105
+ value: e,
106
+ children: ["Priority: ", a(e)]
107
+ }, e))]
108
+ }),
109
+ /* @__PURE__ */ p("select", {
110
+ "aria-label": "Bulk: set assignee",
111
+ className: "rounded-md border border-input bg-background px-2 py-1 text-sm max-w-[12rem]",
112
+ value: A,
113
+ disabled: H.loading,
114
+ onChange: (e) => q(j)(e.target.value),
115
+ children: [
116
+ /* @__PURE__ */ f("option", {
117
+ value: h,
118
+ children: "Assignee: no change"
119
+ }),
120
+ /* @__PURE__ */ f("option", {
121
+ value: g,
122
+ children: "Assignee: Unassign"
123
+ }),
124
+ R.map((e) => /* @__PURE__ */ p("option", {
125
+ value: e.id,
126
+ children: ["Assignee: ", e.name]
127
+ }, e.id))
128
+ ]
129
+ }),
130
+ /* @__PURE__ */ p("select", {
131
+ "aria-label": "Bulk: set sprint",
132
+ className: "rounded-md border border-input bg-background px-2 py-1 text-sm max-w-[12rem]",
133
+ value: M,
134
+ disabled: H.loading,
135
+ onChange: (e) => q(N)(e.target.value),
136
+ children: [
137
+ /* @__PURE__ */ f("option", {
138
+ value: h,
139
+ children: "Sprint: no change"
140
+ }),
141
+ /* @__PURE__ */ f("option", {
142
+ value: _,
143
+ children: "Sprint: Remove from sprint"
144
+ }),
145
+ B.map((e) => /* @__PURE__ */ p("option", {
146
+ value: e.id,
147
+ children: ["Sprint: ", e.name]
148
+ }, e.id))
149
+ ]
150
+ }),
151
+ /* @__PURE__ */ f(m, {
152
+ size: "sm",
153
+ "data-testid": "board-bulk-apply",
154
+ disabled: !W || H.loading || S.length === 0,
155
+ onClick: () => void K(),
156
+ children: H.loading ? "Applying…" : `Apply to ${S.length}`
157
+ }),
158
+ /* @__PURE__ */ p(m, {
159
+ size: "sm",
160
+ variant: "ghost",
161
+ onClick: w,
162
+ disabled: H.loading,
163
+ children: [/* @__PURE__ */ f(c, { className: "mr-1 h-4 w-4" }), "Clear selection"]
164
+ }),
165
+ I !== null && /* @__PURE__ */ p("span", {
166
+ role: "status",
167
+ className: "text-sm text-status-success-text",
168
+ children: [
169
+ I,
170
+ " task",
171
+ I === 1 ? "" : "s",
172
+ " updated."
173
+ ]
174
+ }),
175
+ P && /* @__PURE__ */ f(n, { message: P })
176
+ ]
177
+ });
178
+ }
179
+ //#endregion
180
+ export { S as BulkActionsBar };
181
+
182
+ //# sourceMappingURL=BulkActions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BulkActions.js","names":[],"sources":["../../../src/planmagnet/board/BulkActions.tsx"],"sourcesContent":["import { useState } from 'react';\nimport { gql } from '@apollo/client';\nimport { useMutation, useQuery } from '@apollo/client/react';\nimport { Button } from '@burdenoff/fe-libs/ui';\nimport { X } from 'lucide-react';\nimport { usePlanMagnet } from '../providers/PlanMagnetProvider';\nimport { throwOnError } from '../utils/mutationResult';\nimport { ErrorLine } from '../controls/ConfirmButton';\nimport { WORK_ITEM_PRIORITIES, enumLabel, useAssigneeOptions } from '../controls/WorkItemControls';\nimport { type ProjectWorkflow, workflowLabel } from '../hooks/useProjectWorkflow';\n\n/**\n * Bulk update on the project board (BOFF-8047, capability register: Bulk update, `api-only`). The resolver and its\n * whitelist (`BULK_UPDATE_ALLOWED_FIELDS`: status, priority, assigneeId, sprintId, type, labels) have been real\n * since before this change; nothing in the UI ever called it. The server checks every selected item against the\n * project's workflow (BOFF-8043) and writes all-or-nothing — a refused move names how many items and why, and\n * nothing is changed. This bar only sends the fields the user actually touched; the rest are left out of the\n * mutation input entirely (not sent as \"no change\" — omitted), which is what a real bulk mutation call needs\n * (a `null` on `assigneeId`/`sprintId` explicitly clears it).\n */\n\nconst NO_CHANGE = '';\nconst UNASSIGN = '__unassign__';\nconst NO_SPRINT = '__no_sprint__';\nconst OPEN_SPRINT_STATUSES = new Set(['PLANNING', 'ACTIVE', 'REVIEW']);\n\nconst BULK_UPDATE = gql`\n mutation ProjectBoardBulkUpdate($input: PlanmagnetBulkUpdateWorkItemsInput!) {\n planmagnetBulkUpdateWorkItems(input: $input) {\n id\n status\n priority\n assigneeId\n sprintId\n }\n }\n`;\n\nconst PROJECT_SPRINTS = gql`\n query BulkActionsProjectSprints($workspaceId: ID!, $projectId: String) {\n planmagnetSprints(\n workspaceId: $workspaceId\n filter: { projectId: $projectId }\n pagination: { first: 100 }\n ) {\n items {\n id\n name\n status\n }\n }\n }\n`;\n\n/** Every query whose numbers a bulk change can move — the same list ProjectBoard's own mutations refetch. */\nexport const BULK_REFETCH = [\n 'ProjectBoard',\n 'ProjectBoards',\n 'GetWorkItems',\n 'GetWorkItemCounts',\n 'GetDashboardData',\n];\n\nexport function BulkActionsBar({\n projectId,\n selectedIds,\n workflow,\n onDone,\n}: {\n projectId: string;\n selectedIds: string[];\n workflow: ProjectWorkflow | null;\n onDone: () => void;\n}) {\n const { workspaceId } = usePlanMagnet();\n const [status, setStatus] = useState(NO_CHANGE);\n const [priority, setPriority] = useState(NO_CHANGE);\n const [assigneeId, setAssigneeId] = useState(NO_CHANGE);\n const [sprintId, setSprintId] = useState(NO_CHANGE);\n const [error, setError] = useState<string | null>(null);\n const [applied, setApplied] = useState<number | null>(null);\n\n const { options: assigneeOptions } = useAssigneeOptions(null);\n const { data: sprintsData } = useQuery<{\n planmagnetSprints?: { items: { id: string; name: string; status: string }[] };\n }>(PROJECT_SPRINTS, {\n variables: { workspaceId: workspaceId ?? '', projectId },\n skip: !workspaceId,\n });\n const sprints = (sprintsData?.planmagnetSprints?.items ?? []).filter((s) =>\n OPEN_SPRINT_STATUSES.has(s.status)\n );\n\n const [bulkUpdate, state] = useMutation<{ planmagnetBulkUpdateWorkItems: { id: string }[] }>(\n BULK_UPDATE,\n { refetchQueries: BULK_REFETCH, awaitRefetchQueries: true }\n );\n\n // Visible statuses this project uses; a hidden status stays off the bulk picker (matches every other status\n // control here). The server still owns the real per-item transition rule — this only offers sane targets.\n const statuses = (workflow?.statuses ?? []).filter((s) => !s.hidden);\n\n const dirty =\n status !== NO_CHANGE ||\n priority !== NO_CHANGE ||\n assigneeId !== NO_CHANGE ||\n sprintId !== NO_CHANGE;\n\n const reset = () => {\n setStatus(NO_CHANGE);\n setPriority(NO_CHANGE);\n setAssigneeId(NO_CHANGE);\n setSprintId(NO_CHANGE);\n };\n\n const apply = async () => {\n setError(null);\n setApplied(null);\n const input: Record<string, unknown> = { ids: selectedIds };\n if (status !== NO_CHANGE) input.status = status;\n if (priority !== NO_CHANGE) input.priority = priority;\n if (assigneeId !== NO_CHANGE) input.assigneeId = assigneeId === UNASSIGN ? null : assigneeId;\n if (sprintId !== NO_CHANGE) input.sprintId = sprintId === NO_SPRINT ? null : sprintId;\n try {\n const result = await throwOnError(bulkUpdate({ variables: { input } }));\n // The selection is left in place on success (rather than cleared): clearing it would unmount this bar\n // before its \"N tasks updated\" message could ever be read — the same class of bug as a refusal message\n // sitting on a row a refetch removes. The user clears it themselves once they have seen the result.\n setApplied(result.data?.planmagnetBulkUpdateWorkItems.length ?? selectedIds.length);\n reset();\n } catch (e) {\n setError(e instanceof Error ? e.message : 'The selected tasks could not be updated.');\n }\n };\n\n const onField =\n <T,>(setter: (v: T) => void) =>\n (value: T) => {\n setApplied(null);\n setError(null);\n setter(value);\n };\n\n return (\n <div\n className=\"flex flex-wrap items-center gap-2 rounded-md border bg-muted/40 p-2\"\n data-testid=\"board-bulk-actions\"\n >\n <span className=\"text-sm font-medium\" data-testid=\"board-bulk-count\">\n {selectedIds.length} selected\n </span>\n\n <select\n aria-label=\"Bulk: set status\"\n className=\"rounded-md border border-input bg-background px-2 py-1 text-sm\"\n value={status}\n disabled={state.loading}\n onChange={(e) => onField(setStatus)(e.target.value)}\n >\n <option value={NO_CHANGE}>Status: no change</option>\n {statuses.map((s) => (\n <option key={s.status} value={s.status}>\n Status: {workflowLabel(workflow, s.status)}\n </option>\n ))}\n </select>\n\n <select\n aria-label=\"Bulk: set priority\"\n className=\"rounded-md border border-input bg-background px-2 py-1 text-sm\"\n value={priority}\n disabled={state.loading}\n onChange={(e) => onField(setPriority)(e.target.value)}\n >\n <option value={NO_CHANGE}>Priority: no change</option>\n {WORK_ITEM_PRIORITIES.map((p) => (\n <option key={p} value={p}>\n Priority: {enumLabel(p)}\n </option>\n ))}\n </select>\n\n <select\n aria-label=\"Bulk: set assignee\"\n className=\"rounded-md border border-input bg-background px-2 py-1 text-sm max-w-[12rem]\"\n value={assigneeId}\n disabled={state.loading}\n onChange={(e) => onField(setAssigneeId)(e.target.value)}\n >\n <option value={NO_CHANGE}>Assignee: no change</option>\n <option value={UNASSIGN}>Assignee: Unassign</option>\n {assigneeOptions.map((o) => (\n <option key={o.id} value={o.id}>\n Assignee: {o.name}\n </option>\n ))}\n </select>\n\n <select\n aria-label=\"Bulk: set sprint\"\n className=\"rounded-md border border-input bg-background px-2 py-1 text-sm max-w-[12rem]\"\n value={sprintId}\n disabled={state.loading}\n onChange={(e) => onField(setSprintId)(e.target.value)}\n >\n <option value={NO_CHANGE}>Sprint: no change</option>\n <option value={NO_SPRINT}>Sprint: Remove from sprint</option>\n {sprints.map((s) => (\n <option key={s.id} value={s.id}>\n Sprint: {s.name}\n </option>\n ))}\n </select>\n\n <Button\n size=\"sm\"\n data-testid=\"board-bulk-apply\"\n disabled={!dirty || state.loading || selectedIds.length === 0}\n onClick={() => void apply()}\n >\n {state.loading ? 'Applying…' : `Apply to ${selectedIds.length}`}\n </Button>\n <Button size=\"sm\" variant=\"ghost\" onClick={onDone} disabled={state.loading}>\n <X className=\"mr-1 h-4 w-4\" />\n Clear selection\n </Button>\n\n {applied !== null && (\n <span role=\"status\" className=\"text-sm text-status-success-text\">\n {applied} task{applied === 1 ? '' : 's'} updated.\n </span>\n )}\n {error && <ErrorLine message={error} />}\n </div>\n );\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"ProjectBoard.d.ts","sourceRoot":"","sources":["../../../src/planmagnet/board/ProjectBoard.tsx"],"names":[],"mappings":"AA8NA,8DAA8D;AAC9D,wBAAgB,YAAY,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAGnF;AAgCD,wBAAgB,YAAY,CAAC,EAC3B,SAAS,EACT,WAAW,GACZ,EAAE;IACD,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;CACrB,2CAwPA"}
1
+ {"version":3,"file":"ProjectBoard.d.ts","sourceRoot":"","sources":["../../../src/planmagnet/board/ProjectBoard.tsx"],"names":[],"mappings":"AA+NA,8DAA8D;AAC9D,wBAAgB,YAAY,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAGnF;AAgCD,wBAAgB,YAAY,CAAC,EAC3B,SAAS,EACT,WAAW,GACZ,EAAE;IACD,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;CACrB,2CAuRA"}