2025-04-01 10:38:02 +09:00

87 lines
3.3 KiB
TypeScript

// Libraries
import { useEffect } from 'react';
import { useParams } from 'react-router-dom-v5-compat';
import { usePrevious } from 'react-use';
import { PageLayoutType } from '@grafana/data';
import { config } from '@grafana/runtime';
import { UrlSyncContextProvider } from '@grafana/scenes';
import { Box } from '@grafana/ui';
import { Page } from 'app/core/components/Page/Page';
import PageLoader from 'app/core/components/PageLoader/PageLoader';
import { GrafanaRouteComponentProps } from 'app/core/navigation/types';
import { DashboardPageError } from 'app/features/dashboard/containers/DashboardPageError';
import { DashboardPageRouteParams, DashboardPageRouteSearchParams } from 'app/features/dashboard/containers/types';
import { DashboardRoutes } from 'app/types';
import { DashboardPrompt } from '../saving/DashboardPrompt';
import { getDashboardScenePageStateManager } from './DashboardScenePageStateManager';
export interface Props
extends Omit<GrafanaRouteComponentProps<DashboardPageRouteParams, DashboardPageRouteSearchParams>, 'match'> {}
export function DashboardScenePage({ route, queryParams, location }: Props) {
const params = useParams();
const { type, slug, uid } = params;
const prevMatch = usePrevious({ params });
const stateManager = config.featureToggles.useV2DashboardsAPI
? getDashboardScenePageStateManager('v2')
: getDashboardScenePageStateManager();
const { dashboard, isLoading, loadError } = stateManager.useState();
// After scene migration is complete and we get rid of old dashboard we should refactor dashboardWatcher so this route reload is not need
const routeReloadCounter = (location.state as any)?.routeReloadCounter;
useEffect(() => {
if (route.routeName === DashboardRoutes.Normal && type === 'snapshot') {
stateManager.loadSnapshot(slug!);
} else {
stateManager.loadDashboard({
type,
slug,
uid: uid ?? '',
route: route.routeName as DashboardRoutes,
urlFolderUid: queryParams.folderUid,
});
}
return () => {
stateManager.clearState();
};
}, [stateManager, uid, route.routeName, queryParams.folderUid, routeReloadCounter, slug, type]);
if (!dashboard) {
let errorElement;
if (loadError) {
errorElement = <DashboardPageError error={loadError} type={type} />;
}
return (
errorElement || (
<Page navId="dashboards/browse" layout={PageLayoutType.Canvas} data-testid={'dashboard-scene-page'}>
<Box paddingY={4} display="flex" direction="column" alignItems="center">
{isLoading && <PageLoader />}
</Box>
</Page>
)
);
}
// Do not render anything when transitioning from one dashboard to another
// A bit tricky for transition to or from Home dashboard that does not have a uid in the url (but could have it in the dashboard model)
// if prevMatch is undefined we are going from normal route to home route or vice versa
if (type !== 'snapshot' && (!prevMatch || uid !== prevMatch?.params.uid)) {
console.log('skipping rendering');
return null;
}
return (
<UrlSyncContextProvider scene={dashboard} updateUrlOnInit={true} createBrowserHistorySteps={true}>
<dashboard.Component model={dashboard} key={dashboard.state.key} />
<DashboardPrompt dashboard={dashboard} />
</UrlSyncContextProvider>
);
}
export default DashboardScenePage;