@burdenoff/microfe-planmagnet 2026.928.4 → 2026.928.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.
- package/dist/planmagnet/PlanMagnetRoot.d.ts.map +1 -1
- package/dist/planmagnet/PlanMagnetRoot.js +130 -97
- package/dist/planmagnet/PlanMagnetRoot.js.map +1 -1
- package/dist/planmagnet/PlanMagnetRoutes.d.ts.map +1 -1
- package/dist/planmagnet/PlanMagnetRoutes.js +256 -156
- package/dist/planmagnet/PlanMagnetRoutes.js.map +1 -1
- package/dist/planmagnet/automation/AutomationExecutionsPanel.d.ts +5 -0
- package/dist/planmagnet/automation/AutomationExecutionsPanel.d.ts.map +1 -0
- package/dist/planmagnet/automation/AutomationExecutionsPanel.js +107 -0
- package/dist/planmagnet/automation/AutomationExecutionsPanel.js.map +1 -0
- package/dist/planmagnet/automation/AutomationRuleFields.d.ts +29 -0
- package/dist/planmagnet/automation/AutomationRuleFields.d.ts.map +1 -0
- package/dist/planmagnet/automation/AutomationRuleFields.js +308 -0
- package/dist/planmagnet/automation/AutomationRuleFields.js.map +1 -0
- package/dist/planmagnet/automation/automationRuleTypes.d.ts +60 -0
- package/dist/planmagnet/automation/automationRuleTypes.d.ts.map +1 -0
- package/dist/planmagnet/automation/automationRuleTypes.js +113 -0
- package/dist/planmagnet/automation/automationRuleTypes.js.map +1 -0
- package/dist/planmagnet/board/BulkActions.d.ts +11 -0
- package/dist/planmagnet/board/BulkActions.d.ts.map +1 -0
- package/dist/planmagnet/board/BulkActions.js +182 -0
- package/dist/planmagnet/board/BulkActions.js.map +1 -0
- package/dist/planmagnet/board/ProjectBoard.d.ts.map +1 -1
- package/dist/planmagnet/board/ProjectBoard.js +289 -254
- package/dist/planmagnet/board/ProjectBoard.js.map +1 -1
- package/dist/planmagnet/budgets/BudgetControls.d.ts +30 -0
- package/dist/planmagnet/budgets/BudgetControls.d.ts.map +1 -0
- package/dist/planmagnet/budgets/BudgetControls.js +470 -0
- package/dist/planmagnet/budgets/BudgetControls.js.map +1 -0
- package/dist/planmagnet/budgets/ExpenseControls.d.ts +27 -0
- package/dist/planmagnet/budgets/ExpenseControls.d.ts.map +1 -0
- package/dist/planmagnet/budgets/ExpenseControls.js +366 -0
- package/dist/planmagnet/budgets/ExpenseControls.js.map +1 -0
- package/dist/planmagnet/budgets/ProjectBudgetsSummary.d.ts +5 -0
- package/dist/planmagnet/budgets/ProjectBudgetsSummary.d.ts.map +1 -0
- package/dist/planmagnet/budgets/ProjectBudgetsSummary.js +112 -0
- package/dist/planmagnet/budgets/ProjectBudgetsSummary.js.map +1 -0
- package/dist/planmagnet/budgets/budgetMath.d.ts +26 -0
- package/dist/planmagnet/budgets/budgetMath.d.ts.map +1 -0
- package/dist/planmagnet/budgets/budgetMath.js +49 -0
- package/dist/planmagnet/budgets/budgetMath.js.map +1 -0
- package/dist/planmagnet/controls/AutomationRuleControls.d.ts +23 -0
- package/dist/planmagnet/controls/AutomationRuleControls.d.ts.map +1 -0
- package/dist/planmagnet/controls/AutomationRuleControls.js +172 -0
- package/dist/planmagnet/controls/AutomationRuleControls.js.map +1 -0
- package/dist/planmagnet/controls/CompetitorControls.js +15 -15
- package/dist/planmagnet/controls/CustomFieldControls.d.ts +42 -0
- package/dist/planmagnet/controls/CustomFieldControls.d.ts.map +1 -0
- package/dist/planmagnet/controls/CustomFieldControls.js +84 -0
- package/dist/planmagnet/controls/CustomFieldControls.js.map +1 -0
- package/dist/planmagnet/controls/CustomFieldValuesPanel.d.ts +8 -0
- package/dist/planmagnet/controls/CustomFieldValuesPanel.d.ts.map +1 -0
- package/dist/planmagnet/controls/CustomFieldValuesPanel.js +315 -0
- package/dist/planmagnet/controls/CustomFieldValuesPanel.js.map +1 -0
- package/dist/planmagnet/controls/FeatureControls.js +54 -54
- package/dist/planmagnet/controls/ObjectiveControls.js +15 -15
- package/dist/planmagnet/controls/Pickers.d.ts +7 -0
- package/dist/planmagnet/controls/Pickers.d.ts.map +1 -1
- package/dist/planmagnet/controls/Pickers.js +58 -20
- package/dist/planmagnet/controls/Pickers.js.map +1 -1
- package/dist/planmagnet/controls/PortfolioControls.js +7 -7
- package/dist/planmagnet/controls/ProgramControls.js +19 -19
- package/dist/planmagnet/controls/ProjectControls.d.ts.map +1 -1
- package/dist/planmagnet/controls/ProjectControls.js +54 -47
- package/dist/planmagnet/controls/ProjectControls.js.map +1 -1
- package/dist/planmagnet/controls/ReleaseControls.js +7 -7
- package/dist/planmagnet/controls/RiskControls.d.ts +27 -0
- package/dist/planmagnet/controls/RiskControls.d.ts.map +1 -0
- package/dist/planmagnet/controls/RiskControls.js +346 -0
- package/dist/planmagnet/controls/RiskControls.js.map +1 -0
- package/dist/planmagnet/controls/TemplateControls.d.ts +15 -0
- package/dist/planmagnet/controls/TemplateControls.d.ts.map +1 -0
- package/dist/planmagnet/controls/TemplateControls.js +55 -0
- package/dist/planmagnet/controls/TemplateControls.js.map +1 -0
- package/dist/planmagnet/controls/WorkItemControls.d.ts +6 -2
- package/dist/planmagnet/controls/WorkItemControls.d.ts.map +1 -1
- package/dist/planmagnet/controls/WorkItemControls.js +9 -9
- package/dist/planmagnet/controls/WorkItemControls.js.map +1 -1
- package/dist/planmagnet/create/CreateDialogs.d.ts +20 -0
- package/dist/planmagnet/create/CreateDialogs.d.ts.map +1 -1
- package/dist/planmagnet/create/CreateDialogs.js +455 -116
- package/dist/planmagnet/create/CreateDialogs.js.map +1 -1
- package/dist/planmagnet/dependency/DependencyPanel.d.ts +6 -0
- package/dist/planmagnet/dependency/DependencyPanel.d.ts.map +1 -0
- package/dist/planmagnet/dependency/DependencyPanel.js +310 -0
- package/dist/planmagnet/dependency/DependencyPanel.js.map +1 -0
- package/dist/planmagnet/pages/AutomationAutomationRuleDetailPagePage.d.ts +2 -0
- package/dist/planmagnet/pages/AutomationAutomationRuleDetailPagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/AutomationAutomationRuleDetailPagePage.js +171 -0
- package/dist/planmagnet/pages/AutomationAutomationRuleDetailPagePage.js.map +1 -0
- package/dist/planmagnet/pages/AutomationAutomationRulesPagePage.d.ts +2 -0
- package/dist/planmagnet/pages/AutomationAutomationRulesPagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/AutomationAutomationRulesPagePage.js +232 -0
- package/dist/planmagnet/pages/AutomationAutomationRulesPagePage.js.map +1 -0
- package/dist/planmagnet/pages/AutomationCreateAutomationRulePagePage.d.ts +2 -0
- package/dist/planmagnet/pages/AutomationCreateAutomationRulePagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/AutomationCreateAutomationRulePagePage.js +93 -0
- package/dist/planmagnet/pages/AutomationCreateAutomationRulePagePage.js.map +1 -0
- package/dist/planmagnet/pages/DashboardDashboardPagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/DashboardDashboardPagePage.js +11 -3
- package/dist/planmagnet/pages/DashboardDashboardPagePage.js.map +1 -1
- package/dist/planmagnet/pages/PortfoliosEditPortfolioPagePage.js +5 -5
- package/dist/planmagnet/pages/PortfoliosPortfolioDetailPagePage.js +9 -9
- package/dist/planmagnet/pages/PortfoliosPortfoliosPagePage.js +6 -6
- package/dist/planmagnet/pages/ProgramsCreateProgramPagePage.js +4 -4
- package/dist/planmagnet/pages/ProgramsEditProgramPagePage.js +6 -6
- package/dist/planmagnet/pages/ProgramsProgramsPagePage.js +5 -5
- package/dist/planmagnet/pages/ProjectsBudgetDetailPagePage.d.ts +2 -0
- package/dist/planmagnet/pages/ProjectsBudgetDetailPagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/ProjectsBudgetDetailPagePage.js +315 -0
- package/dist/planmagnet/pages/ProjectsBudgetDetailPagePage.js.map +1 -0
- package/dist/planmagnet/pages/ProjectsBudgetsPagePage.d.ts +2 -0
- package/dist/planmagnet/pages/ProjectsBudgetsPagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/ProjectsBudgetsPagePage.js +186 -0
- package/dist/planmagnet/pages/ProjectsBudgetsPagePage.js.map +1 -0
- package/dist/planmagnet/pages/ProjectsCriticalPathPagePage.d.ts +2 -0
- package/dist/planmagnet/pages/ProjectsCriticalPathPagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/ProjectsCriticalPathPagePage.js +164 -0
- package/dist/planmagnet/pages/ProjectsCriticalPathPagePage.js.map +1 -0
- package/dist/planmagnet/pages/ProjectsCustomFieldsPagePage.d.ts +2 -0
- package/dist/planmagnet/pages/ProjectsCustomFieldsPagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/ProjectsCustomFieldsPagePage.js +348 -0
- package/dist/planmagnet/pages/ProjectsCustomFieldsPagePage.js.map +1 -0
- package/dist/planmagnet/pages/ProjectsEditProjectPagePage.js +10 -10
- package/dist/planmagnet/pages/ProjectsMilestoneDetailPagePage.js +4 -4
- package/dist/planmagnet/pages/ProjectsPlanningDetailPagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/ProjectsPlanningDetailPagePage.js +20 -10
- package/dist/planmagnet/pages/ProjectsPlanningDetailPagePage.js.map +1 -1
- package/dist/planmagnet/pages/ProjectsPlanningEditPagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/ProjectsPlanningEditPagePage.js +13 -8
- package/dist/planmagnet/pages/ProjectsPlanningEditPagePage.js.map +1 -1
- package/dist/planmagnet/pages/ProjectsPlanningPagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/ProjectsPlanningPagePage.js +76 -56
- package/dist/planmagnet/pages/ProjectsPlanningPagePage.js.map +1 -1
- package/dist/planmagnet/pages/ProjectsProjectDetailPagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/ProjectsProjectDetailPagePage.js +372 -203
- package/dist/planmagnet/pages/ProjectsProjectDetailPagePage.js.map +1 -1
- package/dist/planmagnet/pages/ProjectsProjectsPagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/ProjectsProjectsPagePage.js +81 -72
- package/dist/planmagnet/pages/ProjectsProjectsPagePage.js.map +1 -1
- package/dist/planmagnet/pages/RisksRiskDetailPagePage.d.ts +2 -0
- package/dist/planmagnet/pages/RisksRiskDetailPagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/RisksRiskDetailPagePage.js +278 -0
- package/dist/planmagnet/pages/RisksRiskDetailPagePage.js.map +1 -0
- package/dist/planmagnet/pages/RisksRiskRegisterPagePage.d.ts +2 -0
- package/dist/planmagnet/pages/RisksRiskRegisterPagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/RisksRiskRegisterPagePage.js +191 -0
- package/dist/planmagnet/pages/RisksRiskRegisterPagePage.js.map +1 -0
- package/dist/planmagnet/pages/SprintsStartSprintPagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/SprintsStartSprintPagePage.js +168 -122
- package/dist/planmagnet/pages/SprintsStartSprintPagePage.js.map +1 -1
- package/dist/planmagnet/pages/TasksCreateTaskPagePage.js +5 -5
- package/dist/planmagnet/pages/TasksEditTaskPagePage.js +4 -4
- package/dist/planmagnet/pages/TasksTaskDetailPagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/TasksTaskDetailPagePage.js +161 -137
- package/dist/planmagnet/pages/TasksTaskDetailPagePage.js.map +1 -1
- package/dist/planmagnet/pages/TasksTasksPagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/TasksTasksPagePage.js +124 -113
- package/dist/planmagnet/pages/TasksTasksPagePage.js.map +1 -1
- package/dist/planmagnet/pages/TasksTimeEntriesPagePage.d.ts +2 -0
- package/dist/planmagnet/pages/TasksTimeEntriesPagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/TasksTimeEntriesPagePage.js +263 -0
- package/dist/planmagnet/pages/TasksTimeEntriesPagePage.js.map +1 -0
- package/dist/planmagnet/pages/TasksTimesheetDetailPagePage.d.ts +2 -0
- package/dist/planmagnet/pages/TasksTimesheetDetailPagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/TasksTimesheetDetailPagePage.js +254 -0
- package/dist/planmagnet/pages/TasksTimesheetDetailPagePage.js.map +1 -0
- package/dist/planmagnet/pages/TasksTimesheetsPagePage.d.ts +2 -0
- package/dist/planmagnet/pages/TasksTimesheetsPagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/TasksTimesheetsPagePage.js +165 -0
- package/dist/planmagnet/pages/TasksTimesheetsPagePage.js.map +1 -0
- package/dist/planmagnet/pages/TeamCreateTeamPagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/TeamCreateTeamPagePage.js +288 -91
- package/dist/planmagnet/pages/TeamCreateTeamPagePage.js.map +1 -1
- package/dist/planmagnet/pages/TeamTeamDetailPagePage.d.ts +2 -0
- package/dist/planmagnet/pages/TeamTeamDetailPagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/TeamTeamDetailPagePage.js +217 -0
- package/dist/planmagnet/pages/TeamTeamDetailPagePage.js.map +1 -0
- package/dist/planmagnet/pages/TeamTeamEditPagePage.d.ts +2 -0
- package/dist/planmagnet/pages/TeamTeamEditPagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/TeamTeamEditPagePage.js +211 -0
- package/dist/planmagnet/pages/TeamTeamEditPagePage.js.map +1 -0
- package/dist/planmagnet/pages/TeamTeamsListPagePage.d.ts +2 -0
- package/dist/planmagnet/pages/TeamTeamsListPagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/TeamTeamsListPagePage.js +118 -0
- package/dist/planmagnet/pages/TeamTeamsListPagePage.js.map +1 -0
- package/dist/planmagnet/pages/TemplatesEditTemplatePagePage.d.ts +2 -0
- package/dist/planmagnet/pages/TemplatesEditTemplatePagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/TemplatesEditTemplatePagePage.js +316 -0
- package/dist/planmagnet/pages/TemplatesEditTemplatePagePage.js.map +1 -0
- package/dist/planmagnet/pages/TemplatesTemplatesPagePage.d.ts +2 -0
- package/dist/planmagnet/pages/TemplatesTemplatesPagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/TemplatesTemplatesPagePage.js +208 -0
- package/dist/planmagnet/pages/TemplatesTemplatesPagePage.js.map +1 -0
- package/dist/planmagnet/pages/analytics/DeliveryHealthCards.d.ts +0 -5
- package/dist/planmagnet/pages/analytics/DeliveryHealthCards.d.ts.map +1 -1
- package/dist/planmagnet/pages/analytics/DeliveryHealthCards.js +47 -89
- package/dist/planmagnet/pages/analytics/DeliveryHealthCards.js.map +1 -1
- package/dist/planmagnet/roadmaps/RoadmapControls.js +24 -24
- package/dist/planmagnet/sprints/SprintControls.d.ts +15 -3
- package/dist/planmagnet/sprints/SprintControls.d.ts.map +1 -1
- package/dist/planmagnet/sprints/SprintControls.js +293 -190
- package/dist/planmagnet/sprints/SprintControls.js.map +1 -1
- package/dist/planmagnet/team/TeamControls.d.ts +31 -0
- package/dist/planmagnet/team/TeamControls.d.ts.map +1 -0
- package/dist/planmagnet/team/TeamControls.js +407 -0
- package/dist/planmagnet/team/TeamControls.js.map +1 -0
- package/dist/planmagnet/time/TaskTimePanel.d.ts +7 -0
- package/dist/planmagnet/time/TaskTimePanel.d.ts.map +1 -0
- package/dist/planmagnet/time/TaskTimePanel.js +104 -0
- package/dist/planmagnet/time/TaskTimePanel.js.map +1 -0
- package/dist/planmagnet/time/TimeEntryControls.d.ts +37 -0
- package/dist/planmagnet/time/TimeEntryControls.d.ts.map +1 -0
- package/dist/planmagnet/time/TimeEntryControls.js +338 -0
- package/dist/planmagnet/time/TimeEntryControls.js.map +1 -0
- package/dist/planmagnet/time/TimesheetControls.d.ts +18 -0
- package/dist/planmagnet/time/TimesheetControls.d.ts.map +1 -0
- package/dist/planmagnet/time/TimesheetControls.js +244 -0
- package/dist/planmagnet/time/TimesheetControls.js.map +1 -0
- package/dist/planmagnet/time/timeShared.d.ts +29 -0
- package/dist/planmagnet/time/timeShared.d.ts.map +1 -0
- package/dist/planmagnet/time/timeShared.js +34 -0
- package/dist/planmagnet/time/timeShared.js.map +1 -0
- package/dist/planmagnet/utils/rowNavigation.js +5 -2
- package/dist/planmagnet/utils/rowNavigation.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
import { usePlanMagnet as e } from "../providers/PlanMagnetProvider.js";
|
|
2
|
+
import { throwOnError as t } from "../utils/mutationResult.js";
|
|
3
|
+
import { useEntityId as n } from "../hooks/useEntityId.js";
|
|
4
|
+
import { ErrorLine as r } from "../controls/ConfirmButton.js";
|
|
5
|
+
import { AUTOMATION_RULE_QUERIES as i, AutomationRuleDeleteButton as a, AutomationRuleStatusSwitch as o, RunAutomationRuleDialog as s } from "../controls/AutomationRuleControls.js";
|
|
6
|
+
import { AutomationExecutionsPanel as c } from "../automation/AutomationExecutionsPanel.js";
|
|
7
|
+
import { actionsFromApi as l, actionsToApi as u, conditionsFromApi as d, conditionsToApi as f } from "../automation/automationRuleTypes.js";
|
|
8
|
+
import { AutomationRuleFields as p } from "../automation/AutomationRuleFields.js";
|
|
9
|
+
import { useState as m } from "react";
|
|
10
|
+
import { Bot as h, History as g, Save as _ } from "lucide-react";
|
|
11
|
+
import { gql as v } from "@apollo/client";
|
|
12
|
+
import { useMutation as y, useQuery as b } from "@apollo/client/react";
|
|
13
|
+
import { jsx as x, jsxs as S } from "react/jsx-runtime";
|
|
14
|
+
import { Button as C, Card as w, CardContent as T, CardHeader as E, CardTitle as D } from "@burdenoff/fe-libs/ui";
|
|
15
|
+
//#region src/planmagnet/pages/AutomationAutomationRuleDetailPagePage.tsx
|
|
16
|
+
var O = v`
|
|
17
|
+
query GetAutomationRule($id: ID!) {
|
|
18
|
+
planmagnetAutomationRule(id: $id) {
|
|
19
|
+
id
|
|
20
|
+
name
|
|
21
|
+
description
|
|
22
|
+
status
|
|
23
|
+
triggerType
|
|
24
|
+
conditions
|
|
25
|
+
actions
|
|
26
|
+
executionCount
|
|
27
|
+
lastExecutedAt
|
|
28
|
+
projectId
|
|
29
|
+
project {
|
|
30
|
+
id
|
|
31
|
+
name
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
`, k = v`
|
|
36
|
+
mutation UpdateAutomationRule($id: ID!, $input: PlanmagnetUpdateAutomationRuleInput!) {
|
|
37
|
+
planmagnetUpdateAutomationRule(id: $id, input: $input) {
|
|
38
|
+
id
|
|
39
|
+
name
|
|
40
|
+
description
|
|
41
|
+
triggerType
|
|
42
|
+
conditions
|
|
43
|
+
actions
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
`;
|
|
47
|
+
function A(e) {
|
|
48
|
+
return {
|
|
49
|
+
name: e.name,
|
|
50
|
+
description: e.description ?? "",
|
|
51
|
+
projectId: e.projectId ?? "",
|
|
52
|
+
triggerType: e.triggerType,
|
|
53
|
+
conditions: d(e.conditions),
|
|
54
|
+
actions: l(e.actions)
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
function j() {
|
|
58
|
+
let l = n(), { workspaceId: d } = e(), { data: v, loading: j, error: M } = b(O, {
|
|
59
|
+
variables: { id: l ?? "" },
|
|
60
|
+
skip: !l,
|
|
61
|
+
fetchPolicy: "cache-and-network"
|
|
62
|
+
}), [N, { loading: P }] = y(k, { refetchQueries: i }), [F, I] = m(null), [L, R] = m(!1), z = v?.planmagnetAutomationRule ?? null, [B, V] = m(null), [H, U] = m(null);
|
|
63
|
+
if (z && H !== z.id && (U(z.id), V(A(z))), !l) return /* @__PURE__ */ x("div", {
|
|
64
|
+
className: "p-6 text-muted-foreground",
|
|
65
|
+
children: "No rule selected. Open one from the list."
|
|
66
|
+
});
|
|
67
|
+
if (j && !v) return /* @__PURE__ */ x("div", {
|
|
68
|
+
className: "flex items-center justify-center p-12",
|
|
69
|
+
children: /* @__PURE__ */ x("div", { className: "animate-spin h-8 w-8 border-2 border-primary border-t-transparent rounded-full" })
|
|
70
|
+
});
|
|
71
|
+
if (M) return /* @__PURE__ */ S("div", {
|
|
72
|
+
className: "p-6 text-destructive",
|
|
73
|
+
children: ["Automation rule could not be loaded: ", M.message]
|
|
74
|
+
});
|
|
75
|
+
if (!z || !B) return /* @__PURE__ */ x("div", {
|
|
76
|
+
className: "p-6 text-muted-foreground",
|
|
77
|
+
children: "Automation rule not found."
|
|
78
|
+
});
|
|
79
|
+
let W = async () => {
|
|
80
|
+
I(null), R(!1);
|
|
81
|
+
let e = A(z), n = {};
|
|
82
|
+
B.name.trim() !== e.name && (n.name = B.name.trim()), B.description.trim() !== e.description.trim() && (n.description = B.description.trim() || null), B.triggerType !== e.triggerType && (n.triggerType = B.triggerType);
|
|
83
|
+
let r = f(B.conditions);
|
|
84
|
+
JSON.stringify(r ?? null) !== JSON.stringify(f(e.conditions) ?? null) && (n.conditions = r ?? null);
|
|
85
|
+
let i = u(B.actions);
|
|
86
|
+
if (JSON.stringify(i) !== JSON.stringify(u(e.actions)) && (n.actions = i), Object.keys(n).length === 0) {
|
|
87
|
+
R(!0);
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
try {
|
|
91
|
+
await t(N({ variables: {
|
|
92
|
+
id: z.id,
|
|
93
|
+
input: n
|
|
94
|
+
} })), R(!0);
|
|
95
|
+
} catch (e) {
|
|
96
|
+
I(e instanceof Error ? e.message : "The rule could not be saved.");
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
return /* @__PURE__ */ S("div", {
|
|
100
|
+
className: "space-y-6 p-6 max-w-3xl",
|
|
101
|
+
children: [
|
|
102
|
+
/* @__PURE__ */ S("div", {
|
|
103
|
+
className: "flex flex-wrap items-start justify-between gap-3",
|
|
104
|
+
children: [/* @__PURE__ */ S("div", { children: [/* @__PURE__ */ x("h1", {
|
|
105
|
+
className: "text-2xl font-semibold",
|
|
106
|
+
children: z.name
|
|
107
|
+
}), /* @__PURE__ */ x("p", {
|
|
108
|
+
className: "text-sm text-muted-foreground",
|
|
109
|
+
children: z.project?.name ?? "Unknown project"
|
|
110
|
+
})] }), /* @__PURE__ */ x("div", {
|
|
111
|
+
className: "flex flex-col items-end gap-2",
|
|
112
|
+
children: /* @__PURE__ */ S("div", {
|
|
113
|
+
className: "flex items-center gap-2",
|
|
114
|
+
children: [
|
|
115
|
+
/* @__PURE__ */ x(s, {
|
|
116
|
+
ruleId: z.id,
|
|
117
|
+
projectId: z.projectId ?? void 0
|
|
118
|
+
}),
|
|
119
|
+
/* @__PURE__ */ x(o, {
|
|
120
|
+
ruleId: z.id,
|
|
121
|
+
status: z.status
|
|
122
|
+
}),
|
|
123
|
+
/* @__PURE__ */ x(a, {
|
|
124
|
+
ruleId: z.id,
|
|
125
|
+
name: z.name
|
|
126
|
+
})
|
|
127
|
+
]
|
|
128
|
+
})
|
|
129
|
+
})]
|
|
130
|
+
}),
|
|
131
|
+
F && /* @__PURE__ */ x(r, { message: F }),
|
|
132
|
+
L && !F && /* @__PURE__ */ x("p", {
|
|
133
|
+
className: "text-sm text-muted-foreground",
|
|
134
|
+
children: "Saved."
|
|
135
|
+
}),
|
|
136
|
+
/* @__PURE__ */ S(w, { children: [/* @__PURE__ */ x(E, { children: /* @__PURE__ */ S(D, {
|
|
137
|
+
className: "flex items-center gap-2",
|
|
138
|
+
children: [/* @__PURE__ */ x(h, { className: "h-4 w-4" }), "Rule details"]
|
|
139
|
+
}) }), /* @__PURE__ */ S(T, {
|
|
140
|
+
className: "space-y-4",
|
|
141
|
+
children: [/* @__PURE__ */ x(p, {
|
|
142
|
+
form: B,
|
|
143
|
+
onChange: (e) => {
|
|
144
|
+
V(e), R(!1);
|
|
145
|
+
},
|
|
146
|
+
projectLocked: !0
|
|
147
|
+
}), /* @__PURE__ */ x("div", {
|
|
148
|
+
className: "flex justify-end",
|
|
149
|
+
children: /* @__PURE__ */ S(C, {
|
|
150
|
+
size: "sm",
|
|
151
|
+
onClick: () => void W(),
|
|
152
|
+
disabled: P,
|
|
153
|
+
"data-testid": "automation-save",
|
|
154
|
+
children: [/* @__PURE__ */ x(_, { className: "mr-1 h-4 w-4" }), P ? "Saving…" : "Save changes"]
|
|
155
|
+
})
|
|
156
|
+
})]
|
|
157
|
+
})] }),
|
|
158
|
+
/* @__PURE__ */ S(w, { children: [/* @__PURE__ */ x(E, { children: /* @__PURE__ */ S(D, {
|
|
159
|
+
className: "flex items-center gap-2",
|
|
160
|
+
children: [/* @__PURE__ */ x(g, { className: "h-4 w-4" }), "Recent executions"]
|
|
161
|
+
}) }), /* @__PURE__ */ x(T, { children: /* @__PURE__ */ x(c, {
|
|
162
|
+
workspaceId: d,
|
|
163
|
+
ruleId: z.id
|
|
164
|
+
}) })] })
|
|
165
|
+
]
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
//#endregion
|
|
169
|
+
export { j as AutomationAutomationRuleDetailPagePage };
|
|
170
|
+
|
|
171
|
+
//# sourceMappingURL=AutomationAutomationRuleDetailPagePage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AutomationAutomationRuleDetailPagePage.js","names":[],"sources":["../../../src/planmagnet/pages/AutomationAutomationRuleDetailPagePage.tsx"],"sourcesContent":["import { useState } from 'react';\nimport { gql } from '@apollo/client';\nimport { useMutation, useQuery } from '@apollo/client/react';\nimport { Button, Card, CardContent, CardHeader, CardTitle } from '@burdenoff/fe-libs/ui';\nimport { Bot, History, Save } from 'lucide-react';\nimport { useEntityId } from '../hooks/useEntityId';\nimport { usePlanMagnet } from '../providers/PlanMagnetProvider';\nimport { throwOnError } from '../utils/mutationResult';\nimport { ErrorLine } from '../controls/ConfirmButton';\nimport {\n AUTOMATION_RULE_QUERIES,\n AutomationRuleDeleteButton,\n AutomationRuleStatusSwitch,\n RunAutomationRuleDialog,\n} from '../controls/AutomationRuleControls';\nimport { AutomationExecutionsPanel } from '../automation/AutomationExecutionsPanel';\nimport {\n AutomationRuleFields,\n type AutomationRuleFormState,\n} from '../automation/AutomationRuleFields';\nimport {\n actionsFromApi,\n actionsToApi,\n conditionsFromApi,\n conditionsToApi,\n type TriggerType,\n} from '../automation/automationRuleTypes';\n\nconst GET_RULE = gql`\n query GetAutomationRule($id: ID!) {\n planmagnetAutomationRule(id: $id) {\n id\n name\n description\n status\n triggerType\n conditions\n actions\n executionCount\n lastExecutedAt\n projectId\n project {\n id\n name\n }\n }\n }\n`;\n\nconst UPDATE = gql`\n mutation UpdateAutomationRule($id: ID!, $input: PlanmagnetUpdateAutomationRuleInput!) {\n planmagnetUpdateAutomationRule(id: $id, input: $input) {\n id\n name\n description\n triggerType\n conditions\n actions\n }\n }\n`;\n\ninterface RuleDetail {\n id: string;\n name: string;\n description: string | null;\n status: string;\n triggerType: string;\n conditions: unknown;\n actions: unknown;\n executionCount: number;\n lastExecutedAt: string | null;\n projectId: string | null;\n project: { id: string; name: string } | null;\n}\n\nfunction toForm(rule: RuleDetail): AutomationRuleFormState {\n return {\n name: rule.name,\n description: rule.description ?? '',\n projectId: rule.projectId ?? '',\n triggerType: rule.triggerType as TriggerType,\n conditions: conditionsFromApi(rule.conditions),\n actions: actionsFromApi(rule.actions),\n };\n}\n\nexport function AutomationAutomationRuleDetailPagePage() {\n const ruleId = useEntityId();\n const { workspaceId } = usePlanMagnet();\n const { data, loading, error } = useQuery<{ planmagnetAutomationRule: RuleDetail | null }>(\n GET_RULE,\n {\n variables: { id: ruleId ?? '' },\n skip: !ruleId,\n fetchPolicy: 'cache-and-network',\n }\n );\n const [update, { loading: saving }] = useMutation(UPDATE, {\n refetchQueries: AUTOMATION_RULE_QUERIES,\n });\n const [saveError, setSaveError] = useState<string | null>(null);\n const [saved, setSaved] = useState(false);\n\n const rule = data?.planmagnetAutomationRule ?? null;\n const [form, setForm] = useState<AutomationRuleFormState | null>(null);\n const [seededFor, setSeededFor] = useState<string | null>(null);\n\n // The form tracks the loaded rule; a later refetch (status toggle, run now) must not stomp in-progress edits,\n // so this only seeds the form the first time the rule arrives — adjusted during render (React's documented\n // pattern for deriving state from a prop/query change), not in an effect, so it takes effect on the very\n // render the rule shows up rather than one render late.\n if (rule && seededFor !== rule.id) {\n setSeededFor(rule.id);\n setForm(toForm(rule));\n }\n\n if (!ruleId)\n return (\n <div className=\"p-6 text-muted-foreground\">No rule selected. Open one from the list.</div>\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-destructive\">\n Automation rule could not be loaded: {error.message}\n </div>\n );\n if (!rule || !form)\n return <div className=\"p-6 text-muted-foreground\">Automation rule not found.</div>;\n\n const handleSave = async () => {\n setSaveError(null);\n setSaved(false);\n const initial = toForm(rule);\n const input: Record<string, unknown> = {};\n if (form.name.trim() !== initial.name) input.name = form.name.trim();\n if (form.description.trim() !== initial.description.trim())\n input.description = form.description.trim() || null;\n if (form.triggerType !== initial.triggerType) input.triggerType = form.triggerType;\n const conditions = conditionsToApi(form.conditions);\n if (\n JSON.stringify(conditions ?? null) !==\n JSON.stringify(conditionsToApi(initial.conditions) ?? null)\n )\n input.conditions = conditions ?? null;\n const actions = actionsToApi(form.actions);\n if (JSON.stringify(actions) !== JSON.stringify(actionsToApi(initial.actions)))\n input.actions = actions;\n if (Object.keys(input).length === 0) {\n setSaved(true);\n return;\n }\n try {\n await throwOnError(update({ variables: { id: rule.id, input } }));\n setSaved(true);\n } catch (e) {\n setSaveError(e instanceof Error ? e.message : 'The rule could not be saved.');\n }\n };\n\n return (\n <div className=\"space-y-6 p-6 max-w-3xl\">\n <div className=\"flex flex-wrap items-start justify-between gap-3\">\n <div>\n <h1 className=\"text-2xl font-semibold\">{rule.name}</h1>\n <p className=\"text-sm text-muted-foreground\">{rule.project?.name ?? 'Unknown project'}</p>\n </div>\n <div className=\"flex flex-col items-end gap-2\">\n <div className=\"flex items-center gap-2\">\n <RunAutomationRuleDialog ruleId={rule.id} projectId={rule.projectId ?? undefined} />\n <AutomationRuleStatusSwitch ruleId={rule.id} status={rule.status} />\n <AutomationRuleDeleteButton ruleId={rule.id} name={rule.name} />\n </div>\n </div>\n </div>\n\n {saveError && <ErrorLine message={saveError} />}\n {saved && !saveError && <p className=\"text-sm text-muted-foreground\">Saved.</p>}\n\n <Card>\n <CardHeader>\n <CardTitle className=\"flex items-center gap-2\">\n <Bot className=\"h-4 w-4\" />\n Rule details\n </CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-4\">\n <AutomationRuleFields\n form={form}\n onChange={(next) => {\n setForm(next);\n setSaved(false);\n }}\n projectLocked\n />\n <div className=\"flex justify-end\">\n <Button\n size=\"sm\"\n onClick={() => void handleSave()}\n disabled={saving}\n data-testid=\"automation-save\"\n >\n <Save className=\"mr-1 h-4 w-4\" />\n {saving ? 'Saving…' : 'Save changes'}\n </Button>\n </div>\n </CardContent>\n </Card>\n\n <Card>\n <CardHeader>\n <CardTitle className=\"flex items-center gap-2\">\n <History className=\"h-4 w-4\" />\n Recent executions\n </CardTitle>\n </CardHeader>\n <CardContent>\n <AutomationExecutionsPanel workspaceId={workspaceId} ruleId={rule.id} />\n </CardContent>\n </Card>\n </div>\n );\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AutomationAutomationRulesPagePage.d.ts","sourceRoot":"","sources":["../../../src/planmagnet/pages/AutomationAutomationRulesPagePage.tsx"],"names":[],"mappings":"AAkFA,wBAAgB,iCAAiC,4CAmMhD"}
|
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
import { usePlanMagnet as e, usePlanMagnetNavigate as t } from "../providers/PlanMagnetProvider.js";
|
|
2
|
+
import { ProjectSelect as n } from "../controls/Pickers.js";
|
|
3
|
+
import { AutomationRuleDeleteButton as r, AutomationRuleStatusSwitch as i } from "../controls/AutomationRuleControls.js";
|
|
4
|
+
import { RULE_STATUSES as a, TRIGGER_TYPES as o, TRIGGER_TYPE_LABEL as s, triggerTypeLabel as c } from "../automation/automationRuleTypes.js";
|
|
5
|
+
import { ROW_LINK_CLASS as l, detailPath as u, rowLinkProps as d, stopRowActivation as f } from "../utils/rowNavigation.js";
|
|
6
|
+
import { useDeferredValue as p, useState as m } from "react";
|
|
7
|
+
import { Bot as h, Plus as g, Search as _ } from "lucide-react";
|
|
8
|
+
import { gql as v } from "@apollo/client";
|
|
9
|
+
import { useQuery as y } from "@apollo/client/react";
|
|
10
|
+
import { jsx as b, jsxs as x } from "react/jsx-runtime";
|
|
11
|
+
import { Badge as S, Button as C, EmptyState as w, Input as T } from "@burdenoff/fe-libs/ui";
|
|
12
|
+
//#region src/planmagnet/pages/AutomationAutomationRulesPagePage.tsx
|
|
13
|
+
var E = 50, D = v`
|
|
14
|
+
query AutomationRulesList(
|
|
15
|
+
$workspaceId: ID!
|
|
16
|
+
$filter: PlanmagnetAutomationRuleFilter
|
|
17
|
+
$pagination: PlanmagnetPaginationInput
|
|
18
|
+
) {
|
|
19
|
+
planmagnetAutomationRules(workspaceId: $workspaceId, filter: $filter, pagination: $pagination) {
|
|
20
|
+
totalCount
|
|
21
|
+
pageInfo {
|
|
22
|
+
hasNextPage
|
|
23
|
+
endCursor
|
|
24
|
+
}
|
|
25
|
+
items {
|
|
26
|
+
id
|
|
27
|
+
name
|
|
28
|
+
description
|
|
29
|
+
status
|
|
30
|
+
triggerType
|
|
31
|
+
actions
|
|
32
|
+
executionCount
|
|
33
|
+
lastExecutedAt
|
|
34
|
+
projectId
|
|
35
|
+
project {
|
|
36
|
+
id
|
|
37
|
+
name
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
`, O = ["ALL", ...a];
|
|
43
|
+
function k(e) {
|
|
44
|
+
return Array.isArray(e) ? e.length : 0;
|
|
45
|
+
}
|
|
46
|
+
function A() {
|
|
47
|
+
let { workspaceId: a } = e(), v = t(), [A, j] = m(""), [M, N] = m("ALL"), [P, F] = m("ALL"), [I, L] = m(""), [R, z] = m(!1), B = p(A.trim()), V = {
|
|
48
|
+
...B ? { search: B } : {},
|
|
49
|
+
...M === "ALL" ? {} : { status: M },
|
|
50
|
+
...P === "ALL" ? {} : { triggerType: P },
|
|
51
|
+
...I ? { projectId: I } : {}
|
|
52
|
+
}, { data: H, loading: U, error: W, fetchMore: G } = y(D, {
|
|
53
|
+
variables: {
|
|
54
|
+
workspaceId: a ?? "",
|
|
55
|
+
filter: V,
|
|
56
|
+
pagination: { first: E }
|
|
57
|
+
},
|
|
58
|
+
skip: !a,
|
|
59
|
+
fetchPolicy: "cache-and-network"
|
|
60
|
+
}), K = H?.planmagnetAutomationRules, q = K?.items ?? [], J = async () => {
|
|
61
|
+
let e = K?.pageInfo.endCursor;
|
|
62
|
+
if (e) {
|
|
63
|
+
z(!0);
|
|
64
|
+
try {
|
|
65
|
+
await G({
|
|
66
|
+
variables: { pagination: {
|
|
67
|
+
first: E,
|
|
68
|
+
after: e
|
|
69
|
+
} },
|
|
70
|
+
updateQuery: (e, { fetchMoreResult: t }) => ({ planmagnetAutomationRules: {
|
|
71
|
+
...t.planmagnetAutomationRules,
|
|
72
|
+
items: [...e.planmagnetAutomationRules.items, ...t.planmagnetAutomationRules.items]
|
|
73
|
+
} })
|
|
74
|
+
});
|
|
75
|
+
} finally {
|
|
76
|
+
z(!1);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
return /* @__PURE__ */ x("div", {
|
|
81
|
+
className: "space-y-6 p-6",
|
|
82
|
+
"data-testid": "automation-rules-page",
|
|
83
|
+
children: [
|
|
84
|
+
/* @__PURE__ */ x("div", {
|
|
85
|
+
className: "flex flex-wrap items-center justify-between gap-3",
|
|
86
|
+
children: [/* @__PURE__ */ x("div", { children: [/* @__PURE__ */ b("h1", {
|
|
87
|
+
className: "text-2xl font-semibold",
|
|
88
|
+
children: "Automation rules"
|
|
89
|
+
}), /* @__PURE__ */ b("p", {
|
|
90
|
+
className: "text-sm text-muted-foreground",
|
|
91
|
+
children: K ? `${K.totalCount} rule${K.totalCount === 1 ? "" : "s"}` : "Trigger, condition and action rules that run against work items"
|
|
92
|
+
})] }), /* @__PURE__ */ x(C, {
|
|
93
|
+
size: "sm",
|
|
94
|
+
onClick: () => v("/automation/create-automation-rule-page"),
|
|
95
|
+
"data-testid": "automation-new",
|
|
96
|
+
children: [/* @__PURE__ */ b(g, { className: "mr-1 h-4 w-4" }), "New rule"]
|
|
97
|
+
})]
|
|
98
|
+
}),
|
|
99
|
+
/* @__PURE__ */ x("div", {
|
|
100
|
+
className: "flex flex-wrap items-center gap-3",
|
|
101
|
+
children: [
|
|
102
|
+
/* @__PURE__ */ x("div", {
|
|
103
|
+
className: "relative w-full max-w-sm",
|
|
104
|
+
children: [/* @__PURE__ */ b(_, { className: "absolute left-2.5 top-2.5 h-4 w-4 text-muted-foreground" }), /* @__PURE__ */ b(T, {
|
|
105
|
+
"aria-label": "Search automation rules",
|
|
106
|
+
placeholder: "Search by name or description",
|
|
107
|
+
className: "pl-8",
|
|
108
|
+
value: A,
|
|
109
|
+
onChange: (e) => j(e.target.value)
|
|
110
|
+
})]
|
|
111
|
+
}),
|
|
112
|
+
/* @__PURE__ */ x("select", {
|
|
113
|
+
"aria-label": "Filter by trigger",
|
|
114
|
+
className: "rounded-md border border-input bg-background px-2 py-1.5 text-sm",
|
|
115
|
+
value: P,
|
|
116
|
+
onChange: (e) => F(e.target.value),
|
|
117
|
+
children: [/* @__PURE__ */ b("option", {
|
|
118
|
+
value: "ALL",
|
|
119
|
+
children: "Any trigger"
|
|
120
|
+
}), o.map((e) => /* @__PURE__ */ b("option", {
|
|
121
|
+
value: e,
|
|
122
|
+
children: s[e]
|
|
123
|
+
}, e))]
|
|
124
|
+
}),
|
|
125
|
+
/* @__PURE__ */ b("div", {
|
|
126
|
+
className: "w-48",
|
|
127
|
+
children: /* @__PURE__ */ b(n, {
|
|
128
|
+
id: "automation-filter-project",
|
|
129
|
+
value: I,
|
|
130
|
+
onChange: L,
|
|
131
|
+
noneLabel: "Any project"
|
|
132
|
+
})
|
|
133
|
+
})
|
|
134
|
+
]
|
|
135
|
+
}),
|
|
136
|
+
/* @__PURE__ */ b("div", {
|
|
137
|
+
className: "flex gap-1",
|
|
138
|
+
role: "group",
|
|
139
|
+
"aria-label": "Filter by status",
|
|
140
|
+
children: O.map((e) => /* @__PURE__ */ b("button", {
|
|
141
|
+
type: "button",
|
|
142
|
+
"aria-pressed": M === e,
|
|
143
|
+
onClick: () => N(e),
|
|
144
|
+
className: `px-3 py-1.5 text-sm rounded-md capitalize ${M === e ? "bg-primary text-primary-foreground" : "text-muted-foreground hover:bg-muted"}`,
|
|
145
|
+
children: e === "ALL" ? "All" : e.toLowerCase()
|
|
146
|
+
}, e))
|
|
147
|
+
}),
|
|
148
|
+
W && /* @__PURE__ */ x("p", {
|
|
149
|
+
role: "alert",
|
|
150
|
+
className: "text-sm text-destructive",
|
|
151
|
+
children: ["Automation rules could not be loaded: ", W.message]
|
|
152
|
+
}),
|
|
153
|
+
U && !H && /* @__PURE__ */ b("p", {
|
|
154
|
+
className: "text-sm text-muted-foreground",
|
|
155
|
+
children: "Loading automation rules…"
|
|
156
|
+
}),
|
|
157
|
+
K && q.length === 0 && /* @__PURE__ */ b(w, {
|
|
158
|
+
icon: /* @__PURE__ */ b(h, { className: "h-8 w-8 text-muted-foreground" }),
|
|
159
|
+
title: B || M !== "ALL" || P !== "ALL" || I ? "No rules match" : "No automation rules yet",
|
|
160
|
+
description: "Rules watch for an event on a project's work items and act automatically — assign, label, or move status.",
|
|
161
|
+
action: B || M !== "ALL" || P !== "ALL" || I ? void 0 : /* @__PURE__ */ x(C, {
|
|
162
|
+
size: "sm",
|
|
163
|
+
onClick: () => v("/automation/create-automation-rule-page"),
|
|
164
|
+
children: [/* @__PURE__ */ b(g, { className: "mr-1 h-4 w-4" }), "New rule"]
|
|
165
|
+
})
|
|
166
|
+
}),
|
|
167
|
+
/* @__PURE__ */ b("ul", {
|
|
168
|
+
className: "space-y-2",
|
|
169
|
+
children: q.map((e) => /* @__PURE__ */ b("li", { children: /* @__PURE__ */ x("div", {
|
|
170
|
+
...d(() => v(u("/automation/automation-rule-detail-page", e.id)), e.name),
|
|
171
|
+
"data-testid": "automation-rule-row",
|
|
172
|
+
className: `flex flex-wrap items-center justify-between gap-3 rounded-md border p-3 ${l}`,
|
|
173
|
+
children: [/* @__PURE__ */ x("div", {
|
|
174
|
+
className: "min-w-0 flex-1",
|
|
175
|
+
children: [
|
|
176
|
+
/* @__PURE__ */ x("div", {
|
|
177
|
+
className: "flex flex-wrap items-center gap-2",
|
|
178
|
+
children: [/* @__PURE__ */ b("span", {
|
|
179
|
+
className: "truncate text-sm font-medium",
|
|
180
|
+
children: e.name
|
|
181
|
+
}), /* @__PURE__ */ b(S, {
|
|
182
|
+
variant: "outline",
|
|
183
|
+
children: c(e.triggerType)
|
|
184
|
+
})]
|
|
185
|
+
}),
|
|
186
|
+
/* @__PURE__ */ x("p", {
|
|
187
|
+
className: "mt-0.5 truncate text-xs text-muted-foreground",
|
|
188
|
+
children: [
|
|
189
|
+
e.project?.name ?? "Unknown project",
|
|
190
|
+
" · ",
|
|
191
|
+
k(e.actions),
|
|
192
|
+
" action",
|
|
193
|
+
k(e.actions) === 1 ? "" : "s",
|
|
194
|
+
" · run ",
|
|
195
|
+
e.executionCount,
|
|
196
|
+
" time",
|
|
197
|
+
e.executionCount === 1 ? "" : "s",
|
|
198
|
+
e.lastExecutedAt ? ` · last ${new Date(e.lastExecutedAt).toLocaleString()}` : ""
|
|
199
|
+
]
|
|
200
|
+
}),
|
|
201
|
+
e.description && /* @__PURE__ */ b("p", {
|
|
202
|
+
className: "mt-0.5 truncate text-xs text-muted-foreground",
|
|
203
|
+
children: e.description
|
|
204
|
+
})
|
|
205
|
+
]
|
|
206
|
+
}), /* @__PURE__ */ x("div", {
|
|
207
|
+
className: "flex items-center gap-3",
|
|
208
|
+
onClick: f,
|
|
209
|
+
children: [/* @__PURE__ */ b(i, {
|
|
210
|
+
ruleId: e.id,
|
|
211
|
+
status: e.status
|
|
212
|
+
}), /* @__PURE__ */ b(r, {
|
|
213
|
+
ruleId: e.id,
|
|
214
|
+
name: e.name
|
|
215
|
+
})]
|
|
216
|
+
})]
|
|
217
|
+
}) }, e.id))
|
|
218
|
+
}),
|
|
219
|
+
K?.pageInfo.hasNextPage && /* @__PURE__ */ b(C, {
|
|
220
|
+
size: "sm",
|
|
221
|
+
variant: "outline",
|
|
222
|
+
onClick: () => void J(),
|
|
223
|
+
disabled: R,
|
|
224
|
+
children: R ? "Loading…" : `Show more (${q.length} of ${K.totalCount})`
|
|
225
|
+
})
|
|
226
|
+
]
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
//#endregion
|
|
230
|
+
export { A as AutomationAutomationRulesPagePage };
|
|
231
|
+
|
|
232
|
+
//# sourceMappingURL=AutomationAutomationRulesPagePage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AutomationAutomationRulesPagePage.js","names":[],"sources":["../../../src/planmagnet/pages/AutomationAutomationRulesPagePage.tsx"],"sourcesContent":["import { useDeferredValue, useState } from 'react';\nimport { gql } from '@apollo/client';\nimport { useQuery } from '@apollo/client/react';\nimport { Badge, Button, EmptyState, Input } from '@burdenoff/fe-libs/ui';\nimport { Bot, Plus, Search } from 'lucide-react';\nimport { usePlanMagnet, usePlanMagnetNavigate } from '../providers/PlanMagnetProvider';\nimport { ProjectSelect } from '../controls/Pickers';\nimport {\n AutomationRuleStatusSwitch,\n AutomationRuleDeleteButton,\n} from '../controls/AutomationRuleControls';\nimport {\n rowLinkProps,\n detailPath,\n stopRowActivation,\n ROW_LINK_CLASS,\n} from '../utils/rowNavigation';\nimport {\n RULE_STATUSES,\n TRIGGER_TYPES,\n TRIGGER_TYPE_LABEL,\n triggerTypeLabel,\n} from '../automation/automationRuleTypes';\n\n/**\n * Automation rules browse surface (BOFF-8047, capability register \"Automation rules\": model/API/authz were\n * already real and prod-verified — `planmagnetAutomationRules`/Create/Update/Delete/Toggle/Execute — gate 3\n * (UI) was the only gap; \"no UI anywhere\" until now.\n */\n\nconst PAGE = 50;\n\nconst RULES = gql`\n query AutomationRulesList(\n $workspaceId: ID!\n $filter: PlanmagnetAutomationRuleFilter\n $pagination: PlanmagnetPaginationInput\n ) {\n planmagnetAutomationRules(workspaceId: $workspaceId, filter: $filter, pagination: $pagination) {\n totalCount\n pageInfo {\n hasNextPage\n endCursor\n }\n items {\n id\n name\n description\n status\n triggerType\n actions\n executionCount\n lastExecutedAt\n projectId\n project {\n id\n name\n }\n }\n }\n }\n`;\n\ninterface RuleRow {\n id: string;\n name: string;\n description: string | null;\n status: string;\n triggerType: string;\n actions: unknown;\n executionCount: number;\n lastExecutedAt: string | null;\n projectId: string | null;\n project: { id: string; name: string } | null;\n}\n\nconst STATUS_FILTERS = ['ALL', ...RULE_STATUSES] as const;\n\nfunction actionCount(actions: unknown): number {\n return Array.isArray(actions) ? actions.length : 0;\n}\n\nexport function AutomationAutomationRulesPagePage() {\n const { workspaceId } = usePlanMagnet();\n const navigate = usePlanMagnetNavigate();\n const [search, setSearch] = useState('');\n const [status, setStatus] = useState<(typeof STATUS_FILTERS)[number]>('ALL');\n const [triggerType, setTriggerType] = useState('ALL');\n const [projectId, setProjectId] = useState('');\n const [loadingMore, setLoadingMore] = useState(false);\n const term = useDeferredValue(search.trim());\n\n const filter = {\n ...(term ? { search: term } : {}),\n ...(status !== 'ALL' ? { status } : {}),\n ...(triggerType !== 'ALL' ? { triggerType } : {}),\n ...(projectId ? { projectId } : {}),\n };\n\n const { data, loading, error, fetchMore } = useQuery<{\n planmagnetAutomationRules: {\n totalCount: number;\n pageInfo: { hasNextPage: boolean; endCursor: string | null };\n items: RuleRow[];\n };\n }>(RULES, {\n variables: { workspaceId: workspaceId ?? '', filter, pagination: { first: PAGE } },\n skip: !workspaceId,\n fetchPolicy: 'cache-and-network',\n });\n\n const list = data?.planmagnetAutomationRules;\n const rules = list?.items ?? [];\n\n const loadMore = async () => {\n const after = list?.pageInfo.endCursor;\n if (!after) return;\n setLoadingMore(true);\n try {\n await fetchMore({\n variables: { pagination: { first: PAGE, after } },\n updateQuery: (prev, { fetchMoreResult }) => ({\n planmagnetAutomationRules: {\n ...fetchMoreResult.planmagnetAutomationRules,\n items: [\n ...prev.planmagnetAutomationRules.items,\n ...fetchMoreResult.planmagnetAutomationRules.items,\n ],\n },\n }),\n });\n } finally {\n setLoadingMore(false);\n }\n };\n\n return (\n <div className=\"space-y-6 p-6\" data-testid=\"automation-rules-page\">\n <div className=\"flex flex-wrap items-center justify-between gap-3\">\n <div>\n <h1 className=\"text-2xl font-semibold\">Automation rules</h1>\n <p className=\"text-sm text-muted-foreground\">\n {list\n ? `${list.totalCount} rule${list.totalCount === 1 ? '' : 's'}`\n : 'Trigger, condition and action rules that run against work items'}\n </p>\n </div>\n <Button\n size=\"sm\"\n onClick={() => navigate('/automation/create-automation-rule-page')}\n data-testid=\"automation-new\"\n >\n <Plus className=\"mr-1 h-4 w-4\" />\n New rule\n </Button>\n </div>\n\n <div className=\"flex flex-wrap items-center gap-3\">\n <div className=\"relative w-full max-w-sm\">\n <Search className=\"absolute left-2.5 top-2.5 h-4 w-4 text-muted-foreground\" />\n <Input\n aria-label=\"Search automation rules\"\n placeholder=\"Search by name or description\"\n className=\"pl-8\"\n value={search}\n onChange={(e) => setSearch(e.target.value)}\n />\n </div>\n <select\n aria-label=\"Filter by trigger\"\n className=\"rounded-md border border-input bg-background px-2 py-1.5 text-sm\"\n value={triggerType}\n onChange={(e) => setTriggerType(e.target.value)}\n >\n <option value=\"ALL\">Any trigger</option>\n {TRIGGER_TYPES.map((t) => (\n <option key={t} value={t}>\n {TRIGGER_TYPE_LABEL[t]}\n </option>\n ))}\n </select>\n <div className=\"w-48\">\n <ProjectSelect\n id=\"automation-filter-project\"\n value={projectId}\n onChange={setProjectId}\n noneLabel=\"Any project\"\n />\n </div>\n </div>\n <div className=\"flex gap-1\" role=\"group\" aria-label=\"Filter by status\">\n {STATUS_FILTERS.map((s) => (\n <button\n key={s}\n type=\"button\"\n aria-pressed={status === s}\n onClick={() => setStatus(s)}\n className={`px-3 py-1.5 text-sm rounded-md capitalize ${status === s ? 'bg-primary text-primary-foreground' : 'text-muted-foreground hover:bg-muted'}`}\n >\n {s === 'ALL' ? 'All' : s.toLowerCase()}\n </button>\n ))}\n </div>\n\n {error && (\n <p role=\"alert\" className=\"text-sm text-destructive\">\n Automation rules could not be loaded: {error.message}\n </p>\n )}\n {loading && !data && (\n <p className=\"text-sm text-muted-foreground\">Loading automation rules…</p>\n )}\n {list && rules.length === 0 && (\n <EmptyState\n icon={<Bot className=\"h-8 w-8 text-muted-foreground\" />}\n title={\n term || status !== 'ALL' || triggerType !== 'ALL' || projectId\n ? 'No rules match'\n : 'No automation rules yet'\n }\n description=\"Rules watch for an event on a project's work items and act automatically — assign, label, or move status.\"\n action={\n !(term || status !== 'ALL' || triggerType !== 'ALL' || projectId) ? (\n <Button size=\"sm\" onClick={() => navigate('/automation/create-automation-rule-page')}>\n <Plus className=\"mr-1 h-4 w-4\" />\n New rule\n </Button>\n ) : undefined\n }\n />\n )}\n\n <ul className=\"space-y-2\">\n {rules.map((rule) => (\n <li key={rule.id}>\n <div\n {...rowLinkProps(\n () => navigate(detailPath('/automation/automation-rule-detail-page', rule.id)),\n rule.name\n )}\n data-testid=\"automation-rule-row\"\n className={`flex flex-wrap items-center justify-between gap-3 rounded-md border p-3 ${ROW_LINK_CLASS}`}\n >\n <div className=\"min-w-0 flex-1\">\n <div className=\"flex flex-wrap items-center gap-2\">\n <span className=\"truncate text-sm font-medium\">{rule.name}</span>\n <Badge variant=\"outline\">{triggerTypeLabel(rule.triggerType)}</Badge>\n </div>\n <p className=\"mt-0.5 truncate text-xs text-muted-foreground\">\n {rule.project?.name ?? 'Unknown project'} · {actionCount(rule.actions)} action\n {actionCount(rule.actions) === 1 ? '' : 's'} · run {rule.executionCount} time\n {rule.executionCount === 1 ? '' : 's'}\n {rule.lastExecutedAt\n ? ` · last ${new Date(rule.lastExecutedAt).toLocaleString()}`\n : ''}\n </p>\n {rule.description && (\n <p className=\"mt-0.5 truncate text-xs text-muted-foreground\">\n {rule.description}\n </p>\n )}\n </div>\n <div className=\"flex items-center gap-3\" onClick={stopRowActivation}>\n <AutomationRuleStatusSwitch ruleId={rule.id} status={rule.status} />\n <AutomationRuleDeleteButton ruleId={rule.id} name={rule.name} />\n </div>\n </div>\n </li>\n ))}\n </ul>\n {list?.pageInfo.hasNextPage && (\n <Button size=\"sm\" variant=\"outline\" onClick={() => void loadMore()} disabled={loadingMore}>\n {loadingMore ? 'Loading…' : `Show more (${rules.length} of ${list.totalCount})`}\n </Button>\n )}\n </div>\n );\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AutomationCreateAutomationRulePagePage.d.ts","sourceRoot":"","sources":["../../../src/planmagnet/pages/AutomationCreateAutomationRulePagePage.tsx"],"names":[],"mappings":"AAgCA,wBAAgB,sCAAsC,4CA2FrD"}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { usePlanMagnet as e, usePlanMagnetNavigate as t } from "../providers/PlanMagnetProvider.js";
|
|
2
|
+
import { throwOnError as n } from "../utils/mutationResult.js";
|
|
3
|
+
import { AUTOMATION_RULE_QUERIES as r } from "../controls/AutomationRuleControls.js";
|
|
4
|
+
import { actionsToApi as i, conditionsToApi as a } from "../automation/automationRuleTypes.js";
|
|
5
|
+
import { AutomationRuleFields as o } from "../automation/AutomationRuleFields.js";
|
|
6
|
+
import { detailPath as s } from "../utils/rowNavigation.js";
|
|
7
|
+
import { useState as c } from "react";
|
|
8
|
+
import { Bot as l, Save as u, X as d } from "lucide-react";
|
|
9
|
+
import { gql as f } from "@apollo/client";
|
|
10
|
+
import { useMutation as p } from "@apollo/client/react";
|
|
11
|
+
import { jsx as m, jsxs as h } from "react/jsx-runtime";
|
|
12
|
+
import { Button as g, Card as _, CardContent as v, CardHeader as y, CardTitle as b } from "@burdenoff/fe-libs/ui";
|
|
13
|
+
//#region src/planmagnet/pages/AutomationCreateAutomationRulePagePage.tsx
|
|
14
|
+
var x = f`
|
|
15
|
+
mutation CreateAutomationRule($input: PlanmagnetCreateAutomationRuleInput!) {
|
|
16
|
+
planmagnetCreateAutomationRule(input: $input) {
|
|
17
|
+
id
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
`, S = {
|
|
21
|
+
name: "",
|
|
22
|
+
description: "",
|
|
23
|
+
projectId: "",
|
|
24
|
+
triggerType: "WORK_ITEM_CREATED",
|
|
25
|
+
conditions: [],
|
|
26
|
+
actions: []
|
|
27
|
+
};
|
|
28
|
+
function C() {
|
|
29
|
+
let { workspaceId: f } = e(), C = t(), [w, T] = c(S), [E, D] = c(null), [O, { loading: k }] = p(x, { refetchQueries: r }), A = w.name.trim() !== "" && w.projectId !== "" && !k, j = async () => {
|
|
30
|
+
if (!(!A || !f)) {
|
|
31
|
+
D(null);
|
|
32
|
+
try {
|
|
33
|
+
let e = (await n(O({ variables: { input: {
|
|
34
|
+
projectId: w.projectId,
|
|
35
|
+
name: w.name.trim(),
|
|
36
|
+
description: w.description.trim() || void 0,
|
|
37
|
+
triggerType: w.triggerType,
|
|
38
|
+
triggerConfig: {},
|
|
39
|
+
conditions: a(w.conditions),
|
|
40
|
+
actions: i(w.actions)
|
|
41
|
+
} } }))).data?.planmagnetCreateAutomationRule.id;
|
|
42
|
+
C(e ? s("/automation/automation-rule-detail-page", e) : "/automation/automation-rules-page");
|
|
43
|
+
} catch (e) {
|
|
44
|
+
D(e instanceof Error ? e.message : "The rule could not be created.");
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
return /* @__PURE__ */ h("div", {
|
|
49
|
+
className: "space-y-6 p-6 max-w-3xl",
|
|
50
|
+
children: [
|
|
51
|
+
/* @__PURE__ */ h("div", {
|
|
52
|
+
className: "flex items-center justify-between",
|
|
53
|
+
children: [/* @__PURE__ */ h("div", { children: [/* @__PURE__ */ m("h1", {
|
|
54
|
+
className: "text-2xl font-semibold",
|
|
55
|
+
children: "New automation rule"
|
|
56
|
+
}), /* @__PURE__ */ m("p", {
|
|
57
|
+
className: "text-sm text-muted-foreground",
|
|
58
|
+
children: "Runs its actions when the trigger fires and every condition matches."
|
|
59
|
+
})] }), /* @__PURE__ */ h("div", {
|
|
60
|
+
className: "flex gap-2",
|
|
61
|
+
children: [/* @__PURE__ */ h(g, {
|
|
62
|
+
variant: "outline",
|
|
63
|
+
size: "sm",
|
|
64
|
+
onClick: () => C("/automation/automation-rules-page"),
|
|
65
|
+
children: [/* @__PURE__ */ m(d, { className: "mr-1 h-4 w-4" }), "Cancel"]
|
|
66
|
+
}), /* @__PURE__ */ h(g, {
|
|
67
|
+
size: "sm",
|
|
68
|
+
onClick: () => void j(),
|
|
69
|
+
disabled: !A,
|
|
70
|
+
"data-testid": "automation-create-submit",
|
|
71
|
+
children: [/* @__PURE__ */ m(u, { className: "mr-1 h-4 w-4" }), k ? "Creating…" : "Create rule"]
|
|
72
|
+
})]
|
|
73
|
+
})]
|
|
74
|
+
}),
|
|
75
|
+
E && /* @__PURE__ */ m("div", {
|
|
76
|
+
role: "alert",
|
|
77
|
+
className: "p-3 bg-destructive/10 text-destructive rounded-md text-sm",
|
|
78
|
+
children: E
|
|
79
|
+
}),
|
|
80
|
+
/* @__PURE__ */ h(_, { children: [/* @__PURE__ */ m(y, { children: /* @__PURE__ */ h(b, {
|
|
81
|
+
className: "flex items-center gap-2",
|
|
82
|
+
children: [/* @__PURE__ */ m(l, { className: "h-4 w-4" }), "Rule details"]
|
|
83
|
+
}) }), /* @__PURE__ */ m(v, { children: /* @__PURE__ */ m(o, {
|
|
84
|
+
form: w,
|
|
85
|
+
onChange: T
|
|
86
|
+
}) })] })
|
|
87
|
+
]
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
//#endregion
|
|
91
|
+
export { C as AutomationCreateAutomationRulePagePage };
|
|
92
|
+
|
|
93
|
+
//# sourceMappingURL=AutomationCreateAutomationRulePagePage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AutomationCreateAutomationRulePagePage.js","names":[],"sources":["../../../src/planmagnet/pages/AutomationCreateAutomationRulePagePage.tsx"],"sourcesContent":["import { useState } from 'react';\nimport { gql } from '@apollo/client';\nimport { useMutation } from '@apollo/client/react';\nimport { Button, Card, CardContent, CardHeader, CardTitle } from '@burdenoff/fe-libs/ui';\nimport { Bot, Save, X } from 'lucide-react';\nimport { usePlanMagnet, usePlanMagnetNavigate } from '../providers/PlanMagnetProvider';\nimport { throwOnError } from '../utils/mutationResult';\nimport { detailPath } from '../utils/rowNavigation';\nimport {\n AutomationRuleFields,\n type AutomationRuleFormState,\n} from '../automation/AutomationRuleFields';\nimport { actionsToApi, conditionsToApi } from '../automation/automationRuleTypes';\nimport { AUTOMATION_RULE_QUERIES } from '../controls/AutomationRuleControls';\n\nconst CREATE = gql`\n mutation CreateAutomationRule($input: PlanmagnetCreateAutomationRuleInput!) {\n planmagnetCreateAutomationRule(input: $input) {\n id\n }\n }\n`;\n\nconst EMPTY: AutomationRuleFormState = {\n name: '',\n description: '',\n projectId: '',\n triggerType: 'WORK_ITEM_CREATED',\n conditions: [],\n actions: [],\n};\n\nexport function AutomationCreateAutomationRulePagePage() {\n const { workspaceId } = usePlanMagnet();\n const navigate = usePlanMagnetNavigate();\n const [form, setForm] = useState<AutomationRuleFormState>(EMPTY);\n const [error, setError] = useState<string | null>(null);\n const [create, { loading }] = useMutation<{ planmagnetCreateAutomationRule: { id: string } }>(\n CREATE,\n {\n refetchQueries: AUTOMATION_RULE_QUERIES,\n }\n );\n\n const canSubmit = form.name.trim() !== '' && form.projectId !== '' && !loading;\n\n const handleCreate = async () => {\n if (!canSubmit || !workspaceId) return;\n setError(null);\n try {\n const result = await throwOnError(\n create({\n variables: {\n input: {\n projectId: form.projectId,\n name: form.name.trim(),\n description: form.description.trim() || undefined,\n triggerType: form.triggerType,\n triggerConfig: {},\n conditions: conditionsToApi(form.conditions),\n actions: actionsToApi(form.actions),\n },\n },\n })\n );\n const id = result.data?.planmagnetCreateAutomationRule.id;\n navigate(\n id\n ? detailPath('/automation/automation-rule-detail-page', id)\n : '/automation/automation-rules-page'\n );\n } catch (e) {\n setError(e instanceof Error ? e.message : 'The rule could not be created.');\n }\n };\n\n return (\n <div className=\"space-y-6 p-6 max-w-3xl\">\n <div className=\"flex items-center justify-between\">\n <div>\n <h1 className=\"text-2xl font-semibold\">New automation rule</h1>\n <p className=\"text-sm text-muted-foreground\">\n Runs its actions when the trigger fires and every condition matches.\n </p>\n </div>\n <div className=\"flex gap-2\">\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={() => navigate('/automation/automation-rules-page')}\n >\n <X className=\"mr-1 h-4 w-4\" />\n Cancel\n </Button>\n <Button\n size=\"sm\"\n onClick={() => void handleCreate()}\n disabled={!canSubmit}\n data-testid=\"automation-create-submit\"\n >\n <Save className=\"mr-1 h-4 w-4\" />\n {loading ? 'Creating…' : 'Create rule'}\n </Button>\n </div>\n </div>\n {error && (\n <div role=\"alert\" className=\"p-3 bg-destructive/10 text-destructive rounded-md text-sm\">\n {error}\n </div>\n )}\n <Card>\n <CardHeader>\n <CardTitle className=\"flex items-center gap-2\">\n <Bot className=\"h-4 w-4\" />\n Rule details\n </CardTitle>\n </CardHeader>\n <CardContent>\n <AutomationRuleFields form={form} onChange={setForm} />\n </CardContent>\n </Card>\n </div>\n );\n}\n"],"mappings":";;;;;;;;;;;;;AAeA,IAAM,IAAS,CAAG;;;;;;GAQZ,IAAiC;CACrC,MAAM;CACN,aAAa;CACb,WAAW;CACX,aAAa;CACb,YAAY,EAAE;CACd,SAAS,EAAE;CACZ;AAED,SAAgB,IAAyC;CACvD,IAAM,EAAE,mBAAgB,GAAe,EACjC,IAAW,GAAuB,EAClC,CAAC,GAAM,KAAW,EAAkC,EAAM,EAC1D,CAAC,GAAO,KAAY,EAAwB,KAAK,EACjD,CAAC,GAAQ,EAAE,gBAAa,EAC5B,GACA,EACE,gBAAgB,GACjB,CACF,EAEK,IAAY,EAAK,KAAK,MAAM,KAAK,MAAM,EAAK,cAAc,MAAM,CAAC,GAEjE,IAAe,YAAY;AAC3B,SAAC,KAAa,CAAC,IACnB;KAAS,KAAK;AACd,OAAI;IAgBF,IAAM,KAfS,MAAM,EACnB,EAAO,EACL,WAAW,EACT,OAAO;KACL,WAAW,EAAK;KAChB,MAAM,EAAK,KAAK,MAAM;KACtB,aAAa,EAAK,YAAY,MAAM,IAAI,KAAA;KACxC,aAAa,EAAK;KAClB,eAAe,EAAE;KACjB,YAAY,EAAgB,EAAK,WAAW;KAC5C,SAAS,EAAa,EAAK,QAAQ;KACpC,EACF,EACF,CAAC,CACH,EACiB,MAAM,+BAA+B;AACvD,MACE,IACI,EAAW,2CAA2C,EAAG,GACzD,oCACL;YACM,GAAG;AACV,MAAS,aAAa,QAAQ,EAAE,UAAU,iCAAiC;;;;AAI/E,QACE,kBAAC,OAAD;EAAK,WAAU;YAAf;GACE,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,MAAD;KAAI,WAAU;eAAyB;KAAwB,CAAA,EAC/D,kBAAC,KAAD;KAAG,WAAU;eAAgC;KAEzC,CAAA,CACA,EAAA,CAAA,EACN,kBAAC,OAAD;KAAK,WAAU;eAAf,CACE,kBAAC,GAAD;MACE,SAAQ;MACR,MAAK;MACL,eAAe,EAAS,oCAAoC;gBAH9D,CAKE,kBAAC,GAAD,EAAG,WAAU,gBAAiB,CAAA,EAAA,SAEvB;SACT,kBAAC,GAAD;MACE,MAAK;MACL,eAAe,KAAK,GAAc;MAClC,UAAU,CAAC;MACX,eAAY;gBAJd,CAME,kBAAC,GAAD,EAAM,WAAU,gBAAiB,CAAA,EAChC,IAAU,cAAc,cAClB;QACL;OACF;;GACL,KACC,kBAAC,OAAD;IAAK,MAAK;IAAQ,WAAU;cACzB;IACG,CAAA;GAER,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD;IAAW,WAAU;cAArB,CACE,kBAAC,GAAD,EAAK,WAAU,WAAY,CAAA,EAAA,eAEjB;OACD,CAAA,EACb,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD;IAA4B;IAAM,UAAU;IAAW,CAAA,EAC3C,CAAA,CACT,EAAA,CAAA;GACH"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DashboardDashboardPagePage.d.ts","sourceRoot":"","sources":["../../../src/planmagnet/pages/DashboardDashboardPagePage.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"DashboardDashboardPagePage.d.ts","sourceRoot":"","sources":["../../../src/planmagnet/pages/DashboardDashboardPagePage.tsx"],"names":[],"mappings":"AAkIA,wBAAgB,0BAA0B,4CAiYzC"}
|
|
@@ -102,6 +102,10 @@ var A = y`
|
|
|
102
102
|
id
|
|
103
103
|
name
|
|
104
104
|
}
|
|
105
|
+
team {
|
|
106
|
+
id
|
|
107
|
+
name
|
|
108
|
+
}
|
|
105
109
|
workItems {
|
|
106
110
|
id
|
|
107
111
|
status
|
|
@@ -197,14 +201,18 @@ function j() {
|
|
|
197
201
|
children: [/* @__PURE__ */ C("div", { children: [/* @__PURE__ */ S("p", {
|
|
198
202
|
className: "font-medium",
|
|
199
203
|
children: e.name
|
|
200
|
-
}), /* @__PURE__ */
|
|
204
|
+
}), /* @__PURE__ */ S("p", {
|
|
201
205
|
className: "text-xs text-muted-foreground",
|
|
202
|
-
children: [
|
|
206
|
+
children: e.team ? /* @__PURE__ */ C(x, { children: [
|
|
207
|
+
j("planmagnet.dashboard.shared.team", "Team"),
|
|
208
|
+
": ",
|
|
209
|
+
e.team.name
|
|
210
|
+
] }) : /* @__PURE__ */ C(x, { children: [
|
|
203
211
|
j("planmagnet.dashboard.shared.project", "Project"),
|
|
204
212
|
":",
|
|
205
213
|
" ",
|
|
206
214
|
e.project?.name ?? j("planmagnet.dashboard.shared.projectUnavailable", "not available")
|
|
207
|
-
]
|
|
215
|
+
] })
|
|
208
216
|
})] }), /* @__PURE__ */ C(T, {
|
|
209
217
|
variant: "secondary",
|
|
210
218
|
children: [
|