import { css, cx } from '@emotion/css';
import React, { useEffect } from 'react';
import { GrafanaTheme2 } from '@grafana/data';
import { config } from '@grafana/runtime';
import { ErrorBoundaryAlert, useStyles2, useTheme2 } from '@grafana/ui';
import { SplitPaneWrapper } from 'app/core/components/SplitPaneWrapper/SplitPaneWrapper';
import { useGrafana } from 'app/core/context/GrafanaContext';
import { useNavModel } from 'app/core/hooks/useNavModel';
import { Trans } from 'app/core/internationalization';
import { GrafanaRouteComponentProps } from 'app/core/navigation/types';
import { useSelector } from 'app/types';
import { ExploreQueryParams } from 'app/types/explore';
import { CorrelationEditorModeBar } from './CorrelationEditorModeBar';
import { ExploreActions } from './ExploreActions';
import { ExploreDrawer } from './ExploreDrawer';
import { ExplorePaneContainer } from './ExplorePaneContainer';
import { QueriesDrawerContextProvider, useQueriesDrawerContext } from './QueriesDrawer/QueriesDrawerContext';
import RichHistoryContainer from './RichHistory/RichHistoryContainer';
import { useExplorePageTitle } from './hooks/useExplorePageTitle';
import { useKeyboardShortcuts } from './hooks/useKeyboardShortcuts';
import { useSplitSizeUpdater } from './hooks/useSplitSizeUpdater';
import { useStateSync } from './hooks/useStateSync';
import { useTimeSrvFix } from './hooks/useTimeSrvFix';
import { isSplit, selectCorrelationDetails, selectPanesEntries } from './state/selectors';
const MIN_PANE_WIDTH = 200;
export default function ExplorePage(props: GrafanaRouteComponentProps<{}, ExploreQueryParams>) {
return (
);
}
function ExplorePageContent(props: GrafanaRouteComponentProps<{}, ExploreQueryParams>) {
const styles = useStyles2(getStyles);
const theme = useTheme2();
useTimeSrvFix();
useStateSync(props.queryParams);
// We want to set the title according to the URL and not to the state because the URL itself may lag
// (due to how useStateSync above works) by a few milliseconds.
// When a URL is pushed to the history, the browser also saves the title of the page and
// if we were to update the URL on state change, the title would not match the URL.
// Ultimately the URL is the single source of truth from which state is derived, the page title is not different
useExplorePageTitle(props.queryParams);
const { chrome } = useGrafana();
const navModel = useNavModel('explore');
const { updateSplitSize, widthCalc } = useSplitSizeUpdater(MIN_PANE_WIDTH);
const panes = useSelector(selectPanesEntries);
const hasSplit = useSelector(isSplit);
const correlationDetails = useSelector(selectCorrelationDetails);
const { drawerOpened, setDrawerOpened, queryLibraryAvailable } = useQueriesDrawerContext();
const showCorrelationEditorBar = config.featureToggles.correlations && (correlationDetails?.editorMode || false);
useEffect(() => {
//This is needed for breadcrumbs and topnav.
//We should probably abstract this out at some point
chrome.update({
sectionNav: navModel,
});
}, [chrome, navModel]);
useKeyboardShortcuts();
return (
{showCorrelationEditorBar && }
size && updateSplitSize(size)}
>
{panes.map(([exploreId]) => {
return (
);
})}
{drawerOpened && (
{
setDrawerOpened(false);
}}
/>
)}
);
}
const getStyles = (theme: GrafanaTheme2) => {
return {
pageScrollbarWrapper: css({
width: '100%',
flexGrow: 1,
minHeight: 0,
height: '100%',
position: 'relative',
overflow: 'hidden',
}),
correlationsEditorIndicator: css({
borderLeft: `4px solid ${theme.colors.primary.main}`,
borderRight: `4px solid ${theme.colors.primary.main}`,
borderBottom: `4px solid ${theme.colors.primary.main}`,
overflow: 'scroll',
}),
};
};