feat(explore): Redesign of Run/Save buttons (#19558)

* feat(explore): Move save button to header, run button to bottom of control panel

* Make the tabs sticky

* Add error icon to Data tab

* Show message when creating chart and all controls are filled correctly

* Add tests and storybook

* Fix tests

* Disable save button when control have errors

* Fix types

* Apply code review comments

* Replace styled with css

* Remove unused import
This commit is contained in:
Kamil Gabryjelski
2022-04-13 16:58:39 +02:00
committed by GitHub
parent 32239b04aa
commit c8304a2821
13 changed files with 362 additions and 279 deletions

View File

@@ -18,6 +18,7 @@
*/
import React from 'react';
import fetchMock from 'fetch-mock';
import { getChartControlPanelRegistry } from '@superset-ui/core';
import { MemoryRouter, Route } from 'react-router-dom';
import { render, screen, waitFor } from 'spec/helpers/testing-library';
import userEvent from '@testing-library/user-event';
@@ -111,13 +112,17 @@ test('generates a different form_data param when one is provided and is mounting
});
test('reuses the same form_data param when updating', async () => {
getChartControlPanelRegistry().registerValue('table', {
controlPanelSections: [],
});
const replaceState = jest.spyOn(window.history, 'replaceState');
const pushState = jest.spyOn(window.history, 'pushState');
await waitFor(() => renderWithRouter());
expect(replaceState.mock.calls.length).toBe(1);
userEvent.click(screen.getByText('Run'));
userEvent.click(screen.getByText('Update chart'));
await waitFor(() => expect(pushState.mock.calls.length).toBe(1));
expect(replaceState.mock.calls[0]).toEqual(pushState.mock.calls[0]);
replaceState.mockRestore();
pushState.mockRestore();
getChartControlPanelRegistry().remove('table');
});

View File

@@ -48,7 +48,6 @@ import { useTabId } from 'src/hooks/useTabId';
import ExploreChartPanel from '../ExploreChartPanel';
import ConnectedControlPanelsContainer from '../ControlPanelsContainer';
import SaveModal from '../SaveModal';
import QueryAndSaveBtns from '../QueryAndSaveBtns';
import DataSourcePanel from '../DatasourcePanel';
import { mountExploreUrl } from '../../exploreUtils';
import { areObjectsEqual } from '../../../reduxUtils';
@@ -477,8 +476,7 @@ function ExploreViewContainer(props) {
props.actions.logEvent(LOG_ACTIONS_CHANGE_EXPLORE_CONTROLS);
}
function renderErrorMessage() {
// Returns an error message as a node if any errors are in the store
const errorMessage = useMemo(() => {
const controlsWithErrors = Object.values(props.controls).filter(
control =>
control.validationErrors && control.validationErrors.length > 0,
@@ -512,7 +510,7 @@ function ExploreViewContainer(props) {
errorMessage = <div style={{ textAlign: 'left' }}>{errors}</div>;
}
return errorMessage;
}
}, [props.controls]);
function renderChartContainer() {
return (
@@ -520,7 +518,7 @@ function ExploreViewContainer(props) {
width={width}
height={height}
{...props}
errorMessage={renderErrorMessage()}
errorMessage={errorMessage}
refreshOverlayVisible={chartIsStale}
onQuery={onQuery}
/>
@@ -558,6 +556,8 @@ function ExploreViewContainer(props) {
chart={props.chart}
user={props.user}
reports={props.reports}
onSaveChart={toggleModal}
saveDisabled={errorMessage || props.chart.chartStatus === 'loading'}
/>
</ExploreHeaderContainer>
<ExplorePanelContainer id="explore-container">
@@ -669,16 +669,6 @@ function ExploreViewContainer(props) {
enable={{ right: true }}
className="col-sm-3 explore-column controls-column"
>
<QueryAndSaveBtns
canAdd={!!(props.can_add || props.can_overwrite)}
onQuery={onQuery}
onSave={toggleModal}
onStop={onStop}
loading={props.chart.chartStatus === 'loading'}
chartIsStale={chartIsStale}
errorMessage={renderErrorMessage()}
datasourceType={props.datasource_type}
/>
<ConnectedControlPanelsContainer
exploreState={props.exploreState}
actions={props.actions}
@@ -687,6 +677,11 @@ function ExploreViewContainer(props) {
chart={props.chart}
datasource_type={props.datasource_type}
isDatasourceMetaLoading={props.isDatasourceMetaLoading}
onQuery={onQuery}
onStop={onStop}
canStopQuery={props.can_add || props.can_overwrite}
errorMessage={errorMessage}
chartIsStale={chartIsStale}
/>
</Resizable>
<div