@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.
- package/dist/planmagnet/PlanMagnetRoot.d.ts.map +1 -1
- package/dist/planmagnet/PlanMagnetRoot.js +126 -84
- package/dist/planmagnet/PlanMagnetRoot.js.map +1 -1
- package/dist/planmagnet/PlanMagnetRoutes.d.ts.map +1 -1
- package/dist/planmagnet/PlanMagnetRoutes.js +192 -64
- 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.d.ts +20 -0
- package/dist/planmagnet/controls/CompetitorControls.d.ts.map +1 -0
- package/dist/planmagnet/controls/CompetitorControls.js +172 -0
- package/dist/planmagnet/controls/CompetitorControls.js.map +1 -0
- 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 +53 -53
- package/dist/planmagnet/controls/FeatureTriage.js +11 -11
- package/dist/planmagnet/controls/ObjectiveControls.js +37 -37
- package/dist/planmagnet/controls/Pickers.d.ts +17 -2
- package/dist/planmagnet/controls/Pickers.d.ts.map +1 -1
- package/dist/planmagnet/controls/Pickers.js +100 -9
- package/dist/planmagnet/controls/Pickers.js.map +1 -1
- package/dist/planmagnet/controls/PortfolioControls.d.ts +13 -0
- package/dist/planmagnet/controls/PortfolioControls.d.ts.map +1 -0
- package/dist/planmagnet/controls/PortfolioControls.js +114 -0
- package/dist/planmagnet/controls/PortfolioControls.js.map +1 -0
- package/dist/planmagnet/controls/ProgramControls.d.ts +25 -0
- package/dist/planmagnet/controls/ProgramControls.d.ts.map +1 -0
- package/dist/planmagnet/controls/ProgramControls.js +187 -0
- package/dist/planmagnet/controls/ProgramControls.js.map +1 -0
- 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.js +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/CompetitorsCompetitorDetailPagePage.d.ts +2 -0
- package/dist/planmagnet/pages/CompetitorsCompetitorDetailPagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/CompetitorsCompetitorDetailPagePage.js +127 -0
- package/dist/planmagnet/pages/CompetitorsCompetitorDetailPagePage.js.map +1 -0
- package/dist/planmagnet/pages/CompetitorsCompetitorsPagePage.d.ts +2 -0
- package/dist/planmagnet/pages/CompetitorsCompetitorsPagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/CompetitorsCompetitorsPagePage.js +129 -0
- package/dist/planmagnet/pages/CompetitorsCompetitorsPagePage.js.map +1 -0
- package/dist/planmagnet/pages/CompetitorsCreateCompetitorPagePage.d.ts +2 -0
- package/dist/planmagnet/pages/CompetitorsCreateCompetitorPagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/CompetitorsCreateCompetitorPagePage.js +132 -0
- package/dist/planmagnet/pages/CompetitorsCreateCompetitorPagePage.js.map +1 -0
- package/dist/planmagnet/pages/CompetitorsEditCompetitorPagePage.d.ts +2 -0
- package/dist/planmagnet/pages/CompetitorsEditCompetitorPagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/CompetitorsEditCompetitorPagePage.js +181 -0
- package/dist/planmagnet/pages/CompetitorsEditCompetitorPagePage.js.map +1 -0
- package/dist/planmagnet/pages/PortfoliosCreatePortfolioPagePage.d.ts +2 -0
- package/dist/planmagnet/pages/PortfoliosCreatePortfolioPagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/PortfoliosCreatePortfolioPagePage.js +242 -0
- package/dist/planmagnet/pages/PortfoliosCreatePortfolioPagePage.js.map +1 -0
- package/dist/planmagnet/pages/PortfoliosEditPortfolioPagePage.d.ts +2 -0
- package/dist/planmagnet/pages/PortfoliosEditPortfolioPagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/PortfoliosEditPortfolioPagePage.js +302 -0
- package/dist/planmagnet/pages/PortfoliosEditPortfolioPagePage.js.map +1 -0
- package/dist/planmagnet/pages/PortfoliosPortfolioDetailPagePage.d.ts +2 -0
- package/dist/planmagnet/pages/PortfoliosPortfolioDetailPagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/PortfoliosPortfolioDetailPagePage.js +335 -0
- package/dist/planmagnet/pages/PortfoliosPortfolioDetailPagePage.js.map +1 -0
- package/dist/planmagnet/pages/PortfoliosPortfoliosPagePage.d.ts +2 -0
- package/dist/planmagnet/pages/PortfoliosPortfoliosPagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/PortfoliosPortfoliosPagePage.js +154 -0
- package/dist/planmagnet/pages/PortfoliosPortfoliosPagePage.js.map +1 -0
- package/dist/planmagnet/pages/ProductsFeatureDetailPagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/ProductsFeatureDetailPagePage.js +124 -138
- package/dist/planmagnet/pages/ProductsFeatureDetailPagePage.js.map +1 -1
- package/dist/planmagnet/pages/ProgramsCreateProgramPagePage.d.ts +2 -0
- package/dist/planmagnet/pages/ProgramsCreateProgramPagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/ProgramsCreateProgramPagePage.js +221 -0
- package/dist/planmagnet/pages/ProgramsCreateProgramPagePage.js.map +1 -0
- package/dist/planmagnet/pages/ProgramsEditProgramPagePage.d.ts +2 -0
- package/dist/planmagnet/pages/ProgramsEditProgramPagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/ProgramsEditProgramPagePage.js +279 -0
- package/dist/planmagnet/pages/ProgramsEditProgramPagePage.js.map +1 -0
- package/dist/planmagnet/pages/ProgramsProgramDetailPagePage.d.ts +2 -0
- package/dist/planmagnet/pages/ProgramsProgramDetailPagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/ProgramsProgramDetailPagePage.js +178 -0
- package/dist/planmagnet/pages/ProgramsProgramDetailPagePage.js.map +1 -0
- package/dist/planmagnet/pages/ProgramsProgramsPagePage.d.ts +2 -0
- package/dist/planmagnet/pages/ProgramsProgramsPagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/ProgramsProgramsPagePage.js +157 -0
- package/dist/planmagnet/pages/ProgramsProgramsPagePage.js.map +1 -0
- 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.d.ts.map +1 -1
- package/dist/planmagnet/pages/ProjectsEditProjectPagePage.js +130 -103
- package/dist/planmagnet/pages/ProjectsEditProjectPagePage.js.map +1 -1
- package/dist/planmagnet/pages/ProjectsMilestoneDetailPagePage.js +4 -4
- package/dist/planmagnet/pages/ProjectsPlanningDetailPagePage.js +4 -4
- package/dist/planmagnet/pages/ProjectsPlanningEditPagePage.js +6 -6
- package/dist/planmagnet/pages/ProjectsProjectDetailPagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/ProjectsProjectDetailPagePage.js +325 -189
- 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/TasksCreateTaskPagePage.js +5 -5
- package/dist/planmagnet/pages/TasksEditTaskPagePage.js +4 -4
- package/dist/planmagnet/pages/TasksImportPagePage.js +5 -5
- 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/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/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
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { usePlanMagnet as e } from "../providers/PlanMagnetProvider.js";
|
|
2
2
|
import { throwOnError as t } from "../utils/mutationResult.js";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
3
|
+
import { ErrorLine as n } from "./ConfirmButton.js";
|
|
4
|
+
import { ProjectSelect as r } from "./Pickers.js";
|
|
5
5
|
import { useDeferredValue as i, useState as a } from "react";
|
|
6
6
|
import { AlarmClock as o, Check as s, GitMerge as c, Sun as l, X as u } from "lucide-react";
|
|
7
7
|
import { gql as d } from "@apollo/client";
|
|
@@ -66,7 +66,7 @@ var E = {
|
|
|
66
66
|
}
|
|
67
67
|
}
|
|
68
68
|
`, M = 2e3, N = ["SUBMITTED", "UNDER_REVIEW"], P = (e) => N.includes(e), F = (e, t) => !!e && new Date(e).getTime() > t, I = (e, t) => e instanceof Error ? e.message : t;
|
|
69
|
-
function L({ trigger: e, testId: t, title:
|
|
69
|
+
function L({ trigger: e, testId: t, title: r, description: i, children: a, confirmLabel: o, canConfirm: s, busy: c, onConfirm: l, error: u, onOpenChange: d, open: f }) {
|
|
70
70
|
return /* @__PURE__ */ g(y, {
|
|
71
71
|
open: f,
|
|
72
72
|
onOpenChange: d,
|
|
@@ -83,10 +83,10 @@ function L({ trigger: e, testId: t, title: n, description: i, children: a, confi
|
|
|
83
83
|
}), /* @__PURE__ */ g(b, {
|
|
84
84
|
className: "max-w-lg",
|
|
85
85
|
children: [
|
|
86
|
-
/* @__PURE__ */ g(C, { children: [/* @__PURE__ */ h(w, { children:
|
|
86
|
+
/* @__PURE__ */ g(C, { children: [/* @__PURE__ */ h(w, { children: r }), /* @__PURE__ */ h(x, { children: i })] }),
|
|
87
87
|
/* @__PURE__ */ g("div", {
|
|
88
88
|
className: "space-y-3",
|
|
89
|
-
children: [a, u && /* @__PURE__ */ h(
|
|
89
|
+
children: [a, u && /* @__PURE__ */ h(n, { message: u })]
|
|
90
90
|
}),
|
|
91
91
|
/* @__PURE__ */ g(S, { children: [/* @__PURE__ */ h(_, {
|
|
92
92
|
variant: "outline",
|
|
@@ -102,7 +102,7 @@ function L({ trigger: e, testId: t, title: n, description: i, children: a, confi
|
|
|
102
102
|
});
|
|
103
103
|
}
|
|
104
104
|
function R({ feature: e }) {
|
|
105
|
-
let [
|
|
105
|
+
let [n, i] = a(!1), [o, c] = a("PLANNED"), [l, u] = a(e.projectId ?? ""), [d, p] = a(null), [_, v] = f(D, E), y = async () => {
|
|
106
106
|
p(null);
|
|
107
107
|
try {
|
|
108
108
|
await t(_({ variables: {
|
|
@@ -117,7 +117,7 @@ function R({ feature: e }) {
|
|
|
117
117
|
}
|
|
118
118
|
};
|
|
119
119
|
return /* @__PURE__ */ g(L, {
|
|
120
|
-
open:
|
|
120
|
+
open: n,
|
|
121
121
|
onOpenChange: (e) => {
|
|
122
122
|
i(e), e || p(null);
|
|
123
123
|
},
|
|
@@ -152,7 +152,7 @@ function R({ feature: e }) {
|
|
|
152
152
|
children: "Project that will deliver it"
|
|
153
153
|
}), /* @__PURE__ */ h("div", {
|
|
154
154
|
className: "mt-1",
|
|
155
|
-
children: /* @__PURE__ */ h(
|
|
155
|
+
children: /* @__PURE__ */ h(r, {
|
|
156
156
|
id: `triage-accept-project-${e.id}`,
|
|
157
157
|
value: l,
|
|
158
158
|
noneLabel: "No project yet",
|
|
@@ -354,10 +354,10 @@ function H({ feature: n }) {
|
|
|
354
354
|
});
|
|
355
355
|
}
|
|
356
356
|
function U({ feature: e }) {
|
|
357
|
-
let [
|
|
357
|
+
let [r, i] = f(k, E), [o, s] = a(null), c = async () => {
|
|
358
358
|
s(null);
|
|
359
359
|
try {
|
|
360
|
-
await t(
|
|
360
|
+
await t(r({ variables: {
|
|
361
361
|
id: e.id,
|
|
362
362
|
until: null
|
|
363
363
|
} }));
|
|
@@ -374,7 +374,7 @@ function U({ feature: e }) {
|
|
|
374
374
|
e.stopPropagation(), c();
|
|
375
375
|
},
|
|
376
376
|
children: [/* @__PURE__ */ h(l, { className: "mr-1 h-4 w-4" }), "Back to triage"]
|
|
377
|
-
}), o && /* @__PURE__ */ h(
|
|
377
|
+
}), o && /* @__PURE__ */ h(n, { message: o })] });
|
|
378
378
|
}
|
|
379
379
|
function W({ feature: e, now: t }) {
|
|
380
380
|
if (!P(e.status)) return null;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { throwOnError as e } from "../utils/mutationResult.js";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
2
|
+
import { ErrorLine as t } from "./ConfirmButton.js";
|
|
3
|
+
import { WorkItemSearchSelect as n } from "./Pickers.js";
|
|
4
|
+
import { enumLabel as r } from "./WorkItemControls.js";
|
|
5
|
+
import { endBeforeStart as i } from "../utils/formValidation.js";
|
|
6
6
|
import { useState as a } from "react";
|
|
7
7
|
import { Link2 as o, Pencil as s, X as c } from "lucide-react";
|
|
8
8
|
import { gql as l } from "@apollo/client";
|
|
@@ -41,13 +41,13 @@ var S = [
|
|
|
41
41
|
refetchQueries: C,
|
|
42
42
|
awaitRefetchQueries: !0
|
|
43
43
|
};
|
|
44
|
-
function O({ objective:
|
|
45
|
-
let [
|
|
44
|
+
function O({ objective: n }) {
|
|
45
|
+
let [i, o] = u(w, D), [s, c] = a(null), l = S.includes(n.status) ? S : [n.status, ...S], p = async (t) => {
|
|
46
46
|
c(null);
|
|
47
47
|
try {
|
|
48
|
-
await e(
|
|
49
|
-
id:
|
|
50
|
-
input: { status:
|
|
48
|
+
await e(i({ variables: {
|
|
49
|
+
id: n.id,
|
|
50
|
+
input: { status: t }
|
|
51
51
|
} }));
|
|
52
52
|
} catch (e) {
|
|
53
53
|
c(e instanceof Error ? e.message : "The status could not be changed.");
|
|
@@ -61,38 +61,38 @@ function O({ objective: t }) {
|
|
|
61
61
|
"aria-label": "Objective status",
|
|
62
62
|
"data-testid": "objective-status",
|
|
63
63
|
className: "rounded-md border border-input bg-background px-2 py-1 text-sm disabled:opacity-60",
|
|
64
|
-
value:
|
|
64
|
+
value: n.status,
|
|
65
65
|
disabled: o.loading,
|
|
66
66
|
onChange: (e) => {
|
|
67
|
-
e.target.value !==
|
|
67
|
+
e.target.value !== n.status && p(e.target.value);
|
|
68
68
|
},
|
|
69
69
|
children: l.map((e) => /* @__PURE__ */ d("option", {
|
|
70
70
|
value: e,
|
|
71
|
-
children:
|
|
71
|
+
children: r(e)
|
|
72
72
|
}, e))
|
|
73
|
-
}), /* @__PURE__ */ d(A, { objective:
|
|
74
|
-
}), s && /* @__PURE__ */ d(
|
|
73
|
+
}), /* @__PURE__ */ d(A, { objective: n })]
|
|
74
|
+
}), s && /* @__PURE__ */ d(t, { message: s })]
|
|
75
75
|
});
|
|
76
76
|
}
|
|
77
77
|
var k = (e) => e ? e.slice(0, 10) : "";
|
|
78
|
-
function A({ objective:
|
|
79
|
-
let
|
|
80
|
-
title:
|
|
81
|
-
description:
|
|
82
|
-
periodLabel:
|
|
83
|
-
startDate: k(
|
|
84
|
-
endDate: k(
|
|
85
|
-
}, [o, c] = a(!1), [l, S] = a(
|
|
78
|
+
function A({ objective: n }) {
|
|
79
|
+
let r = {
|
|
80
|
+
title: n.title,
|
|
81
|
+
description: n.description ?? "",
|
|
82
|
+
periodLabel: n.periodLabel,
|
|
83
|
+
startDate: k(n.startDate),
|
|
84
|
+
endDate: k(n.endDate)
|
|
85
|
+
}, [o, c] = a(!1), [l, S] = a(r), [C, T] = a(null), [E, O] = u(w, D), A = i(l.startDate, l.endDate), j = l.title.trim() !== "" && l.periodLabel.trim() !== "" && !A && !O.loading, M = async () => {
|
|
86
86
|
T(null);
|
|
87
|
-
let
|
|
88
|
-
if (l.title.trim() !==
|
|
87
|
+
let t = {};
|
|
88
|
+
if (l.title.trim() !== r.title && (t.title = l.title.trim()), l.periodLabel.trim() !== r.periodLabel && (t.periodLabel = l.periodLabel.trim()), l.description.trim() !== r.description.trim() && (t.description = l.description.trim() || null), l.startDate !== r.startDate && (t.startDate = l.startDate || null), l.endDate !== r.endDate && (t.endDate = l.endDate || null), Object.keys(t).length === 0) {
|
|
89
89
|
c(!1);
|
|
90
90
|
return;
|
|
91
91
|
}
|
|
92
92
|
try {
|
|
93
93
|
await e(E({ variables: {
|
|
94
|
-
id:
|
|
95
|
-
input:
|
|
94
|
+
id: n.id,
|
|
95
|
+
input: t
|
|
96
96
|
} })), c(!1);
|
|
97
97
|
} catch (e) {
|
|
98
98
|
T(e instanceof Error ? e.message : "The objective could not be saved.");
|
|
@@ -101,7 +101,7 @@ function A({ objective: t }) {
|
|
|
101
101
|
return /* @__PURE__ */ f(h, {
|
|
102
102
|
open: o,
|
|
103
103
|
onOpenChange: (e) => {
|
|
104
|
-
c(e), e ? S(
|
|
104
|
+
c(e), e ? S(r) : T(null);
|
|
105
105
|
},
|
|
106
106
|
children: [/* @__PURE__ */ d(x, {
|
|
107
107
|
asChild: !0,
|
|
@@ -177,7 +177,7 @@ function A({ objective: t }) {
|
|
|
177
177
|
})
|
|
178
178
|
})] })]
|
|
179
179
|
}),
|
|
180
|
-
A && /* @__PURE__ */ d(
|
|
180
|
+
A && /* @__PURE__ */ d(t, { message: "The end date is before the start date." }),
|
|
181
181
|
/* @__PURE__ */ f("div", { children: [/* @__PURE__ */ d("label", {
|
|
182
182
|
htmlFor: "objective-edit-description",
|
|
183
183
|
className: N,
|
|
@@ -191,7 +191,7 @@ function A({ objective: t }) {
|
|
|
191
191
|
description: e.target.value
|
|
192
192
|
})
|
|
193
193
|
})] }),
|
|
194
|
-
C && /* @__PURE__ */ d(
|
|
194
|
+
C && /* @__PURE__ */ d(t, { message: C })
|
|
195
195
|
]
|
|
196
196
|
}),
|
|
197
197
|
/* @__PURE__ */ f(v, { children: [/* @__PURE__ */ d(p, {
|
|
@@ -207,14 +207,14 @@ function A({ objective: t }) {
|
|
|
207
207
|
})]
|
|
208
208
|
});
|
|
209
209
|
}
|
|
210
|
-
function j({ keyResultId:
|
|
211
|
-
let [m, h] = u(T, D), [g, _] = u(E, D), [v, y] = a(!1), [b, x] = a(""), [S, C] = a(null), w = h.loading || _.loading, O = async (t, n,
|
|
210
|
+
function j({ keyResultId: i, keyResultTitle: s, linked: l }) {
|
|
211
|
+
let [m, h] = u(T, D), [g, _] = u(E, D), [v, y] = a(!1), [b, x] = a(""), [S, C] = a(null), w = h.loading || _.loading, O = async (t, n, r) => {
|
|
212
212
|
C(null);
|
|
213
213
|
try {
|
|
214
214
|
await e(t({ variables: {
|
|
215
|
-
keyResultId:
|
|
215
|
+
keyResultId: i,
|
|
216
216
|
workItemId: n
|
|
217
|
-
} })),
|
|
217
|
+
} })), r?.();
|
|
218
218
|
} catch (e) {
|
|
219
219
|
C(e instanceof Error ? e.message : "The link could not be changed.");
|
|
220
220
|
}
|
|
@@ -241,7 +241,7 @@ function j({ keyResultId: r, keyResultTitle: s, linked: l }) {
|
|
|
241
241
|
className: "text-muted-foreground",
|
|
242
242
|
children: [
|
|
243
243
|
"(",
|
|
244
|
-
|
|
244
|
+
r(e.status),
|
|
245
245
|
")"
|
|
246
246
|
]
|
|
247
247
|
})
|
|
@@ -259,8 +259,8 @@ function j({ keyResultId: r, keyResultTitle: s, linked: l }) {
|
|
|
259
259
|
}),
|
|
260
260
|
v ? /* @__PURE__ */ f("div", {
|
|
261
261
|
className: "space-y-2 rounded-md border border-input p-2",
|
|
262
|
-
children: [/* @__PURE__ */ d(
|
|
263
|
-
id: `kr-link-${
|
|
262
|
+
children: [/* @__PURE__ */ d(n, {
|
|
263
|
+
id: `kr-link-${i}`,
|
|
264
264
|
value: b,
|
|
265
265
|
onChange: x,
|
|
266
266
|
exclude: l.map((e) => e.id)
|
|
@@ -286,7 +286,7 @@ function j({ keyResultId: r, keyResultTitle: s, linked: l }) {
|
|
|
286
286
|
onClick: () => y(!0),
|
|
287
287
|
children: [/* @__PURE__ */ d(o, { className: "mr-1 h-4 w-4" }), "Link work item"]
|
|
288
288
|
}),
|
|
289
|
-
S && /* @__PURE__ */ d(
|
|
289
|
+
S && /* @__PURE__ */ d(t, { message: S })
|
|
290
290
|
]
|
|
291
291
|
});
|
|
292
292
|
}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
/** A project select. '' means "no project" when `noneLabel` is given. */
|
|
2
|
-
export declare function ProjectSelect({ id, value, onChange, noneLabel, }: {
|
|
1
|
+
/** A project select. '' means "no project" when `noneLabel` is given. `exclude` hides ids already spoken for. */
|
|
2
|
+
export declare function ProjectSelect({ id, value, onChange, noneLabel, exclude, }: {
|
|
3
3
|
id?: string;
|
|
4
4
|
value: string;
|
|
5
5
|
onChange: (projectId: string) => void;
|
|
6
6
|
noneLabel?: string;
|
|
7
|
+
exclude?: string[];
|
|
7
8
|
}): import("react/jsx-runtime").JSX.Element;
|
|
8
9
|
/**
|
|
9
10
|
* Search, then pick one work item. The server matches the key, title and description. `exclude` hides items that are
|
|
@@ -23,4 +24,18 @@ export declare function DocSearchSelect({ id, value, onChange, exclude, }: {
|
|
|
23
24
|
onChange: (docId: string) => void;
|
|
24
25
|
exclude?: string[];
|
|
25
26
|
}): import("react/jsx-runtime").JSX.Element;
|
|
27
|
+
/** A program select. '' means "no program" when `noneLabel` is given. */
|
|
28
|
+
export declare function ProgramSelect({ id, value, onChange, noneLabel, }: {
|
|
29
|
+
id?: string;
|
|
30
|
+
value: string;
|
|
31
|
+
onChange: (programId: string) => void;
|
|
32
|
+
noneLabel?: string;
|
|
33
|
+
}): import("react/jsx-runtime").JSX.Element;
|
|
34
|
+
/** Search, then pick one competitor. `exclude` hides competitors already linked. */
|
|
35
|
+
export declare function CompetitorSearchSelect({ id, value, onChange, exclude, }: {
|
|
36
|
+
id: string;
|
|
37
|
+
value: string;
|
|
38
|
+
onChange: (competitorId: string) => void;
|
|
39
|
+
exclude?: string[];
|
|
40
|
+
}): import("react/jsx-runtime").JSX.Element;
|
|
26
41
|
//# sourceMappingURL=Pickers.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Pickers.d.ts","sourceRoot":"","sources":["../../../src/planmagnet/controls/Pickers.tsx"],"names":[],"mappings":"AA2BA,
|
|
1
|
+
{"version":3,"file":"Pickers.d.ts","sourceRoot":"","sources":["../../../src/planmagnet/controls/Pickers.tsx"],"names":[],"mappings":"AA2BA,iHAAiH;AACjH,wBAAgB,aAAa,CAAC,EAC5B,EAAE,EACF,KAAK,EACL,QAAQ,EACR,SAAS,EACT,OAAY,GACb,EAAE;IACD,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IACtC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;CACpB,2CA8BA;AAeD;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,EACnC,EAAE,EACF,SAAS,EACT,KAAK,EACL,QAAQ,EACR,OAAY,GACb,EAAE;IACD,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,IAAI,CAAC;IACvC,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;CACpB,2CAqDA;AAcD,iCAAiC;AACjC,wBAAgB,eAAe,CAAC,EAC9B,EAAE,EACF,KAAK,EACL,QAAQ,EACR,OAAY,GACb,EAAE;IACD,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;CACpB,2CA8CA;AAcD,yEAAyE;AACzE,wBAAgB,aAAa,CAAC,EAC5B,EAAE,EACF,KAAK,EACL,QAAQ,EACR,SAAS,GACV,EAAE;IACD,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IACtC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,2CA8BA;AAcD,oFAAoF;AACpF,wBAAgB,sBAAsB,CAAC,EACrC,EAAE,EACF,KAAK,EACL,QAAQ,EACR,OAAY,GACb,EAAE;IACD,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,IAAI,CAAC;IACzC,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;CACpB,2CAkDA"}
|
|
@@ -16,11 +16,11 @@ var c = "w-full rounded-md border border-input bg-background px-3 py-2 text-sm d
|
|
|
16
16
|
}
|
|
17
17
|
}
|
|
18
18
|
`;
|
|
19
|
-
function u({ id: t, value: n, onChange: r, noneLabel: s }) {
|
|
20
|
-
let { workspaceId:
|
|
21
|
-
variables: { workspaceId:
|
|
22
|
-
skip: !
|
|
23
|
-
}),
|
|
19
|
+
function u({ id: t, value: n, onChange: r, noneLabel: s, exclude: u = [] }) {
|
|
20
|
+
let { workspaceId: d } = e(), { data: f, loading: p, error: m } = i(l, {
|
|
21
|
+
variables: { workspaceId: d ?? "" },
|
|
22
|
+
skip: !d
|
|
23
|
+
}), h = (f?.planmagnetProjects.items ?? []).filter((e) => !u.includes(e.id));
|
|
24
24
|
return /* @__PURE__ */ o("select", {
|
|
25
25
|
id: t,
|
|
26
26
|
className: c,
|
|
@@ -31,11 +31,11 @@ function u({ id: t, value: n, onChange: r, noneLabel: s }) {
|
|
|
31
31
|
value: "",
|
|
32
32
|
children: s
|
|
33
33
|
}),
|
|
34
|
-
|
|
34
|
+
h.length === 0 && s === void 0 && /* @__PURE__ */ a("option", {
|
|
35
35
|
value: "",
|
|
36
|
-
children:
|
|
36
|
+
children: p && !f ? "Loading projects…" : m ? "Projects could not be loaded" : "No projects yet"
|
|
37
37
|
}),
|
|
38
|
-
|
|
38
|
+
h.map((e) => /* @__PURE__ */ a("option", {
|
|
39
39
|
value: e.id,
|
|
40
40
|
children: e.name
|
|
41
41
|
}, e.id))
|
|
@@ -165,7 +165,98 @@ function m({ id: r, value: l, onChange: u, exclude: d = [] }) {
|
|
|
165
165
|
]
|
|
166
166
|
});
|
|
167
167
|
}
|
|
168
|
+
var h = r`
|
|
169
|
+
query PickerPrograms($workspaceId: ID!) {
|
|
170
|
+
planmagnetPrograms(workspaceId: $workspaceId, pagination: { first: 100 }) {
|
|
171
|
+
items {
|
|
172
|
+
id
|
|
173
|
+
name
|
|
174
|
+
}
|
|
175
|
+
totalCount
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
`;
|
|
179
|
+
function g({ id: t, value: n, onChange: r, noneLabel: s }) {
|
|
180
|
+
let { workspaceId: l } = e(), { data: u, loading: d, error: f } = i(h, {
|
|
181
|
+
variables: { workspaceId: l ?? "" },
|
|
182
|
+
skip: !l
|
|
183
|
+
}), p = u?.planmagnetPrograms.items ?? [];
|
|
184
|
+
return /* @__PURE__ */ o("select", {
|
|
185
|
+
id: t,
|
|
186
|
+
className: c,
|
|
187
|
+
value: n,
|
|
188
|
+
onChange: (e) => r(e.target.value),
|
|
189
|
+
children: [
|
|
190
|
+
s !== void 0 && /* @__PURE__ */ a("option", {
|
|
191
|
+
value: "",
|
|
192
|
+
children: s
|
|
193
|
+
}),
|
|
194
|
+
p.length === 0 && s === void 0 && /* @__PURE__ */ a("option", {
|
|
195
|
+
value: "",
|
|
196
|
+
children: d && !u ? "Loading programs…" : f ? "Programs could not be loaded" : "No programs yet"
|
|
197
|
+
}),
|
|
198
|
+
p.map((e) => /* @__PURE__ */ a("option", {
|
|
199
|
+
value: e.id,
|
|
200
|
+
children: e.name
|
|
201
|
+
}, e.id))
|
|
202
|
+
]
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
var _ = r`
|
|
206
|
+
query PickerCompetitors($workspaceId: ID!, $filter: PlanmagnetCompetitorFilter) {
|
|
207
|
+
planmagnetCompetitors(workspaceId: $workspaceId, filter: $filter, pagination: { first: 20 }) {
|
|
208
|
+
items {
|
|
209
|
+
id
|
|
210
|
+
name
|
|
211
|
+
}
|
|
212
|
+
totalCount
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
`;
|
|
216
|
+
function v({ id: r, value: l, onChange: u, exclude: d = [] }) {
|
|
217
|
+
let { workspaceId: f } = e(), [p, m] = n(""), h = t(p.trim()), { data: g, loading: v } = i(_, {
|
|
218
|
+
variables: {
|
|
219
|
+
workspaceId: f ?? "",
|
|
220
|
+
filter: h ? { search: h } : void 0
|
|
221
|
+
},
|
|
222
|
+
skip: !f
|
|
223
|
+
}), y = g?.planmagnetCompetitors.items ?? [], b = y.filter((e) => !d.includes(e.id)), x = g?.planmagnetCompetitors.totalCount ?? 0;
|
|
224
|
+
return /* @__PURE__ */ o("div", {
|
|
225
|
+
className: "space-y-1",
|
|
226
|
+
children: [
|
|
227
|
+
/* @__PURE__ */ a(s, {
|
|
228
|
+
"aria-label": "Search competitors",
|
|
229
|
+
placeholder: "Search competitors by name",
|
|
230
|
+
value: p,
|
|
231
|
+
onChange: (e) => m(e.target.value)
|
|
232
|
+
}),
|
|
233
|
+
/* @__PURE__ */ o("select", {
|
|
234
|
+
id: r,
|
|
235
|
+
className: c,
|
|
236
|
+
value: l,
|
|
237
|
+
onChange: (e) => u(e.target.value),
|
|
238
|
+
children: [/* @__PURE__ */ a("option", {
|
|
239
|
+
value: "",
|
|
240
|
+
children: v && !g ? "Searching…" : b.length ? "Choose a competitor" : "No match"
|
|
241
|
+
}), b.map((e) => /* @__PURE__ */ a("option", {
|
|
242
|
+
value: e.id,
|
|
243
|
+
children: e.name
|
|
244
|
+
}, e.id))]
|
|
245
|
+
}),
|
|
246
|
+
x > y.length && /* @__PURE__ */ o("p", {
|
|
247
|
+
className: "text-xs text-muted-foreground",
|
|
248
|
+
children: [
|
|
249
|
+
"Showing ",
|
|
250
|
+
y.length,
|
|
251
|
+
" of ",
|
|
252
|
+
x,
|
|
253
|
+
" — type to narrow the list."
|
|
254
|
+
]
|
|
255
|
+
})
|
|
256
|
+
]
|
|
257
|
+
});
|
|
258
|
+
}
|
|
168
259
|
//#endregion
|
|
169
|
-
export { m as DocSearchSelect, u as ProjectSelect, f as WorkItemSearchSelect };
|
|
260
|
+
export { v as CompetitorSearchSelect, m as DocSearchSelect, g as ProgramSelect, u as ProjectSelect, f as WorkItemSearchSelect };
|
|
170
261
|
|
|
171
262
|
//# sourceMappingURL=Pickers.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Pickers.js","names":[],"sources":["../../../src/planmagnet/controls/Pickers.tsx"],"sourcesContent":["import { useDeferredValue, useState } from 'react';\nimport { gql } from '@apollo/client';\nimport { useQuery } from '@apollo/client/react';\nimport { Input } from '@burdenoff/fe-libs/ui';\nimport { usePlanMagnet } from '../providers/PlanMagnetProvider';\n\n/**\n * Record pickers shared by forms and dialogs: a project select, and search-then-pick selects for work items and\n * docs. Values are record ids. Search runs on the server (never \"the first page, filtered in the browser\"), so a\n * record past the first page can still be found.\n */\n\nconst selectClass =\n 'w-full rounded-md border border-input bg-background px-3 py-2 text-sm disabled:opacity-60';\n\nconst PICKER_PROJECTS = gql`\n query PickerProjects($workspaceId: ID!) {\n planmagnetProjects(workspaceId: $workspaceId, pagination: { first: 100 }) {\n items {\n id\n name\n }\n totalCount\n }\n }\n`;\n\n/** A project select. '' means \"no project\" when `noneLabel` is given. */\nexport function ProjectSelect({\n id,\n value,\n onChange,\n noneLabel,\n}: {\n id?: string;\n value: string;\n onChange: (projectId: string) => void;\n noneLabel?: string;\n}) {\n const { workspaceId } = usePlanMagnet();\n const { data, loading, error } = useQuery<{\n planmagnetProjects: { items: { id: string; name: string }[]; totalCount: number };\n }>(PICKER_PROJECTS, { variables: { workspaceId: workspaceId ?? '' }, skip: !workspaceId });\n const projects = data?.planmagnetProjects.items ?? [];\n return (\n <select\n id={id}\n className={selectClass}\n value={value}\n onChange={(e) => onChange(e.target.value)}\n >\n {noneLabel !== undefined && <option value=\"\">{noneLabel}</option>}\n {projects.length === 0 && noneLabel === undefined && (\n <option value=\"\">\n {loading && !data\n ? 'Loading projects…'\n : error\n ? 'Projects could not be loaded'\n : 'No projects yet'}\n </option>\n )}\n {projects.map((p) => (\n <option key={p.id} value={p.id}>\n {p.name}\n </option>\n ))}\n </select>\n );\n}\n\nconst PICKER_WORK_ITEMS = gql`\n query PickerWorkItems($workspaceId: ID!, $filter: PlanmagnetWorkItemFilter) {\n planmagnetWorkItems(workspaceId: $workspaceId, filter: $filter, pagination: { first: 20 }) {\n items {\n id\n key\n title\n }\n totalCount\n }\n }\n`;\n\n/**\n * Search, then pick one work item. The server matches the key, title and description. `exclude` hides items that are\n * already linked (the result says how many more exist, so an empty list never claims \"nothing left\" falsely).\n */\nexport function WorkItemSearchSelect({\n id,\n projectId,\n value,\n onChange,\n exclude = [],\n}: {\n id: string;\n projectId?: string;\n value: string;\n onChange: (workItemId: string) => void;\n exclude?: string[];\n}) {\n const { workspaceId } = usePlanMagnet();\n const [search, setSearch] = useState('');\n const deferred = useDeferredValue(search.trim());\n const { data, loading } = useQuery<{\n planmagnetWorkItems: {\n items: { id: string; key: string; title: string }[];\n totalCount: number;\n };\n }>(PICKER_WORK_ITEMS, {\n variables: {\n workspaceId: workspaceId ?? '',\n filter: { ...(deferred && { search: deferred }), ...(projectId && { projectId }) },\n },\n skip: !workspaceId,\n });\n const found = data?.planmagnetWorkItems.items ?? [];\n const items = found.filter((w) => !exclude.includes(w.id));\n const total = data?.planmagnetWorkItems.totalCount ?? 0;\n return (\n <div className=\"space-y-1\">\n <Input\n aria-label=\"Search work items\"\n placeholder=\"Search by key or title\"\n value={search}\n onChange={(e) => setSearch(e.target.value)}\n />\n <select\n id={id}\n className={selectClass}\n value={value}\n onChange={(e) => onChange(e.target.value)}\n >\n <option value=\"\">\n {loading && !data ? 'Searching…' : items.length ? 'Choose a work item' : 'No match'}\n </option>\n {/* The current value stays selectable (and visible) when it is not in this page of results. */}\n {value && !items.some((w) => w.id === value) && (\n <option value={value}>Currently linked work item</option>\n )}\n {items.map((w) => (\n <option key={w.id} value={w.id}>\n {w.key} — {w.title}\n </option>\n ))}\n </select>\n {total > found.length && (\n <p className=\"text-xs text-muted-foreground\">\n Showing {found.length} of {total} — type to narrow the list.\n </p>\n )}\n </div>\n );\n}\n\nconst PICKER_DOCS = gql`\n query PickerDocs($workspaceId: String, $filter: PlanmagnetDocFilter) {\n planmagnetDocs(workspaceId: $workspaceId, filter: $filter, pagination: { first: 20 }) {\n items {\n id\n title\n }\n totalCount\n }\n }\n`;\n\n/** Search, then pick one doc. */\nexport function DocSearchSelect({\n id,\n value,\n onChange,\n exclude = [],\n}: {\n id: string;\n value: string;\n onChange: (docId: string) => void;\n exclude?: string[];\n}) {\n const { workspaceId } = usePlanMagnet();\n const [search, setSearch] = useState('');\n const deferred = useDeferredValue(search.trim());\n const { data, loading } = useQuery<{\n planmagnetDocs: { items: { id: string; title: string }[]; totalCount: number };\n }>(PICKER_DOCS, {\n variables: {\n workspaceId: workspaceId ?? '',\n filter: deferred ? { search: deferred } : undefined,\n },\n skip: !workspaceId,\n });\n const found = data?.planmagnetDocs.items ?? [];\n const docs = found.filter((d) => !exclude.includes(d.id));\n const total = data?.planmagnetDocs.totalCount ?? 0;\n return (\n <div className=\"space-y-1\">\n <Input\n aria-label=\"Search docs\"\n placeholder=\"Search docs by title\"\n value={search}\n onChange={(e) => setSearch(e.target.value)}\n />\n <select\n id={id}\n className={selectClass}\n value={value}\n onChange={(e) => onChange(e.target.value)}\n >\n <option value=\"\">\n {loading && !data ? 'Searching…' : docs.length ? 'Choose a doc' : 'No match'}\n </option>\n {docs.map((d) => (\n <option key={d.id} value={d.id}>\n {d.title}\n </option>\n ))}\n </select>\n {total > found.length && (\n <p className=\"text-xs text-muted-foreground\">\n Showing {found.length} of {total} — type to narrow the list.\n </p>\n )}\n </div>\n );\n}\n"],"mappings":";;;;;;;AAYA,IAAM,IACJ,6FAEI,IAAkB,CAAG;;;;;;;;;;;AAa3B,SAAgB,EAAc,EAC5B,OACA,UACA,aACA,gBAMC;CACD,IAAM,EAAE,mBAAgB,GAAe,EACjC,EAAE,SAAM,YAAS,aAAU,EAE9B,GAAiB;EAAE,WAAW,EAAE,aAAa,KAAe,IAAI;EAAE,MAAM,CAAC;EAAa,CAAC,EACpF,IAAW,GAAM,mBAAmB,SAAS,EAAE;AACrD,QACE,kBAAC,UAAD;EACM;EACJ,WAAW;EACJ;EACP,WAAW,MAAM,EAAS,EAAE,OAAO,MAAM;YAJ3C;GAMG,MAAc,KAAA,KAAa,kBAAC,UAAD;IAAQ,OAAM;cAAI;IAAmB,CAAA;GAChE,EAAS,WAAW,KAAK,MAAc,KAAA,KACtC,kBAAC,UAAD;IAAQ,OAAM;cACX,KAAW,CAAC,IACT,sBACA,IACE,iCACA;IACC,CAAA;GAEV,EAAS,KAAK,MACb,kBAAC,UAAD;IAAmB,OAAO,EAAE;cACzB,EAAE;IACI,EAFI,EAAE,GAEN,CACT;GACK;;;AAIb,IAAM,IAAoB,CAAG;;;;;;;;;;;;AAiB7B,SAAgB,EAAqB,EACnC,OACA,cACA,UACA,aACA,aAAU,EAAE,IAOX;CACD,IAAM,EAAE,mBAAgB,GAAe,EACjC,CAAC,GAAQ,KAAa,EAAS,GAAG,EAClC,IAAW,EAAiB,EAAO,MAAM,CAAC,EAC1C,EAAE,SAAM,eAAY,EAKvB,GAAmB;EACpB,WAAW;GACT,aAAa,KAAe;GAC5B,QAAQ;IAAE,GAAI,KAAY,EAAE,QAAQ,GAAU;IAAG,GAAI,KAAa,EAAE,cAAW;IAAG;GACnF;EACD,MAAM,CAAC;EACR,CAAC,EACI,IAAQ,GAAM,oBAAoB,SAAS,EAAE,EAC7C,IAAQ,EAAM,QAAQ,MAAM,CAAC,EAAQ,SAAS,EAAE,GAAG,CAAC,EACpD,IAAQ,GAAM,oBAAoB,cAAc;AACtD,QACE,kBAAC,OAAD;EAAK,WAAU;YAAf;GACE,kBAAC,GAAD;IACE,cAAW;IACX,aAAY;IACZ,OAAO;IACP,WAAW,MAAM,EAAU,EAAE,OAAO,MAAM;IAC1C,CAAA;GACF,kBAAC,UAAD;IACM;IACJ,WAAW;IACJ;IACP,WAAW,MAAM,EAAS,EAAE,OAAO,MAAM;cAJ3C;KAME,kBAAC,UAAD;MAAQ,OAAM;gBACX,KAAW,CAAC,IAAO,eAAe,EAAM,SAAS,uBAAuB;MAClE,CAAA;KAER,KAAS,CAAC,EAAM,MAAM,MAAM,EAAE,OAAO,EAAM,IAC1C,kBAAC,UAAD;MAAe;gBAAO;MAAmC,CAAA;KAE1D,EAAM,KAAK,MACV,kBAAC,UAAD;MAAmB,OAAO,EAAE;gBAA5B;OACG,EAAE;OAAI;OAAI,EAAE;OACN;QAFI,EAAE,GAEN,CACT;KACK;;GACR,IAAQ,EAAM,UACb,kBAAC,KAAD;IAAG,WAAU;cAAb;KAA6C;KAClC,EAAM;KAAO;KAAK;KAAM;KAC/B;;GAEF;;;AAIV,IAAM,IAAc,CAAG;;;;;;;;;;;AAavB,SAAgB,EAAgB,EAC9B,OACA,UACA,aACA,aAAU,EAAE,IAMX;CACD,IAAM,EAAE,mBAAgB,GAAe,EACjC,CAAC,GAAQ,KAAa,EAAS,GAAG,EAClC,IAAW,EAAiB,EAAO,MAAM,CAAC,EAC1C,EAAE,SAAM,eAAY,EAEvB,GAAa;EACd,WAAW;GACT,aAAa,KAAe;GAC5B,QAAQ,IAAW,EAAE,QAAQ,GAAU,GAAG,KAAA;GAC3C;EACD,MAAM,CAAC;EACR,CAAC,EACI,IAAQ,GAAM,eAAe,SAAS,EAAE,EACxC,IAAO,EAAM,QAAQ,MAAM,CAAC,EAAQ,SAAS,EAAE,GAAG,CAAC,EACnD,IAAQ,GAAM,eAAe,cAAc;AACjD,QACE,kBAAC,OAAD;EAAK,WAAU;YAAf;GACE,kBAAC,GAAD;IACE,cAAW;IACX,aAAY;IACZ,OAAO;IACP,WAAW,MAAM,EAAU,EAAE,OAAO,MAAM;IAC1C,CAAA;GACF,kBAAC,UAAD;IACM;IACJ,WAAW;IACJ;IACP,WAAW,MAAM,EAAS,EAAE,OAAO,MAAM;cAJ3C,CAME,kBAAC,UAAD;KAAQ,OAAM;eACX,KAAW,CAAC,IAAO,eAAe,EAAK,SAAS,iBAAiB;KAC3D,CAAA,EACR,EAAK,KAAK,MACT,kBAAC,UAAD;KAAmB,OAAO,EAAE;eACzB,EAAE;KACI,EAFI,EAAE,GAEN,CACT,CACK;;GACR,IAAQ,EAAM,UACb,kBAAC,KAAD;IAAG,WAAU;cAAb;KAA6C;KAClC,EAAM;KAAO;KAAK;KAAM;KAC/B;;GAEF"}
|
|
1
|
+
{"version":3,"file":"Pickers.js","names":[],"sources":["../../../src/planmagnet/controls/Pickers.tsx"],"sourcesContent":["import { useDeferredValue, useState } from 'react';\nimport { gql } from '@apollo/client';\nimport { useQuery } from '@apollo/client/react';\nimport { Input } from '@burdenoff/fe-libs/ui';\nimport { usePlanMagnet } from '../providers/PlanMagnetProvider';\n\n/**\n * Record pickers shared by forms and dialogs: a project select, and search-then-pick selects for work items and\n * docs. Values are record ids. Search runs on the server (never \"the first page, filtered in the browser\"), so a\n * record past the first page can still be found.\n */\n\nconst selectClass =\n 'w-full rounded-md border border-input bg-background px-3 py-2 text-sm disabled:opacity-60';\n\nconst PICKER_PROJECTS = gql`\n query PickerProjects($workspaceId: ID!) {\n planmagnetProjects(workspaceId: $workspaceId, pagination: { first: 100 }) {\n items {\n id\n name\n }\n totalCount\n }\n }\n`;\n\n/** A project select. '' means \"no project\" when `noneLabel` is given. `exclude` hides ids already spoken for. */\nexport function ProjectSelect({\n id,\n value,\n onChange,\n noneLabel,\n exclude = [],\n}: {\n id?: string;\n value: string;\n onChange: (projectId: string) => void;\n noneLabel?: string;\n exclude?: string[];\n}) {\n const { workspaceId } = usePlanMagnet();\n const { data, loading, error } = useQuery<{\n planmagnetProjects: { items: { id: string; name: string }[]; totalCount: number };\n }>(PICKER_PROJECTS, { variables: { workspaceId: workspaceId ?? '' }, skip: !workspaceId });\n const projects = (data?.planmagnetProjects.items ?? []).filter((p) => !exclude.includes(p.id));\n return (\n <select\n id={id}\n className={selectClass}\n value={value}\n onChange={(e) => onChange(e.target.value)}\n >\n {noneLabel !== undefined && <option value=\"\">{noneLabel}</option>}\n {projects.length === 0 && noneLabel === undefined && (\n <option value=\"\">\n {loading && !data\n ? 'Loading projects…'\n : error\n ? 'Projects could not be loaded'\n : 'No projects yet'}\n </option>\n )}\n {projects.map((p) => (\n <option key={p.id} value={p.id}>\n {p.name}\n </option>\n ))}\n </select>\n );\n}\n\nconst PICKER_WORK_ITEMS = gql`\n query PickerWorkItems($workspaceId: ID!, $filter: PlanmagnetWorkItemFilter) {\n planmagnetWorkItems(workspaceId: $workspaceId, filter: $filter, pagination: { first: 20 }) {\n items {\n id\n key\n title\n }\n totalCount\n }\n }\n`;\n\n/**\n * Search, then pick one work item. The server matches the key, title and description. `exclude` hides items that are\n * already linked (the result says how many more exist, so an empty list never claims \"nothing left\" falsely).\n */\nexport function WorkItemSearchSelect({\n id,\n projectId,\n value,\n onChange,\n exclude = [],\n}: {\n id: string;\n projectId?: string;\n value: string;\n onChange: (workItemId: string) => void;\n exclude?: string[];\n}) {\n const { workspaceId } = usePlanMagnet();\n const [search, setSearch] = useState('');\n const deferred = useDeferredValue(search.trim());\n const { data, loading } = useQuery<{\n planmagnetWorkItems: {\n items: { id: string; key: string; title: string }[];\n totalCount: number;\n };\n }>(PICKER_WORK_ITEMS, {\n variables: {\n workspaceId: workspaceId ?? '',\n filter: { ...(deferred && { search: deferred }), ...(projectId && { projectId }) },\n },\n skip: !workspaceId,\n });\n const found = data?.planmagnetWorkItems.items ?? [];\n const items = found.filter((w) => !exclude.includes(w.id));\n const total = data?.planmagnetWorkItems.totalCount ?? 0;\n return (\n <div className=\"space-y-1\">\n <Input\n aria-label=\"Search work items\"\n placeholder=\"Search by key or title\"\n value={search}\n onChange={(e) => setSearch(e.target.value)}\n />\n <select\n id={id}\n className={selectClass}\n value={value}\n onChange={(e) => onChange(e.target.value)}\n >\n <option value=\"\">\n {loading && !data ? 'Searching…' : items.length ? 'Choose a work item' : 'No match'}\n </option>\n {/* The current value stays selectable (and visible) when it is not in this page of results. */}\n {value && !items.some((w) => w.id === value) && (\n <option value={value}>Currently linked work item</option>\n )}\n {items.map((w) => (\n <option key={w.id} value={w.id}>\n {w.key} — {w.title}\n </option>\n ))}\n </select>\n {total > found.length && (\n <p className=\"text-xs text-muted-foreground\">\n Showing {found.length} of {total} — type to narrow the list.\n </p>\n )}\n </div>\n );\n}\n\nconst PICKER_DOCS = gql`\n query PickerDocs($workspaceId: String, $filter: PlanmagnetDocFilter) {\n planmagnetDocs(workspaceId: $workspaceId, filter: $filter, pagination: { first: 20 }) {\n items {\n id\n title\n }\n totalCount\n }\n }\n`;\n\n/** Search, then pick one doc. */\nexport function DocSearchSelect({\n id,\n value,\n onChange,\n exclude = [],\n}: {\n id: string;\n value: string;\n onChange: (docId: string) => void;\n exclude?: string[];\n}) {\n const { workspaceId } = usePlanMagnet();\n const [search, setSearch] = useState('');\n const deferred = useDeferredValue(search.trim());\n const { data, loading } = useQuery<{\n planmagnetDocs: { items: { id: string; title: string }[]; totalCount: number };\n }>(PICKER_DOCS, {\n variables: {\n workspaceId: workspaceId ?? '',\n filter: deferred ? { search: deferred } : undefined,\n },\n skip: !workspaceId,\n });\n const found = data?.planmagnetDocs.items ?? [];\n const docs = found.filter((d) => !exclude.includes(d.id));\n const total = data?.planmagnetDocs.totalCount ?? 0;\n return (\n <div className=\"space-y-1\">\n <Input\n aria-label=\"Search docs\"\n placeholder=\"Search docs by title\"\n value={search}\n onChange={(e) => setSearch(e.target.value)}\n />\n <select\n id={id}\n className={selectClass}\n value={value}\n onChange={(e) => onChange(e.target.value)}\n >\n <option value=\"\">\n {loading && !data ? 'Searching…' : docs.length ? 'Choose a doc' : 'No match'}\n </option>\n {docs.map((d) => (\n <option key={d.id} value={d.id}>\n {d.title}\n </option>\n ))}\n </select>\n {total > found.length && (\n <p className=\"text-xs text-muted-foreground\">\n Showing {found.length} of {total} — type to narrow the list.\n </p>\n )}\n </div>\n );\n}\n\nconst PICKER_PROGRAMS = gql`\n query PickerPrograms($workspaceId: ID!) {\n planmagnetPrograms(workspaceId: $workspaceId, pagination: { first: 100 }) {\n items {\n id\n name\n }\n totalCount\n }\n }\n`;\n\n/** A program select. '' means \"no program\" when `noneLabel` is given. */\nexport function ProgramSelect({\n id,\n value,\n onChange,\n noneLabel,\n}: {\n id?: string;\n value: string;\n onChange: (programId: string) => void;\n noneLabel?: string;\n}) {\n const { workspaceId } = usePlanMagnet();\n const { data, loading, error } = useQuery<{\n planmagnetPrograms: { items: { id: string; name: string }[]; totalCount: number };\n }>(PICKER_PROGRAMS, { variables: { workspaceId: workspaceId ?? '' }, skip: !workspaceId });\n const programs = data?.planmagnetPrograms.items ?? [];\n return (\n <select\n id={id}\n className={selectClass}\n value={value}\n onChange={(e) => onChange(e.target.value)}\n >\n {noneLabel !== undefined && <option value=\"\">{noneLabel}</option>}\n {programs.length === 0 && noneLabel === undefined && (\n <option value=\"\">\n {loading && !data\n ? 'Loading programs…'\n : error\n ? 'Programs could not be loaded'\n : 'No programs yet'}\n </option>\n )}\n {programs.map((p) => (\n <option key={p.id} value={p.id}>\n {p.name}\n </option>\n ))}\n </select>\n );\n}\n\nconst PICKER_COMPETITORS = gql`\n query PickerCompetitors($workspaceId: ID!, $filter: PlanmagnetCompetitorFilter) {\n planmagnetCompetitors(workspaceId: $workspaceId, filter: $filter, pagination: { first: 20 }) {\n items {\n id\n name\n }\n totalCount\n }\n }\n`;\n\n/** Search, then pick one competitor. `exclude` hides competitors already linked. */\nexport function CompetitorSearchSelect({\n id,\n value,\n onChange,\n exclude = [],\n}: {\n id: string;\n value: string;\n onChange: (competitorId: string) => void;\n exclude?: string[];\n}) {\n const { workspaceId } = usePlanMagnet();\n const [search, setSearch] = useState('');\n const deferred = useDeferredValue(search.trim());\n const { data, loading } = useQuery<{\n planmagnetCompetitors: { items: { id: string; name: string }[]; totalCount: number };\n }>(PICKER_COMPETITORS, {\n variables: {\n workspaceId: workspaceId ?? '',\n filter: deferred ? { search: deferred } : undefined,\n },\n skip: !workspaceId,\n });\n const found = data?.planmagnetCompetitors.items ?? [];\n const competitors = found.filter((c) => !exclude.includes(c.id));\n const total = data?.planmagnetCompetitors.totalCount ?? 0;\n return (\n <div className=\"space-y-1\">\n <Input\n aria-label=\"Search competitors\"\n placeholder=\"Search competitors by name\"\n value={search}\n onChange={(e) => setSearch(e.target.value)}\n />\n <select\n id={id}\n className={selectClass}\n value={value}\n onChange={(e) => onChange(e.target.value)}\n >\n <option value=\"\">\n {loading && !data\n ? 'Searching…'\n : competitors.length\n ? 'Choose a competitor'\n : 'No match'}\n </option>\n {competitors.map((c) => (\n <option key={c.id} value={c.id}>\n {c.name}\n </option>\n ))}\n </select>\n {total > found.length && (\n <p className=\"text-xs text-muted-foreground\">\n Showing {found.length} of {total} — type to narrow the list.\n </p>\n )}\n </div>\n );\n}\n"],"mappings":";;;;;;;AAYA,IAAM,IACJ,6FAEI,IAAkB,CAAG;;;;;;;;;;;AAa3B,SAAgB,EAAc,EAC5B,OACA,UACA,aACA,cACA,aAAU,EAAE,IAOX;CACD,IAAM,EAAE,mBAAgB,GAAe,EACjC,EAAE,SAAM,YAAS,aAAU,EAE9B,GAAiB;EAAE,WAAW,EAAE,aAAa,KAAe,IAAI;EAAE,MAAM,CAAC;EAAa,CAAC,EACpF,KAAY,GAAM,mBAAmB,SAAS,EAAE,EAAE,QAAQ,MAAM,CAAC,EAAQ,SAAS,EAAE,GAAG,CAAC;AAC9F,QACE,kBAAC,UAAD;EACM;EACJ,WAAW;EACJ;EACP,WAAW,MAAM,EAAS,EAAE,OAAO,MAAM;YAJ3C;GAMG,MAAc,KAAA,KAAa,kBAAC,UAAD;IAAQ,OAAM;cAAI;IAAmB,CAAA;GAChE,EAAS,WAAW,KAAK,MAAc,KAAA,KACtC,kBAAC,UAAD;IAAQ,OAAM;cACX,KAAW,CAAC,IACT,sBACA,IACE,iCACA;IACC,CAAA;GAEV,EAAS,KAAK,MACb,kBAAC,UAAD;IAAmB,OAAO,EAAE;cACzB,EAAE;IACI,EAFI,EAAE,GAEN,CACT;GACK;;;AAIb,IAAM,IAAoB,CAAG;;;;;;;;;;;;AAiB7B,SAAgB,EAAqB,EACnC,OACA,cACA,UACA,aACA,aAAU,EAAE,IAOX;CACD,IAAM,EAAE,mBAAgB,GAAe,EACjC,CAAC,GAAQ,KAAa,EAAS,GAAG,EAClC,IAAW,EAAiB,EAAO,MAAM,CAAC,EAC1C,EAAE,SAAM,eAAY,EAKvB,GAAmB;EACpB,WAAW;GACT,aAAa,KAAe;GAC5B,QAAQ;IAAE,GAAI,KAAY,EAAE,QAAQ,GAAU;IAAG,GAAI,KAAa,EAAE,cAAW;IAAG;GACnF;EACD,MAAM,CAAC;EACR,CAAC,EACI,IAAQ,GAAM,oBAAoB,SAAS,EAAE,EAC7C,IAAQ,EAAM,QAAQ,MAAM,CAAC,EAAQ,SAAS,EAAE,GAAG,CAAC,EACpD,IAAQ,GAAM,oBAAoB,cAAc;AACtD,QACE,kBAAC,OAAD;EAAK,WAAU;YAAf;GACE,kBAAC,GAAD;IACE,cAAW;IACX,aAAY;IACZ,OAAO;IACP,WAAW,MAAM,EAAU,EAAE,OAAO,MAAM;IAC1C,CAAA;GACF,kBAAC,UAAD;IACM;IACJ,WAAW;IACJ;IACP,WAAW,MAAM,EAAS,EAAE,OAAO,MAAM;cAJ3C;KAME,kBAAC,UAAD;MAAQ,OAAM;gBACX,KAAW,CAAC,IAAO,eAAe,EAAM,SAAS,uBAAuB;MAClE,CAAA;KAER,KAAS,CAAC,EAAM,MAAM,MAAM,EAAE,OAAO,EAAM,IAC1C,kBAAC,UAAD;MAAe;gBAAO;MAAmC,CAAA;KAE1D,EAAM,KAAK,MACV,kBAAC,UAAD;MAAmB,OAAO,EAAE;gBAA5B;OACG,EAAE;OAAI;OAAI,EAAE;OACN;QAFI,EAAE,GAEN,CACT;KACK;;GACR,IAAQ,EAAM,UACb,kBAAC,KAAD;IAAG,WAAU;cAAb;KAA6C;KAClC,EAAM;KAAO;KAAK;KAAM;KAC/B;;GAEF;;;AAIV,IAAM,IAAc,CAAG;;;;;;;;;;;AAavB,SAAgB,EAAgB,EAC9B,OACA,UACA,aACA,aAAU,EAAE,IAMX;CACD,IAAM,EAAE,mBAAgB,GAAe,EACjC,CAAC,GAAQ,KAAa,EAAS,GAAG,EAClC,IAAW,EAAiB,EAAO,MAAM,CAAC,EAC1C,EAAE,SAAM,eAAY,EAEvB,GAAa;EACd,WAAW;GACT,aAAa,KAAe;GAC5B,QAAQ,IAAW,EAAE,QAAQ,GAAU,GAAG,KAAA;GAC3C;EACD,MAAM,CAAC;EACR,CAAC,EACI,IAAQ,GAAM,eAAe,SAAS,EAAE,EACxC,IAAO,EAAM,QAAQ,MAAM,CAAC,EAAQ,SAAS,EAAE,GAAG,CAAC,EACnD,IAAQ,GAAM,eAAe,cAAc;AACjD,QACE,kBAAC,OAAD;EAAK,WAAU;YAAf;GACE,kBAAC,GAAD;IACE,cAAW;IACX,aAAY;IACZ,OAAO;IACP,WAAW,MAAM,EAAU,EAAE,OAAO,MAAM;IAC1C,CAAA;GACF,kBAAC,UAAD;IACM;IACJ,WAAW;IACJ;IACP,WAAW,MAAM,EAAS,EAAE,OAAO,MAAM;cAJ3C,CAME,kBAAC,UAAD;KAAQ,OAAM;eACX,KAAW,CAAC,IAAO,eAAe,EAAK,SAAS,iBAAiB;KAC3D,CAAA,EACR,EAAK,KAAK,MACT,kBAAC,UAAD;KAAmB,OAAO,EAAE;eACzB,EAAE;KACI,EAFI,EAAE,GAEN,CACT,CACK;;GACR,IAAQ,EAAM,UACb,kBAAC,KAAD;IAAG,WAAU;cAAb;KAA6C;KAClC,EAAM;KAAO;KAAK;KAAM;KAC/B;;GAEF;;;AAIV,IAAM,IAAkB,CAAG;;;;;;;;;;;AAa3B,SAAgB,EAAc,EAC5B,OACA,UACA,aACA,gBAMC;CACD,IAAM,EAAE,mBAAgB,GAAe,EACjC,EAAE,SAAM,YAAS,aAAU,EAE9B,GAAiB;EAAE,WAAW,EAAE,aAAa,KAAe,IAAI;EAAE,MAAM,CAAC;EAAa,CAAC,EACpF,IAAW,GAAM,mBAAmB,SAAS,EAAE;AACrD,QACE,kBAAC,UAAD;EACM;EACJ,WAAW;EACJ;EACP,WAAW,MAAM,EAAS,EAAE,OAAO,MAAM;YAJ3C;GAMG,MAAc,KAAA,KAAa,kBAAC,UAAD;IAAQ,OAAM;cAAI;IAAmB,CAAA;GAChE,EAAS,WAAW,KAAK,MAAc,KAAA,KACtC,kBAAC,UAAD;IAAQ,OAAM;cACX,KAAW,CAAC,IACT,sBACA,IACE,iCACA;IACC,CAAA;GAEV,EAAS,KAAK,MACb,kBAAC,UAAD;IAAmB,OAAO,EAAE;cACzB,EAAE;IACI,EAFI,EAAE,GAEN,CACT;GACK;;;AAIb,IAAM,IAAqB,CAAG;;;;;;;;;;;AAa9B,SAAgB,EAAuB,EACrC,OACA,UACA,aACA,aAAU,EAAE,IAMX;CACD,IAAM,EAAE,mBAAgB,GAAe,EACjC,CAAC,GAAQ,KAAa,EAAS,GAAG,EAClC,IAAW,EAAiB,EAAO,MAAM,CAAC,EAC1C,EAAE,SAAM,eAAY,EAEvB,GAAoB;EACrB,WAAW;GACT,aAAa,KAAe;GAC5B,QAAQ,IAAW,EAAE,QAAQ,GAAU,GAAG,KAAA;GAC3C;EACD,MAAM,CAAC;EACR,CAAC,EACI,IAAQ,GAAM,sBAAsB,SAAS,EAAE,EAC/C,IAAc,EAAM,QAAQ,MAAM,CAAC,EAAQ,SAAS,EAAE,GAAG,CAAC,EAC1D,IAAQ,GAAM,sBAAsB,cAAc;AACxD,QACE,kBAAC,OAAD;EAAK,WAAU;YAAf;GACE,kBAAC,GAAD;IACE,cAAW;IACX,aAAY;IACZ,OAAO;IACP,WAAW,MAAM,EAAU,EAAE,OAAO,MAAM;IAC1C,CAAA;GACF,kBAAC,UAAD;IACM;IACJ,WAAW;IACJ;IACP,WAAW,MAAM,EAAS,EAAE,OAAO,MAAM;cAJ3C,CAME,kBAAC,UAAD;KAAQ,OAAM;eACX,KAAW,CAAC,IACT,eACA,EAAY,SACV,wBACA;KACC,CAAA,EACR,EAAY,KAAK,MAChB,kBAAC,UAAD;KAAmB,OAAO,EAAE;eACzB,EAAE;KACI,EAFI,EAAE,GAEN,CACT,CACK;;GACR,IAAQ,EAAM,UACb,kBAAC,KAAD;IAAG,WAAU;cAAb;KAA6C;KAClC,EAAM;KAAO;KAAK;KAAM;KAC/B;;GAEF"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Portfolio controls (BOFF-8047). Portfolios were `api-only` — full CRUD and the overview roll-up existed in
|
|
3
|
+
* the service (BOFF-7704, BOFF-7934) but had zero routes anywhere in the UI.
|
|
4
|
+
*/
|
|
5
|
+
export declare const PORTFOLIO_STATUSES: readonly ["ACTIVE", "ON_HOLD", "CLOSED", "ARCHIVED"];
|
|
6
|
+
/** Every StrategicAlignment value. CUSTOM requires `alignmentLabel` — the service refuses CUSTOM without one. */
|
|
7
|
+
export declare const STRATEGIC_ALIGNMENTS: readonly ["REVENUE_GROWTH", "COST_REDUCTION", "CUSTOMER_SATISFACTION", "INNOVATION", "COMPLIANCE", "OPERATIONAL_EXCELLENCE", "MARKET_EXPANSION", "RISK_MITIGATION", "CUSTOM"];
|
|
8
|
+
export declare function PortfolioHeaderActions({ portfolioId, name, status, }: {
|
|
9
|
+
portfolioId: string;
|
|
10
|
+
name: string;
|
|
11
|
+
status: string;
|
|
12
|
+
}): import("react/jsx-runtime").JSX.Element;
|
|
13
|
+
//# sourceMappingURL=PortfolioControls.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PortfolioControls.d.ts","sourceRoot":"","sources":["../../../src/planmagnet/controls/PortfolioControls.tsx"],"names":[],"mappings":"AAWA;;;GAGG;AAEH,eAAO,MAAM,kBAAkB,sDAAuD,CAAC;AAEvF,iHAAiH;AACjH,eAAO,MAAM,oBAAoB,+KAUvB,CAAC;AAuBX,wBAAgB,sBAAsB,CAAC,EACrC,WAAW,EACX,IAAI,EACJ,MAAM,GACP,EAAE;IACD,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CAChB,2CA+EA"}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { usePlanMagnetNavigate as e } from "../providers/PlanMagnetProvider.js";
|
|
2
|
+
import { LEAVES_PAGE_CONTEXT as t, throwOnError as n } from "../utils/mutationResult.js";
|
|
3
|
+
import { ConfirmButton as r, ErrorLine as i } from "./ConfirmButton.js";
|
|
4
|
+
import { enumLabel as a } from "./WorkItemControls.js";
|
|
5
|
+
import { detailPath as o } from "../utils/rowNavigation.js";
|
|
6
|
+
import { useState as s } from "react";
|
|
7
|
+
import { Pencil as c, Trash2 as l } from "lucide-react";
|
|
8
|
+
import { gql as u } from "@apollo/client";
|
|
9
|
+
import { useMutation 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/controls/PortfolioControls.tsx
|
|
13
|
+
var h = [
|
|
14
|
+
"ACTIVE",
|
|
15
|
+
"ON_HOLD",
|
|
16
|
+
"CLOSED",
|
|
17
|
+
"ARCHIVED"
|
|
18
|
+
], g = [
|
|
19
|
+
"REVENUE_GROWTH",
|
|
20
|
+
"COST_REDUCTION",
|
|
21
|
+
"CUSTOMER_SATISFACTION",
|
|
22
|
+
"INNOVATION",
|
|
23
|
+
"COMPLIANCE",
|
|
24
|
+
"OPERATIONAL_EXCELLENCE",
|
|
25
|
+
"MARKET_EXPANSION",
|
|
26
|
+
"RISK_MITIGATION",
|
|
27
|
+
"CUSTOM"
|
|
28
|
+
], _ = [
|
|
29
|
+
"ListPortfolios",
|
|
30
|
+
"GetPortfolio",
|
|
31
|
+
"GetPortfolioForEdit",
|
|
32
|
+
"GetPortfolioOverview"
|
|
33
|
+
], v = u`
|
|
34
|
+
mutation PortfolioControlsStatus($id: ID!, $input: PlanmagnetUpdatePortfolioInput!) {
|
|
35
|
+
planmagnetUpdatePortfolio(id: $id, input: $input) {
|
|
36
|
+
id
|
|
37
|
+
status
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
`, y = u`
|
|
41
|
+
mutation PortfolioControlsDelete($id: ID!) {
|
|
42
|
+
planmagnetDeletePortfolio(id: $id)
|
|
43
|
+
}
|
|
44
|
+
`;
|
|
45
|
+
function b({ portfolioId: u, name: g, status: b }) {
|
|
46
|
+
let x = e(), [S, C] = d(v, {
|
|
47
|
+
refetchQueries: _,
|
|
48
|
+
awaitRefetchQueries: !0
|
|
49
|
+
}), [w, T] = d(y, {
|
|
50
|
+
refetchQueries: _.filter((e) => e !== "GetPortfolio" && e !== "GetPortfolioOverview"),
|
|
51
|
+
context: t
|
|
52
|
+
}), [E, D] = s(null), O = C.loading || T.loading, k = h.includes(b) ? h : [b, ...h], A = async (e) => {
|
|
53
|
+
D(null);
|
|
54
|
+
try {
|
|
55
|
+
await n(S({ variables: {
|
|
56
|
+
id: u,
|
|
57
|
+
input: { status: e }
|
|
58
|
+
} }));
|
|
59
|
+
} catch (e) {
|
|
60
|
+
D(e instanceof Error ? e.message : "The status could not be changed.");
|
|
61
|
+
}
|
|
62
|
+
}, j = async () => {
|
|
63
|
+
D(null);
|
|
64
|
+
try {
|
|
65
|
+
await n(w({ variables: { id: u } })), x("/products/portfolios-page");
|
|
66
|
+
} catch (e) {
|
|
67
|
+
D(e instanceof Error ? e.message : "The portfolio could not be deleted.");
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
return /* @__PURE__ */ p("div", {
|
|
71
|
+
className: "flex flex-col items-end gap-2",
|
|
72
|
+
children: [/* @__PURE__ */ p("div", {
|
|
73
|
+
className: "flex flex-wrap items-center justify-end gap-2",
|
|
74
|
+
children: [
|
|
75
|
+
/* @__PURE__ */ f("select", {
|
|
76
|
+
"aria-label": "Portfolio status",
|
|
77
|
+
"data-testid": "portfolio-status",
|
|
78
|
+
className: "rounded-md border border-input bg-background px-2 py-1 text-sm disabled:opacity-60",
|
|
79
|
+
value: b,
|
|
80
|
+
disabled: O,
|
|
81
|
+
onChange: (e) => {
|
|
82
|
+
e.target.value !== b && A(e.target.value);
|
|
83
|
+
},
|
|
84
|
+
children: k.map((e) => /* @__PURE__ */ f("option", {
|
|
85
|
+
value: e,
|
|
86
|
+
children: a(e)
|
|
87
|
+
}, e))
|
|
88
|
+
}),
|
|
89
|
+
/* @__PURE__ */ p(m, {
|
|
90
|
+
size: "sm",
|
|
91
|
+
variant: "outline",
|
|
92
|
+
"data-testid": "portfolio-edit",
|
|
93
|
+
onClick: () => x(o("/products/edit-portfolio-page", u)),
|
|
94
|
+
children: [/* @__PURE__ */ f(c, { className: "mr-1 h-4 w-4" }), "Edit"]
|
|
95
|
+
}),
|
|
96
|
+
/* @__PURE__ */ f(r, {
|
|
97
|
+
label: "Delete",
|
|
98
|
+
variant: "outline",
|
|
99
|
+
icon: /* @__PURE__ */ f(l, { className: "mr-1 h-4 w-4" }),
|
|
100
|
+
title: `Delete portfolio ${g}?`,
|
|
101
|
+
description: "The portfolio is deleted. Programs and projects it groups are not deleted. This cannot be undone here.",
|
|
102
|
+
confirmLabel: "Delete portfolio",
|
|
103
|
+
destructive: !0,
|
|
104
|
+
disabled: O,
|
|
105
|
+
onConfirm: () => void j()
|
|
106
|
+
})
|
|
107
|
+
]
|
|
108
|
+
}), E && /* @__PURE__ */ f(i, { message: E })]
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
//#endregion
|
|
112
|
+
export { h as PORTFOLIO_STATUSES, b as PortfolioHeaderActions, g as STRATEGIC_ALIGNMENTS };
|
|
113
|
+
|
|
114
|
+
//# sourceMappingURL=PortfolioControls.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PortfolioControls.js","names":[],"sources":["../../../src/planmagnet/controls/PortfolioControls.tsx"],"sourcesContent":["import { useState } from 'react';\nimport { gql } from '@apollo/client';\nimport { useMutation } from '@apollo/client/react';\nimport { Button } from '@burdenoff/fe-libs/ui';\nimport { Pencil, Trash2 } from 'lucide-react';\nimport { usePlanMagnetNavigate } from '../providers/PlanMagnetProvider';\nimport { detailPath } from '../utils/rowNavigation';\nimport { throwOnError, LEAVES_PAGE_CONTEXT } from '../utils/mutationResult';\nimport { ConfirmButton, ErrorLine } from './ConfirmButton';\nimport { enumLabel } from './WorkItemControls';\n\n/**\n * Portfolio controls (BOFF-8047). Portfolios were `api-only` — full CRUD and the overview roll-up existed in\n * the service (BOFF-7704, BOFF-7934) but had zero routes anywhere in the UI.\n */\n\nexport const PORTFOLIO_STATUSES = ['ACTIVE', 'ON_HOLD', 'CLOSED', 'ARCHIVED'] as const;\n\n/** Every StrategicAlignment value. CUSTOM requires `alignmentLabel` — the service refuses CUSTOM without one. */\nexport const STRATEGIC_ALIGNMENTS = [\n 'REVENUE_GROWTH',\n 'COST_REDUCTION',\n 'CUSTOMER_SATISFACTION',\n 'INNOVATION',\n 'COMPLIANCE',\n 'OPERATIONAL_EXCELLENCE',\n 'MARKET_EXPANSION',\n 'RISK_MITIGATION',\n 'CUSTOM',\n] as const;\n\nconst PORTFOLIO_QUERIES = [\n 'ListPortfolios',\n 'GetPortfolio',\n 'GetPortfolioForEdit',\n 'GetPortfolioOverview',\n];\n\nconst UPDATE_STATUS = gql`\n mutation PortfolioControlsStatus($id: ID!, $input: PlanmagnetUpdatePortfolioInput!) {\n planmagnetUpdatePortfolio(id: $id, input: $input) {\n id\n status\n }\n }\n`;\nconst DELETE = gql`\n mutation PortfolioControlsDelete($id: ID!) {\n planmagnetDeletePortfolio(id: $id)\n }\n`;\n\nexport function PortfolioHeaderActions({\n portfolioId,\n name,\n status,\n}: {\n portfolioId: string;\n name: string;\n status: string;\n}) {\n const navigate = usePlanMagnetNavigate();\n const [updateStatus, statusState] = useMutation(UPDATE_STATUS, {\n refetchQueries: PORTFOLIO_QUERIES,\n awaitRefetchQueries: true,\n });\n const [remove, removeState] = useMutation(DELETE, {\n refetchQueries: PORTFOLIO_QUERIES.filter(\n (q) => q !== 'GetPortfolio' && q !== 'GetPortfolioOverview'\n ),\n context: LEAVES_PAGE_CONTEXT,\n });\n const [error, setError] = useState<string | null>(null);\n const busy = statusState.loading || removeState.loading;\n const statuses = (PORTFOLIO_STATUSES as readonly string[]).includes(status)\n ? PORTFOLIO_STATUSES\n : [status, ...PORTFOLIO_STATUSES];\n\n const onStatus = async (next: string) => {\n setError(null);\n try {\n await throwOnError(updateStatus({ variables: { id: portfolioId, input: { status: next } } }));\n } catch (e) {\n setError(e instanceof Error ? e.message : 'The status could not be changed.');\n }\n };\n const onDelete = async () => {\n setError(null);\n try {\n await throwOnError(remove({ variables: { id: portfolioId } }));\n navigate('/products/portfolios-page');\n } catch (e) {\n setError(e instanceof Error ? e.message : 'The portfolio could not be deleted.');\n }\n };\n\n return (\n <div className=\"flex flex-col items-end gap-2\">\n <div className=\"flex flex-wrap items-center justify-end gap-2\">\n <select\n aria-label=\"Portfolio status\"\n data-testid=\"portfolio-status\"\n className=\"rounded-md border border-input bg-background px-2 py-1 text-sm disabled:opacity-60\"\n value={status}\n disabled={busy}\n onChange={(e) => {\n if (e.target.value !== status) void onStatus(e.target.value);\n }}\n >\n {statuses.map((s) => (\n <option key={s} value={s}>\n {enumLabel(s)}\n </option>\n ))}\n </select>\n <Button\n size=\"sm\"\n variant=\"outline\"\n data-testid=\"portfolio-edit\"\n onClick={() => navigate(detailPath('/products/edit-portfolio-page', portfolioId))}\n >\n <Pencil className=\"mr-1 h-4 w-4\" />\n Edit\n </Button>\n <ConfirmButton\n label=\"Delete\"\n variant=\"outline\"\n icon={<Trash2 className=\"mr-1 h-4 w-4\" />}\n title={`Delete portfolio ${name}?`}\n description=\"The portfolio is deleted. Programs and projects it groups are not deleted. This cannot be undone here.\"\n confirmLabel=\"Delete portfolio\"\n destructive\n disabled={busy}\n onConfirm={() => void onDelete()}\n />\n </div>\n {error && <ErrorLine message={error} />}\n </div>\n );\n}\n"],"mappings":";;;;;;;;;;;;AAgBA,IAAa,IAAqB;CAAC;CAAU;CAAW;CAAU;CAAW,EAGhE,IAAuB;CAClC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD,EAEK,IAAoB;CACxB;CACA;CACA;CACA;CACD,EAEK,IAAgB,CAAG;;;;;;;GAQnB,IAAS,CAAG;;;;;AAMlB,SAAgB,EAAuB,EACrC,gBACA,SACA,aAKC;CACD,IAAM,IAAW,GAAuB,EAClC,CAAC,GAAc,KAAe,EAAY,GAAe;EAC7D,gBAAgB;EAChB,qBAAqB;EACtB,CAAC,EACI,CAAC,GAAQ,KAAe,EAAY,GAAQ;EAChD,gBAAgB,EAAkB,QAC/B,MAAM,MAAM,kBAAkB,MAAM,uBACtC;EACD,SAAS;EACV,CAAC,EACI,CAAC,GAAO,KAAY,EAAwB,KAAK,EACjD,IAAO,EAAY,WAAW,EAAY,SAC1C,IAAY,EAAyC,SAAS,EAAO,GACvE,IACA,CAAC,GAAQ,GAAG,EAAmB,EAE7B,IAAW,OAAO,MAAiB;AACvC,IAAS,KAAK;AACd,MAAI;AACF,SAAM,EAAa,EAAa,EAAE,WAAW;IAAE,IAAI;IAAa,OAAO,EAAE,QAAQ,GAAM;IAAE,EAAE,CAAC,CAAC;WACtF,GAAG;AACV,KAAS,aAAa,QAAQ,EAAE,UAAU,mCAAmC;;IAG3E,IAAW,YAAY;AAC3B,IAAS,KAAK;AACd,MAAI;AAEF,GADA,MAAM,EAAa,EAAO,EAAE,WAAW,EAAE,IAAI,GAAa,EAAE,CAAC,CAAC,EAC9D,EAAS,4BAA4B;WAC9B,GAAG;AACV,KAAS,aAAa,QAAQ,EAAE,UAAU,sCAAsC;;;AAIpF,QACE,kBAAC,OAAD;EAAK,WAAU;YAAf,CACE,kBAAC,OAAD;GAAK,WAAU;aAAf;IACE,kBAAC,UAAD;KACE,cAAW;KACX,eAAY;KACZ,WAAU;KACV,OAAO;KACP,UAAU;KACV,WAAW,MAAM;AACf,MAAI,EAAE,OAAO,UAAU,KAAa,EAAS,EAAE,OAAO,MAAM;;eAG7D,EAAS,KAAK,MACb,kBAAC,UAAD;MAAgB,OAAO;gBACpB,EAAU,EAAE;MACN,EAFI,EAEJ,CACT;KACK,CAAA;IACT,kBAAC,GAAD;KACE,MAAK;KACL,SAAQ;KACR,eAAY;KACZ,eAAe,EAAS,EAAW,iCAAiC,EAAY,CAAC;eAJnF,CAME,kBAAC,GAAD,EAAQ,WAAU,gBAAiB,CAAA,EAAA,OAE5B;;IACT,kBAAC,GAAD;KACE,OAAM;KACN,SAAQ;KACR,MAAM,kBAAC,GAAD,EAAQ,WAAU,gBAAiB,CAAA;KACzC,OAAO,oBAAoB,EAAK;KAChC,aAAY;KACZ,cAAa;KACb,aAAA;KACA,UAAU;KACV,iBAAiB,KAAK,GAAU;KAChC,CAAA;IACE;MACL,KAAS,kBAAC,GAAD,EAAW,SAAS,GAAS,CAAA,CACnC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Program controls (BOFF-8047). Programs were `api-only` — full CRUD and project attachment existed in the
|
|
3
|
+
* service (BOFF-7704) but had zero routes anywhere in the UI. `Program.status` reuses `PlanmagnetProjectStatus`
|
|
4
|
+
* (the SDL declares it that way), so the status list is the same as a project's.
|
|
5
|
+
*/
|
|
6
|
+
export declare const PROGRAM_STATUSES: readonly ["PLANNING", "ACTIVE", "ON_HOLD", "COMPLETED", "CANCELLED", "ARCHIVED"];
|
|
7
|
+
export declare function ProgramHeaderActions({ programId, name, status, }: {
|
|
8
|
+
programId: string;
|
|
9
|
+
name: string;
|
|
10
|
+
status: string;
|
|
11
|
+
}): import("react/jsx-runtime").JSX.Element;
|
|
12
|
+
/**
|
|
13
|
+
* Add / remove projects on a program. `Program.projects` reads `Project.programId` (BOFF-7704); the only
|
|
14
|
+
* mutation that writes it is `planmagnetUpdateProject`, so attaching happens from the project side even
|
|
15
|
+
* though this card lives on the program.
|
|
16
|
+
*/
|
|
17
|
+
export declare function ProgramProjectsCard({ programId, projects, }: {
|
|
18
|
+
programId: string;
|
|
19
|
+
projects: {
|
|
20
|
+
id: string;
|
|
21
|
+
name: string;
|
|
22
|
+
status: string;
|
|
23
|
+
}[];
|
|
24
|
+
}): import("react/jsx-runtime").JSX.Element;
|
|
25
|
+
//# sourceMappingURL=ProgramControls.d.ts.map
|