Skip to content

🚧 DO NOT MERGE: Dashboard Studio: unified customization panel#4365

Merged
clubanderson merged 53 commits intomainfrom
dashboard-studio
Apr 7, 2026
Merged

🚧 DO NOT MERGE: Dashboard Studio: unified customization panel#4365
clubanderson merged 53 commits intomainfrom
dashboard-studio

Conversation

@clubanderson
Copy link
Copy Markdown
Collaborator

@clubanderson clubanderson commented Apr 3, 2026

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

  • Single FAB button (palette icon) or Cmd+K opens Console Studio
  • Flat left nav: Cards, Card Collections, Dashboards, Create Custom Card, Create Stats Card
  • Cards section: AI query bar at top + full browse catalog below (combined view)
  • Card Collections: pre-built card sets with Add/Replace choice
  • Dashboards: sidebar customizer rendered inline (embedded mode)
  • Card/Stat factories rendered inline (embedded mode)
  • Shared card catalog data extracted to shared/cardCatalog.ts (AddCardModal reduced from 1,692 to 670 lines)

Known issues to address before merge

  • "Generate from Behavior" auto-applies without preview/confirmation — needs a diff preview with approve/reject flow
  • Modal height still shifts slightly between some sections
  • "Add" vs "Replace" on Card Collections both call the same handler — need separate logic for "Add" (append cards) vs "Replace" (clear + set)
  • Dashboard name shows "Dashboard" instead of the actual custom dashboard name when on the main dashboard
  • Left sidebar "Add more" button should open Console Studio with Dashboards pre-selected
  • Cards, Collections, and Dashboards sections could share more visual structure (consistent action bar placement, spacing)

Test plan

  • npm run build passes
  • npm run lint — no new errors in new files
  • Manual: FAB opens Console Studio, Cmd+K shortcut works
  • Manual: Cards section — AI generates on preset click, search filters catalog, add cards works
  • Manual: Card Collections — browse/filter, Add/Replace choice shown
  • Manual: Dashboards — add/create/generate/reset all work inline
  • Manual: Create Custom Card and Create Stats Card render inline
  • Manual: Preview panel shows card visualization on hover
  • Manual: Existing AddCardModal still works on legacy Dashboard.tsx/CustomDashboard.tsx routes

@kubestellar-prow kubestellar-prow Bot added the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Apr 3, 2026
@netlify
Copy link
Copy Markdown

netlify Bot commented Apr 3, 2026

Deploy Preview for kubestellarconsole failed. Why did it fail? →

Name Link
🔨 Latest commit 1f3bed5
🔍 Latest deploy log https://app.netlify.com/projects/kubestellarconsole/deploys/69d44c71c615fd0008d498e9

@kubestellar-prow kubestellar-prow Bot added the dco-signoff: yes Indicates the PR's author has signed the DCO. label Apr 3, 2026
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 3, 2026

👋 Hey @clubanderson — thanks for opening this PR!

🤖 This project is developed exclusively using AI coding assistants.

Please do not attempt to code anything for this project manually.
All contributions should be authored using an AI coding tool such as:

This ensures consistency in code style, architecture patterns, test coverage,
and commit quality across the entire codebase.


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]>
@kubestellar-prow kubestellar-prow Bot added the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Apr 6, 2026
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]>
@kubestellar-prow kubestellar-prow Bot removed the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Apr 7, 2026
@clubanderson clubanderson marked this pull request as ready for review April 7, 2026 00:16
Copilot AI review requested due to automatic review settings April 7, 2026 00:16
@kubestellar-prow kubestellar-prow Bot removed the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Apr 7, 2026
@clubanderson clubanderson merged commit f9925f7 into main Apr 7, 2026
17 of 25 checks passed
@kubestellar-prow kubestellar-prow Bot deleted the dashboard-studio branch April 7, 2026 00:16
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 7, 2026

Thank you for your contribution! Your PR has been merged.

Check out what's new:

Stay connected: Slack #kubestellar-dev | Multi-Cluster Survey

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.tsx and DashboardPage.tsx with a unified DashboardCustomizer opened via a palette FAB and Cmd/Ctrl+K.
  • Extracts shared card catalog + preview logic into web/src/components/dashboard/shared/ and adds new Console Studio section components under dashboard/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.

Comment on lines +310 to +314
'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' },
Copy link

Copilot AI Apr 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copilot uses AI. Check for mistakes.
Comment on lines +153 to +157
onCreate={async (name, _template, _description) => {
await _createDashboard(name)
// Close Studio — the SidebarCustomizer's handleCreateDashboard
// handles sidebar item creation and navigation
onClose()
Copy link

Copilot AI Apr 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copilot uses AI. Check for mistakes.
initialWidgetCardType?: string
initialSearch?: string
onApplyTemplate?: (template: DashboardTemplate) => void
onExport?: () => void
Copy link

Copilot AI Apr 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Suggested change
onExport?: () => void

Copilot uses AI. Check for mistakes.
Comment on lines +684 to +699
{ 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' },
Copy link

Copilot AI Apr 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Suggested change
{ 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: '📊' },

Copilot uses AI. Check for mistakes.
Comment on lines +27 to +32
}))

vi.mock('../../../shared/TechnicalAcronym', () => ({
TechnicalAcronym: ({ children }: { children: React.ReactNode }) => children,
}))

Copy link

Copilot AI Apr 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copilot uses AI. Check for mistakes.
Comment on lines +7 to +11
vi.mock('../../../../lib/modals', () => ({
BaseModal: Object.assign(
({ children }: { children: React.ReactNode }) => children,
{ Header: () => null, Content: ({ children }: { children: React.ReactNode }) => children, Footer: () => null, Tabs: () => null }
),
Copy link

Copilot AI Apr 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copilot uses AI. Check for mistakes.
Comment on lines +12 to +16
vi.mock('../../../../lib/modals', () => ({
BaseModal: Object.assign(
({ children }: { children: React.ReactNode }) => children,
{ Header: () => null, Content: ({ children }: { children: React.ReactNode }) => children, Footer: () => null, Tabs: () => null }
),
Copy link

Copilot AI Apr 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copilot uses AI. Check for mistakes.
}
} else {
setGenerationResult(t('sidebar.customizer.notEnoughData'))
const AUTO_DISMISS_MS = 5000
Copy link

Copilot AI Apr 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Suggested change
const AUTO_DISMISS_MS = 5000

Copilot uses AI. Check for mistakes.
Comment on lines +32 to +39
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 },
Copy link

Copilot AI Apr 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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).

Copilot uses AI. Check for mistakes.
Comment on lines 78 to 81
// 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')
Copy link

Copilot AI Apr 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copilot uses AI. Check for mistakes.
@clubanderson
Copy link
Copy Markdown
Collaborator Author

🔄 Auto-Applying Copilot Code Review

Copilot code review found 3 code suggestion(s) and 7 general comment(s).

@copilot Please apply all of the following code review suggestions:

  • web/src/components/dashboard/customizer/DashboardCustomizer.tsx (line 37): ``
  • web/src/components/dashboard/templates.ts (line 699): { id: 'cluster', name: 'Cluster', icon: '🌐' }, { id: 'namespace', name: 'Name...
  • web/src/components/layout/SidebarCustomizer.tsx (line 301): ``

Also address these general comments:

  • web/src/components/dashboard/shared/cardCatalog.ts (line 314): CARD_CATALOG includes visualization types like "chart" (and also "timeline"/"metrics" elsewhere) that are not covered by
  • web/src/components/dashboard/customizer/DashboardCustomizer.tsx (line 157): The create-dashboard flow ignores the selected template/description and only calls _createDashboard(name), then clos
  • web/src/components/dashboard/customizer/__tests__/sections.test.tsx (line 32): This test file references React.ReactNode but does not import React (or type ReactNode). In TS, React is not in sc
  • web/src/components/dashboard/customizer/__tests__/DashboardCustomizer.test.tsx (line 11): This test file uses React.ReactNode in types but does not import React (or type ReactNode). This will fail TypeScrip
  • web/src/components/dashboard/customizer/__tests__/comprehensive.test.tsx (line 16): This test file uses React.ReactNode in mock type annotations but does not import React (or type ReactNode). In TS mo
  • web/src/components/dashboard/customizer/customizerNav.ts (line 39): Customizer nav labels are hard-coded strings (e.g. "Add Cards", "Manage Dashboards") even though this PR adds `dashboard
  • web/src/components/dashboard/Dashboard.tsx (line 81): PR description mentions that the legacy AddCardModal still works on Dashboard.tsx routes, but this file now routes c

Push all fixes in a single commit. Run cd web && npm run build && npm run lint before committing.


Auto-generated by copilot-review-apply workflow.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 7, 2026

❌ Post-Merge Verification: failed

Commit: f9925f7b8b0f6facd17c235723545b6f83350c1f
Specs run: Dashboard.spec.ts navbar-responsive.spec.ts smoke.spec.ts
Report: https://github.com/kubestellar/console/actions/runs/24057755331

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 7, 2026

❌ Post-Merge Verification: failed

Commit: eadf290dd140747dbfb9e0fabc140515c63b6bb5
Specs run: Dashboard.spec.ts navbar-responsive.spec.ts smoke.spec.ts
Report: https://github.com/kubestellar/console/actions/runs/24061533672

clubanderson added a commit that referenced this pull request Apr 7, 2026
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]>
clubanderson added a commit that referenced this pull request Apr 7, 2026
* 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]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dco-signoff: yes Indicates the PR's author has signed the DCO. size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants