feat: custom refresh frequency (#24449)
Co-authored-by: Nitesh Kumar Dubey Samsung <136478415+dubey-nitesh@users.noreply.github.com>
This commit is contained in:
parent
9db431b430
commit
cf90def462
|
|
@ -171,6 +171,23 @@ test('should change selected value', async () => {
|
|||
expect(selectedValue.title).not.toMatch(/don't refresh/i);
|
||||
});
|
||||
|
||||
test('should change selected value to custom value', async () => {
|
||||
render(setup(editModeOnProps));
|
||||
await openRefreshIntervalModal();
|
||||
|
||||
// Initial selected value should be "Don't refresh"
|
||||
const selectedValue = screen.getByText(/don't refresh/i);
|
||||
expect(selectedValue.title).toMatch(/don't refresh/i);
|
||||
|
||||
// Display options and select "Custom interval"
|
||||
await displayOptions();
|
||||
userEvent.click(screen.getByText(/Custom interval/i));
|
||||
|
||||
// Selected value should now be "Custom interval"
|
||||
expect(selectedValue.title).toMatch(/Custom interval/i);
|
||||
expect(selectedValue.title).not.toMatch(/don't refresh/i);
|
||||
});
|
||||
|
||||
test('should save a newly-selected value', async () => {
|
||||
render(setup(editModeOnProps));
|
||||
await openRefreshIntervalModal();
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ import Select from 'src/components/Select/Select';
|
|||
import { t, styled } from '@superset-ui/core';
|
||||
import Alert from 'src/components/Alert';
|
||||
import Button from 'src/components/Button';
|
||||
import { Input } from 'src/components/Input';
|
||||
|
||||
import ModalTrigger, { ModalTriggerRef } from 'src/components/ModalTrigger';
|
||||
import { FormLabel } from 'src/components/Form';
|
||||
|
|
@ -36,6 +37,16 @@ const RefreshWarningContainer = styled.div`
|
|||
margin-top: ${({ theme }) => theme.gridUnit * 6}px;
|
||||
`;
|
||||
|
||||
const StyledDiv = styled.div`
|
||||
display: flex;
|
||||
margin-top: ${({ theme }) => theme.gridUnit * 3}px;
|
||||
`;
|
||||
|
||||
const InnerStyledDiv = styled.div`
|
||||
width: 30%;
|
||||
margin: auto;
|
||||
`;
|
||||
|
||||
type RefreshIntervalModalProps = {
|
||||
addSuccessToast: (msg: string) => void;
|
||||
triggerNode: JSX.Element;
|
||||
|
|
@ -49,6 +60,10 @@ type RefreshIntervalModalProps = {
|
|||
|
||||
type RefreshIntervalModalState = {
|
||||
refreshFrequency: number;
|
||||
custom_hour: number;
|
||||
custom_min: number;
|
||||
custom_sec: number;
|
||||
custom_block: boolean;
|
||||
};
|
||||
|
||||
class RefreshIntervalModal extends React.PureComponent<
|
||||
|
|
@ -67,6 +82,10 @@ class RefreshIntervalModal extends React.PureComponent<
|
|||
this.modalRef = React.createRef() as ModalTriggerRef;
|
||||
this.state = {
|
||||
refreshFrequency: props.refreshFrequency,
|
||||
custom_hour: 0,
|
||||
custom_min: 0,
|
||||
custom_sec: 0,
|
||||
custom_block: false,
|
||||
};
|
||||
this.handleFrequencyChange = this.handleFrequencyChange.bind(this);
|
||||
this.onSave = this.onSave.bind(this);
|
||||
|
|
@ -91,6 +110,85 @@ class RefreshIntervalModal extends React.PureComponent<
|
|||
this.setState({
|
||||
refreshFrequency: value || refreshIntervalOptions[0][0],
|
||||
});
|
||||
|
||||
this.setState({
|
||||
custom_block: value === -1,
|
||||
});
|
||||
|
||||
if (value === -1) {
|
||||
this.setState({
|
||||
custom_hour: 0,
|
||||
custom_min: 0,
|
||||
custom_sec: 0,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
onSaveValue(value: number) {
|
||||
this.props.onChange(value, this.props.editMode);
|
||||
this.modalRef?.current?.close();
|
||||
this.props.addSuccessToast(t('Refresh interval saved'));
|
||||
}
|
||||
|
||||
createIntervalOptions(refreshIntervalOptions: [number, string][]) {
|
||||
const refresh_options = [];
|
||||
|
||||
refresh_options.push({ value: -1, label: t('Custom interval') });
|
||||
refresh_options.push(
|
||||
...refreshIntervalOptions.map(option => ({
|
||||
value: option[0],
|
||||
label: t(option[1]),
|
||||
})),
|
||||
);
|
||||
|
||||
return refresh_options;
|
||||
}
|
||||
|
||||
min_sec_options(min_or_sec: string) {
|
||||
return Array.from({ length: 60 }, (_, i) => ({
|
||||
value: i,
|
||||
label: `${i} ${min_or_sec}`,
|
||||
}));
|
||||
}
|
||||
|
||||
refresh_custom_val(
|
||||
custom_block: boolean,
|
||||
custom_hour: number,
|
||||
custom_min: number,
|
||||
custom_sec: number,
|
||||
) {
|
||||
if (custom_block === true) {
|
||||
// Get hour value
|
||||
const hour_value = custom_hour;
|
||||
|
||||
// Get minutes value
|
||||
const minute_value = custom_min;
|
||||
|
||||
// Get seconds value
|
||||
const second_value = custom_sec;
|
||||
|
||||
if (
|
||||
hour_value < 0 ||
|
||||
minute_value < 0 ||
|
||||
second_value < 0 ||
|
||||
minute_value >= 60 ||
|
||||
second_value >= 60
|
||||
) {
|
||||
this.props.addSuccessToast(
|
||||
t(
|
||||
'Put positive values and valid minute and second value less than 60',
|
||||
),
|
||||
);
|
||||
}
|
||||
// Convert given input to seconds
|
||||
const value = hour_value * 60 * 60 + minute_value * 60 + second_value;
|
||||
if (value === 0) {
|
||||
this.props.addSuccessToast(t('Put some positive value greater than 0'));
|
||||
return;
|
||||
}
|
||||
this.handleFrequencyChange(value);
|
||||
this.onSaveValue(value);
|
||||
} else this.onSave();
|
||||
}
|
||||
|
||||
render() {
|
||||
|
|
@ -100,7 +198,13 @@ class RefreshIntervalModal extends React.PureComponent<
|
|||
editMode,
|
||||
refreshIntervalOptions,
|
||||
} = this.props;
|
||||
const { refreshFrequency = 0 } = this.state;
|
||||
const {
|
||||
refreshFrequency = 0,
|
||||
custom_hour = 0,
|
||||
custom_min = 0,
|
||||
custom_sec = 0,
|
||||
custom_block = false,
|
||||
} = this.state;
|
||||
const showRefreshWarning =
|
||||
!!refreshFrequency && !!refreshWarning && refreshFrequency < refreshLimit;
|
||||
|
||||
|
|
@ -111,17 +215,74 @@ class RefreshIntervalModal extends React.PureComponent<
|
|||
modalTitle={t('Refresh interval')}
|
||||
modalBody={
|
||||
<div>
|
||||
<FormLabel>{t('Refresh frequency')}</FormLabel>
|
||||
<Select
|
||||
ariaLabel={t('Refresh interval')}
|
||||
options={refreshIntervalOptions.map(option => ({
|
||||
value: option[0],
|
||||
label: t(option[1]),
|
||||
}))}
|
||||
value={refreshFrequency}
|
||||
onChange={this.handleFrequencyChange}
|
||||
sortComparator={propertyComparator('value')}
|
||||
/>
|
||||
<div id="refresh_from_dropdown">
|
||||
<FormLabel>
|
||||
<b>{t('Refresh frequency')}</b>
|
||||
</FormLabel>
|
||||
<Select
|
||||
ariaLabel={t('Refresh interval')}
|
||||
options={this.createIntervalOptions(refreshIntervalOptions)}
|
||||
value={refreshFrequency}
|
||||
onChange={this.handleFrequencyChange}
|
||||
sortComparator={propertyComparator('value')}
|
||||
/>
|
||||
</div>
|
||||
{custom_block && (
|
||||
<StyledDiv>
|
||||
<InnerStyledDiv>
|
||||
<FormLabel>
|
||||
<b>{t('HOUR')}</b>
|
||||
</FormLabel>{' '}
|
||||
<br />
|
||||
<Input
|
||||
type="number"
|
||||
min="0"
|
||||
className="form-control input-sm"
|
||||
placeholder={t('Type a number')}
|
||||
onChange={event => {
|
||||
this.setState({
|
||||
custom_hour: Number(event.target.value),
|
||||
});
|
||||
}}
|
||||
value={custom_hour}
|
||||
/>
|
||||
</InnerStyledDiv>
|
||||
<InnerStyledDiv>
|
||||
<FormLabel>
|
||||
<b>{t('MINUTE')}</b>
|
||||
</FormLabel>{' '}
|
||||
<br />
|
||||
<Select
|
||||
ariaLabel={t('Minutes value')}
|
||||
options={this.min_sec_options('minutes')}
|
||||
value={custom_min}
|
||||
onChange={(value: number) => {
|
||||
this.setState({
|
||||
custom_min: value,
|
||||
});
|
||||
}}
|
||||
sortComparator={propertyComparator('value')}
|
||||
/>
|
||||
</InnerStyledDiv>
|
||||
<InnerStyledDiv>
|
||||
<FormLabel>
|
||||
<b>{t('SECOND')}</b>
|
||||
</FormLabel>{' '}
|
||||
<br />
|
||||
<Select
|
||||
ariaLabel={t('Seconds value')}
|
||||
options={this.min_sec_options('seconds')}
|
||||
value={custom_sec}
|
||||
onChange={(value: number) => {
|
||||
this.setState({
|
||||
custom_sec: value,
|
||||
});
|
||||
}}
|
||||
sortComparator={propertyComparator('value')}
|
||||
/>
|
||||
</InnerStyledDiv>
|
||||
</StyledDiv>
|
||||
)}
|
||||
{showRefreshWarning && (
|
||||
<RefreshWarningContainer>
|
||||
<Alert
|
||||
|
|
@ -140,16 +301,23 @@ class RefreshIntervalModal extends React.PureComponent<
|
|||
}
|
||||
modalFooter={
|
||||
<>
|
||||
<Button onClick={this.onCancel} buttonSize="small">
|
||||
{t('Cancel')}
|
||||
</Button>
|
||||
<Button
|
||||
buttonStyle="primary"
|
||||
buttonSize="small"
|
||||
onClick={this.onSave}
|
||||
onClick={() =>
|
||||
this.refresh_custom_val(
|
||||
custom_block,
|
||||
custom_hour,
|
||||
custom_min,
|
||||
custom_sec,
|
||||
)
|
||||
}
|
||||
>
|
||||
{editMode ? t('Save') : t('Save for this session')}
|
||||
</Button>
|
||||
<Button onClick={this.onCancel} buttonSize="small">
|
||||
{t('Cancel')}
|
||||
</Button>
|
||||
</>
|
||||
}
|
||||
/>
|
||||
|
|
|
|||
Loading…
Reference in New Issue