mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
* Create basic feature toggle * Rename context to reflect it contains query history and query library * Update icons and variants * Rename hooks * Update tests * Fix mock * Add tracking * Turn button into a toggle * Make dropdown active as well This is required to have better UI and an indication of selected state in split view * Update Query Library icon This is to make it consistent with the toolbar button * Hide query history button when query library is available This is to avoid confusing UX with 2 button triggering the drawer but with slightly different behavior * Make the drawer bigger for query library To avoid confusion for current users and test it internally a bit more it's behind a feature toggle. Bigger drawer may obstruct the view and add more friction in the UX. * Fix tests The test was failing because queryLibraryAvailable was set to true for tests. This change makes it more explicit what use case is being tested * Remove active state underline from the dropdown * Allow closing Query Library drawer from the toolbar * Simplify dropdown design
130 lines
5.0 KiB
TypeScript
130 lines
5.0 KiB
TypeScript
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 (
|
|
<QueriesDrawerContextProvider>
|
|
<ExplorePageContent {...props} />
|
|
</QueriesDrawerContextProvider>
|
|
);
|
|
}
|
|
|
|
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 (
|
|
<div
|
|
className={cx(styles.pageScrollbarWrapper, {
|
|
[styles.correlationsEditorIndicator]: showCorrelationEditorBar,
|
|
})}
|
|
>
|
|
<h1 className="sr-only">
|
|
<Trans i18nKey="nav.explore.title" />
|
|
</h1>
|
|
<ExploreActions />
|
|
{showCorrelationEditorBar && <CorrelationEditorModeBar panes={panes} />}
|
|
<SplitPaneWrapper
|
|
splitOrientation="vertical"
|
|
paneSize={widthCalc}
|
|
minSize={MIN_PANE_WIDTH}
|
|
maxSize={MIN_PANE_WIDTH * -1}
|
|
primary="second"
|
|
splitVisible={hasSplit}
|
|
parentStyle={showCorrelationEditorBar ? { height: `calc(100% - ${theme.spacing(6)}` } : {}} // button = 4, padding = 1 x 2
|
|
paneStyle={{ overflow: 'auto', display: 'flex', flexDirection: 'column' }}
|
|
onDragFinished={(size) => size && updateSplitSize(size)}
|
|
>
|
|
{panes.map(([exploreId]) => {
|
|
return (
|
|
<ErrorBoundaryAlert key={exploreId} style="page">
|
|
<ExplorePaneContainer exploreId={exploreId} />
|
|
</ErrorBoundaryAlert>
|
|
);
|
|
})}
|
|
</SplitPaneWrapper>
|
|
{drawerOpened && (
|
|
<ExploreDrawer initialHeight={queryLibraryAvailable ? '75vh' : undefined}>
|
|
<RichHistoryContainer
|
|
onClose={() => {
|
|
setDrawerOpened(false);
|
|
}}
|
|
/>
|
|
</ExploreDrawer>
|
|
)}
|
|
</div>
|
|
);
|
|
}
|
|
|
|
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',
|
|
}),
|
|
};
|
|
};
|