chore: Replaces the select for a dropdown button in the CSS editor (#16043)

This commit is contained in:
Michael S. Molina 2021-08-06 07:59:15 -03:00 committed by GitHub
parent e59f318ef9
commit 6edc1ee3bb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 65 additions and 38 deletions

View File

@ -17,7 +17,7 @@
* under the License. * under the License.
*/ */
import React from 'react'; import React from 'react';
import { render, screen } from 'spec/helpers/testing-library'; import { render, screen, waitFor } from 'spec/helpers/testing-library';
import { CssEditor as AceCssEditor } from 'src/components/AsyncAceEditor'; import { CssEditor as AceCssEditor } from 'src/components/AsyncAceEditor';
import { AceEditorProps } from 'react-ace'; import { AceEditorProps } from 'react-ace';
import userEvent from '@testing-library/user-event'; import userEvent from '@testing-library/user-event';
@ -32,6 +32,12 @@ jest.mock('src/components/AsyncAceEditor', () => ({
), ),
})); }));
const templates = [
{ label: 'Template A', css: 'background-color: red;' },
{ label: 'Template B', css: 'background-color: blue;' },
{ label: 'Template C', css: 'background-color: yellow;' },
];
AceCssEditor.preload = () => new Promise(() => {}); AceCssEditor.preload = () => new Promise(() => {});
test('renders with default props', () => { test('renders with default props', () => {
@ -46,14 +52,15 @@ test('renders with initial CSS', () => {
expect(screen.getByText(initialCss)).toBeInTheDocument(); expect(screen.getByText(initialCss)).toBeInTheDocument();
}); });
test('renders with templates', () => { test('renders with templates', async () => {
const templates = ['Template A', 'Template B', 'Template C'];
render(<CssEditor triggerNode={<>Click</>} templates={templates} />); render(<CssEditor triggerNode={<>Click</>} templates={templates} />);
userEvent.click(screen.getByRole('button', { name: 'Click' })); userEvent.click(screen.getByRole('button', { name: 'Click' }));
userEvent.click(screen.getByText('Load a CSS template')); userEvent.hover(screen.getByText('Load a CSS template'));
templates.forEach(template => await waitFor(() => {
expect(screen.getByText(template)).toBeInTheDocument(), templates.forEach(template =>
); expect(screen.getByText(template.label)).toBeInTheDocument(),
);
});
}); });
test('triggers onChange when using the editor', () => { test('triggers onChange when using the editor', () => {
@ -73,9 +80,8 @@ test('triggers onChange when using the editor', () => {
expect(onChange).toHaveBeenLastCalledWith(initialCss.concat(additionalCss)); expect(onChange).toHaveBeenLastCalledWith(initialCss.concat(additionalCss));
}); });
test('triggers onChange when selecting a template', () => { test('triggers onChange when selecting a template', async () => {
const onChange = jest.fn(); const onChange = jest.fn();
const templates = ['Template A', 'Template B', 'Template C'];
render( render(
<CssEditor <CssEditor
triggerNode={<>Click</>} triggerNode={<>Click</>}
@ -86,6 +92,6 @@ test('triggers onChange when selecting a template', () => {
userEvent.click(screen.getByRole('button', { name: 'Click' })); userEvent.click(screen.getByRole('button', { name: 'Click' }));
userEvent.click(screen.getByText('Load a CSS template')); userEvent.click(screen.getByText('Load a CSS template'));
expect(onChange).not.toHaveBeenCalled(); expect(onChange).not.toHaveBeenCalled();
userEvent.click(screen.getByText('Template A')); userEvent.click(await screen.findByText('Template A'));
expect(onChange).toHaveBeenCalledTimes(1); expect(onChange).toHaveBeenCalledTimes(1);
}); });

View File

@ -18,11 +18,30 @@
*/ */
import React from 'react'; import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import Select from 'src/components/Select'; import { Menu, Dropdown } from 'src/common/components';
import { t } from '@superset-ui/core'; import Button from 'src/components/Button';
import { t, styled } from '@superset-ui/core';
import ModalTrigger from 'src/components/ModalTrigger'; import ModalTrigger from 'src/components/ModalTrigger';
import { CssEditor as AceCssEditor } from 'src/components/AsyncAceEditor'; import { CssEditor as AceCssEditor } from 'src/components/AsyncAceEditor';
const StyledWrapper = styled.div`
${({ theme }) => `
.css-editor-header {
display: flex;
flex-direction: row;
justify-content: space-between;
margin-bottom: ${theme.gridUnit * 2}px;
h5 {
margin-top: ${theme.gridUnit}px;
}
}
.css-editor {
border: 1px solid ${theme.colors.grayscale.light1};
}
`}
`;
const propTypes = { const propTypes = {
initialCss: PropTypes.string, initialCss: PropTypes.string,
triggerNode: PropTypes.node.isRequired, triggerNode: PropTypes.node.isRequired,
@ -55,21 +74,24 @@ class CssEditor extends React.PureComponent {
}); });
} }
changeCssTemplate(opt) { changeCssTemplate({ key }) {
this.changeCss(opt.css); this.changeCss(key);
} }
renderTemplateSelector() { renderTemplateSelector() {
if (this.props.templates) { if (this.props.templates) {
const menu = (
<Menu onClick={this.changeCssTemplate}>
{this.props.templates.map(template => (
<Menu.Item key={template.css}>{template.label}</Menu.Item>
))}
</Menu>
);
return ( return (
<div style={{ zIndex: 10 }}> <Dropdown overlay={menu} placement="bottomRight">
<h5>{t('Load a template')}</h5> <Button>{t('Load a CSS template')}</Button>
<Select </Dropdown>
options={this.props.templates}
placeholder={t('Load a CSS template')}
onChange={this.changeCssTemplate}
/>
</div>
); );
} }
return null; return null;
@ -81,24 +103,23 @@ class CssEditor extends React.PureComponent {
triggerNode={this.props.triggerNode} triggerNode={this.props.triggerNode}
modalTitle={t('CSS')} modalTitle={t('CSS')}
modalBody={ modalBody={
<div> <StyledWrapper>
{this.renderTemplateSelector()} <div className="css-editor-header">
<div style={{ zIndex: 1 }}>
<h5>{t('Live CSS editor')}</h5> <h5>{t('Live CSS editor')}</h5>
<div style={{ border: 'solid 1px grey' }}> {this.renderTemplateSelector()}
<AceCssEditor
minLines={12}
maxLines={30}
onChange={this.changeCss}
height="200px"
width="100%"
editorProps={{ $blockScrolling: true }}
enableLiveAutocompletion
value={this.state.css || ''}
/>
</div>
</div> </div>
</div> <AceCssEditor
className="css-editor"
minLines={12}
maxLines={30}
onChange={this.changeCss}
height="200px"
width="100%"
editorProps={{ $blockScrolling: true }}
enableLiveAutocompletion
value={this.state.css || ''}
/>
</StyledWrapper>
} }
/> />
); );