🚧 DO NOT MERGE: Dashboard Studio: unified customization panel#4365
🚧 DO NOT MERGE: Dashboard Studio: unified customization panel#4365clubanderson merged 53 commits intomainfrom
Conversation
❌ Deploy Preview for kubestellarconsole failed. Why did it fail? →
|
|
👋 Hey @clubanderson — thanks for opening this PR!
This is an automated message. |
Introduces a new DashboardCustomizer ("Dashboard Studio") that unifies
the AddCardModal, SidebarCustomizer, and TemplatesModal into a single
full-screen panel with persistent left sidebar navigation.
Phase 1-3 complete:
- Extract shared card catalog data (CARD_CATALOG, types, helpers) into
shared/cardCatalog.ts and shared/CardPreview.tsx
- Refactor AddCardModal to import from shared modules (1692→670 lines)
- Create DashboardCustomizer shell with sidebar nav, section routing,
and preview panel
- Create section components: CardCatalogSection, AISuggestionsSection,
NavigationSection, TemplateGallerySection, DashboardSettingsSection
Design patterns: Grafana edit mode, Notion/Linear settings sidebar,
VS Code global search, Figma contextual preview, Material Design FAB.
Remaining work:
- Phase 4: Wire into DashboardPage, simplify FAB to single button
- Phase 5: Refactor tests
- Phase 6: Clean up old code, add i18n keys
Signed-off-by: Andrew Anderson <[email protected]>
- DashboardPage now renders DashboardCustomizer instead of separate AddCardModal + TemplatesModal - FAB shows single Palette button (Dashboard Studio) + inline undo/redo in unified mode; legacy mode preserved for Dashboard.tsx/CustomDashboard - Cmd+K / Ctrl+K keyboard shortcut opens Dashboard Studio - URL params ?addCard=true and ?customizeSidebar=true route to correct DashboardCustomizer sections Signed-off-by: Andrew Anderson <[email protected]>
- 14 new tests covering DashboardCustomizer, sidebar, preview panel, all 5 section components, shared cardCatalog data, and CardPreview - Add i18n keys under dashboard.studio.* for all section labels - All existing tests still pass (8/8 affected tests green) Signed-off-by: Andrew Anderson <[email protected]>
- Replace magic number 2000 with APPLIED_CONFIRMATION_MS constant - Replace toBeDefined() no-op assertions with meaningful type checks (typeof === 'function', .length checks, string type checks) Signed-off-by: Andrew Anderson <[email protected]>
The root / route uses Dashboard.tsx, not DashboardPage.tsx. Replace AddCardModal + TemplatesModal + old FAB menu with DashboardCustomizer in Dashboard.tsx so the new UI is visible on the main dashboard. Signed-off-by: Andrew Anderson <[email protected]>
- Navigation renders inline (embedded SidebarCustomizer) instead of
requiring a separate dialog
- "Sidebar Items" + "Add Pages" → single "Dashboards" nav item
- Remove Dashboard Settings section (confusing, actions in sidebar footer)
- AI presets auto-generate on click instead of just filling input
- Add context text to AI section explaining what cards are and where
they'll be added
- Add template explanation banner ("replaces all cards on dashboard")
- Show dashboard name in header subtitle for context
- Reduce modal size to 75vw/75vh for less overwhelming feel
- Fixed height/width to prevent layout shifts between sections
Signed-off-by: Andrew Anderson <[email protected]>
- "Dashboard Studio" → "Console Studio" - "Templates" / "Template Gallery" → "Card Collections" - Add subtitle: "Add cards, apply card collections, and manage your dashboards" - Update search placeholder and i18n keys Signed-off-by: Andrew Anderson <[email protected]>
- Add hardcoded fallbacks to all nav labels so they render even if i18n keys aren't loaded yet - AI suggestion cards now emit hover events to preview panel - "Try asking" pills stay visible after generating suggestions - Console Studio naming applied to all surfaces Signed-off-by: Andrew Anderson <[email protected]>
- Combine Browse Catalog + AI Suggestions into single "Cards" section with AI query bar at top and catalog below (no tabs) - Flatten nav: 3 items (Cards, Dashboards, Card Collections) — no group headers - Sidebar narrowed to w-48 - Limit recommended dashboards to 6 (was showing all ~20) - Match purple color scheme for dashboard recommendations (was blue) - "Add N to <dashboard>" button shows target dashboard name - AI suggestion cards show hover preview Signed-off-by: Andrew Anderson <[email protected]>
Footer with "Add N cards" only appears when cards are actually selected. Removes the dark bar that was always visible at the bottom of the Cards section. Signed-off-by: Andrew Anderson <[email protected]>
- Add Create Custom Card and Create Stats Card as sidebar nav items - Both render inline (embedded mode) instead of separate modals - Remove search bar and undo/redo from sidebar (unnecessary with 5 items) - Pass dashboard name to DashboardCustomizer for context - Fix footer bar only showing when cards are selected Signed-off-by: Andrew Anderson <[email protected]>
- Remove static recommendations from both Cards and Dashboards (AI suggestions and Generate from Behavior are smarter) - Remove Create Custom/Stats buttons from Cards section (now in sidebar) - Uniform purple-themed button styling in Dashboards section - "New Dashboard" → "Create Dashboard" - "Reset" → "Reset Sidebar" with tooltip explaining what it does - "Generate from Behavior" gets tooltip: "Analyzes your navigation history to suggest dashboards you actually use" - Card Collections: offer "Add" or "Replace" choice instead of always replacing all cards - Update explanation banner for Add/Replace choice - Reorder nav: Cards → Collections → Dashboards → Create Custom → Create Stats (most common first, advanced last) - Show actual dashboard name in Cards and Collections context text - Clean up unused imports Signed-off-by: Andrew Anderson <[email protected]>
- Force fixed height (h-[75vh]) so modal doesn't shrink when switching to sections with less content - Update subtitle to explain the console's mental model: dashboards contain cards that show real-time cluster data Signed-off-by: Andrew Anderson <[email protected]>
- Merge AI query + catalog search into single unified search bar (type to filter catalog, click AI Suggest or press Enter for AI) - Show card names in each collection tile so users know what's included - Append "Collection" to each collection title - Update subtitle to mention stat blocks - Fix unused variable build errors Signed-off-by: Andrew Anderson <[email protected]>
- Remove factory nav items (Create Custom Card, Create Stats Card) — keep as modal-based until they can be redesigned for consistency - Remove health warnings from Create Dashboard modal (irrelevant) - "Start with Template" → "Start with Card Collection" in Create Dashboard - "Available Templates (42 templates)" → "Card Collections (42 collections)" - "template" → "collection" throughout CreateDashboardModal - Constrain Dashboards section to max-w-3xl to fix horizontal spacing - Add footer bar with Undo/Redo/Reset Dashboard to Console Studio - Fix "current dashboard" → "Main Dashboard" as fallback name - Unified search bar (merged AI + catalog search into one input) - Remove unused factory imports Signed-off-by: Andrew Anderson <[email protected]>
Major restructure of the Dashboards section (SidebarCustomizer embedded): - Replace toggle "Add Dashboard" button with always-visible search bar (type to find, click to add — like VS Code command palette) - Remove confusing collapsible sections: "Primary Navigation", "Secondary Navigation", "Dashboard Cards", "Available Templates" - Replace with single "Your Dashboards" flat list (always visible, drag to reorder, click trash to remove) - "Generate from Behavior" → "Suggest from History" (clearer label) - Remove "Dashboard Cards" section (managed via Cards tab) - Remove "Available Templates" section (now Card Collections tab) - Clean up ~200 lines of unused code, imports, and state Signed-off-by: Andrew Anderson <[email protected]>
- Pass dashboardName from DashboardPage (uses page title) - "current dashboard" fallback → "your dashboard" (less confusing) - Add "Try:" label before AI suggestion pills so new users understand they're clickable prompts Signed-off-by: Andrew Anderson <[email protected]>
Route path shown as subtle suffix right after dashboard name instead of pushed to far right edge. Removes the huge horizontal gap. Also pass dashboardName from DashboardPage title prop. Signed-off-by: Andrew Anderson <[email protected]>
More honest label — it reorders dashboards by visit frequency and adds frequently visited ones, not just "suggests". Updated tooltip to explain the actual behavior. Signed-off-by: Andrew Anderson <[email protected]>
- handleAddCards now calls onClose() after adding - handleApplyTemplate now calls onClose() after replacing - Create Dashboard onCreate calls onClose() after creation - Fix code review issues: setTimeout cleanup, activeSection reset, Add more fallback Signed-off-by: Andrew Anderson <[email protected]>
- Add "Export Widgets" nav item in Console Studio sidebar - WidgetExportModal gains embedded mode (renders inline without BaseModal) - Widget export section shows Templates, Cards, and Stats tabs inline - Gives widgets discoverability — no longer hidden in card context menus - Card menu "Export as Widget" can open Studio at widgets section (future) Signed-off-by: Andrew Anderson <[email protected]>
- Card context menu "Export as Widget" now opens Console Studio at the Widgets section with that card pre-selected - Added studioWidgetCardType to useDashboardContext for passing card type from CardWrapper → Dashboard → DashboardCustomizer → WidgetExportModal - Falls back to standalone WidgetExportModal when Studio context is unavailable (e.g., widget page, non-dashboard routes) - Added 'widgets' to StudioInitialSection type Signed-off-by: Andrew Anderson <[email protected]>
The undo/redo bar next to the FAB palette button now also shows a reset button (red on hover) when the dashboard has been customized. Users can reset to defaults without opening Console Studio. Bar shows when any of: canUndo, canRedo, or isCustomized. Signed-off-by: Andrew Anderson <[email protected]>
The "Create New Dashboard" button in the drag drop zone was a plain button with only onClick — cards could not be dropped on it. Fix: - Add DroppableCreateDashboard component with useDroppable() hook (id: 'create-new-dashboard', data.type: 'create-new-dashboard') - Add handleDragEnd handler for create-new-dashboard: creates a new dashboard via createDashboard() and moves the dropped card to it - Update collision detection to recognize the new droppable target - Update handleDragOver for visual feedback on hover - Green highlight when hovering over "Create New Dashboard" with a card Signed-off-by: Andrew Anderson <[email protected]>
Signed-off-by: Andrew Anderson <[email protected]>
|
Thank you for your contribution! Your PR has been merged. Check out what's new:
Stay connected: Slack #kubestellar-dev | Multi-Cluster Survey |
There was a problem hiding this comment.
Pull request overview
This PR introduces Console Studio, a unified “dashboard customization” modal that consolidates card browsing/AI suggestions, templates (card collections), dashboard navigation customization, and embedded factories into a single experience. It also refactors shared catalog/preview code out of the legacy AddCardModal to support reuse.
Changes:
- Replaces legacy Add Card / Templates flows on
Dashboard.tsxandDashboardPage.tsxwith a unifiedDashboardCustomizeropened via a palette FAB andCmd/Ctrl+K. - Extracts shared card catalog + preview logic into
web/src/components/dashboard/shared/and adds new Console Studio section components underdashboard/customizer/. - Adds preview/confirm flow for “generate sidebar from behavior” and introduces embedded rendering modes for several modals/factories.
Reviewed changes
Copilot reviewed 34 out of 34 changed files in this pull request and generated 10 comments.
Show a summary per file
| File | Description |
|---|---|
| web/src/locales/en/common.json | Adds i18n strings for Console Studio and renames some factory tab labels. |
| web/src/lib/modals/useModalNavigation.ts | Ensures nested modals don’t both close on Escape by stopping immediate propagation. |
| web/src/lib/dashboards/DashboardPage.tsx | Swaps AddCard/Templates modals for DashboardCustomizer and wires URL params to initial sections. |
| web/src/hooks/useSidebarConfig.ts | Adds preview/apply APIs for behavior-based sidebar generation. |
| web/src/hooks/useDashboardContext.tsx | Extends openAddCardModal to accept a Studio section + optional widget card type. |
| web/src/components/widgets/WidgetExportModal.tsx | Adds embedded rendering mode for inline Console Studio usage. |
| web/src/components/layout/SidebarCustomizer.tsx | Refactors dashboards/nav customization UI; adds preview/confirm for behavior-based reordering and embedded mode. |
| web/src/components/layout/Sidebar.tsx | Routes “Add more” to open Console Studio on the Dashboards section when context exists. |
| web/src/components/dashboard/templates.ts | Changes template/category icons from emojis to Lucide icon names. |
| web/src/components/dashboard/StatBlockFactoryModal.tsx | Adds embedded mode and adjusts layout styling. |
| web/src/components/dashboard/shared/CardPreview.tsx | New extracted mini card visualization preview component. |
| web/src/components/dashboard/shared/cardCatalog.ts | New shared catalog data + helpers (abbreviation wrapping, recommendations, suggestion engine). |
| web/src/components/dashboard/FloatingDashboardActions.tsx | Adds unified palette FAB mode + Cmd/Ctrl+K shortcut; keeps legacy mode fallback. |
| web/src/components/dashboard/DashboardDropZone.tsx | Adds droppable “Create New Dashboard” target for cross-dashboard drag-and-drop. |
| web/src/components/dashboard/Dashboard.tsx | Uses DashboardCustomizer (replacing AddCard/Templates); supports drag-drop to “Create New Dashboard”. |
| web/src/components/dashboard/customizer/sections/UnifiedCardsSection.tsx | New combined AI suggestions + full catalog section for Studio. |
| web/src/components/dashboard/customizer/sections/TemplateGallerySection.tsx | New inline template/collection gallery section. |
| web/src/components/dashboard/customizer/sections/NavigationSection.tsx | New section embedding SidebarCustomizer for dashboard/nav management. |
| web/src/components/dashboard/customizer/sections/DashboardSettingsSection.tsx | New settings-style section for health/export/reset (currently not wired into Studio). |
| web/src/components/dashboard/customizer/sections/CardCatalogSection.tsx | Extracted legacy “Browse catalog” section (not used by UnifiedCardsSection path). |
| web/src/components/dashboard/customizer/sections/AISuggestionsSection.tsx | Extracted legacy AI suggestions section (not used by UnifiedCardsSection path). |
| web/src/components/dashboard/customizer/SectionLayout.tsx | New shared section layout wrapper (not used broadly yet). |
| web/src/components/dashboard/customizer/PreviewPanel.tsx | New right-side hover preview panel for Studio. |
| web/src/components/dashboard/customizer/DashboardCustomizerSidebar.tsx | New left nav sidebar for Studio. |
| web/src/components/dashboard/customizer/DashboardCustomizer.tsx | New Console Studio modal orchestrator (sections, preview panel, footer undo/redo/reset). |
| web/src/components/dashboard/customizer/customizerNav.ts | New nav model for Studio sections. |
| web/src/components/dashboard/customizer/AIAssistBar.tsx | New shared AI assist input component (not yet adopted by sections). |
| web/src/components/dashboard/customizer/tests/sections.test.tsx | Adds basic export/smoke tests for Studio sections and shared modules. |
| web/src/components/dashboard/customizer/tests/DashboardCustomizer.test.tsx | Adds basic export/smoke tests for Studio orchestrator components. |
| web/src/components/dashboard/customizer/tests/comprehensive.test.tsx | Adds broader smoke tests covering Studio modules and template icon assumptions. |
| web/src/components/dashboard/CreateDashboardModal.tsx | Adds embedded mode and switches template icons to getIcon(...). |
| web/src/components/dashboard/CardFactoryModal.tsx | Adds embedded mode and updates styling. |
| web/src/components/cards/CardWrapper.tsx | Routes “Export as Widget” to open Studio Widgets section when available. |
| 'Multi-Tenancy': [ | ||
| { type: 'tenant_topology', title: 'Tenant Architecture', description: 'Interactive SVG topology of the multi-tenancy architecture with live status', visualization: 'chart' }, | ||
| { type: 'tenant_isolation_setup', title: 'Tenant Isolation Setup', description: 'AI-powered multi-tenancy setup wizard', visualization: 'status' }, | ||
| { type: 'multi_tenancy_overview', title: 'Multi-Tenancy Overview', description: 'Aggregated tenant isolation status', visualization: 'status' }, | ||
| { type: 'ovn_status', title: 'OVN-Kubernetes', description: 'OVN network and UDN status', visualization: 'status' }, |
There was a problem hiding this comment.
CARD_CATALOG includes visualization types like "chart" (and also "timeline"/"metrics" elsewhere) that are not covered by CardSuggestion['visualization'] or visualizationIcons. This leads to missing/undefined icons in the UI and forces unsafe casts when creating CardSuggestion objects. Consider either constraining catalog visualization values to the supported set, or expanding the visualization union + visualizationIcons (and preview rendering) to handle these extra types consistently.
| onCreate={async (name, _template, _description) => { | ||
| await _createDashboard(name) | ||
| // Close Studio — the SidebarCustomizer's handleCreateDashboard | ||
| // handles sidebar item creation and navigation | ||
| onClose() |
There was a problem hiding this comment.
The create-dashboard flow ignores the selected template/description and only calls _createDashboard(name), then closes the Studio. This means the collection choice is dropped and the new dashboard won't be added to sidebar navigation (SidebarCustomizer is the place that calls addItem + navigate). Consider wiring onCreate to also (a) apply the chosen template/description and (b) update sidebar config / navigate to the new dashboard so the dashboard is reachable immediately.
| initialWidgetCardType?: string | ||
| initialSearch?: string | ||
| onApplyTemplate?: (template: DashboardTemplate) => void | ||
| onExport?: () => void |
There was a problem hiding this comment.
onExport is declared as a prop but is never destructured/used, so callers (e.g. Dashboard.tsx) passing onExport currently get no export UI in Console Studio. Either add a Settings/Export section (you already have DashboardSettingsSection) or remove the prop until it’s wired to avoid silent feature regression.
| onExport?: () => void |
| { id: 'cluster', name: 'Cluster', icon: 'Globe' }, | ||
| { id: 'namespace', name: 'Namespace', icon: 'FolderOpen' }, | ||
| { id: 'workloads', name: 'Workloads', icon: 'Box' }, | ||
| { id: 'alerting', name: 'Alerting', icon: 'Bell' }, | ||
| { id: 'compliance', name: 'Compliance', icon: 'ClipboardCheck' }, | ||
| { id: 'cost', name: 'Cost Management', icon: 'DollarSign' }, | ||
| { id: 'storage', name: 'Storage', icon: 'Database' }, | ||
| { id: 'compute', name: 'Compute', icon: 'Cpu' }, | ||
| { id: 'network', name: 'Network', icon: 'Globe' }, | ||
| { id: 'gitops', name: 'GitOps', icon: 'GitBranch' }, | ||
| { id: 'security', name: 'Security', icon: 'Shield' }, | ||
| { id: 'gpu', name: 'GPU', icon: 'Zap' }, | ||
| { id: 'ai', name: 'AI Assistant', icon: 'Sparkles' }, | ||
| { id: 'arcade', name: 'Arcade', icon: 'Gamepad2' }, | ||
| { id: 'deploy', name: 'Deploy', icon: 'Rocket' }, | ||
| { id: 'custom', name: 'Other', icon: 'LayoutGrid' }, |
There was a problem hiding this comment.
TEMPLATE_CATEGORIES (and template icon values) are now Lucide icon names, but existing consumers like TemplatesModal.tsx render category.icon / template.icon directly as text/emoji. This will make the legacy TemplatesModal show strings like "Globe" instead of an icon. Either update TemplatesModal to resolve icons via getIcon(...) (matching CreateDashboardModal/TemplateGallerySection), or keep emoji values until all consumers are migrated.
| { id: 'cluster', name: 'Cluster', icon: 'Globe' }, | |
| { id: 'namespace', name: 'Namespace', icon: 'FolderOpen' }, | |
| { id: 'workloads', name: 'Workloads', icon: 'Box' }, | |
| { id: 'alerting', name: 'Alerting', icon: 'Bell' }, | |
| { id: 'compliance', name: 'Compliance', icon: 'ClipboardCheck' }, | |
| { id: 'cost', name: 'Cost Management', icon: 'DollarSign' }, | |
| { id: 'storage', name: 'Storage', icon: 'Database' }, | |
| { id: 'compute', name: 'Compute', icon: 'Cpu' }, | |
| { id: 'network', name: 'Network', icon: 'Globe' }, | |
| { id: 'gitops', name: 'GitOps', icon: 'GitBranch' }, | |
| { id: 'security', name: 'Security', icon: 'Shield' }, | |
| { id: 'gpu', name: 'GPU', icon: 'Zap' }, | |
| { id: 'ai', name: 'AI Assistant', icon: 'Sparkles' }, | |
| { id: 'arcade', name: 'Arcade', icon: 'Gamepad2' }, | |
| { id: 'deploy', name: 'Deploy', icon: 'Rocket' }, | |
| { id: 'custom', name: 'Other', icon: 'LayoutGrid' }, | |
| { id: 'cluster', name: 'Cluster', icon: '🌐' }, | |
| { id: 'namespace', name: 'Namespace', icon: '📂' }, | |
| { id: 'workloads', name: 'Workloads', icon: '📦' }, | |
| { id: 'alerting', name: 'Alerting', icon: '🔔' }, | |
| { id: 'compliance', name: 'Compliance', icon: '📋' }, | |
| { id: 'cost', name: 'Cost Management', icon: '💲' }, | |
| { id: 'storage', name: 'Storage', icon: '🗄️' }, | |
| { id: 'compute', name: 'Compute', icon: '🖥️' }, | |
| { id: 'network', name: 'Network', icon: '🌐' }, | |
| { id: 'gitops', name: 'GitOps', icon: '🌿' }, | |
| { id: 'security', name: 'Security', icon: '🛡️' }, | |
| { id: 'gpu', name: 'GPU', icon: '⚡' }, | |
| { id: 'ai', name: 'AI Assistant', icon: '✨' }, | |
| { id: 'arcade', name: 'Arcade', icon: '🎮' }, | |
| { id: 'deploy', name: 'Deploy', icon: '🚀' }, | |
| { id: 'custom', name: 'Other', icon: '📊' }, |
| })) | ||
|
|
||
| vi.mock('../../../shared/TechnicalAcronym', () => ({ | ||
| TechnicalAcronym: ({ children }: { children: React.ReactNode }) => children, | ||
| })) | ||
|
|
There was a problem hiding this comment.
This test file references React.ReactNode but does not import React (or type ReactNode). In TS, React is not in scope by default, so this will fail typechecking/build. Import type ReactNode from 'react' (or import * as React from 'react') and use that instead.
| vi.mock('../../../../lib/modals', () => ({ | ||
| BaseModal: Object.assign( | ||
| ({ children }: { children: React.ReactNode }) => children, | ||
| { Header: () => null, Content: ({ children }: { children: React.ReactNode }) => children, Footer: () => null, Tabs: () => null } | ||
| ), |
There was a problem hiding this comment.
This test file uses React.ReactNode in types but does not import React (or type ReactNode). This will fail TypeScript compilation in module scope. Add a import type { ReactNode } from 'react' (or import React) and update the annotations.
| vi.mock('../../../../lib/modals', () => ({ | ||
| BaseModal: Object.assign( | ||
| ({ children }: { children: React.ReactNode }) => children, | ||
| { Header: () => null, Content: ({ children }: { children: React.ReactNode }) => children, Footer: () => null, Tabs: () => null } | ||
| ), |
There was a problem hiding this comment.
This test file uses React.ReactNode in mock type annotations but does not import React (or type ReactNode). In TS modules, React isn’t globally available, so this will break the build. Import type ReactNode from 'react' (or import React) and update the annotations.
| } | ||
| } else { | ||
| setGenerationResult(t('sidebar.customizer.notEnoughData')) | ||
| const AUTO_DISMISS_MS = 5000 |
There was a problem hiding this comment.
AUTO_DISMISS_MS is already defined at module scope, but this block redeclares const AUTO_DISMISS_MS = 5000 inside the else branch. This shadowing is redundant and makes it easy to accidentally diverge values. Reuse the module-level constant instead of redefining it locally.
| const AUTO_DISMISS_MS = 5000 |
| export const CUSTOMIZER_NAV: NavItem[] = [ | ||
| { id: 'cards', label: 'Add Cards', icon: LayoutGrid }, | ||
| { id: 'collections', label: 'Add Card Collections', icon: Layout }, | ||
| { id: 'dashboards', label: 'Manage Dashboards', icon: LayoutDashboard }, | ||
| { id: 'widgets', label: 'Export Widgets', icon: Download }, | ||
| { id: 'create-dashboard', label: 'Create Custom Dashboard', icon: FolderPlus, dividerBefore: true }, | ||
| { id: 'card-factory', label: 'Create Custom Card', icon: Wand2 }, | ||
| { id: 'stat-factory', label: 'Create Stat Blocks', icon: Activity }, |
There was a problem hiding this comment.
Customizer nav labels are hard-coded strings (e.g. "Add Cards", "Manage Dashboards") even though this PR adds dashboard.studio.sections.* i18n keys in common.json. To keep localization consistent, consider using t(...) when building CUSTOMIZER_NAV labels (or define them as i18n keys instead of raw text).
| // Lazy-load modal components — only shown on explicit user action, | ||
| // so deferring their chunk until first use reduces the initial dashboard bundle. | ||
| const AddCardModal = safeLazy(() => import('./AddCardModal'), 'AddCardModal') | ||
| // AddCardModal replaced by DashboardCustomizer (imported above) | ||
| const ConfigureCardModal = safeLazy(() => import('./ConfigureCardModal'), 'ConfigureCardModal') |
There was a problem hiding this comment.
PR description mentions that the legacy AddCardModal still works on Dashboard.tsx routes, but this file now routes customization through DashboardCustomizer and removes the lazy-loaded AddCardModal. Either update the PR description/test plan to reflect the new behavior, or keep the legacy modal on Dashboard.tsx until Console Studio is ready for merge.
🔄 Auto-Applying Copilot Code ReviewCopilot code review found 3 code suggestion(s) and 7 general comment(s). @copilot Please apply all of the following code review suggestions:
Also address these general comments:
Push all fixes in a single commit. Run Auto-generated by copilot-review-apply workflow. |
❌ Post-Merge Verification: failedCommit: |
❌ Post-Merge Verification: failedCommit: |
Reintroduces the Dashboard Studio (originally #4365) with all stability fixes applied. The unified panel provides: - Card catalog with search and category filtering - Dashboard settings (name, layout, theme) - Template gallery for quick dashboard creation - AI suggestions for card placement - Widget export functionality - Navigation section for dashboard switching Includes TypeScript fixes for React 19 compatibility and test fixes. Does NOT include the memoization removal that caused infinite loops. Signed-off-by: Andrew Anderson <[email protected]>
* fix: stabilize useEffect deps to eliminate infinite re-render loops - useWorkloadMonitor: wrap fetchData in useCallback with refs for params - PDDisaggregation: memoize prefillIds/decodeIds, use string key for deps - EPPRouting: remove unstable deps from effect - GitHubActivity: remove fetchGitHubData from effect deps - LatencyBreakdown/ThroughputComparison: fix empty key warnings Signed-off-by: Andrew Anderson <[email protected]> * fix: stabilize context deps, suppress auth errors, fix route transitions - Layout: wrap Outlet in Suspense to prevent full-page flash on navigation - AlertsContext: memoize stats, activeAlerts, acknowledgedAlerts - StackContext: memoize liveStacks, healthyStacks, disaggregatedStacks - useInsightEnrichment: stabilize heuristicInsights dep with length key - workloads: downgrade auth errors to console.debug (5 hooks) - useTopology: suppress 401 errors in demo mode - sseClient: skip retries on 401 auth errors Signed-off-by: Andrew Anderson <[email protected]> * fix: add MSW handlers for prometheus/query and github avatar CSP - Mock /prometheus/query with plausible vLLM metric values - Return transparent PNG for github.com/*.png to avoid CSP violation - Add avatars.githubusercontent.com passthrough Signed-off-by: Andrew Anderson <[email protected]> * feat: Dashboard Studio — unified customization panel Reintroduces the Dashboard Studio (originally #4365) with all stability fixes applied. The unified panel provides: - Card catalog with search and category filtering - Dashboard settings (name, layout, theme) - Template gallery for quick dashboard creation - AI suggestions for card placement - Widget export functionality - Navigation section for dashboard switching Includes TypeScript fixes for React 19 compatibility and test fixes. Does NOT include the memoization removal that caused infinite loops. Signed-off-by: Andrew Anderson <[email protected]> --------- Signed-off-by: Andrew Anderson <[email protected]>
Summary
Introduces Console Studio — a unified customization panel that replaces the separate AddCardModal, SidebarCustomizer, and TemplatesModal with a single coherent experience.
What's in this PR
Cmd+Kopens Console Studioshared/cardCatalog.ts(AddCardModal reduced from 1,692 to 670 lines)Known issues to address before merge
Test plan
npm run buildpassesnpm run lint— no new errors in new files