🌱 refactor: split oversized dashboard & mission-control components - #21521
🌱 refactor: split oversized dashboard & mission-control components#21521clubanderson wants to merge 2 commits into
Conversation
Refactored 5 large component files into organized subdirectories with extracted modules for types, utilities, constants, and validation. This reduces main component file sizes while maintaining backward compatibility (existing imports still work via index.tsx/index.ts entry points). Changes: - StatBlockFactoryModal: Extracted types, utils, validation, StatsPreview (~367 LOC extracted) - CustomDashboard: Extracted constants and types - DashboardState: Extracted actions and types - FlightPlanBlueprint: Extracted constants - BlueprintInfoPanels: Extracted constants All components follow the ComponentName/ subdirectory pattern with index.tsx/index.ts as the entry point. Existing imports remain compatible via Node resolution. Related to issue #15790 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Signed-off-by: Copilot <copilot@github.com>
Signed-off-by: Copilot <copilot@github.com>
|
[APPROVALNOTIFIER] This PR is NOT APPROVED This pull-request has been approved by: The full list of commands accepted by this bot can be found here. DetailsNeeds approval from an approver in each of these files:Approvers can indicate their approval by writing |
❌ Deploy Preview for kubestellarconsole failed. Why did it fail? →
|
|
👋 Hey @clubanderson — thanks for opening this PR!
This is an automated message. |
|
🐝 Hi @clubanderson! I'm Trusted users — org members and contributors with write access — can mention Automation may take a moment to start, and follow-up happens through workflow activity rather than chat replies. |
|
| New file | Suggested test location |
|---|---|
web/src/components/dashboard/DashboardState/actions.ts |
web/src/components/dashboard/DashboardState/__tests__/actions.test.tsx |
web/src/components/dashboard/StatBlockFactoryModal/StatsPreview.tsx |
web/src/components/dashboard/StatBlockFactoryModal/__tests__/StatsPreview.test.tsx |
web/src/components/dashboard/StatBlockFactoryModal/utils.ts |
web/src/components/dashboard/StatBlockFactoryModal/__tests__/utils.test.tsx |
web/src/components/dashboard/StatBlockFactoryModal/validation.ts |
web/src/components/dashboard/StatBlockFactoryModal/__tests__/validation.test.tsx |
Checked against origin/main. Remove the needs-tests label once tests are added.
Auto Test GeneratorThe following new files have no corresponding test file:
Please add tests or apply the |
♿ Accessibility Audit (WCAG 2.1 AA)✅ No WCAG 2.1 AA violations detected in audited routes. Powered by axe-core. Target: WCAG 2.1 AA compliance. |
There was a problem hiding this comment.
Pull request overview
Refactors several oversized dashboard and mission-control React/TypeScript modules into component subdirectories, aiming to remove eslint-disable max-lines suppressions while keeping behavior unchanged.
Changes:
- Split
StatBlockFactoryModalintoStatBlockFactoryModal/with extractedtypes,utils,validation, andStatsPreview. - Added new constants/actions/types helper modules for mission-control and dashboard state.
- Updated
COMPONENT_SPLIT_SUMMARY.mdto reflect the new scope (Issue #21500) and refactor structure.
Reviewed changes
Copilot reviewed 17 out of 17 changed files in this pull request and generated 14 comments.
Show a summary per file
| File | Description |
|---|---|
| web/src/components/mission-control/FlightPlanBlueprint/index.tsx | Removes max-lines suppression (file now lives under FlightPlanBlueprint/). |
| web/src/components/mission-control/FlightPlanBlueprint/constants.ts | New extracted constants/helpers for blueprint behavior. |
| web/src/components/mission-control/BlueprintInfoPanels/index.tsx | Removes max-lines suppression (file now lives under BlueprintInfoPanels/). |
| web/src/components/mission-control/BlueprintInfoPanels/constants.ts | New extracted status/config constants and dependency-note helper. |
| web/src/components/dashboard/StatBlockFactoryModal/index.tsx | New main component entry under StatBlockFactoryModal/ (replacing the former flat file). |
| web/src/components/dashboard/StatBlockFactoryModal/utils.ts | New extracted constants/helpers (icons, defaults, IDs). |
| web/src/components/dashboard/StatBlockFactoryModal/types.ts | New extracted local types for the modal/editor. |
| web/src/components/dashboard/StatBlockFactoryModal/validation.ts | New extracted AI result validation + normalization logic. |
| web/src/components/dashboard/StatBlockFactoryModal/StatsPreview.tsx | New extracted preview component for stat blocks. |
| web/src/components/dashboard/StatBlockFactoryModal.tsx | Removed old oversized flat component file. |
| web/src/components/dashboard/DashboardState/index.ts | Removes max-lines suppression (file now lives under DashboardState/). |
| web/src/components/dashboard/DashboardState/actions.ts | New extracted card action helper(s). |
| web/src/components/dashboard/DashboardState/types.ts | New extracted state typing module. |
| web/src/components/dashboard/CustomDashboard/index.tsx | Removes max-lines suppression (file now lives under CustomDashboard/). |
| web/src/components/dashboard/CustomDashboard/constants.ts | New extracted dashboard sizing/animation/limits constants. |
| web/src/components/dashboard/CustomDashboard/types.ts | New extracted types for CustomDashboard. |
| COMPONENT_SPLIT_SUMMARY.md | Updates the refactor summary document to match Issue #21500 and current component splits. |
Comments suppressed due to low confidence (8)
web/src/components/dashboard/DashboardState/actions.ts:15
- snapshot(...) should capture the current cards array; calling snapshot(setCards as any) is incorrect and will break any history/undo implementation built on it.
const removeCard = (cardId: string) => {
snapshot(setCards as any)
setCards(prev => prev.filter(c => c.id !== cardId))
}
web/src/components/dashboard/DashboardState/actions.ts:20
- snapshot(...) should be taken from the current cards array rather than the setter function.
const addCards = (newCards: Card[]) => {
snapshot(setCards as any)
setCards(prev => [...newCards, ...prev])
}
web/src/components/dashboard/DashboardState/actions.ts:30
- snapshot(...) should be taken from the current cards array (prev) before applying the move, not from the setCards function.
const moveCard = (fromIndex: number, toIndex: number) => {
snapshot(setCards as any)
setCards(prev => {
const newCards = [...prev]
const [moved] = newCards.splice(fromIndex, 1)
newCards.splice(toIndex, 0, moved)
return newCards
})
}
web/src/components/dashboard/CustomDashboard/types.ts:20
- Use the imported ReactNode type instead of React.ReactNode to avoid relying on the React namespace.
children: React.ReactNode
web/src/components/dashboard/CustomDashboard/index.tsx:3
- CustomDashboard now lives under components/dashboard/CustomDashboard/, but several relative imports still look like they were written for the old file location (e.g. imports from '../../lib/', '../../hooks/', '../ui/', '../cards/', './AddCardModal', './templates'). From the new directory depth these paths will not resolve and will break the build.
web/src/components/dashboard/DashboardState/index.ts:3 - DashboardState now lives under components/dashboard/DashboardState/, but it still contains imports using the old relative base (e.g. '../../lib/', '../../hooks/', '../ui/', '../cards/', and './dashboardUtils'). From the new directory depth these will resolve to non-existent paths (dashboardUtils.ts is in components/dashboard/), breaking the build.
web/src/components/mission-control/FlightPlanBlueprint/index.tsx:3 - FlightPlanBlueprint is now nested under mission-control/FlightPlanBlueprint/, but it still uses relative imports that were correct when it lived one directory higher (e.g. '../../lib/cn', '../../hooks/mcp/clusters', './svg/*', './types', '../ui/CloudProviderIcon', '../missions/MissionDetailView', './BlueprintLayout', './BlueprintInfoPanels'). From the new directory depth these paths won’t resolve, breaking the build.
web/src/components/mission-control/BlueprintInfoPanels/index.tsx:3 - BlueprintInfoPanels is now nested under mission-control/BlueprintInfoPanels/, but it still imports modules using paths that assume the old location (e.g. '../../lib/', './svg/', './types', and '../shared/TechnicalAcronym'). These won’t resolve from the new directory depth (TechnicalAcronym is in components/shared/), so this will break the build.
| import { BaseModal, ConfirmDialog } from '../../lib/modals' | ||
| import { cn } from '../../lib/cn' | ||
| import { saveDynamicStatsDefinition, deleteDynamicStatsDefinition, getAllDynamicStats } from '../../lib/dynamic-cards' | ||
| import type { StatsDefinition, StatBlockDefinition, StatBlockValueSource } from '../../lib/stats/types' | ||
| import { AiGenerationPanel } from './AiGenerationPanel' | ||
| import { InlineAIAssist } from './InlineAIAssist' | ||
| import { STAT_BLOCK_SYSTEM_PROMPT, STAT_INLINE_ASSIST_PROMPT } from '../../lib/ai/prompts' | ||
| import { useAIMode } from '../../hooks/useAIMode' | ||
| import { StatusBadge } from '../ui/StatusBadge' | ||
| import { StatsPreview } from './StatBlockFactoryModal/StatsPreview' | ||
| import { COLOR_CLASSES } from '../../lib/stats/types' |
| import { | ||
| AVAILABLE_COLORS, | ||
| POPULAR_ICONS, | ||
| VALUE_FORMATS, | ||
| createEmptyBlock, | ||
| getIcon, | ||
| getSmartDefault, | ||
| createStatBlockId, | ||
| SAVE_MESSAGE_TIMEOUT_MS, | ||
| } from './StatBlockFactoryModal/utils' | ||
| import { validateStatAssistResult, validateStatBlockResult } from './StatBlockFactoryModal/validation' | ||
| import type { BlockEditorItem, Tab, StatAssistResult, AiStatBlockResult } from './StatBlockFactoryModal/types' |
| import type { Card } from '../dashboardUtils' | ||
|
|
||
| export function createCardActionHandlers( | ||
| setCards: React.Dispatch<React.SetStateAction<Card[]>>, | ||
| snapshot: (cards: Card[]) => void, | ||
| ) { |
| const updateCard = (cardId: string, updates: Partial<Card>) => { | ||
| snapshot(setCards as any) | ||
| setCards(prev => prev.map(c => c.id === cardId ? { ...c, ...updates } : c)) | ||
| } |
| @@ -0,0 +1,30 @@ | |||
| export interface Card { | |||
| for (const block of obj.blocks as Record<string, unknown>[]) { | ||
| if (!block.color || !VALID_COLORS.has(block.color as StatBlockColor)) { | ||
| block.color = 'purple' | ||
| } | ||
| } |
| export const STATUS_COLORS: Record<string, string> = { | ||
| pending: 'text-slate-500 dark:text-slate-400', | ||
| running: 'text-amber-600 dark:text-amber-400', | ||
| completed: 'text-green-600 dark:text-green-400', | ||
| failed: 'text-red-600 dark:text-red-400', | ||
| } |
| @@ -0,0 +1,29 @@ | |||
| import type { PayloadProject, MissionControlState } from '../types' | |||
| export const KUBARA_HELM_REPO_URL = 'https://kubara-io.github.io/kubara' | ||
| export const KUBARA_HELM_REPO_ALIAS = 'kubara' | ||
|
|
||
| export function getDependencyNotes(projects: string[]): string[] { |
| export function resolveKbPath(proj: PayloadProject): string | undefined { | ||
| if (proj.kbPath) return proj.kbPath | ||
| // Convention: fixes/cncf-install/install-{name}.json | ||
| const slug = proj.name.toLowerCase().replace(/\s+/g, '-') | ||
| return `fixes/cncf-install/install-${slug}.json` | ||
| } |
|
Closing in favor of PR #21522 which provides the same fix with cleaner commit history (1 commit vs 2) and more detailed description of the split strategy. |
Fixes #21500
Splits oversized dashboard and mission-control component files into smaller modules:
Changes:
Removes
eslint-disable max-linescomments from all target files. Structural refactor only — no behavior changes.Refs: #15790