You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@superset.apache.org by mi...@apache.org on 2024/03/14 12:35:18 UTC
(superset) 02/05: fix(dashboard): Only fetch CSS templates for dashboard header menu when in edit mode (#27411)
This is an automated email from the ASF dual-hosted git repository.
michaelsmolina pushed a commit to branch 4.0
in repository https://gitbox.apache.org/repos/asf/superset.git
commit 759863553d342f9c72a7dcd66661b39adeaeb707
Author: Mark Skelton <ma...@federato.ai>
AuthorDate: Fri Mar 8 07:21:36 2024 -0600
fix(dashboard): Only fetch CSS templates for dashboard header menu when in edit mode (#27411)
Co-authored-by: Michael S. Molina <mi...@gmail.com>
(cherry picked from commit fde93dcf08122d8b41ca296213e09616d1b71782)
---
.../components/CssEditor/CssEditor.test.tsx | 54 +++++++++++++---------
.../src/dashboard/components/CssEditor/index.jsx | 25 ++++++++--
.../Header/HeaderActionsDropdown/index.jsx | 22 +--------
3 files changed, 55 insertions(+), 46 deletions(-)
diff --git a/superset-frontend/src/dashboard/components/CssEditor/CssEditor.test.tsx b/superset-frontend/src/dashboard/components/CssEditor/CssEditor.test.tsx
index 16b2a1afbb..28ac7672f6 100644
--- a/superset-frontend/src/dashboard/components/CssEditor/CssEditor.test.tsx
+++ b/superset-frontend/src/dashboard/components/CssEditor/CssEditor.test.tsx
@@ -21,6 +21,7 @@ import { render, screen, waitFor } from 'spec/helpers/testing-library';
import { CssEditor as AceCssEditor } from 'src/components/AsyncAceEditor';
import { IAceEditorProps } from 'react-ace';
import userEvent from '@testing-library/user-event';
+import fetchMock from 'fetch-mock';
import CssEditor from '.';
jest.mock('src/components/AsyncAceEditor', () => ({
@@ -33,46 +34,59 @@ 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;' },
+ { template_name: 'Template A', css: 'background-color: red;' },
+ { template_name: 'Template B', css: 'background-color: blue;' },
+ { template_name: 'Template C', css: 'background-color: yellow;' },
];
+fetchMock.get('glob:*/csstemplateasyncmodelview/api/read', {
+ result: templates,
+});
+
AceCssEditor.preload = () => new Promise(() => {});
-test('renders with default props', () => {
- render(<CssEditor triggerNode={<>Click</>} />);
+const defaultProps = {
+ triggerNode: <>Click</>,
+ addDangerToast: jest.fn(),
+};
+
+test('renders with default props', async () => {
+ await waitFor(() => render(<CssEditor {...defaultProps} />));
expect(screen.getByRole('button', { name: 'Click' })).toBeInTheDocument();
});
-test('renders with initial CSS', () => {
+test('renders with initial CSS', async () => {
const initialCss = 'margin: 10px;';
- render(<CssEditor triggerNode={<>Click</>} initialCss={initialCss} />);
+ await waitFor(() =>
+ render(<CssEditor {...defaultProps} initialCss={initialCss} />),
+ );
userEvent.click(screen.getByRole('button', { name: 'Click' }));
expect(screen.getByText(initialCss)).toBeInTheDocument();
});
test('renders with templates', async () => {
- render(<CssEditor triggerNode={<>Click</>} templates={templates} />);
+ await waitFor(() => render(<CssEditor {...defaultProps} />));
userEvent.click(screen.getByRole('button', { name: 'Click' }));
userEvent.hover(screen.getByText('Load a CSS template'));
await waitFor(() => {
templates.forEach(template =>
- expect(screen.getByText(template.label)).toBeInTheDocument(),
+ expect(screen.getByText(template.template_name)).toBeInTheDocument(),
);
});
});
-test('triggers onChange when using the editor', () => {
+test('triggers onChange when using the editor', async () => {
const onChange = jest.fn();
const initialCss = 'margin: 10px;';
const additionalCss = 'color: red;';
- render(
- <CssEditor
- triggerNode={<>Click</>}
- initialCss={initialCss}
- onChange={onChange}
- />,
+ await waitFor(() =>
+ render(
+ <CssEditor
+ {...defaultProps}
+ initialCss={initialCss}
+ onChange={onChange}
+ />,
+ ),
);
userEvent.click(screen.getByRole('button', { name: 'Click' }));
expect(onChange).not.toHaveBeenCalled();
@@ -82,12 +96,8 @@ test('triggers onChange when using the editor', () => {
test('triggers onChange when selecting a template', async () => {
const onChange = jest.fn();
- render(
- <CssEditor
- triggerNode={<>Click</>}
- templates={templates}
- onChange={onChange}
- />,
+ await waitFor(() =>
+ render(<CssEditor {...defaultProps} onChange={onChange} />),
);
userEvent.click(screen.getByRole('button', { name: 'Click' }));
userEvent.click(screen.getByText('Load a CSS template'));
diff --git a/superset-frontend/src/dashboard/components/CssEditor/index.jsx b/superset-frontend/src/dashboard/components/CssEditor/index.jsx
index ad12cb6c78..9fcd1768a8 100644
--- a/superset-frontend/src/dashboard/components/CssEditor/index.jsx
+++ b/superset-frontend/src/dashboard/components/CssEditor/index.jsx
@@ -21,7 +21,7 @@ import PropTypes from 'prop-types';
import { AntdDropdown } from 'src/components';
import { Menu } from 'src/components/Menu';
import Button from 'src/components/Button';
-import { t, styled } from '@superset-ui/core';
+import { t, styled, SupersetClient } from '@superset-ui/core';
import ModalTrigger from 'src/components/ModalTrigger';
import { CssEditor as AceCssEditor } from 'src/components/AsyncAceEditor';
@@ -47,7 +47,7 @@ const propTypes = {
initialCss: PropTypes.string,
triggerNode: PropTypes.node.isRequired,
onChange: PropTypes.func,
- templates: PropTypes.array,
+ addDangerToast: PropTypes.func.isRequired,
};
const defaultProps = {
@@ -60,6 +60,7 @@ class CssEditor extends React.PureComponent {
super(props);
this.state = {
css: props.initialCss,
+ templates: [],
};
this.changeCss = this.changeCss.bind(this);
this.changeCssTemplate = this.changeCssTemplate.bind(this);
@@ -67,6 +68,22 @@ class CssEditor extends React.PureComponent {
componentDidMount() {
AceCssEditor.preload();
+
+ SupersetClient.get({ endpoint: '/csstemplateasyncmodelview/api/read' })
+ .then(({ json }) => {
+ const templates = json.result.map(row => ({
+ value: row.template_name,
+ css: row.css,
+ label: row.template_name,
+ }));
+
+ this.setState({ templates });
+ })
+ .catch(() => {
+ this.props.addDangerToast(
+ t('An error occurred while fetching available CSS templates'),
+ );
+ });
}
changeCss(css) {
@@ -80,10 +97,10 @@ class CssEditor extends React.PureComponent {
}
renderTemplateSelector() {
- if (this.props.templates) {
+ if (this.state.templates) {
const menu = (
<Menu onClick={this.changeCssTemplate}>
- {this.props.templates.map(template => (
+ {this.state.templates.map(template => (
<Menu.Item key={template.css}>{template.label}</Menu.Item>
))}
</Menu>
diff --git a/superset-frontend/src/dashboard/components/Header/HeaderActionsDropdown/index.jsx b/superset-frontend/src/dashboard/components/Header/HeaderActionsDropdown/index.jsx
index f1a3f59039..1926a975bb 100644
--- a/superset-frontend/src/dashboard/components/Header/HeaderActionsDropdown/index.jsx
+++ b/superset-frontend/src/dashboard/components/Header/HeaderActionsDropdown/index.jsx
@@ -19,7 +19,7 @@
import React from 'react';
import PropTypes from 'prop-types';
import { isEmpty } from 'lodash';
-import { SupersetClient, t } from '@superset-ui/core';
+import { t } from '@superset-ui/core';
import { Menu } from 'src/components/Menu';
import { URL_PARAMS } from 'src/constants';
import ShareMenuItems from 'src/dashboard/components/menu/ShareMenuItems';
@@ -99,7 +99,6 @@ class HeaderActionsDropdown extends React.PureComponent {
super(props);
this.state = {
css: props.customCss,
- cssTemplates: [],
showReportSubMenu: null,
};
@@ -109,23 +108,6 @@ class HeaderActionsDropdown extends React.PureComponent {
this.setShowReportSubMenu = this.setShowReportSubMenu.bind(this);
}
- UNSAFE_componentWillMount() {
- SupersetClient.get({ endpoint: '/csstemplateasyncmodelview/api/read' })
- .then(({ json }) => {
- const cssTemplates = json.result.map(row => ({
- value: row.template_name,
- css: row.css,
- label: row.template_name,
- }));
- this.setState({ cssTemplates });
- })
- .catch(() => {
- this.props.addDangerToast(
- t('An error occurred while fetching available CSS templates'),
- );
- });
- }
-
UNSAFE_componentWillReceiveProps(nextProps) {
if (this.props.customCss !== nextProps.customCss) {
this.setState({ css: nextProps.customCss }, () => {
@@ -257,8 +239,8 @@ class HeaderActionsDropdown extends React.PureComponent {
<CssEditor
triggerNode={<span>{t('Edit CSS')}</span>}
initialCss={this.state.css}
- templates={this.state.cssTemplates}
onChange={this.changeCss}
+ addDangerToast={addDangerToast}
/>
</Menu.Item>
)}