refactor(Radio): Upgrade Radio Component to Ant Design 5 (#32004)
This commit is contained in:
parent
1c1494d3e0
commit
468bb5f47a
|
|
@ -19,8 +19,8 @@
|
|||
|
||||
import { useCallback, useState, FormEvent } from 'react';
|
||||
|
||||
import { Radio } from 'src/components/Radio';
|
||||
import { RadioChangeEvent, AsyncSelect } from 'src/components';
|
||||
import { Radio, RadioChangeEvent } from 'src/components/Radio';
|
||||
import { AsyncSelect } from 'src/components';
|
||||
import { Input } from 'src/components/Input';
|
||||
import StyledModal from 'src/components/Modal';
|
||||
import Button from 'src/components/Button';
|
||||
|
|
|
|||
|
|
@ -32,33 +32,21 @@ export const useDisplayModeToggle = () => {
|
|||
<div
|
||||
css={(theme: SupersetTheme) => css`
|
||||
margin-bottom: ${theme.gridUnit * 6}px;
|
||||
.ant-radio-button-wrapper-checked:not(
|
||||
.ant-radio-button-wrapper-disabled
|
||||
):focus-within {
|
||||
box-shadow: none;
|
||||
}
|
||||
`}
|
||||
data-test="drill-by-display-toggle"
|
||||
>
|
||||
<Radio.Group
|
||||
<Radio.GroupWrapper
|
||||
onChange={({ target: { value } }) => {
|
||||
setDrillByDisplayMode(value);
|
||||
}}
|
||||
defaultValue={DrillByType.Chart}
|
||||
>
|
||||
<Radio.Button
|
||||
value={DrillByType.Chart}
|
||||
data-test="drill-by-chart-radio"
|
||||
>
|
||||
{t('Chart')}
|
||||
</Radio.Button>
|
||||
<Radio.Button
|
||||
value={DrillByType.Table}
|
||||
data-test="drill-by-table-radio"
|
||||
>
|
||||
{t('Table')}
|
||||
</Radio.Button>
|
||||
</Radio.Group>
|
||||
options={[
|
||||
{ label: t('Chart'), value: DrillByType.Chart },
|
||||
{ label: t('Table'), value: DrillByType.Table },
|
||||
]}
|
||||
optionType="button"
|
||||
buttonStyle="outline"
|
||||
/>
|
||||
</div>
|
||||
),
|
||||
[],
|
||||
|
|
|
|||
|
|
@ -16,40 +16,139 @@
|
|||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
import { useArgs } from '@storybook/preview-api';
|
||||
import { Radio } from './index';
|
||||
import { Space } from 'src/components/Space';
|
||||
import {
|
||||
BarChartOutlined,
|
||||
DotChartOutlined,
|
||||
LineChartOutlined,
|
||||
PieChartOutlined,
|
||||
} from '@ant-design/icons';
|
||||
import { Radio, RadioProps, RadioGroupWrapperProps } from './index';
|
||||
|
||||
export default {
|
||||
title: 'Radio',
|
||||
component: Radio,
|
||||
parameters: {
|
||||
controls: { hideNoControlsWarning: true },
|
||||
tags: ['autodocs'],
|
||||
};
|
||||
|
||||
const RadioArgsType = {
|
||||
value: {
|
||||
control: 'text',
|
||||
description: 'The value of the radio button.',
|
||||
},
|
||||
argTypes: {
|
||||
theme: {
|
||||
table: {
|
||||
disable: true,
|
||||
},
|
||||
},
|
||||
checked: { control: 'boolean' },
|
||||
disabled: { control: 'boolean' },
|
||||
disabled: {
|
||||
control: 'boolean',
|
||||
description: 'Whether the radio button is disabled or not.',
|
||||
},
|
||||
checked: {
|
||||
control: 'boolean',
|
||||
description: 'The checked state of the radio button.',
|
||||
},
|
||||
};
|
||||
|
||||
export const SupersetRadio = () => {
|
||||
const [{ checked, ...rest }, updateArgs] = useArgs();
|
||||
return (
|
||||
<Radio
|
||||
checked={checked}
|
||||
onChange={() => updateArgs({ checked: !checked })}
|
||||
{...rest}
|
||||
>
|
||||
Example
|
||||
</Radio>
|
||||
);
|
||||
const radioGroupWrapperArgsType = {
|
||||
onChange: { action: 'changed' },
|
||||
disabled: { control: 'boolean' },
|
||||
size: {
|
||||
control: 'select',
|
||||
options: ['small', 'middle', 'large'],
|
||||
},
|
||||
options: { control: 'object' },
|
||||
'spaceConfig.direction': {
|
||||
control: 'select',
|
||||
options: ['horizontal', 'vertical'],
|
||||
description: 'Direction of the Space layout',
|
||||
if: { arg: 'enableSpaceConfig', truthy: true },
|
||||
},
|
||||
'spaceConfig.size': {
|
||||
control: 'select',
|
||||
options: ['small', 'middle', 'large'],
|
||||
description: 'Layout size Space',
|
||||
if: { arg: 'enableSpaceConfig', truthy: true },
|
||||
},
|
||||
'spaceConfig.align': {
|
||||
control: 'select',
|
||||
options: ['start', 'center', 'end'],
|
||||
description: 'Alignment of the Space layout',
|
||||
if: { arg: 'enableSpaceConfig', truthy: true },
|
||||
},
|
||||
'spaceConfig.wrap': {
|
||||
control: 'boolean',
|
||||
description:
|
||||
'Controls whether the items inside the Space component should wrap to the next line when space is insufficient',
|
||||
if: { arg: 'enableSpaceConfig', truthy: true },
|
||||
},
|
||||
};
|
||||
|
||||
SupersetRadio.args = {
|
||||
export const RadioStory = {
|
||||
args: {
|
||||
value: 'radio1',
|
||||
disabled: false,
|
||||
checked: false,
|
||||
children: 'Radio',
|
||||
},
|
||||
argTypes: RadioArgsType,
|
||||
};
|
||||
|
||||
export const RadioButtonStory = (args: RadioProps) => (
|
||||
<Radio.Button {...args}>Radio Button</Radio.Button>
|
||||
);
|
||||
RadioButtonStory.args = {
|
||||
value: 'button1',
|
||||
disabled: false,
|
||||
checked: false,
|
||||
};
|
||||
RadioButtonStory.argTypes = RadioArgsType;
|
||||
|
||||
export const RadioGroupWithOptionsStory = (args: RadioGroupWrapperProps) => (
|
||||
<Radio.GroupWrapper {...args} />
|
||||
);
|
||||
RadioGroupWithOptionsStory.args = {
|
||||
spaceConfig: {
|
||||
direction: 'vertical',
|
||||
size: 'middle',
|
||||
align: 'center',
|
||||
wrap: false,
|
||||
},
|
||||
size: 'middle',
|
||||
options: [
|
||||
{
|
||||
value: 1,
|
||||
label: (
|
||||
<Space align="center" direction="vertical">
|
||||
<LineChartOutlined style={{ fontSize: 18 }} />
|
||||
LineChart
|
||||
</Space>
|
||||
),
|
||||
},
|
||||
{
|
||||
value: 2,
|
||||
label: (
|
||||
<Space align="center" direction="vertical">
|
||||
<DotChartOutlined style={{ fontSize: 18 }} />
|
||||
DotChart
|
||||
</Space>
|
||||
),
|
||||
},
|
||||
{
|
||||
value: 3,
|
||||
label: (
|
||||
<Space align="center" direction="vertical">
|
||||
<BarChartOutlined style={{ fontSize: 18 }} />
|
||||
BarChart
|
||||
</Space>
|
||||
),
|
||||
},
|
||||
{
|
||||
value: 4,
|
||||
label: (
|
||||
<Space align="center" direction="vertical">
|
||||
<PieChartOutlined style={{ fontSize: 18 }} />
|
||||
PieChart
|
||||
</Space>
|
||||
),
|
||||
},
|
||||
],
|
||||
disabled: false,
|
||||
};
|
||||
RadioGroupWithOptionsStory.argTypes = radioGroupWrapperArgsType;
|
||||
|
|
|
|||
|
|
@ -16,46 +16,48 @@
|
|||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
import { styled } from '@superset-ui/core';
|
||||
import { Radio as AntdRadio } from 'antd';
|
||||
import { Radio as Antd5Radio, CheckboxOptionType } from 'antd-v5';
|
||||
import type {
|
||||
RadioChangeEvent,
|
||||
RadioProps,
|
||||
RadioGroupProps,
|
||||
} from 'antd-v5/lib/radio';
|
||||
|
||||
const StyledRadio = styled(AntdRadio)`
|
||||
.ant-radio-inner {
|
||||
top: -1px;
|
||||
left: 2px;
|
||||
width: ${({ theme }) => theme.gridUnit * 4}px;
|
||||
height: ${({ theme }) => theme.gridUnit * 4}px;
|
||||
border-width: 2px;
|
||||
border-color: ${({ theme }) => theme.colors.grayscale.light2};
|
||||
}
|
||||
import { Space, SpaceProps } from 'src/components/Space';
|
||||
|
||||
.ant-radio.ant-radio-checked {
|
||||
.ant-radio-inner {
|
||||
border-width: ${({ theme }) => theme.gridUnit + 1}px;
|
||||
border-color: ${({ theme }) => theme.colors.primary.base};
|
||||
}
|
||||
export type RadioGroupWrapperProps = RadioGroupProps & {
|
||||
spaceConfig?: {
|
||||
direction?: SpaceProps['direction'];
|
||||
size?: SpaceProps['size'];
|
||||
align?: SpaceProps['align'];
|
||||
wrap?: SpaceProps['wrap'];
|
||||
};
|
||||
options: CheckboxOptionType[];
|
||||
};
|
||||
|
||||
.ant-radio-inner::after {
|
||||
background-color: ${({ theme }) => theme.colors.grayscale.light5};
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: ${({ theme }) => theme.gridUnit + 2}px;
|
||||
height: ${({ theme }) => theme.gridUnit + 2}px;
|
||||
}
|
||||
}
|
||||
|
||||
.ant-radio:hover,
|
||||
.ant-radio:focus {
|
||||
.ant-radio-inner {
|
||||
border-color: ${({ theme }) => theme.colors.primary.dark1};
|
||||
}
|
||||
}
|
||||
`;
|
||||
const StyledGroup = styled(AntdRadio.Group)`
|
||||
font-size: inherit;
|
||||
`;
|
||||
|
||||
export const Radio = Object.assign(StyledRadio, {
|
||||
Group: StyledGroup,
|
||||
Button: AntdRadio.Button,
|
||||
const RadioGroup = ({
|
||||
spaceConfig,
|
||||
options,
|
||||
...props
|
||||
}: RadioGroupWrapperProps) => {
|
||||
const content = options.map((option: CheckboxOptionType) => (
|
||||
<Radio key={option.value} value={option.value}>
|
||||
{option.label}
|
||||
</Radio>
|
||||
));
|
||||
return (
|
||||
<Radio.Group {...props}>
|
||||
{spaceConfig ? <Space {...spaceConfig}>{content}</Space> : content}
|
||||
</Radio.Group>
|
||||
);
|
||||
};
|
||||
export type {
|
||||
RadioChangeEvent,
|
||||
RadioGroupProps,
|
||||
RadioProps,
|
||||
CheckboxOptionType,
|
||||
};
|
||||
export const Radio = Object.assign(Antd5Radio, {
|
||||
GroupWrapper: RadioGroup,
|
||||
Button: Antd5Radio.Button,
|
||||
});
|
||||
|
|
|
|||
|
|
@ -19,7 +19,6 @@
|
|||
import { useState } from 'react';
|
||||
import { css, useTheme } from '@superset-ui/core';
|
||||
import { Radio } from 'src/components/Radio';
|
||||
import { Space } from 'src/components/Space';
|
||||
import Icons from 'src/components/Icons';
|
||||
import Popover from 'src/components/Popover';
|
||||
|
||||
|
|
@ -56,21 +55,20 @@ function HeaderWithRadioGroup(props: HeaderWithRadioGroupProps) {
|
|||
>
|
||||
{groupTitle}
|
||||
</div>
|
||||
<Radio.Group
|
||||
<Radio.GroupWrapper
|
||||
spaceConfig={{
|
||||
direction: 'vertical',
|
||||
size: 4,
|
||||
wrap: false,
|
||||
align: 'start',
|
||||
}}
|
||||
value={value}
|
||||
onChange={e => {
|
||||
onChange(e.target.value);
|
||||
setPopoverVisible(false);
|
||||
}}
|
||||
>
|
||||
<Space direction="vertical">
|
||||
{groupOptions.map(option => (
|
||||
<Radio key={option.value} value={option.value}>
|
||||
{option.label}
|
||||
</Radio>
|
||||
))}
|
||||
</Space>
|
||||
</Radio.Group>
|
||||
options={groupOptions}
|
||||
/>
|
||||
</div>
|
||||
}
|
||||
placement="bottomLeft"
|
||||
|
|
|
|||
|
|
@ -1106,15 +1106,16 @@ const FiltersConfigForm = (
|
|||
initialValue={sort}
|
||||
label={<StyledLabel>{t('Sort type')}</StyledLabel>}
|
||||
>
|
||||
<Radio.Group
|
||||
<Radio.GroupWrapper
|
||||
options={[
|
||||
{ value: true, label: t('Sort ascending') },
|
||||
{ value: false, label: t('Sort descending') },
|
||||
]}
|
||||
onChange={value => {
|
||||
onSortChanged(value.target.value);
|
||||
formChanged();
|
||||
}}
|
||||
>
|
||||
<Radio value>{t('Sort ascending')}</Radio>
|
||||
<Radio value={false}>{t('Sort descending')}</Radio>
|
||||
</Radio.Group>
|
||||
/>
|
||||
</StyledRowFormItem>
|
||||
{hasMetrics && (
|
||||
<StyledRowSubFormItem
|
||||
|
|
@ -1181,22 +1182,23 @@ const FiltersConfigForm = (
|
|||
<StyledLabel>{t('Single value type')}</StyledLabel>
|
||||
}
|
||||
>
|
||||
<Radio.Group
|
||||
<Radio.GroupWrapper
|
||||
onChange={value => {
|
||||
onEnableSingleValueChanged(value.target.value);
|
||||
formChanged();
|
||||
}}
|
||||
>
|
||||
<Radio value={SingleValueType.Minimum}>
|
||||
{t('Minimum')}
|
||||
</Radio>
|
||||
<Radio value={SingleValueType.Exact}>
|
||||
{t('Exact')}
|
||||
</Radio>
|
||||
<Radio value={SingleValueType.Maximum}>
|
||||
{t('Maximum')}
|
||||
</Radio>
|
||||
</Radio.Group>
|
||||
options={[
|
||||
{
|
||||
label: t('Minimum'),
|
||||
value: SingleValueType.Minimum,
|
||||
},
|
||||
{ label: t('Exact'), value: SingleValueType.Exact },
|
||||
{
|
||||
label: t('Maximum'),
|
||||
value: SingleValueType.Maximum,
|
||||
},
|
||||
]}
|
||||
/>
|
||||
</StyledRowFormItem>
|
||||
</CollapsibleControl>
|
||||
</CleanFormItem>
|
||||
|
|
|
|||
|
|
@ -30,7 +30,6 @@ import {
|
|||
import { Global } from '@emotion/react';
|
||||
import { Column } from 'react-table';
|
||||
import { debounce } from 'lodash';
|
||||
import { Space } from 'src/components/Space';
|
||||
import { Input } from 'src/components/Input';
|
||||
import {
|
||||
BOOL_FALSE_DISPLAY,
|
||||
|
|
@ -141,12 +140,21 @@ const FormatPicker = ({
|
|||
onChange: any;
|
||||
value: FormatPickerValue;
|
||||
}) => (
|
||||
<Radio.Group value={value} onChange={onChange}>
|
||||
<Space direction="vertical">
|
||||
<Radio value={FormatPickerValue.Formatted}>{t('Formatted date')}</Radio>
|
||||
<Radio value={FormatPickerValue.Original}>{t('Original value')}</Radio>
|
||||
</Space>
|
||||
</Radio.Group>
|
||||
<Radio.GroupWrapper
|
||||
spaceConfig={{
|
||||
direction: 'vertical',
|
||||
align: 'start',
|
||||
size: 15,
|
||||
wrap: false,
|
||||
}}
|
||||
size="large"
|
||||
value={value}
|
||||
onChange={onChange}
|
||||
options={[
|
||||
{ label: t('Formatted date'), value: FormatPickerValue.Formatted },
|
||||
{ label: t('Original value'), value: FormatPickerValue.Original },
|
||||
]}
|
||||
/>
|
||||
);
|
||||
|
||||
const FormatPickerContainer = styled.div`
|
||||
|
|
|
|||
|
|
@ -87,12 +87,6 @@ const ContentStyleWrapper = styled.div`
|
|||
margin: 8px 0;
|
||||
}
|
||||
|
||||
.vertical-radio {
|
||||
display: block;
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-style: normal;
|
||||
font-weight: ${theme.typography.weights.bold};
|
||||
|
|
|
|||
|
|
@ -45,16 +45,18 @@ export function CalendarFrame({ onChange, value }: FrameComponentProps) {
|
|||
<div className="section-title">
|
||||
{t('Configure Time Range: Previous...')}
|
||||
</div>
|
||||
<Radio.Group
|
||||
<Radio.GroupWrapper
|
||||
spaceConfig={{
|
||||
direction: 'vertical',
|
||||
size: 15,
|
||||
align: 'start',
|
||||
wrap: false,
|
||||
}}
|
||||
size="large"
|
||||
value={value}
|
||||
onChange={(e: any) => onChange(e.target.value)}
|
||||
>
|
||||
{CALENDAR_RANGE_OPTIONS.map(({ value, label }) => (
|
||||
<Radio key={value} value={value} className="vertical-radio">
|
||||
{label}
|
||||
</Radio>
|
||||
))}
|
||||
</Radio.Group>
|
||||
options={CALENDAR_RANGE_OPTIONS}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,16 +41,18 @@ export function CommonFrame(props: FrameComponentProps) {
|
|||
<div className="section-title" data-test={DateFilterTestKey.CommonFrame}>
|
||||
{t('Configure Time Range: Last...')}
|
||||
</div>
|
||||
<Radio.Group
|
||||
<Radio.GroupWrapper
|
||||
spaceConfig={{
|
||||
direction: 'vertical',
|
||||
size: 15,
|
||||
align: 'start',
|
||||
wrap: false,
|
||||
}}
|
||||
size="large"
|
||||
value={commonRange}
|
||||
onChange={(e: any) => props.onChange(e.target.value)}
|
||||
>
|
||||
{COMMON_RANGE_OPTIONS.map(({ value, label }) => (
|
||||
<Radio key={value} value={value} className="vertical-radio">
|
||||
{label}
|
||||
</Radio>
|
||||
))}
|
||||
</Radio.Group>
|
||||
options={COMMON_RANGE_OPTIONS}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,25 +41,22 @@ export function CurrentCalendarFrame({ onChange, value }: FrameComponentProps) {
|
|||
<div className="section-title">
|
||||
{t('Configure Time Range: Current...')}
|
||||
</div>
|
||||
<Radio.Group
|
||||
value={value}
|
||||
<Radio.GroupWrapper
|
||||
spaceConfig={{
|
||||
direction: 'vertical',
|
||||
size: 15,
|
||||
align: 'start',
|
||||
wrap: true,
|
||||
}}
|
||||
size="large"
|
||||
onChange={(e: any) => {
|
||||
let newValue = e.target.value;
|
||||
// Sanitization: Trim whitespace
|
||||
newValue = newValue.trim();
|
||||
// Validation: Check if the value is non-empty
|
||||
if (newValue === '') {
|
||||
return;
|
||||
}
|
||||
if (newValue === '') return;
|
||||
onChange(newValue);
|
||||
}}
|
||||
>
|
||||
{CURRENT_RANGE_OPTIONS.map(({ value, label }) => (
|
||||
<Radio key={value} value={value} className="vertical-radio">
|
||||
{label}
|
||||
</Radio>
|
||||
))}
|
||||
</Radio.Group>
|
||||
options={CURRENT_RANGE_OPTIONS}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -238,18 +238,15 @@ export function CustomFrame(props: FrameComponentProps) {
|
|||
<div className="control-label">{t('Anchor to')}</div>
|
||||
<Row align="middle">
|
||||
<Col>
|
||||
<Radio.Group
|
||||
<Radio.GroupWrapper
|
||||
options={[
|
||||
{ value: 'now', label: t('Now') },
|
||||
{ value: 'specific', label: t('Date/Time') },
|
||||
]}
|
||||
onChange={onAnchorMode}
|
||||
defaultValue="now"
|
||||
value={anchorMode}
|
||||
>
|
||||
<Radio key="now" value="now">
|
||||
{t('NOW')}
|
||||
</Radio>
|
||||
<Radio key="specific" value="specific">
|
||||
{t('Date/Time')}
|
||||
</Radio>
|
||||
</Radio.Group>
|
||||
/>
|
||||
</Col>
|
||||
{anchorMode !== 'now' && (
|
||||
<Col>
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ describe('CalendarFrame', () => {
|
|||
const radios = screen.getAllByRole('radio');
|
||||
expect(radios).toHaveLength(CALENDAR_RANGE_OPTIONS.length);
|
||||
CALENDAR_RANGE_OPTIONS.forEach(option => {
|
||||
expect(screen.getByText(option.label)).toBeInTheDocument();
|
||||
expect(screen.getByText(option.label as string)).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -56,7 +56,7 @@ describe('CalendarFrame', () => {
|
|||
);
|
||||
|
||||
const secondOption = CALENDAR_RANGE_OPTIONS[1];
|
||||
const radio = screen.getByLabelText(secondOption.label);
|
||||
const radio = screen.getByLabelText(secondOption.label as string);
|
||||
fireEvent.click(radio);
|
||||
|
||||
expect(mockOnChange).toHaveBeenCalledWith(secondOption.value);
|
||||
|
|
@ -85,6 +85,8 @@ describe('CalendarFrame', () => {
|
|||
const thirdOption = CALENDAR_RANGE_OPTIONS[2];
|
||||
expect(thirdOption.value).toBe(PreviousCalendarQuarter);
|
||||
|
||||
expect(screen.getByLabelText(thirdOption.label)).toBeInTheDocument();
|
||||
expect(
|
||||
screen.getByLabelText(thirdOption.label as string),
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -167,8 +167,8 @@ test('renders anchor with now option', async () => {
|
|||
);
|
||||
await waitForElementToBeRemoved(() => screen.queryByLabelText('Loading'));
|
||||
expect(screen.getByText('Anchor to')).toBeInTheDocument();
|
||||
expect(screen.getByRole('radio', { name: 'NOW' })).toBeInTheDocument();
|
||||
expect(screen.getByRole('radio', { name: 'Date/Time' })).toBeInTheDocument();
|
||||
expect(screen.getByLabelText('Now')).toBeInTheDocument();
|
||||
expect(screen.getByLabelText('Date/Time')).toBeInTheDocument();
|
||||
expect(screen.queryByPlaceholderText('Select date')).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
|
|
@ -180,8 +180,8 @@ test('renders anchor with date/time option', async () => {
|
|||
);
|
||||
await waitForElementToBeRemoved(() => screen.queryByLabelText('Loading'));
|
||||
expect(screen.getByText('Anchor to')).toBeInTheDocument();
|
||||
expect(screen.getByRole('radio', { name: 'NOW' })).toBeInTheDocument();
|
||||
expect(screen.getByRole('radio', { name: 'Date/Time' })).toBeInTheDocument();
|
||||
expect(screen.getByLabelText('Now')).toBeInTheDocument();
|
||||
expect(screen.getByLabelText('Date/Time')).toBeInTheDocument();
|
||||
expect(screen.getByPlaceholderText('Select date')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ import {
|
|||
CurrentQuarter,
|
||||
CurrentDay,
|
||||
} from 'src/explore/components/controls/DateFilterControl/types';
|
||||
import { CheckboxOptionType } from 'src/components/Radio';
|
||||
import { extendedDayjs } from 'src/utils/dates';
|
||||
|
||||
export const FRAME_OPTIONS: SelectOptionType[] = [
|
||||
|
|
@ -43,7 +44,7 @@ export const FRAME_OPTIONS: SelectOptionType[] = [
|
|||
{ value: 'No filter', label: t('No filter') },
|
||||
];
|
||||
|
||||
export const COMMON_RANGE_OPTIONS: SelectOptionType[] = [
|
||||
export const COMMON_RANGE_OPTIONS: CheckboxOptionType[] = [
|
||||
{ value: 'Last day', label: t('Last day') },
|
||||
{ value: 'Last week', label: t('Last week') },
|
||||
{ value: 'Last month', label: t('Last month') },
|
||||
|
|
@ -51,20 +52,20 @@ export const COMMON_RANGE_OPTIONS: SelectOptionType[] = [
|
|||
{ value: 'Last year', label: t('Last year') },
|
||||
];
|
||||
export const COMMON_RANGE_VALUES_SET = new Set(
|
||||
COMMON_RANGE_OPTIONS.map(({ value }) => value),
|
||||
COMMON_RANGE_OPTIONS.map(value => value.value),
|
||||
);
|
||||
|
||||
export const CALENDAR_RANGE_OPTIONS: SelectOptionType[] = [
|
||||
export const CALENDAR_RANGE_OPTIONS: CheckboxOptionType[] = [
|
||||
{ value: PreviousCalendarWeek, label: t('previous calendar week') },
|
||||
{ value: PreviousCalendarMonth, label: t('previous calendar month') },
|
||||
{ value: PreviousCalendarQuarter, label: t('previous calendar quarter') },
|
||||
{ value: PreviousCalendarYear, label: t('previous calendar year') },
|
||||
];
|
||||
export const CALENDAR_RANGE_VALUES_SET = new Set(
|
||||
CALENDAR_RANGE_OPTIONS.map(({ value }) => value),
|
||||
CALENDAR_RANGE_OPTIONS.map(value => value.value),
|
||||
);
|
||||
|
||||
export const CURRENT_RANGE_OPTIONS: SelectOptionType[] = [
|
||||
export const CURRENT_RANGE_OPTIONS: CheckboxOptionType[] = [
|
||||
{ value: CurrentDay, label: t('Current day') },
|
||||
{ value: CurrentWeek, label: t('Current week') },
|
||||
{ value: CurrentMonth, label: t('Current month') },
|
||||
|
|
@ -72,7 +73,7 @@ export const CURRENT_RANGE_OPTIONS: SelectOptionType[] = [
|
|||
{ value: CurrentYear, label: t('Current year') },
|
||||
];
|
||||
export const CURRENT_RANGE_VALUES_SET = new Set(
|
||||
CURRENT_RANGE_OPTIONS.map(({ value }) => value),
|
||||
CURRENT_RANGE_OPTIONS.map(value => value.value),
|
||||
);
|
||||
|
||||
const GRAIN_OPTIONS = [
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ import TimezoneSelector from 'src/components/TimezoneSelector';
|
|||
import LabeledErrorBoundInput from 'src/components/Form/LabeledErrorBoundInput';
|
||||
import Icons from 'src/components/Icons';
|
||||
import { CronError } from 'src/components/CronPicker';
|
||||
import { RadioChangeEvent } from 'src/components';
|
||||
import { Radio, RadioChangeEvent } from 'src/components/Radio';
|
||||
import { Input } from 'src/components/Input';
|
||||
import withToasts from 'src/components/MessageToasts/withToasts';
|
||||
import { ChartState } from 'src/explore/types';
|
||||
|
|
@ -68,8 +68,6 @@ import {
|
|||
TimezoneHeaderStyle,
|
||||
SectionHeaderStyle,
|
||||
StyledMessageContentTitle,
|
||||
StyledRadio,
|
||||
StyledRadioGroup,
|
||||
} from './styles';
|
||||
|
||||
interface ReportProps {
|
||||
|
|
@ -257,24 +255,32 @@ function ReportModal({
|
|||
<h4>{t('Message content')}</h4>
|
||||
</StyledMessageContentTitle>
|
||||
<div className="inline-container">
|
||||
<StyledRadioGroup
|
||||
<Radio.GroupWrapper
|
||||
spaceConfig={{
|
||||
direction: 'vertical',
|
||||
size: 'middle',
|
||||
align: 'start',
|
||||
wrap: false,
|
||||
}}
|
||||
onChange={(event: RadioChangeEvent) => {
|
||||
setCurrentReport({ report_format: event.target.value });
|
||||
}}
|
||||
value={currentReport.report_format || defaultNotificationFormat}
|
||||
>
|
||||
{isTextBasedChart && (
|
||||
<StyledRadio value={NotificationFormats.Text}>
|
||||
{t('Text embedded in email')}
|
||||
</StyledRadio>
|
||||
)}
|
||||
<StyledRadio value={NotificationFormats.PNG}>
|
||||
{t('Image (PNG) embedded in email')}
|
||||
</StyledRadio>
|
||||
<StyledRadio value={NotificationFormats.CSV}>
|
||||
{t('Formatted CSV attached in email')}
|
||||
</StyledRadio>
|
||||
</StyledRadioGroup>
|
||||
options={[
|
||||
{
|
||||
label: t('Text embedded in email'),
|
||||
value: NotificationFormats.Text,
|
||||
},
|
||||
{
|
||||
label: t('Image (PNG) embedded in email'),
|
||||
value: NotificationFormats.PNG,
|
||||
},
|
||||
{
|
||||
label: t('Formatted CSV attached in email'),
|
||||
value: NotificationFormats.CSV,
|
||||
},
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -108,10 +108,6 @@ export const StyledRadio = styled(Radio)`
|
|||
line-height: ${({ theme }) => theme.gridUnit * 8}px;
|
||||
`;
|
||||
|
||||
export const StyledRadioGroup = styled(Radio.Group)`
|
||||
margin-left: ${({ theme }) => theme.gridUnit * 0.5}px;
|
||||
`;
|
||||
|
||||
export const antDErrorAlertStyles = (theme: SupersetTheme) => css`
|
||||
margin: ${theme.gridUnit * 4}px;
|
||||
margin-top: 0;
|
||||
|
|
|
|||
Loading…
Reference in New Issue