mirror of
https://github.com/apache/superset.git
synced 2026-04-19 08:04:53 +00:00
fix: Broken splitter in sql lab and some minor visual fixes (#35416)
This commit is contained in:
committed by
GitHub
parent
bf88d9bb1c
commit
88e5581d04
6
superset-frontend/package-lock.json
generated
6
superset-frontend/package-lock.json
generated
@@ -56,7 +56,7 @@
|
||||
"@visx/xychart": "^3.5.1",
|
||||
"ag-grid-community": "34.2.0",
|
||||
"ag-grid-react": "34.2.0",
|
||||
"antd": "^5.24.6",
|
||||
"antd": "^5.24.9",
|
||||
"chrono-node": "^2.7.8",
|
||||
"classnames": "^2.2.5",
|
||||
"content-disposition": "^0.5.4",
|
||||
@@ -60754,7 +60754,7 @@
|
||||
"typescript": "^5.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"antd": "^5.24.6",
|
||||
"antd": "^5.24.9",
|
||||
"react": "^17.0.2"
|
||||
}
|
||||
},
|
||||
@@ -63543,7 +63543,7 @@
|
||||
"@types/react-loadable": "*",
|
||||
"@types/react-window": "^1.8.8",
|
||||
"@types/tinycolor2": "*",
|
||||
"antd": "^5.24.6",
|
||||
"antd": "^5.24.9",
|
||||
"nanoid": "^5.0.9",
|
||||
"react": "^17.0.2",
|
||||
"react-dom": "^17.0.2",
|
||||
|
||||
@@ -129,7 +129,7 @@
|
||||
"@visx/xychart": "^3.5.1",
|
||||
"ag-grid-community": "34.2.0",
|
||||
"ag-grid-react": "34.2.0",
|
||||
"antd": "^5.24.6",
|
||||
"antd": "^5.24.9",
|
||||
"chrono-node": "^2.7.8",
|
||||
"classnames": "^2.2.5",
|
||||
"content-disposition": "^0.5.4",
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
"typescript": "^5.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"antd": "^5.24.6",
|
||||
"antd": "^5.24.9",
|
||||
"react": "^17.0.2"
|
||||
},
|
||||
"scripts": {
|
||||
|
||||
@@ -91,7 +91,7 @@
|
||||
"timezone-mock": "1.3.6"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"antd": "^5.24.6",
|
||||
"antd": "^5.24.9",
|
||||
"@emotion/cache": "^11.4.0",
|
||||
"@emotion/react": "^11.4.1",
|
||||
"@emotion/styled": "^11.14.1",
|
||||
|
||||
@@ -265,7 +265,9 @@ const ChangeDatasourceModal: FunctionComponent<ChangeDatasourceModalProps> = ({
|
||||
{confirmChange && (
|
||||
<ConfirmModalStyled>
|
||||
<div className="btn-container">
|
||||
<Button onClick={handlerCancelConfirm}>{t('Cancel')}</Button>
|
||||
<Button buttonStyle="secondary" onClick={handlerCancelConfirm}>
|
||||
{t('Cancel')}
|
||||
</Button>
|
||||
<Button
|
||||
className="proceed-btn"
|
||||
buttonStyle="primary"
|
||||
|
||||
@@ -100,6 +100,7 @@ export const ErrorAlert: React.FC<ErrorAlertProps> = ({
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
const renderAlert = (closable: boolean) => (
|
||||
@@ -129,7 +130,6 @@ export const ErrorAlert: React.FC<ErrorAlertProps> = ({
|
||||
footer={null}
|
||||
>
|
||||
{renderAlert(false)}
|
||||
{children}
|
||||
</Modal>
|
||||
</>
|
||||
);
|
||||
|
||||
248
superset-frontend/src/explore/components/ExploreAlert.test.tsx
Normal file
248
superset-frontend/src/explore/components/ExploreAlert.test.tsx
Normal file
@@ -0,0 +1,248 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
import { render, screen } from 'spec/helpers/testing-library';
|
||||
import userEvent from '@testing-library/user-event';
|
||||
import { ExploreAlert } from './ExploreAlert';
|
||||
|
||||
test('renders with title and body text', () => {
|
||||
render(
|
||||
<ExploreAlert title="Test Title" bodyText="Test body text" type="info" />,
|
||||
);
|
||||
|
||||
expect(screen.getByText('Test Title')).toBeInTheDocument();
|
||||
expect(screen.getByText('Test body text')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
test('renders info type alert', () => {
|
||||
const { container } = render(
|
||||
<ExploreAlert title="Info Alert" bodyText="Info message" type="info" />,
|
||||
);
|
||||
|
||||
expect(container.querySelector('.ant-alert-info')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
test('renders warning type alert', () => {
|
||||
const { container } = render(
|
||||
<ExploreAlert
|
||||
title="Warning Alert"
|
||||
bodyText="Warning message"
|
||||
type="warning"
|
||||
/>,
|
||||
);
|
||||
|
||||
expect(container.querySelector('.ant-alert-warning')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
test('renders error type alert', () => {
|
||||
const { container } = render(
|
||||
<ExploreAlert title="Error Alert" bodyText="Error message" type="error" />,
|
||||
);
|
||||
|
||||
expect(container.querySelector('.ant-alert-error')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
test('renders primary button when text and action provided', () => {
|
||||
const primaryAction = jest.fn();
|
||||
|
||||
render(
|
||||
<ExploreAlert
|
||||
title="Alert with button"
|
||||
bodyText="Body text"
|
||||
type="info"
|
||||
primaryButtonText="Primary Action"
|
||||
primaryButtonAction={primaryAction}
|
||||
/>,
|
||||
);
|
||||
|
||||
expect(screen.getByText('Primary Action')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
test('calls primary button action when clicked', async () => {
|
||||
const primaryAction = jest.fn();
|
||||
|
||||
render(
|
||||
<ExploreAlert
|
||||
title="Alert with button"
|
||||
bodyText="Body text"
|
||||
type="info"
|
||||
primaryButtonText="Click Me"
|
||||
primaryButtonAction={primaryAction}
|
||||
/>,
|
||||
);
|
||||
|
||||
await userEvent.click(screen.getByText('Click Me'));
|
||||
expect(primaryAction).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
test('renders both primary and secondary buttons when provided', () => {
|
||||
const primaryAction = jest.fn();
|
||||
const secondaryAction = jest.fn();
|
||||
|
||||
render(
|
||||
<ExploreAlert
|
||||
title="Alert with buttons"
|
||||
bodyText="Body text"
|
||||
type="info"
|
||||
primaryButtonText="Primary"
|
||||
primaryButtonAction={primaryAction}
|
||||
secondaryButtonText="Secondary"
|
||||
secondaryButtonAction={secondaryAction}
|
||||
/>,
|
||||
);
|
||||
|
||||
expect(screen.getByText('Primary')).toBeInTheDocument();
|
||||
expect(screen.getByText('Secondary')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
test('calls secondary button action when clicked', async () => {
|
||||
const primaryAction = jest.fn();
|
||||
const secondaryAction = jest.fn();
|
||||
|
||||
render(
|
||||
<ExploreAlert
|
||||
title="Alert with buttons"
|
||||
bodyText="Body text"
|
||||
type="info"
|
||||
primaryButtonText="Primary"
|
||||
primaryButtonAction={primaryAction}
|
||||
secondaryButtonText="Secondary"
|
||||
secondaryButtonAction={secondaryAction}
|
||||
/>,
|
||||
);
|
||||
|
||||
await userEvent.click(screen.getByText('Secondary'));
|
||||
expect(secondaryAction).toHaveBeenCalledTimes(1);
|
||||
expect(primaryAction).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test('does not render buttons when only text is provided without action', () => {
|
||||
render(
|
||||
<ExploreAlert
|
||||
title="Alert without action"
|
||||
bodyText="Body text"
|
||||
type="info"
|
||||
primaryButtonText="Primary"
|
||||
/>,
|
||||
);
|
||||
|
||||
expect(screen.queryByText('Primary')).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
test('does not render buttons when only action is provided without text', () => {
|
||||
const primaryAction = jest.fn();
|
||||
|
||||
render(
|
||||
<ExploreAlert
|
||||
title="Alert without text"
|
||||
bodyText="Body text"
|
||||
type="info"
|
||||
primaryButtonAction={primaryAction}
|
||||
/>,
|
||||
);
|
||||
|
||||
expect(screen.queryByRole('button')).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
test('does not render secondary button when secondary action is missing', () => {
|
||||
const primaryAction = jest.fn();
|
||||
|
||||
render(
|
||||
<ExploreAlert
|
||||
title="Alert"
|
||||
bodyText="Body text"
|
||||
type="info"
|
||||
primaryButtonText="Primary"
|
||||
primaryButtonAction={primaryAction}
|
||||
secondaryButtonText="Secondary"
|
||||
/>,
|
||||
);
|
||||
|
||||
expect(screen.getByText('Primary')).toBeInTheDocument();
|
||||
expect(screen.queryByText('Secondary')).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
test('does not render secondary button when secondary text is missing', () => {
|
||||
const primaryAction = jest.fn();
|
||||
const secondaryAction = jest.fn();
|
||||
|
||||
render(
|
||||
<ExploreAlert
|
||||
title="Alert"
|
||||
bodyText="Body text"
|
||||
type="info"
|
||||
primaryButtonText="Primary"
|
||||
primaryButtonAction={primaryAction}
|
||||
secondaryButtonAction={secondaryAction}
|
||||
/>,
|
||||
);
|
||||
|
||||
expect(screen.getByText('Primary')).toBeInTheDocument();
|
||||
expect(
|
||||
screen.queryByRole('button', { name: /secondary/i }),
|
||||
).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
test('applies custom className', () => {
|
||||
const { container } = render(
|
||||
<ExploreAlert
|
||||
title="Alert"
|
||||
bodyText="Body text"
|
||||
type="info"
|
||||
className="custom-class"
|
||||
/>,
|
||||
);
|
||||
|
||||
expect(container.querySelector('.custom-class')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
test('renders with ReactNode as bodyText', () => {
|
||||
render(
|
||||
<ExploreAlert
|
||||
title="Alert"
|
||||
bodyText={
|
||||
<div>
|
||||
<span>Line 1</span>
|
||||
<span>Line 2</span>
|
||||
</div>
|
||||
}
|
||||
type="info"
|
||||
/>,
|
||||
);
|
||||
|
||||
expect(screen.getByText('Line 1')).toBeInTheDocument();
|
||||
expect(screen.getByText('Line 2')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
test('is not closable by default', () => {
|
||||
const { container } = render(
|
||||
<ExploreAlert title="Alert" bodyText="Body text" type="info" />,
|
||||
);
|
||||
|
||||
expect(
|
||||
container.querySelector('.ant-alert-close-icon'),
|
||||
).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
test('shows icon by default', () => {
|
||||
const { container } = render(
|
||||
<ExploreAlert title="Alert" bodyText="Body text" type="info" />,
|
||||
);
|
||||
|
||||
expect(container.querySelector('.anticon')).toBeInTheDocument();
|
||||
});
|
||||
@@ -20,6 +20,7 @@
|
||||
import { forwardRef, RefObject, MouseEvent } from 'react';
|
||||
import { Button } from '@superset-ui/core/components';
|
||||
import { ErrorAlert } from 'src/components';
|
||||
import { styled } from '@superset-ui/core';
|
||||
|
||||
interface ControlPanelAlertProps {
|
||||
title: string;
|
||||
@@ -32,6 +33,12 @@ interface ControlPanelAlertProps {
|
||||
className?: string;
|
||||
}
|
||||
|
||||
const ButtonContainer = styled.div`
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
margin-top: ${({ theme }) => theme.sizeUnit * 4}px;
|
||||
`;
|
||||
|
||||
export const ExploreAlert = forwardRef(
|
||||
(
|
||||
{
|
||||
@@ -55,14 +62,16 @@ export const ExploreAlert = forwardRef(
|
||||
showIcon
|
||||
>
|
||||
{primaryButtonText && primaryButtonAction && (
|
||||
<div>
|
||||
<ButtonContainer>
|
||||
{secondaryButtonAction && secondaryButtonText && (
|
||||
<Button onClick={secondaryButtonAction}>
|
||||
<Button buttonStyle="secondary" onClick={secondaryButtonAction}>
|
||||
{secondaryButtonText}
|
||||
</Button>
|
||||
)}
|
||||
<Button onClick={primaryButtonAction}>{primaryButtonText}</Button>
|
||||
</div>
|
||||
<Button buttonStyle="secondary" onClick={primaryButtonAction}>
|
||||
{primaryButtonText}
|
||||
</Button>
|
||||
</ButtonContainer>
|
||||
)}
|
||||
</ErrorAlert>
|
||||
),
|
||||
|
||||
Reference in New Issue
Block a user