@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
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DashboardDashboardPagePage.js","names":[],"sources":["../../../src/planmagnet/pages/DashboardDashboardPagePage.tsx"],"sourcesContent":["// eslint-disable-next-line @typescript-eslint/ban-ts-comment\n// @ts-nocheck\nimport { gql } from '@apollo/client';\nimport { useQuery } from '@apollo/client/react';\nimport { Card, CardContent, CardHeader, CardTitle, Badge } from '@burdenoff/fe-libs/ui';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport {\n LayoutDashboard,\n FolderKanban,\n CheckSquare,\n Zap,\n Users,\n Calendar,\n TrendingUp,\n AlertTriangle,\n ArrowUpRight,\n} from 'lucide-react';\nimport { usePlanMagnet, usePlanMagnetNavigate } from '../providers/PlanMagnetProvider';\nimport { countLabel, useProjectCounts, useSprintCounts, workProgress } from '../hooks/useCounts';\nimport { ROW_LINK_CLASS, detailPath, rowLinkProps } from '../utils/rowNavigation';\nimport { PersonName } from '../people/People';\n\n// What the dashboard shows is what it queries (BOFF-7969/7970/7975): active and in-review sprints, the nearest\n// upcoming milestones, active and on-hold projects. It used to load the 50 newest of everything and filter in the\n// browser, so a long-running sprint or an older project dropped off, and \"upcoming\" meant \"newest-created\".\nconst GET_DASHBOARD_DATA = gql`\n query GetDashboardData($workspaceId: ID!, $today: DateTime) {\n activeProjects: planmagnetProjects(\n workspaceId: $workspaceId\n filter: { status: ACTIVE }\n pagination: { first: 20 }\n ) {\n items {\n id\n name\n status\n ownerId\n }\n totalCount\n }\n onHoldProjects: planmagnetProjects(\n workspaceId: $workspaceId\n filter: { status: ON_HOLD }\n pagination: { first: 20 }\n ) {\n items {\n id\n name\n status\n }\n totalCount\n }\n activeSprints: planmagnetSprints(\n workspaceId: $workspaceId\n filter: { status: ACTIVE }\n pagination: { first: 20 }\n ) {\n items {\n ...DashboardSprint\n }\n }\n reviewSprints: planmagnetSprints(\n workspaceId: $workspaceId\n filter: { status: REVIEW }\n pagination: { first: 20 }\n ) {\n items {\n ...DashboardSprint\n }\n }\n upcomingMilestones: planmagnetMilestones(\n workspaceId: $workspaceId\n filter: { open: true, dueFrom: $today }\n orderBy: DUE_SOONEST\n pagination: { first: 4 }\n ) {\n items {\n id\n name\n status\n dueDate\n project {\n id\n name\n }\n }\n totalCount\n }\n allMilestones: planmagnetMilestones(workspaceId: $workspaceId, pagination: { first: 1 }) {\n totalCount\n }\n planmagnetWorkItems(workspaceId: $workspaceId, pagination: { first: 5 }) {\n items {\n id\n key\n title\n status\n storyPoints\n assigneeId\n project {\n id\n name\n }\n }\n totalCount\n }\n }\n\n fragment DashboardSprint on Sprint {\n id\n name\n status\n startDate\n endDate\n project {\n id\n name\n }\n workItems {\n id\n status\n storyPoints\n }\n }\n`;\n\nexport function DashboardDashboardPagePage() {\n const { workspaceId } = usePlanMagnet();\n const { t } = useI18n();\n\n const {\n data,\n loading,\n error,\n } = // eslint-disable-next-line @typescript-eslint/no-explicit-any\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n useQuery<Record<string, any>>(GET_DASHBOARD_DATA, {\n // \"Upcoming\" starts today (UTC day); overdue milestones are Analytics' \"at risk\", not upcoming.\n variables: {\n workspaceId: workspaceId ?? 'default',\n today: new Date().toISOString().slice(0, 10),\n },\n });\n const projectCounts = useProjectCounts();\n const sprintCounts = useSprintCounts();\n const navigate = usePlanMagnetNavigate();\n\n // Only before the first load: a refetch must not blank the page (it\n\n // unmounts every component on it and loses their state).\n\n if (loading && !data)\n return (\n <div className=\"flex items-center justify-center p-12\">\n <div className=\"animate-spin h-8 w-8 border-2 border-primary border-t-transparent rounded-full\" />\n </div>\n );\n if (error)\n return (\n <div className=\"p-6 text-red-500\">\n {t('planmagnet.dashboard.errorLoading', 'Error loading dashboard')}: {error.message}\n </div>\n );\n\n const activeProjects = data?.activeProjects?.items ?? [];\n const onHoldProjects = data?.onHoldProjects?.items ?? [];\n const activeSprints = [\n ...(data?.activeSprints?.items ?? []),\n ...(data?.reviewSprints?.items ?? []),\n ];\n const upcomingMilestones = data?.upcomingMilestones?.items ?? [];\n const recentWorkItems = data?.planmagnetWorkItems?.items ?? [];\n\n const metrics = [\n {\n label: t('planmagnet.dashboard.metrics.totalProjects.label', 'Total Projects'),\n value: countLabel(projectCounts?.all),\n trend: `${countLabel(projectCounts?.active)} ${t('planmagnet.dashboard.metrics.totalProjects.trend', 'active')}`,\n },\n {\n label: t('planmagnet.dashboard.metrics.activeSprints.label', 'Active Sprints'),\n value: countLabel(sprintCounts?.running),\n trend: `${countLabel(sprintCounts?.all)} ${t('planmagnet.dashboard.metrics.activeSprints.trend', 'total')}`,\n },\n {\n label: t('planmagnet.dashboard.metrics.workItems.label', 'Work Items'),\n value: countLabel(data?.planmagnetWorkItems?.totalCount),\n trend: t('planmagnet.dashboard.metrics.workItems.trend', 'across all projects'),\n },\n {\n label: t('planmagnet.dashboard.metrics.milestones.label', 'Milestones'),\n value: countLabel(data?.allMilestones?.totalCount),\n trend: `${countLabel(data?.upcomingMilestones?.totalCount)} ${t('planmagnet.dashboard.metrics.milestones.trend', 'upcoming')}`,\n },\n ];\n\n return (\n <div className=\"space-y-6 p-6\">\n <div className=\"flex items-center justify-between\">\n <div>\n <h1 className=\"text-2xl font-semibold flex items-center gap-2\">\n <LayoutDashboard className=\"h-6 w-6\" />\n {t('planmagnet.dashboard.title', 'Dashboard')}\n </h1>\n <p className=\"text-sm text-muted-foreground mt-1\">\n {t('planmagnet.dashboard.subtitle', 'Welcome back! Here is your project overview.')}\n </p>\n </div>\n </div>\n\n {/* KPI Metrics */}\n <div className=\"grid gap-4 md:grid-cols-2 lg:grid-cols-4\">\n {metrics.map((m) => (\n <Card key={m.label}>\n <CardHeader className=\"flex flex-row items-center justify-between space-y-0 pb-2\">\n <CardTitle className=\"text-sm font-medium\">{m.label}</CardTitle>\n <TrendingUp className=\"h-4 w-4 text-muted-foreground\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold\">{m.value}</div>\n <p className=\"text-xs text-muted-foreground\">{m.trend}</p>\n </CardContent>\n </Card>\n ))}\n </div>\n\n <div className=\"grid gap-6 lg:grid-cols-12\">\n {/* Active Sprints */}\n <Card className=\"lg:col-span-8\">\n <CardHeader>\n <CardTitle className=\"flex items-center gap-2 text-base\">\n <Zap className=\"h-5 w-5 text-blue-500\" />\n {t('planmagnet.dashboard.activeSprints.title', 'Active Sprints')}\n </CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-4\">\n {activeSprints.map(\n (sprint: {\n id: string;\n name: string;\n projectId: string;\n capacity: number | null;\n velocity: number | null;\n startDate: string | null;\n endDate: string | null;\n workItems: { id: string; status: string; storyPoints: number | null }[];\n }) => {\n const totalPoints = sprint.workItems.reduce(\n (sum: number, wi: { storyPoints: number | null }) => sum + (wi.storyPoints ?? 0),\n 0\n );\n const completedPoints = sprint.workItems\n .filter((wi: { status: string }) => wi.status === 'DONE')\n .reduce(\n (sum: number, wi: { storyPoints: number | null }) =>\n sum + (wi.storyPoints ?? 0),\n 0\n );\n const totalTasks = sprint.workItems.length;\n const completedTasks = sprint.workItems.filter(\n (wi: { status: string }) => wi.status === 'DONE'\n ).length;\n // Done over everything not cancelled; by points, or by tasks when nothing is estimated (BOFF-7989).\n const pct = workProgress(sprint.workItems) ?? 0;\n return (\n <div\n key={sprint.id}\n {...rowLinkProps(\n () => navigate(detailPath('/projects/planning-detail-page', sprint.id)),\n sprint.name\n )}\n className={`rounded-lg border p-4 ${ROW_LINK_CLASS}`}\n >\n <div className=\"flex items-center justify-between mb-2\">\n <div>\n <p className=\"font-medium\">{sprint.name}</p>\n <p className=\"text-xs text-muted-foreground\">\n {t('planmagnet.dashboard.shared.project', 'Project')}:{' '}\n {sprint.project?.name ??\n t('planmagnet.dashboard.shared.projectUnavailable', 'not available')}\n </p>\n </div>\n <Badge variant=\"secondary\">\n {completedPoints}/{totalPoints}{' '}\n {t('planmagnet.dashboard.shared.pointsShort', 'pts')}\n </Badge>\n </div>\n <div className=\"w-full h-2 bg-muted rounded-full overflow-hidden\">\n <div\n className=\"h-full bg-primary rounded-full transition-all\"\n style={{ width: `${pct}%` }}\n />\n </div>\n <div className=\"flex items-center justify-between mt-2 text-xs text-muted-foreground\">\n <span>\n {completedTasks}/{totalTasks}{' '}\n {t('planmagnet.dashboard.shared.tasks', 'tasks')}\n </span>\n <span>\n {sprint.startDate ? new Date(sprint.startDate).toLocaleDateString() : '—'} -{' '}\n {sprint.endDate ? new Date(sprint.endDate).toLocaleDateString() : '—'}\n </span>\n </div>\n </div>\n );\n }\n )}\n {activeSprints.length === 0 && (\n <p className=\"text-sm text-muted-foreground text-center py-4\">\n {t('planmagnet.dashboard.activeSprints.empty', 'No active sprints.')}\n </p>\n )}\n </CardContent>\n </Card>\n\n {/* Sidebar */}\n <div className=\"lg:col-span-4 space-y-6\">\n {/* On-Hold Projects */}\n {onHoldProjects.length > 0 && (\n <Card>\n <CardHeader>\n <CardTitle className=\"flex items-center gap-2 text-base\">\n <AlertTriangle className=\"h-5 w-5 text-orange-500\" />\n {t('planmagnet.dashboard.onHoldProjects.title', 'On-Hold Projects')}\n </CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n {onHoldProjects.map((p: { id: string; name: string; status: string }) => (\n <div key={p.id} className=\"flex items-center justify-between rounded border p-2\">\n <div>\n <p className=\"text-sm font-medium\">{p.name}</p>\n </div>\n <Badge variant=\"destructive\">{p.status.toLowerCase().replace('_', ' ')}</Badge>\n </div>\n ))}\n </CardContent>\n </Card>\n )}\n\n {/* Upcoming Milestones */}\n <Card>\n <CardHeader>\n <CardTitle className=\"flex items-center gap-2 text-base\">\n <Calendar className=\"h-5 w-5 text-green-500\" />\n {t('planmagnet.dashboard.upcomingMilestones.title', 'Upcoming Milestones')}\n </CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n {upcomingMilestones.map(\n (ms: {\n id: string;\n name: string;\n projectId: string;\n dueDate: string | null;\n status: string;\n }) => (\n <div\n key={ms.id}\n {...rowLinkProps(\n () => navigate(detailPath('/projects/milestone-detail-page', ms.id)),\n ms.name\n )}\n className={`flex items-start gap-3 rounded border p-2 ${ROW_LINK_CLASS}`}\n >\n <div className=\"flex-1 min-w-0\">\n <p className=\"text-sm font-medium truncate\">{ms.name}</p>\n <p className=\"text-xs text-muted-foreground\">\n {t('planmagnet.dashboard.shared.project', 'Project')}:{' '}\n {ms.project?.name ??\n t('planmagnet.dashboard.shared.projectUnavailable', 'not available')}\n </p>\n <p className=\"text-xs text-muted-foreground\">\n {t('planmagnet.dashboard.shared.due', 'Due')}{' '}\n {ms.dueDate ? new Date(ms.dueDate).toLocaleDateString() : '—'}\n </p>\n </div>\n <Badge variant=\"secondary\" className=\"text-xs flex-shrink-0 capitalize\">\n {ms.status.toLowerCase().replace('_', ' ')}\n </Badge>\n </div>\n )\n )}\n {upcomingMilestones.length === 0 && (\n <p className=\"text-sm text-muted-foreground text-center py-2\">\n {t('planmagnet.dashboard.upcomingMilestones.empty', 'No upcoming milestones.')}\n </p>\n )}\n </CardContent>\n </Card>\n </div>\n </div>\n\n {/* Recent Work Items & Project Status */}\n <div className=\"grid gap-6 lg:grid-cols-2\">\n <Card>\n <CardHeader>\n <CardTitle className=\"flex items-center gap-2 text-base\">\n <CheckSquare className=\"h-5 w-5 text-purple-500\" />\n {t('planmagnet.dashboard.recentWorkItems.title', 'Recent Work Items')}\n </CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n {recentWorkItems.map(\n (item: {\n id: string;\n key: string;\n description: string | null;\n status: string;\n storyPoints: number | null;\n assigneeId: string | null;\n projectId: string;\n }) => (\n <div\n key={item.id}\n {...rowLinkProps(\n () => navigate(`/tasks/task-detail-page?taskId=${encodeURIComponent(item.id)}`),\n `${item.key} ${item.title}`\n )}\n className={`flex items-center justify-between rounded border p-2 ${ROW_LINK_CLASS}`}\n >\n <div className=\"min-w-0 flex-1\">\n <p className=\"text-sm font-medium truncate\">\n {item.key} <span className=\"font-normal\">{item.title}</span>\n </p>\n <p className=\"text-xs text-muted-foreground\">\n {item.project?.name ??\n t('planmagnet.dashboard.shared.projectUnavailable', 'not available')}\n {item.assigneeId ? (\n <>\n {' \\u00b7 '}\n <PersonName id={item.assigneeId} />\n </>\n ) : null}\n </p>\n </div>\n <div className=\"flex items-center gap-2 flex-shrink-0\">\n <Badge variant=\"outline\" className=\"text-xs\">\n {item.storyPoints ?? 0} {t('planmagnet.dashboard.shared.pointsShort', 'pts')}\n </Badge>\n <Badge variant=\"secondary\" className=\"text-xs capitalize\">\n {item.status.toLowerCase().replace('_', ' ')}\n </Badge>\n </div>\n </div>\n )\n )}\n {recentWorkItems.length === 0 && (\n <p className=\"text-sm text-muted-foreground text-center py-4\">\n {t('planmagnet.dashboard.recentWorkItems.empty', 'No work items yet.')}\n </p>\n )}\n </CardContent>\n </Card>\n\n <Card>\n <CardHeader>\n <CardTitle className=\"flex items-center gap-2 text-base\">\n <FolderKanban className=\"h-5 w-5 text-cyan-500\" />\n {t('planmagnet.dashboard.projectStatus.title', 'Project Status')}\n </CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n {activeProjects.map(\n (p: { id: string; name: string; status: string; ownerId: string }) => (\n // The row opens the project: it drew an \"open\" arrow but did nothing (BOFF-7981).\n <div\n key={p.id}\n {...rowLinkProps(\n () => navigate(detailPath('/projects/project-detail-page', p.id)),\n p.name\n )}\n className={`flex items-center justify-between rounded border p-2 ${ROW_LINK_CLASS}`}\n >\n <div className=\"min-w-0 flex-1\">\n <p className=\"text-sm font-medium truncate\">{p.name}</p>\n <p className=\"text-xs text-muted-foreground capitalize\">\n {p.status.toLowerCase().replace('_', ' ')}\n </p>\n </div>\n <div className=\"flex items-center gap-2 ml-3 flex-shrink-0\">\n <Users className=\"h-3 w-3 text-muted-foreground\" />\n <span className=\"text-xs text-muted-foreground\">\n <PersonName id={p.ownerId} />\n </span>\n <ArrowUpRight className=\"h-3 w-3 text-muted-foreground\" />\n </div>\n </div>\n )\n )}\n {activeProjects.length === 0 && (\n <p className=\"text-sm text-muted-foreground text-center py-4\">\n {t('planmagnet.dashboard.projectStatus.empty', 'No active projects.')}\n </p>\n )}\n </CardContent>\n </Card>\n </div>\n </div>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"DashboardDashboardPagePage.js","names":[],"sources":["../../../src/planmagnet/pages/DashboardDashboardPagePage.tsx"],"sourcesContent":["// eslint-disable-next-line @typescript-eslint/ban-ts-comment\n// @ts-nocheck\nimport { gql } from '@apollo/client';\nimport { useQuery } from '@apollo/client/react';\nimport { Card, CardContent, CardHeader, CardTitle, Badge } from '@burdenoff/fe-libs/ui';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport {\n LayoutDashboard,\n FolderKanban,\n CheckSquare,\n Zap,\n Users,\n Calendar,\n TrendingUp,\n AlertTriangle,\n ArrowUpRight,\n} from 'lucide-react';\nimport { usePlanMagnet, usePlanMagnetNavigate } from '../providers/PlanMagnetProvider';\nimport { countLabel, useProjectCounts, useSprintCounts, workProgress } from '../hooks/useCounts';\nimport { ROW_LINK_CLASS, detailPath, rowLinkProps } from '../utils/rowNavigation';\nimport { PersonName } from '../people/People';\n\n// What the dashboard shows is what it queries (BOFF-7969/7970/7975): active and in-review sprints, the nearest\n// upcoming milestones, active and on-hold projects. It used to load the 50 newest of everything and filter in the\n// browser, so a long-running sprint or an older project dropped off, and \"upcoming\" meant \"newest-created\".\nconst GET_DASHBOARD_DATA = gql`\n query GetDashboardData($workspaceId: ID!, $today: DateTime) {\n activeProjects: planmagnetProjects(\n workspaceId: $workspaceId\n filter: { status: ACTIVE }\n pagination: { first: 20 }\n ) {\n items {\n id\n name\n status\n ownerId\n }\n totalCount\n }\n onHoldProjects: planmagnetProjects(\n workspaceId: $workspaceId\n filter: { status: ON_HOLD }\n pagination: { first: 20 }\n ) {\n items {\n id\n name\n status\n }\n totalCount\n }\n activeSprints: planmagnetSprints(\n workspaceId: $workspaceId\n filter: { status: ACTIVE }\n pagination: { first: 20 }\n ) {\n items {\n ...DashboardSprint\n }\n }\n reviewSprints: planmagnetSprints(\n workspaceId: $workspaceId\n filter: { status: REVIEW }\n pagination: { first: 20 }\n ) {\n items {\n ...DashboardSprint\n }\n }\n upcomingMilestones: planmagnetMilestones(\n workspaceId: $workspaceId\n filter: { open: true, dueFrom: $today }\n orderBy: DUE_SOONEST\n pagination: { first: 4 }\n ) {\n items {\n id\n name\n status\n dueDate\n project {\n id\n name\n }\n }\n totalCount\n }\n allMilestones: planmagnetMilestones(workspaceId: $workspaceId, pagination: { first: 1 }) {\n totalCount\n }\n planmagnetWorkItems(workspaceId: $workspaceId, pagination: { first: 5 }) {\n items {\n id\n key\n title\n status\n storyPoints\n assigneeId\n project {\n id\n name\n }\n }\n totalCount\n }\n }\n\n fragment DashboardSprint on Sprint {\n id\n name\n status\n startDate\n endDate\n project {\n id\n name\n }\n team {\n id\n name\n }\n workItems {\n id\n status\n storyPoints\n }\n }\n`;\n\nexport function DashboardDashboardPagePage() {\n const { workspaceId } = usePlanMagnet();\n const { t } = useI18n();\n\n const {\n data,\n loading,\n error,\n } = // eslint-disable-next-line @typescript-eslint/no-explicit-any\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n useQuery<Record<string, any>>(GET_DASHBOARD_DATA, {\n // \"Upcoming\" starts today (UTC day); overdue milestones are Analytics' \"at risk\", not upcoming.\n variables: {\n workspaceId: workspaceId ?? 'default',\n today: new Date().toISOString().slice(0, 10),\n },\n });\n const projectCounts = useProjectCounts();\n const sprintCounts = useSprintCounts();\n const navigate = usePlanMagnetNavigate();\n\n // Only before the first load: a refetch must not blank the page (it\n\n // unmounts every component on it and loses their state).\n\n if (loading && !data)\n return (\n <div className=\"flex items-center justify-center p-12\">\n <div className=\"animate-spin h-8 w-8 border-2 border-primary border-t-transparent rounded-full\" />\n </div>\n );\n if (error)\n return (\n <div className=\"p-6 text-red-500\">\n {t('planmagnet.dashboard.errorLoading', 'Error loading dashboard')}: {error.message}\n </div>\n );\n\n const activeProjects = data?.activeProjects?.items ?? [];\n const onHoldProjects = data?.onHoldProjects?.items ?? [];\n const activeSprints = [\n ...(data?.activeSprints?.items ?? []),\n ...(data?.reviewSprints?.items ?? []),\n ];\n const upcomingMilestones = data?.upcomingMilestones?.items ?? [];\n const recentWorkItems = data?.planmagnetWorkItems?.items ?? [];\n\n const metrics = [\n {\n label: t('planmagnet.dashboard.metrics.totalProjects.label', 'Total Projects'),\n value: countLabel(projectCounts?.all),\n trend: `${countLabel(projectCounts?.active)} ${t('planmagnet.dashboard.metrics.totalProjects.trend', 'active')}`,\n },\n {\n label: t('planmagnet.dashboard.metrics.activeSprints.label', 'Active Sprints'),\n value: countLabel(sprintCounts?.running),\n trend: `${countLabel(sprintCounts?.all)} ${t('planmagnet.dashboard.metrics.activeSprints.trend', 'total')}`,\n },\n {\n label: t('planmagnet.dashboard.metrics.workItems.label', 'Work Items'),\n value: countLabel(data?.planmagnetWorkItems?.totalCount),\n trend: t('planmagnet.dashboard.metrics.workItems.trend', 'across all projects'),\n },\n {\n label: t('planmagnet.dashboard.metrics.milestones.label', 'Milestones'),\n value: countLabel(data?.allMilestones?.totalCount),\n trend: `${countLabel(data?.upcomingMilestones?.totalCount)} ${t('planmagnet.dashboard.metrics.milestones.trend', 'upcoming')}`,\n },\n ];\n\n return (\n <div className=\"space-y-6 p-6\">\n <div className=\"flex items-center justify-between\">\n <div>\n <h1 className=\"text-2xl font-semibold flex items-center gap-2\">\n <LayoutDashboard className=\"h-6 w-6\" />\n {t('planmagnet.dashboard.title', 'Dashboard')}\n </h1>\n <p className=\"text-sm text-muted-foreground mt-1\">\n {t('planmagnet.dashboard.subtitle', 'Welcome back! Here is your project overview.')}\n </p>\n </div>\n </div>\n\n {/* KPI Metrics */}\n <div className=\"grid gap-4 md:grid-cols-2 lg:grid-cols-4\">\n {metrics.map((m) => (\n <Card key={m.label}>\n <CardHeader className=\"flex flex-row items-center justify-between space-y-0 pb-2\">\n <CardTitle className=\"text-sm font-medium\">{m.label}</CardTitle>\n <TrendingUp className=\"h-4 w-4 text-muted-foreground\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold\">{m.value}</div>\n <p className=\"text-xs text-muted-foreground\">{m.trend}</p>\n </CardContent>\n </Card>\n ))}\n </div>\n\n <div className=\"grid gap-6 lg:grid-cols-12\">\n {/* Active Sprints */}\n <Card className=\"lg:col-span-8\">\n <CardHeader>\n <CardTitle className=\"flex items-center gap-2 text-base\">\n <Zap className=\"h-5 w-5 text-blue-500\" />\n {t('planmagnet.dashboard.activeSprints.title', 'Active Sprints')}\n </CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-4\">\n {activeSprints.map(\n (sprint: {\n id: string;\n name: string;\n project: { id: string; name: string } | null;\n team: { id: string; name: string } | null;\n capacity: number | null;\n velocity: number | null;\n startDate: string | null;\n endDate: string | null;\n workItems: { id: string; status: string; storyPoints: number | null }[];\n }) => {\n const totalPoints = sprint.workItems.reduce(\n (sum: number, wi: { storyPoints: number | null }) => sum + (wi.storyPoints ?? 0),\n 0\n );\n const completedPoints = sprint.workItems\n .filter((wi: { status: string }) => wi.status === 'DONE')\n .reduce(\n (sum: number, wi: { storyPoints: number | null }) =>\n sum + (wi.storyPoints ?? 0),\n 0\n );\n const totalTasks = sprint.workItems.length;\n const completedTasks = sprint.workItems.filter(\n (wi: { status: string }) => wi.status === 'DONE'\n ).length;\n // Done over everything not cancelled; by points, or by tasks when nothing is estimated (BOFF-7989).\n const pct = workProgress(sprint.workItems) ?? 0;\n return (\n <div\n key={sprint.id}\n {...rowLinkProps(\n () => navigate(detailPath('/projects/planning-detail-page', sprint.id)),\n sprint.name\n )}\n className={`rounded-lg border p-4 ${ROW_LINK_CLASS}`}\n >\n <div className=\"flex items-center justify-between mb-2\">\n <div>\n <p className=\"font-medium\">{sprint.name}</p>\n <p className=\"text-xs text-muted-foreground\">\n {sprint.team ? (\n <>\n {t('planmagnet.dashboard.shared.team', 'Team')}: {sprint.team.name}\n </>\n ) : (\n <>\n {t('planmagnet.dashboard.shared.project', 'Project')}:{' '}\n {sprint.project?.name ??\n t(\n 'planmagnet.dashboard.shared.projectUnavailable',\n 'not available'\n )}\n </>\n )}\n </p>\n </div>\n <Badge variant=\"secondary\">\n {completedPoints}/{totalPoints}{' '}\n {t('planmagnet.dashboard.shared.pointsShort', 'pts')}\n </Badge>\n </div>\n <div className=\"w-full h-2 bg-muted rounded-full overflow-hidden\">\n <div\n className=\"h-full bg-primary rounded-full transition-all\"\n style={{ width: `${pct}%` }}\n />\n </div>\n <div className=\"flex items-center justify-between mt-2 text-xs text-muted-foreground\">\n <span>\n {completedTasks}/{totalTasks}{' '}\n {t('planmagnet.dashboard.shared.tasks', 'tasks')}\n </span>\n <span>\n {sprint.startDate ? new Date(sprint.startDate).toLocaleDateString() : '—'} -{' '}\n {sprint.endDate ? new Date(sprint.endDate).toLocaleDateString() : '—'}\n </span>\n </div>\n </div>\n );\n }\n )}\n {activeSprints.length === 0 && (\n <p className=\"text-sm text-muted-foreground text-center py-4\">\n {t('planmagnet.dashboard.activeSprints.empty', 'No active sprints.')}\n </p>\n )}\n </CardContent>\n </Card>\n\n {/* Sidebar */}\n <div className=\"lg:col-span-4 space-y-6\">\n {/* On-Hold Projects */}\n {onHoldProjects.length > 0 && (\n <Card>\n <CardHeader>\n <CardTitle className=\"flex items-center gap-2 text-base\">\n <AlertTriangle className=\"h-5 w-5 text-orange-500\" />\n {t('planmagnet.dashboard.onHoldProjects.title', 'On-Hold Projects')}\n </CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n {onHoldProjects.map((p: { id: string; name: string; status: string }) => (\n <div key={p.id} className=\"flex items-center justify-between rounded border p-2\">\n <div>\n <p className=\"text-sm font-medium\">{p.name}</p>\n </div>\n <Badge variant=\"destructive\">{p.status.toLowerCase().replace('_', ' ')}</Badge>\n </div>\n ))}\n </CardContent>\n </Card>\n )}\n\n {/* Upcoming Milestones */}\n <Card>\n <CardHeader>\n <CardTitle className=\"flex items-center gap-2 text-base\">\n <Calendar className=\"h-5 w-5 text-green-500\" />\n {t('planmagnet.dashboard.upcomingMilestones.title', 'Upcoming Milestones')}\n </CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n {upcomingMilestones.map(\n (ms: {\n id: string;\n name: string;\n projectId: string;\n dueDate: string | null;\n status: string;\n }) => (\n <div\n key={ms.id}\n {...rowLinkProps(\n () => navigate(detailPath('/projects/milestone-detail-page', ms.id)),\n ms.name\n )}\n className={`flex items-start gap-3 rounded border p-2 ${ROW_LINK_CLASS}`}\n >\n <div className=\"flex-1 min-w-0\">\n <p className=\"text-sm font-medium truncate\">{ms.name}</p>\n <p className=\"text-xs text-muted-foreground\">\n {t('planmagnet.dashboard.shared.project', 'Project')}:{' '}\n {ms.project?.name ??\n t('planmagnet.dashboard.shared.projectUnavailable', 'not available')}\n </p>\n <p className=\"text-xs text-muted-foreground\">\n {t('planmagnet.dashboard.shared.due', 'Due')}{' '}\n {ms.dueDate ? new Date(ms.dueDate).toLocaleDateString() : '—'}\n </p>\n </div>\n <Badge variant=\"secondary\" className=\"text-xs flex-shrink-0 capitalize\">\n {ms.status.toLowerCase().replace('_', ' ')}\n </Badge>\n </div>\n )\n )}\n {upcomingMilestones.length === 0 && (\n <p className=\"text-sm text-muted-foreground text-center py-2\">\n {t('planmagnet.dashboard.upcomingMilestones.empty', 'No upcoming milestones.')}\n </p>\n )}\n </CardContent>\n </Card>\n </div>\n </div>\n\n {/* Recent Work Items & Project Status */}\n <div className=\"grid gap-6 lg:grid-cols-2\">\n <Card>\n <CardHeader>\n <CardTitle className=\"flex items-center gap-2 text-base\">\n <CheckSquare className=\"h-5 w-5 text-purple-500\" />\n {t('planmagnet.dashboard.recentWorkItems.title', 'Recent Work Items')}\n </CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n {recentWorkItems.map(\n (item: {\n id: string;\n key: string;\n description: string | null;\n status: string;\n storyPoints: number | null;\n assigneeId: string | null;\n projectId: string;\n }) => (\n <div\n key={item.id}\n {...rowLinkProps(\n () => navigate(`/tasks/task-detail-page?taskId=${encodeURIComponent(item.id)}`),\n `${item.key} ${item.title}`\n )}\n className={`flex items-center justify-between rounded border p-2 ${ROW_LINK_CLASS}`}\n >\n <div className=\"min-w-0 flex-1\">\n <p className=\"text-sm font-medium truncate\">\n {item.key} <span className=\"font-normal\">{item.title}</span>\n </p>\n <p className=\"text-xs text-muted-foreground\">\n {item.project?.name ??\n t('planmagnet.dashboard.shared.projectUnavailable', 'not available')}\n {item.assigneeId ? (\n <>\n {' \\u00b7 '}\n <PersonName id={item.assigneeId} />\n </>\n ) : null}\n </p>\n </div>\n <div className=\"flex items-center gap-2 flex-shrink-0\">\n <Badge variant=\"outline\" className=\"text-xs\">\n {item.storyPoints ?? 0} {t('planmagnet.dashboard.shared.pointsShort', 'pts')}\n </Badge>\n <Badge variant=\"secondary\" className=\"text-xs capitalize\">\n {item.status.toLowerCase().replace('_', ' ')}\n </Badge>\n </div>\n </div>\n )\n )}\n {recentWorkItems.length === 0 && (\n <p className=\"text-sm text-muted-foreground text-center py-4\">\n {t('planmagnet.dashboard.recentWorkItems.empty', 'No work items yet.')}\n </p>\n )}\n </CardContent>\n </Card>\n\n <Card>\n <CardHeader>\n <CardTitle className=\"flex items-center gap-2 text-base\">\n <FolderKanban className=\"h-5 w-5 text-cyan-500\" />\n {t('planmagnet.dashboard.projectStatus.title', 'Project Status')}\n </CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n {activeProjects.map(\n (p: { id: string; name: string; status: string; ownerId: string }) => (\n // The row opens the project: it drew an \"open\" arrow but did nothing (BOFF-7981).\n <div\n key={p.id}\n {...rowLinkProps(\n () => navigate(detailPath('/projects/project-detail-page', p.id)),\n p.name\n )}\n className={`flex items-center justify-between rounded border p-2 ${ROW_LINK_CLASS}`}\n >\n <div className=\"min-w-0 flex-1\">\n <p className=\"text-sm font-medium truncate\">{p.name}</p>\n <p className=\"text-xs text-muted-foreground capitalize\">\n {p.status.toLowerCase().replace('_', ' ')}\n </p>\n </div>\n <div className=\"flex items-center gap-2 ml-3 flex-shrink-0\">\n <Users className=\"h-3 w-3 text-muted-foreground\" />\n <span className=\"text-xs text-muted-foreground\">\n <PersonName id={p.ownerId} />\n </span>\n <ArrowUpRight className=\"h-3 w-3 text-muted-foreground\" />\n </div>\n </div>\n )\n )}\n {activeProjects.length === 0 && (\n <p className=\"text-sm text-muted-foreground text-center py-4\">\n {t('planmagnet.dashboard.projectStatus.empty', 'No active projects.')}\n </p>\n )}\n </CardContent>\n </Card>\n </div>\n </div>\n );\n}\n"],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { usePlanMagnetNavigate as e } from "../providers/PlanMagnetProvider.js";
|
|
2
2
|
import { throwOnError as t } from "../utils/mutationResult.js";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
3
|
+
import { enumLabel as n } from "../controls/WorkItemControls.js";
|
|
4
|
+
import { detailPath as r } from "../utils/rowNavigation.js";
|
|
5
5
|
import { PORTFOLIO_STATUSES as i, STRATEGIC_ALIGNMENTS as a } from "../controls/PortfolioControls.js";
|
|
6
6
|
import { useMemo as o, useState as s } from "react";
|
|
7
7
|
import { ArrowLeft as c, Loader2 as l, Save as u } from "lucide-react";
|
|
@@ -86,7 +86,7 @@ function T() {
|
|
|
86
86
|
variant: "ghost",
|
|
87
87
|
size: "sm",
|
|
88
88
|
"aria-label": "Back to the portfolio",
|
|
89
|
-
onClick: () => f(
|
|
89
|
+
onClick: () => f(r("/products/portfolio-detail-page", T)),
|
|
90
90
|
children: /* @__PURE__ */ h(c, { className: "h-4 w-4" })
|
|
91
91
|
}), /* @__PURE__ */ g("div", { children: [/* @__PURE__ */ h("h1", {
|
|
92
92
|
className: "text-2xl font-semibold",
|
|
@@ -188,7 +188,7 @@ function T() {
|
|
|
188
188
|
}),
|
|
189
189
|
children: V.map((e) => /* @__PURE__ */ h("option", {
|
|
190
190
|
value: e,
|
|
191
|
-
children:
|
|
191
|
+
children: n(e)
|
|
192
192
|
}, e))
|
|
193
193
|
})] }), /* @__PURE__ */ g("div", { children: [/* @__PURE__ */ h("label", {
|
|
194
194
|
htmlFor: "portfolio-edit-alignment",
|
|
@@ -207,7 +207,7 @@ function T() {
|
|
|
207
207
|
children: "Not set"
|
|
208
208
|
}), a.map((e) => /* @__PURE__ */ h("option", {
|
|
209
209
|
value: e,
|
|
210
|
-
children: e === "CUSTOM" ? "Custom…" :
|
|
210
|
+
children: e === "CUSTOM" ? "Custom…" : n(e)
|
|
211
211
|
}, e))]
|
|
212
212
|
})] })]
|
|
213
213
|
}),
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { usePlanMagnetNavigate as e } from "../providers/PlanMagnetProvider.js";
|
|
2
2
|
import { PersonName as t } from "../people/People.js";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
3
|
+
import { enumLabel as n } from "../controls/WorkItemControls.js";
|
|
4
|
+
import { detailPath as r } from "../utils/rowNavigation.js";
|
|
5
5
|
import { PortfolioHeaderActions as i } from "../controls/PortfolioControls.js";
|
|
6
6
|
import { AlertTriangle as a, Briefcase as o, Clock as s, Loader2 as c, Target as l } from "lucide-react";
|
|
7
7
|
import { useParams as u } from "react-router";
|
|
@@ -93,12 +93,12 @@ function S() {
|
|
|
93
93
|
/* @__PURE__ */ p(h, {
|
|
94
94
|
variant: "outline",
|
|
95
95
|
className: "text-xs",
|
|
96
|
-
children:
|
|
96
|
+
children: n(D.status)
|
|
97
97
|
})
|
|
98
98
|
]
|
|
99
99
|
}), D.alignment && /* @__PURE__ */ p("p", {
|
|
100
100
|
className: "text-sm text-muted-foreground mt-1",
|
|
101
|
-
children: D.alignment === "CUSTOM" ? D.alignmentLabel ?? "Custom alignment" :
|
|
101
|
+
children: D.alignment === "CUSTOM" ? D.alignmentLabel ?? "Custom alignment" : n(D.alignment)
|
|
102
102
|
})] }), /* @__PURE__ */ p(i, {
|
|
103
103
|
portfolioId: D.id,
|
|
104
104
|
name: D.name,
|
|
@@ -216,7 +216,7 @@ function S() {
|
|
|
216
216
|
children: "Projects by Status"
|
|
217
217
|
}), /* @__PURE__ */ p("p", {
|
|
218
218
|
className: "text-sm mt-1",
|
|
219
|
-
children: Object.keys(O.projectsByStatus).length > 0 ? Object.entries(O.projectsByStatus).map(([e, t]) => `${
|
|
219
|
+
children: Object.keys(O.projectsByStatus).length > 0 ? Object.entries(O.projectsByStatus).map(([e, t]) => `${n(e)}: ${t}`).join(", ") : "No projects yet"
|
|
220
220
|
})]
|
|
221
221
|
})
|
|
222
222
|
]
|
|
@@ -237,14 +237,14 @@ function S() {
|
|
|
237
237
|
}), D.programs.map((e) => /* @__PURE__ */ m("button", {
|
|
238
238
|
type: "button",
|
|
239
239
|
className: "flex w-full items-center justify-between rounded-md border p-3 text-left hover:bg-muted",
|
|
240
|
-
onClick: () => d(
|
|
240
|
+
onClick: () => d(r("/products/program-detail-page", e.id)),
|
|
241
241
|
children: [/* @__PURE__ */ p("span", {
|
|
242
242
|
className: "text-sm font-medium",
|
|
243
243
|
children: e.name
|
|
244
244
|
}), /* @__PURE__ */ p(h, {
|
|
245
245
|
variant: "outline",
|
|
246
246
|
className: "text-xs",
|
|
247
|
-
children:
|
|
247
|
+
children: n(e.status)
|
|
248
248
|
})]
|
|
249
249
|
}, e.id))]
|
|
250
250
|
})] }),
|
|
@@ -260,14 +260,14 @@ function S() {
|
|
|
260
260
|
}), D.projects.map((e) => /* @__PURE__ */ m("button", {
|
|
261
261
|
type: "button",
|
|
262
262
|
className: "flex w-full items-center justify-between rounded-md border p-3 text-left hover:bg-muted",
|
|
263
|
-
onClick: () => d(
|
|
263
|
+
onClick: () => d(r("/projects/project-detail-page", e.id)),
|
|
264
264
|
children: [/* @__PURE__ */ p("span", {
|
|
265
265
|
className: "text-sm font-medium",
|
|
266
266
|
children: e.name
|
|
267
267
|
}), /* @__PURE__ */ p(h, {
|
|
268
268
|
variant: "outline",
|
|
269
269
|
className: "text-xs",
|
|
270
|
-
children:
|
|
270
|
+
children: n(e.status)
|
|
271
271
|
})]
|
|
272
272
|
}, e.id))]
|
|
273
273
|
})] })
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { usePlanMagnet as e, usePlanMagnetNavigate as t } from "../providers/PlanMagnetProvider.js";
|
|
2
2
|
import { PersonName as n } from "../people/People.js";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
3
|
+
import { enumLabel as r } from "../controls/WorkItemControls.js";
|
|
4
|
+
import { detailPath as i, rowLinkProps as a } from "../utils/rowNavigation.js";
|
|
5
5
|
import { PORTFOLIO_STATUSES as o } from "../controls/PortfolioControls.js";
|
|
6
6
|
import { useState as s } from "react";
|
|
7
7
|
import { Briefcase as c, Loader2 as l, Plus as u } from "lucide-react";
|
|
@@ -93,14 +93,14 @@ function C() {
|
|
|
93
93
|
"aria-pressed": w === e,
|
|
94
94
|
onClick: () => T(e),
|
|
95
95
|
className: `px-2 py-1 text-xs rounded-md capitalize ${w === e ? "bg-primary text-primary-foreground" : "bg-muted text-muted-foreground"}`,
|
|
96
|
-
children: e === "all" ? "All" :
|
|
96
|
+
children: e === "all" ? "All" : r(e)
|
|
97
97
|
}, e))
|
|
98
98
|
})]
|
|
99
99
|
}),
|
|
100
100
|
/* @__PURE__ */ p("div", {
|
|
101
101
|
className: "grid grid-cols-1 md:grid-cols-2 gap-4",
|
|
102
102
|
children: j.map((e) => /* @__PURE__ */ m(_, {
|
|
103
|
-
...
|
|
103
|
+
...a(() => d(i("/products/portfolio-detail-page", e.id)), e.name),
|
|
104
104
|
children: [/* @__PURE__ */ p(y, {
|
|
105
105
|
className: "pb-2",
|
|
106
106
|
children: /* @__PURE__ */ m("div", {
|
|
@@ -111,7 +111,7 @@ function C() {
|
|
|
111
111
|
}), /* @__PURE__ */ p(h, {
|
|
112
112
|
variant: "outline",
|
|
113
113
|
className: "text-xs",
|
|
114
|
-
children:
|
|
114
|
+
children: r(e.status)
|
|
115
115
|
})]
|
|
116
116
|
})
|
|
117
117
|
}), /* @__PURE__ */ m(v, {
|
|
@@ -126,7 +126,7 @@ function C() {
|
|
|
126
126
|
children: [e.alignment && /* @__PURE__ */ p(h, {
|
|
127
127
|
variant: "secondary",
|
|
128
128
|
className: "text-xs",
|
|
129
|
-
children: e.alignment === "CUSTOM" ? e.alignmentLabel ?? "Custom" :
|
|
129
|
+
children: e.alignment === "CUSTOM" ? e.alignmentLabel ?? "Custom" : r(e.alignment)
|
|
130
130
|
}), e.fiscalPeriod && /* @__PURE__ */ p(h, {
|
|
131
131
|
variant: "outline",
|
|
132
132
|
className: "text-xs",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { usePlanMagnet as e, usePlanMagnetNavigate as t } from "../providers/PlanMagnetProvider.js";
|
|
2
2
|
import { throwOnError as n } from "../utils/mutationResult.js";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
3
|
+
import { enumLabel as r } from "../controls/WorkItemControls.js";
|
|
4
|
+
import { endBeforeStart as i } from "../utils/formValidation.js";
|
|
5
5
|
import { PROGRAM_STATUSES as a } from "../controls/ProgramControls.js";
|
|
6
6
|
import { useState as o } from "react";
|
|
7
7
|
import { FolderKanban as s, Loader2 as c, Save as l, X as u } from "lucide-react";
|
|
@@ -28,7 +28,7 @@ function S() {
|
|
|
28
28
|
budgetTotal: "",
|
|
29
29
|
currency: "",
|
|
30
30
|
tags: ""
|
|
31
|
-
}), [T, E] = o(null), [D, { loading: O }] = f(x, { refetchQueries: ["ListPrograms"] }), k =
|
|
31
|
+
}), [T, E] = o(null), [D, { loading: O }] = f(x, { refetchQueries: ["ListPrograms"] }), k = i(C.startDate, C.endDate), A = C.budgetTotal !== "" && Number(C.budgetTotal) < 0;
|
|
32
32
|
return /* @__PURE__ */ m("div", {
|
|
33
33
|
className: "space-y-6 p-6 max-w-4xl",
|
|
34
34
|
children: [
|
|
@@ -123,7 +123,7 @@ function S() {
|
|
|
123
123
|
}),
|
|
124
124
|
children: a.map((e) => /* @__PURE__ */ p("option", {
|
|
125
125
|
value: e,
|
|
126
|
-
children:
|
|
126
|
+
children: r(e)
|
|
127
127
|
}, e))
|
|
128
128
|
})] }),
|
|
129
129
|
/* @__PURE__ */ m("div", {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { usePlanMagnetNavigate as e } from "../providers/PlanMagnetProvider.js";
|
|
2
2
|
import { throwOnError as t } from "../utils/mutationResult.js";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
3
|
+
import { enumLabel as n } from "../controls/WorkItemControls.js";
|
|
4
|
+
import { detailPath as r } from "../utils/rowNavigation.js";
|
|
5
|
+
import { endBeforeStart as i } from "../utils/formValidation.js";
|
|
6
6
|
import { PROGRAM_STATUSES as a } from "../controls/ProgramControls.js";
|
|
7
7
|
import { useMemo as o, useState as s } from "react";
|
|
8
8
|
import { ArrowLeft as c, Loader2 as l, Save as u } from "lucide-react";
|
|
@@ -65,7 +65,7 @@ function T() {
|
|
|
65
65
|
}), [F]), [L, R] = s({}), z = {
|
|
66
66
|
...I,
|
|
67
67
|
...L
|
|
68
|
-
}, B = (e) => R(e), V = a.includes(z.status) ? a : [z.status, ...a], H =
|
|
68
|
+
}, B = (e) => R(e), V = a.includes(z.status) ? a : [z.status, ...a], H = i(z.startDate, z.endDate), U = z.budgetTotal !== "" && Number(z.budgetTotal) < 0;
|
|
69
69
|
return D && !E ? /* @__PURE__ */ h("div", {
|
|
70
70
|
className: "flex items-center justify-center p-12",
|
|
71
71
|
children: /* @__PURE__ */ h(l, { className: "h-8 w-8 animate-spin text-muted-foreground" })
|
|
@@ -83,7 +83,7 @@ function T() {
|
|
|
83
83
|
variant: "ghost",
|
|
84
84
|
size: "sm",
|
|
85
85
|
"aria-label": "Back to the program",
|
|
86
|
-
onClick: () => f(
|
|
86
|
+
onClick: () => f(r("/products/program-detail-page", T)),
|
|
87
87
|
children: /* @__PURE__ */ h(c, { className: "h-4 w-4" })
|
|
88
88
|
}), /* @__PURE__ */ g("div", { children: [/* @__PURE__ */ h("h1", {
|
|
89
89
|
className: "text-2xl font-semibold",
|
|
@@ -181,7 +181,7 @@ function T() {
|
|
|
181
181
|
}),
|
|
182
182
|
children: V.map((e) => /* @__PURE__ */ h("option", {
|
|
183
183
|
value: e,
|
|
184
|
-
children:
|
|
184
|
+
children: n(e)
|
|
185
185
|
}, e))
|
|
186
186
|
})] }),
|
|
187
187
|
/* @__PURE__ */ g("div", {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { usePlanMagnet as e, usePlanMagnetNavigate as t } from "../providers/PlanMagnetProvider.js";
|
|
2
2
|
import { PersonName as n } from "../people/People.js";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
3
|
+
import { enumLabel as r } from "../controls/WorkItemControls.js";
|
|
4
|
+
import { detailPath as i, rowLinkProps as a } from "../utils/rowNavigation.js";
|
|
5
5
|
import { PROGRAM_STATUSES as o } from "../controls/ProgramControls.js";
|
|
6
6
|
import { useState as s } from "react";
|
|
7
7
|
import { FolderKanban as c, Loader2 as l, Plus as u } from "lucide-react";
|
|
@@ -95,14 +95,14 @@ function C() {
|
|
|
95
95
|
"aria-pressed": w === e,
|
|
96
96
|
onClick: () => T(e),
|
|
97
97
|
className: `px-2 py-1 text-xs rounded-md capitalize ${w === e ? "bg-primary text-primary-foreground" : "bg-muted text-muted-foreground"}`,
|
|
98
|
-
children: e === "all" ? "All" :
|
|
98
|
+
children: e === "all" ? "All" : r(e)
|
|
99
99
|
}, e))
|
|
100
100
|
})]
|
|
101
101
|
}),
|
|
102
102
|
/* @__PURE__ */ p("div", {
|
|
103
103
|
className: "grid grid-cols-1 md:grid-cols-2 gap-4",
|
|
104
104
|
children: j.map((e) => /* @__PURE__ */ m(_, {
|
|
105
|
-
...
|
|
105
|
+
...a(() => d(i("/products/program-detail-page", e.id)), e.name),
|
|
106
106
|
children: [/* @__PURE__ */ p(y, {
|
|
107
107
|
className: "pb-2",
|
|
108
108
|
children: /* @__PURE__ */ m("div", {
|
|
@@ -113,7 +113,7 @@ function C() {
|
|
|
113
113
|
}), /* @__PURE__ */ p(h, {
|
|
114
114
|
variant: "outline",
|
|
115
115
|
className: "text-xs",
|
|
116
|
-
children:
|
|
116
|
+
children: r(e.status)
|
|
117
117
|
})]
|
|
118
118
|
})
|
|
119
119
|
}), /* @__PURE__ */ m(v, {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ProjectsBudgetDetailPagePage.d.ts","sourceRoot":"","sources":["../../../src/planmagnet/pages/ProjectsBudgetDetailPagePage.tsx"],"names":[],"mappings":"AAsFA,wBAAgB,4BAA4B,4CAqP3C"}
|