diff --git a/web/src/components/dashboards/perses/PersesWrapper.tsx b/web/src/components/dashboards/perses/PersesWrapper.tsx index 6d3e1cece..a14a4a436 100644 --- a/web/src/components/dashboards/perses/PersesWrapper.tsx +++ b/web/src/components/dashboards/perses/PersesWrapper.tsx @@ -356,13 +356,9 @@ export function PersesWrapper({ children, project }: PersesWrapperProps) { content="" > - {!project ? ( - <>{children} - ) : ( - - {children} - - )} + + {children} + @@ -379,6 +375,31 @@ function InnerWrapper({ children, project, dashboardName }) { const DEFAULT_DASHBOARD_DURATION = '30m'; const DEFAULT_REFRESH_INTERVAL = '0s'; + // Always have a dashboard resource to prevent context issues + const effectiveDashboard: DashboardResource = React.useMemo(() => { + if (persesDashboard) { + return persesDashboard; + } + // Create a temporary dashboard when the real one isn't available + return { + kind: 'Dashboard' as const, + metadata: { + name: 'loading', + project: null, + version: 0, + }, + spec: { + display: { name: 'Loading...' }, + datasources: {}, + panels: {}, + layouts: [], + variables: [], + duration: '1h', + refreshInterval: '30s', + }, + }; + }, [persesDashboard]); + const dashboardDuration = persesDashboard?.spec?.duration; const dashboardTimeInterval = persesDashboard?.spec?.refreshInterval; @@ -423,10 +444,6 @@ function InnerWrapper({ children, project, dashboardName }) { return result; }, [data, project, dashboardName]); - if (persesDashboardLoading) { - return ; - } - return ( - - {persesDashboard ? ( - - {children} - - ) : ( - <>{children} - )} + + + + {persesDashboardLoading ? : children} + + diff --git a/web/src/components/dashboards/perses/dashboard-page.tsx b/web/src/components/dashboards/perses/dashboard-page.tsx index e8709896d..25f38de0b 100644 --- a/web/src/components/dashboards/perses/dashboard-page.tsx +++ b/web/src/components/dashboards/perses/dashboard-page.tsx @@ -9,6 +9,15 @@ import { OCPDashboardApp } from './dashboard-app'; import { DashboardFrame } from './dashboard-frame'; import { ProjectEmptyState } from './emptystates/ProjectEmptyState'; import { useDashboardsData } from './hooks/useDashboardsData'; +import { + Bullseye, + EmptyState, + EmptyStateBody, + EmptyStateHeader, + EmptyStateIcon, + Spinner, +} from '@patternfly/react-core'; +import { SearchIcon } from '@patternfly/react-icons'; const queryClient = new QueryClient({ defaultOptions: { @@ -19,6 +28,39 @@ const queryClient = new QueryClient({ }, }); +export const EmptyStateSpinner: React.FunctionComponent = () => ( + + + } + /> + + +); + +interface EmptyStateNoMatchFoundProps { + headerMsg: string; + bodyMsg: string; +} + +export const EmptyStateNoMatchFound: React.FunctionComponent = ({ + headerMsg, + bodyMsg, +}) => ( + + + } + /> + {bodyMsg} + + +); + const DashboardPage_: React.FC = () => { const { t } = useTranslation(process.env.I18N_NAMESPACE); const location = useLocation(); @@ -65,17 +107,16 @@ const DashboardPage_: React.FC = () => { ); if (!currentDashboard) { - return ( -
-

{t('Dashboard not found')}

-

- {t('The dashboard "{{name}}" was not found in project "{{project}}".', { - name: targetDashboardName, - project: activeProject || urlProject, - })} -

-
- ); + const headerMsg = t('Dashboard not found'); + const bodyMsg = t('The dashboard "{{name}}" was not found in project "{{project}}".', { + name: targetDashboardName, + project: activeProject || urlProject, + }); + return ; + } + + if (!currentDashboard.persesDashboard) { + return ; } return (