mirror of
https://github.com/apache/superset.git
synced 2026-05-11 19:05:24 +00:00
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:
committed by
GitHub
parent
32239b04aa
commit
c8304a2821
@@ -90,6 +90,7 @@ const createProps = () => ({
|
||||
user: {
|
||||
userId: 1,
|
||||
},
|
||||
onSaveChart: jest.fn(),
|
||||
});
|
||||
|
||||
test('Cancelling changes to the properties should reset previous properties', () => {
|
||||
@@ -115,3 +116,17 @@ test('Cancelling changes to the properties should reset previous properties', ()
|
||||
|
||||
expect(screen.getByDisplayValue(prevChartName)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
test('Save chart', () => {
|
||||
const props = createProps();
|
||||
render(<ExploreHeader {...props} />, { useRedux: true });
|
||||
userEvent.click(screen.getByText('Save'));
|
||||
expect(props.onSaveChart).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test('Save disabled', () => {
|
||||
const props = createProps();
|
||||
render(<ExploreHeader {...props} saveDisabled />, { useRedux: true });
|
||||
userEvent.click(screen.getByText('Save'));
|
||||
expect(props.onSaveChart).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
@@ -24,7 +24,6 @@ import {
|
||||
CategoricalColorNamespace,
|
||||
css,
|
||||
SupersetClient,
|
||||
styled,
|
||||
t,
|
||||
} from '@superset-ui/core';
|
||||
import {
|
||||
@@ -36,9 +35,12 @@ import { isFeatureEnabled, FeatureFlag } from 'src/featureFlags';
|
||||
import { chartPropShape } from 'src/dashboard/util/propShapes';
|
||||
import AlteredSliceTag from 'src/components/AlteredSliceTag';
|
||||
import FaveStar from 'src/components/FaveStar';
|
||||
import Button from 'src/components/Button';
|
||||
import Icons from 'src/components/Icons';
|
||||
import PropertiesModal from 'src/explore/components/PropertiesModal';
|
||||
import { sliceUpdated } from 'src/explore/actions/exploreActions';
|
||||
import CertifiedBadge from 'src/components/CertifiedBadge';
|
||||
import { Tooltip } from 'src/components/Tooltip';
|
||||
import ExploreAdditionalActionsMenu from '../ExploreAdditionalActionsMenu';
|
||||
import { ChartEditableTitle } from './ChartEditableTitle';
|
||||
|
||||
@@ -55,60 +57,58 @@ const propTypes = {
|
||||
ownState: PropTypes.object,
|
||||
timeout: PropTypes.number,
|
||||
chart: chartPropShape,
|
||||
saveDisabled: PropTypes.bool,
|
||||
};
|
||||
|
||||
const StyledHeader = styled.div`
|
||||
${({ theme }) => css`
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
flex-wrap: nowrap;
|
||||
justify-content: space-between;
|
||||
height: 100%;
|
||||
|
||||
span[role='button'] {
|
||||
display: flex;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.title-panel {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
min-width: 0;
|
||||
margin-right: ${theme.gridUnit * 12}px;
|
||||
}
|
||||
|
||||
.right-button-panel {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
> .btn-group {
|
||||
flex: 0 0 auto;
|
||||
margin-left: ${theme.gridUnit}px;
|
||||
}
|
||||
}
|
||||
|
||||
.action-button {
|
||||
color: ${theme.colors.grayscale.base};
|
||||
margin: 0 ${theme.gridUnit * 1.5}px 0 ${theme.gridUnit}px;
|
||||
}
|
||||
`}
|
||||
const saveButtonStyles = theme => css`
|
||||
color: ${theme.colors.primary.dark2};
|
||||
& > span[role='img'] {
|
||||
margin-right: 0;
|
||||
}
|
||||
`;
|
||||
|
||||
const StyledButtons = styled.span`
|
||||
${({ theme }) => css`
|
||||
const headerStyles = theme => css`
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
flex-wrap: nowrap;
|
||||
justify-content: space-between;
|
||||
height: 100%;
|
||||
|
||||
span[role='button'] {
|
||||
display: flex;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.title-panel {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding-left: ${theme.gridUnit * 2}px;
|
||||
min-width: 0;
|
||||
margin-right: ${theme.gridUnit * 12}px;
|
||||
}
|
||||
|
||||
& .fave-unfave-icon {
|
||||
padding: 0 ${theme.gridUnit}px;
|
||||
.right-button-panel {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
`;
|
||||
|
||||
&:first-child {
|
||||
padding-left: 0;
|
||||
}
|
||||
const buttonsStyles = theme => css`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding-left: ${theme.gridUnit * 2}px;
|
||||
|
||||
& .fave-unfave-icon {
|
||||
padding: 0 ${theme.gridUnit}px;
|
||||
|
||||
&:first-child {
|
||||
padding-left: 0;
|
||||
}
|
||||
`}
|
||||
}
|
||||
`;
|
||||
|
||||
const saveButtonContainerStyles = theme => css`
|
||||
margin-right: ${theme.gridUnit * 2}px;
|
||||
`;
|
||||
|
||||
export class ExploreChartHeader extends React.PureComponent {
|
||||
@@ -231,11 +231,13 @@ export class ExploreChartHeader extends React.PureComponent {
|
||||
isStarred,
|
||||
sliceUpdated,
|
||||
sliceName,
|
||||
onSaveChart,
|
||||
saveDisabled,
|
||||
} = this.props;
|
||||
const { latestQueryFormData, sliceFormData } = chart;
|
||||
const oldSliceName = slice?.slice_name;
|
||||
return (
|
||||
<StyledHeader id="slice-header">
|
||||
<div id="slice-header" css={headerStyles}>
|
||||
<div className="title-panel">
|
||||
<ChartEditableTitle
|
||||
title={sliceName}
|
||||
@@ -248,7 +250,7 @@ export class ExploreChartHeader extends React.PureComponent {
|
||||
placeholder={t('Add the name of the chart')}
|
||||
/>
|
||||
{slice && (
|
||||
<StyledButtons>
|
||||
<span css={buttonsStyles}>
|
||||
{slice.certified_by && (
|
||||
<CertifiedBadge
|
||||
certifiedBy={slice.certified_by}
|
||||
@@ -279,10 +281,31 @@ export class ExploreChartHeader extends React.PureComponent {
|
||||
currentFormData={{ ...formData, chartTitle: sliceName }}
|
||||
/>
|
||||
)}
|
||||
</StyledButtons>
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
<div className="right-button-panel">
|
||||
<Tooltip
|
||||
title={
|
||||
saveDisabled
|
||||
? t('Add required control values to save chart')
|
||||
: null
|
||||
}
|
||||
>
|
||||
{/* needed to wrap button in a div - antd tooltip doesn't work with disabled button */}
|
||||
<div css={saveButtonContainerStyles}>
|
||||
<Button
|
||||
buttonStyle="secondary"
|
||||
onClick={onSaveChart}
|
||||
disabled={saveDisabled}
|
||||
data-test="query-save-button"
|
||||
css={saveButtonStyles}
|
||||
>
|
||||
<Icons.SaveOutlined iconSize="l" />
|
||||
{t('Save')}
|
||||
</Button>
|
||||
</div>
|
||||
</Tooltip>
|
||||
<ExploreAdditionalActionsMenu
|
||||
onOpenInEditor={actions.redirectSQLLab}
|
||||
onOpenPropertiesModal={this.openPropertiesModal}
|
||||
@@ -292,7 +315,7 @@ export class ExploreChartHeader extends React.PureComponent {
|
||||
canAddReports={this.canAddReports()}
|
||||
/>
|
||||
</div>
|
||||
</StyledHeader>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user