ButtonSelect & RefreshPicker: Rewrite of components to use new emotion based ToolbarButton & Menu (#30510)

* ButtonSelect: Trying to rewrite the button select to use ToggleButtonGroup & Menu

* minor update

* Progress

* Updated

* Moving all the explore scenarios into the refresh picker component

* Minor fixes

* Fixed responsive part of run button

* More minor fixes

* typescript fix

* Update packages/grafana-ui/src/components/Icon/Icon.tsx

Co-authored-by: Alex Khomenko <Clarity-89@users.noreply.github.com>

* Update packages/grafana-ui/src/components/Menu/Menu.tsx

Co-authored-by: Alex Khomenko <Clarity-89@users.noreply.github.com>

* Review feedback fixes and more

* Fixes small ts issue

* Updated return to dashboard button and tests, moved ButtonSelect out of LegacyForms

* fixed ts issue

* Fixed test

Co-authored-by: Alex Khomenko <Clarity-89@users.noreply.github.com>
This commit is contained in:
Torkel Ödegaard
2021-01-23 08:17:50 +01:00
committed by GitHub
parent 8c1a79f24b
commit 2a21f067b7
28 changed files with 504 additions and 592 deletions

View File

@@ -217,7 +217,7 @@ export class UnConnectedExploreToolbar extends PureComponent<Props> {
<RunButton
refreshInterval={refreshInterval}
onChangeRefreshInterval={this.onChangeRefreshInterval}
splitted={splitted}
isSmall={splitted || showSmallTimePicker}
isLive={isLive}
loading={loading || (isLive && !isPaused)}
onRun={this.onRunQuery}

View File

@@ -1,5 +1,5 @@
import React, { ComponentProps } from 'react';
import { render, screen, fireEvent } from '@testing-library/react';
import { render, screen } from '@testing-library/react';
import { UnconnectedReturnToDashboardButton as ReturnToDashboardButton } from './ReturnToDashboardButton';
import { ExploreId } from 'app/types/explore';
@@ -21,21 +21,21 @@ describe('ReturnToDashboardButton', () => {
render(<ReturnToDashboardButton {...createProps()} />);
expect(screen.getAllByTestId(/returnButton/i)).toHaveLength(2);
});
it('should not render any button if originPanelId is not provided', () => {
render(<ReturnToDashboardButton {...createProps({ originPanelId: undefined })} />);
expect(screen.queryByTestId(/returnButton/i)).toBeNull();
});
it('should not render any button if split view', () => {
render(<ReturnToDashboardButton {...createProps({ splitted: true })} />);
expect(screen.queryByTestId(/returnButton/i)).toBeNull();
});
it('should show option to return to dashboard with changes', () => {
render(<ReturnToDashboardButton {...createProps()} />);
const returnWithChangesButton = screen.getByTestId('returnButtonWithChanges');
const selectButton = returnWithChangesButton.querySelector('.select-button');
if (selectButton) {
fireEvent.click(selectButton);
}
returnWithChangesButton.click();
expect(screen.getAllByText('Return to panel with changes')).toHaveLength(1);
});
});

View File

@@ -1,8 +1,7 @@
import React, { FC } from 'react';
import classNames from 'classnames';
import { connect } from 'react-redux';
import { hot } from 'react-hot-loader';
import { Icon, Tooltip, LegacyForms } from '@grafana/ui';
import { Icon, Tooltip, ButtonSelect, ToolbarButton, ButtonGroup } from '@grafana/ui';
import { DataQuery } from '@grafana/data';
import kbn from '../../core/utils/kbn';
@@ -12,8 +11,6 @@ import { ExploreId } from 'app/types/explore';
import { updateLocation } from 'app/core/actions';
import { setDashboardQueriesToUpdateOnLoad } from '../dashboard/state/reducers';
const { ButtonSelect } = LegacyForms;
interface Props {
exploreId: ExploreId;
splitted: boolean;
@@ -37,11 +34,6 @@ export const UnconnectedReturnToDashboardButton: FC<Props> = ({
return null;
}
const panelReturnClasses = classNames('btn', 'navbar-button', {
'btn--radius-right-0': withOriginId,
'navbar-button navbar-button--border-right-0': withOriginId,
});
const cleanQueries = (queries: DataQuery[]) => {
return queries.map((query: DataQuery & { context?: string }) => {
delete query.context;
@@ -74,26 +66,19 @@ export const UnconnectedReturnToDashboardButton: FC<Props> = ({
};
return (
<div className="explore-toolbar-content-item">
<ButtonGroup className="explore-toolbar-content-item" noSpacing>
<Tooltip content={'Return to panel'} placement="bottom">
<button
data-testid="returnButton"
title={'Return to panel'}
className={panelReturnClasses}
onClick={() => returnToPanel()}
>
<ToolbarButton data-testid="returnButton" title={'Return to panel'} onClick={() => returnToPanel()}>
<Icon name="arrow-left" />
</button>
</ToolbarButton>
</Tooltip>
<div data-testid="returnButtonWithChanges">
<ButtonSelect
className="navbar-button--attached btn--radius-left-0$"
options={[{ label: 'Return to panel with changes', value: '' }]}
onChange={() => returnToPanel({ withChanges: true })}
maxMenuHeight={380}
/>
</div>
</div>
<ButtonSelect
data-testid="returnButtonWithChanges"
options={[{ label: 'Return to panel with changes', value: '' }]}
onChange={() => returnToPanel({ withChanges: true })}
maxMenuHeight={380}
/>
</ButtonGroup>
);
};

View File

@@ -6,7 +6,7 @@ import { getTimeSrv, TimeSrv } from 'app/features/dashboard/services/TimeSrv';
const setup = (propOverrides?: object) => {
const props: Props = {
splitted: false,
isSmall: false,
loading: false,
isLive: false,
onRun: jest.fn(),

View File

@@ -1,27 +1,9 @@
import React from 'react';
import { RefreshPicker, defaultIntervals } from '@grafana/ui';
import { selectors } from '@grafana/e2e-selectors';
import memoizeOne from 'memoize-one';
import { css } from 'emotion';
import classNames from 'classnames';
import { ResponsiveButton } from './ResponsiveButton';
import { getTimeSrv } from 'app/features/dashboard/services/TimeSrv';
const getStyles = memoizeOne(() => {
return {
selectButtonOverride: css`
label: selectButtonOverride;
.select-button-value {
color: white !important;
}
`,
};
});
export type Props = {
splitted: boolean;
isSmall?: boolean;
loading: boolean;
isLive: boolean;
onRun: (loading: boolean) => void;
@@ -31,38 +13,29 @@ export type Props = {
};
export function RunButton(props: Props) {
const { splitted, loading, onRun, onChangeRefreshInterval, refreshInterval, showDropdown, isLive } = props;
const styles = getStyles();
const { isSmall, loading, onRun, onChangeRefreshInterval, refreshInterval, showDropdown, isLive } = props;
const intervals = getTimeSrv().getValidIntervals(defaultIntervals);
let text: string | undefined;
const runButton = (
<ResponsiveButton
splitted={splitted}
title={loading && !isLive ? 'Cancel' : 'Run Query'}
onClick={() => onRun(loading)}
buttonClassName={classNames({
'navbar-button--primary': isLive || !loading,
'navbar-button--danger': loading && !isLive,
'btn--radius-right-0': showDropdown,
})}
icon={loading ? 'fa fa-spinner' : 'sync'}
iconClassName={loading ? ' fa-spin' : undefined}
aria-label={selectors.pages.Explore.General.runButton}
if (isLive) {
return null;
}
if (!isSmall) {
text = loading ? 'Cancel' : 'Run query';
}
return (
<RefreshPicker
onIntervalChanged={onChangeRefreshInterval}
value={refreshInterval}
isLoading={loading}
text={text}
intervals={intervals}
isLive={isLive}
onRefresh={() => onRun(loading)}
noIntervalPicker={!showDropdown}
primary={true}
/>
);
if (showDropdown) {
return (
<RefreshPicker
onIntervalChanged={onChangeRefreshInterval}
value={refreshInterval}
buttonSelectClassName={`${loading ? 'navbar-button--danger' : 'navbar-button--primary'} ${
styles.selectButtonOverride
}`}
refreshButton={runButton}
intervals={intervals}
/>
);
}
return runButton;
}