mirror of
https://github.com/grafana/grafana.git
synced 2026-09-05 04:40:13 -05:00
Explore: move items out of topnav & use canvas variant for toolbar buttons (#60630)
* Explore: remove topnav * PageToolbar: fix left items margin when no title or page icon is set * add missing key prop & fix tests * use canvas variant in live logs * avoid rendering empty space * fix test * avoid disabling split resize button when live tailing * minor touchups * Update packages/grafana-ui/src/components/PageLayout/PageToolbar.tsx Co-authored-by: Torkel Ödegaard <torkel@grafana.com> Co-authored-by: Torkel Ödegaard <torkel@grafana.com>
This commit is contained in:
co-authored by
Torkel Ödegaard
parent
97e25d70e7
commit
dfed7e59a5
@@ -190,7 +190,7 @@ const getStyles = (theme: GrafanaTheme2) => {
|
|||||||
min-width: 0;
|
min-width: 0;
|
||||||
`,
|
`,
|
||||||
h1Styles: css`
|
h1Styles: css`
|
||||||
margin: 0;
|
margin: ${spacing(0, 1, 0, 0)};
|
||||||
line-height: inherit;
|
line-height: inherit;
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
@@ -229,7 +229,7 @@ const getStyles = (theme: GrafanaTheme2) => {
|
|||||||
${theme.breakpoints.up('md')} {
|
${theme.breakpoints.up('md')} {
|
||||||
align-items: center;
|
align-items: center;
|
||||||
display: flex;
|
display: flex;
|
||||||
padding-left: ${spacing(0.5)};
|
padding-right: ${spacing(0.5)};
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ export const AddToDashboard = ({ exploreId }: Props) => {
|
|||||||
<>
|
<>
|
||||||
<ToolbarButton
|
<ToolbarButton
|
||||||
icon="apps"
|
icon="apps"
|
||||||
|
variant="canvas"
|
||||||
onClick={() => setIsOpen(true)}
|
onClick={() => setIsOpen(true)}
|
||||||
aria-label="Add to dashboard"
|
aria-label="Add to dashboard"
|
||||||
disabled={!explorePaneHasQueries}
|
disabled={!explorePaneHasQueries}
|
||||||
|
|||||||
@@ -79,9 +79,6 @@ const getStyles = (theme: GrafanaTheme2) => {
|
|||||||
padding: ${theme.spacing(2)};
|
padding: ${theme.spacing(2)};
|
||||||
padding-top: 0;
|
padding-top: 0;
|
||||||
`,
|
`,
|
||||||
exploreContainerTopnav: css`
|
|
||||||
padding-top: ${theme.spacing(2)};
|
|
||||||
`,
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -409,7 +406,6 @@ export class Explore extends React.PureComponent<Props, ExploreState> {
|
|||||||
showTrace,
|
showTrace,
|
||||||
showNodeGraph,
|
showNodeGraph,
|
||||||
showFlameGraph,
|
showFlameGraph,
|
||||||
splitted,
|
|
||||||
timeZone,
|
timeZone,
|
||||||
isFromCompactUrl,
|
isFromCompactUrl,
|
||||||
} = this.props;
|
} = this.props;
|
||||||
@@ -441,11 +437,7 @@ export class Explore extends React.PureComponent<Props, ExploreState> {
|
|||||||
{isFromCompactUrl ? this.renderCompactUrlWarning() : null}
|
{isFromCompactUrl ? this.renderCompactUrlWarning() : null}
|
||||||
{datasourceMissing ? this.renderEmptyState(styles.exploreContainer) : null}
|
{datasourceMissing ? this.renderEmptyState(styles.exploreContainer) : null}
|
||||||
{datasourceInstance && (
|
{datasourceInstance && (
|
||||||
<div
|
<div className={styles.exploreContainer}>
|
||||||
className={cx(styles.exploreContainer, {
|
|
||||||
[styles.exploreContainerTopnav]: Boolean(config.featureToggles.topnav && !splitted),
|
|
||||||
})}
|
|
||||||
>
|
|
||||||
<PanelContainer className={styles.queryContainer}>
|
<PanelContainer className={styles.queryContainer}>
|
||||||
<QueryRows exploreId={exploreId} />
|
<QueryRows exploreId={exploreId} />
|
||||||
<SecondaryActions
|
<SecondaryActions
|
||||||
|
|||||||
@@ -88,6 +88,7 @@ export class ExploreTimeControls extends Component<Props> {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<TimePickerWithHistory
|
<TimePickerWithHistory
|
||||||
|
isOnCanvas
|
||||||
{...timePickerCommonProps}
|
{...timePickerCommonProps}
|
||||||
timeSyncButton={timeSyncButton}
|
timeSyncButton={timeSyncButton}
|
||||||
isSynced={syncedTimes}
|
isSynced={syncedTimes}
|
||||||
|
|||||||
@@ -4,14 +4,7 @@ import { connect, ConnectedProps } from 'react-redux';
|
|||||||
|
|
||||||
import { DataSourceInstanceSettings, RawTimeRange } from '@grafana/data';
|
import { DataSourceInstanceSettings, RawTimeRange } from '@grafana/data';
|
||||||
import { config, DataSourcePicker, reportInteraction } from '@grafana/runtime';
|
import { config, DataSourcePicker, reportInteraction } from '@grafana/runtime';
|
||||||
import {
|
import { defaultIntervals, PageToolbar, RefreshPicker, SetInterval, ToolbarButton, ButtonGroup } from '@grafana/ui';
|
||||||
defaultIntervals,
|
|
||||||
PageToolbar,
|
|
||||||
RefreshPicker,
|
|
||||||
SetInterval,
|
|
||||||
ToolbarButton,
|
|
||||||
ToolbarButtonRow,
|
|
||||||
} from '@grafana/ui';
|
|
||||||
import { AppChromeUpdate } from 'app/core/components/AppChrome/AppChromeUpdate';
|
import { AppChromeUpdate } from 'app/core/components/AppChrome/AppChromeUpdate';
|
||||||
import { contextSrv } from 'app/core/core';
|
import { contextSrv } from 'app/core/core';
|
||||||
import { createAndCopyShortLink } from 'app/core/utils/shortLinks';
|
import { createAndCopyShortLink } from 'app/core/utils/shortLinks';
|
||||||
@@ -142,8 +135,6 @@ class UnConnectedExploreToolbar extends PureComponent<Props> {
|
|||||||
syncedTimes,
|
syncedTimes,
|
||||||
onChangeTimeZone,
|
onChangeTimeZone,
|
||||||
onChangeFiscalYearStartMonth,
|
onChangeFiscalYearStartMonth,
|
||||||
refreshInterval,
|
|
||||||
loading,
|
|
||||||
isPaused,
|
isPaused,
|
||||||
hasLiveOption,
|
hasLiveOption,
|
||||||
containerWidth,
|
containerWidth,
|
||||||
@@ -168,6 +159,7 @@ class UnConnectedExploreToolbar extends PureComponent<Props> {
|
|||||||
return [
|
return [
|
||||||
!splitted ? (
|
!splitted ? (
|
||||||
<ToolbarButton
|
<ToolbarButton
|
||||||
|
variant="canvas"
|
||||||
key="split"
|
key="split"
|
||||||
tooltip="Split the pane"
|
tooltip="Split the pane"
|
||||||
onClick={this.onOpenSplitView}
|
onClick={this.onOpenSplitView}
|
||||||
@@ -177,19 +169,19 @@ class UnConnectedExploreToolbar extends PureComponent<Props> {
|
|||||||
Split
|
Split
|
||||||
</ToolbarButton>
|
</ToolbarButton>
|
||||||
) : (
|
) : (
|
||||||
<React.Fragment key="splitActions">
|
<ButtonGroup key="split-controls">
|
||||||
<ToolbarButton
|
<ToolbarButton
|
||||||
|
variant="canvas"
|
||||||
tooltip={`${isLargerExploreId ? 'Narrow' : 'Widen'} pane`}
|
tooltip={`${isLargerExploreId ? 'Narrow' : 'Widen'} pane`}
|
||||||
disabled={isLive}
|
|
||||||
onClick={onClickResize}
|
onClick={onClickResize}
|
||||||
icon={isLargerExploreId ? 'gf-movepane-left' : 'gf-movepane-right'}
|
icon={isLargerExploreId ? 'gf-movepane-left' : 'gf-movepane-right'}
|
||||||
iconOnly={true}
|
iconOnly={true}
|
||||||
className={styles.rotateIcon}
|
className={styles.rotateIcon}
|
||||||
/>
|
/>
|
||||||
<ToolbarButton tooltip="Close split pane" onClick={this.onCloseSplitView} icon="times">
|
<ToolbarButton tooltip="Close split pane" onClick={this.onCloseSplitView} icon="times" variant="canvas">
|
||||||
Close
|
Close
|
||||||
</ToolbarButton>
|
</ToolbarButton>
|
||||||
</React.Fragment>
|
</ButtonGroup>
|
||||||
),
|
),
|
||||||
|
|
||||||
showExploreToDashboard && (
|
showExploreToDashboard && (
|
||||||
@@ -217,10 +209,6 @@ class UnConnectedExploreToolbar extends PureComponent<Props> {
|
|||||||
|
|
||||||
this.renderRefreshPicker(showSmallTimePicker),
|
this.renderRefreshPicker(showSmallTimePicker),
|
||||||
|
|
||||||
refreshInterval && (
|
|
||||||
<SetInterval key="setInterval" func={this.onRunQuery} interval={refreshInterval} loading={loading} />
|
|
||||||
),
|
|
||||||
|
|
||||||
hasLiveOption && (
|
hasLiveOption && (
|
||||||
<LiveTailControls key="liveControls" exploreId={exploreId}>
|
<LiveTailControls key="liveControls" exploreId={exploreId}>
|
||||||
{(c) => {
|
{(c) => {
|
||||||
@@ -251,12 +239,13 @@ class UnConnectedExploreToolbar extends PureComponent<Props> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { datasourceMissing, exploreId, splitted, containerWidth, topOfViewRef } = this.props;
|
const { datasourceMissing, exploreId, splitted, containerWidth, topOfViewRef, refreshInterval, loading } =
|
||||||
|
this.props;
|
||||||
|
|
||||||
const showSmallDataSourcePicker = (splitted ? containerWidth < 700 : containerWidth < 800) || false;
|
const showSmallDataSourcePicker = (splitted ? containerWidth < 700 : containerWidth < 800) || false;
|
||||||
const isTopnav = config.featureToggles.topnav;
|
const isTopnav = config.featureToggles.topnav;
|
||||||
|
|
||||||
const getDashNav = () => (
|
const shareButton = (
|
||||||
<DashNavButton
|
<DashNavButton
|
||||||
key="share"
|
key="share"
|
||||||
tooltip="Copy shortened link"
|
tooltip="Copy shortened link"
|
||||||
@@ -278,39 +267,25 @@ class UnConnectedExploreToolbar extends PureComponent<Props> {
|
|||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
||||||
const topNavActions = [
|
const toolbarLeftItems = [
|
||||||
getDashNav(),
|
// We only want to show the shortened link button in the left Toolbar if topnav is not enabled as with topnav enabled it sits next to the brecrumbs
|
||||||
!splitted && getDataSourcePicker(),
|
!isTopnav && exploreId === ExploreId.left && shareButton,
|
||||||
<div style={{ flex: 1 }} key="spacer" />,
|
|
||||||
<ToolbarButtonRow key="actions" alignment="right">
|
|
||||||
{this.renderActions()}
|
|
||||||
</ToolbarButtonRow>,
|
|
||||||
].filter(Boolean);
|
|
||||||
|
|
||||||
const toolbarLeftItems = [exploreId === ExploreId.left && getDashNav(), getDataSourcePicker()].filter(Boolean);
|
|
||||||
|
|
||||||
const toolbarLeftItemsTopNav = [
|
|
||||||
exploreId === ExploreId.left && (
|
|
||||||
<AppChromeUpdate
|
|
||||||
actions={[getDashNav(), !splitted && getDataSourcePicker(), <div style={{ flex: 1 }} key="spacer" />].filter(
|
|
||||||
Boolean
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
),
|
|
||||||
getDataSourcePicker(),
|
getDataSourcePicker(),
|
||||||
].filter(Boolean);
|
].filter(Boolean);
|
||||||
|
|
||||||
return isTopnav && !splitted ? (
|
return (
|
||||||
<div ref={topOfViewRef}>
|
|
||||||
<AppChromeUpdate actions={topNavActions} />
|
|
||||||
</div>
|
|
||||||
) : (
|
|
||||||
<div ref={topOfViewRef}>
|
<div ref={topOfViewRef}>
|
||||||
|
{refreshInterval && <SetInterval func={this.onRunQuery} interval={refreshInterval} loading={loading} />}
|
||||||
|
{isTopnav && (
|
||||||
|
<div ref={topOfViewRef}>
|
||||||
|
<AppChromeUpdate actions={[shareButton, <div style={{ flex: 1 }} key="spacer" />]} />
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
<PageToolbar
|
<PageToolbar
|
||||||
aria-label="Explore toolbar"
|
aria-label="Explore toolbar"
|
||||||
title={exploreId === ExploreId.left && !isTopnav ? 'Explore' : undefined}
|
title={exploreId === ExploreId.left && !isTopnav ? 'Explore' : undefined}
|
||||||
pageIcon={exploreId === ExploreId.left && !isTopnav ? 'compass' : undefined}
|
pageIcon={exploreId === ExploreId.left && !isTopnav ? 'compass' : undefined}
|
||||||
leftItems={isTopnav ? toolbarLeftItemsTopNav : toolbarLeftItems}
|
leftItems={toolbarLeftItems}
|
||||||
>
|
>
|
||||||
{this.renderActions()}
|
{this.renderActions()}
|
||||||
</PageToolbar>
|
</PageToolbar>
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ type LiveTailButtonProps = {
|
|||||||
|
|
||||||
export function LiveTailButton(props: LiveTailButtonProps) {
|
export function LiveTailButton(props: LiveTailButtonProps) {
|
||||||
const { start, pause, resume, isLive, isPaused, stop, splitted } = props;
|
const { start, pause, resume, isLive, isPaused, stop, splitted } = props;
|
||||||
const buttonVariant = isLive && !isPaused ? 'active' : 'default';
|
const buttonVariant = isLive && !isPaused ? 'active' : 'canvas';
|
||||||
const onClickMain = isLive ? (isPaused ? resume : pause) : start;
|
const onClickMain = isLive ? (isPaused ? resume : pause) : start;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ export function TimeSyncButton(props: TimeSyncButtonProps) {
|
|||||||
<Tooltip content={syncTimesTooltip} placement="bottom">
|
<Tooltip content={syncTimesTooltip} placement="bottom">
|
||||||
<ToolbarButton
|
<ToolbarButton
|
||||||
icon="link"
|
icon="link"
|
||||||
variant={isSynced ? 'active' : 'default'}
|
variant={isSynced ? 'active' : 'canvas'}
|
||||||
aria-label={isSynced ? 'Synced times' : 'Unsynced times'}
|
aria-label={isSynced ? 'Synced times' : 'Unsynced times'}
|
||||||
onClick={onClick}
|
onClick={onClick}
|
||||||
/>
|
/>
|
||||||
|
|||||||
Reference in New Issue
Block a user