blob: 5f0352a0750089a92d4ba956f56ec2afd0f05832 [file] [log] [blame]
/**
* 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 { useState } from 'react';
import { t, styled } from '@superset-ui/core';
import { Radio, Input } from '@superset-ui/core/components';
// Minimum safe refresh interval to prevent server overload
export const MINIMUM_REFRESH_INTERVAL = 10;
const StyledRadioGroup = styled(Radio.Group)`
padding-left: ${({ theme }) => theme.sizeUnit * 2}px;
.ant-radio-wrapper {
display: flex;
align-items: center;
margin-bottom: ${({ theme }) => theme.sizeUnit * 0.5}px;
&:last-child {
margin-bottom: 0;
}
}
`;
const CustomContent = styled.div`
display: flex;
align-items: center;
.ant-input {
width: 80px;
margin-left: ${({ theme }) => theme.sizeUnit}px;
margin-right: ${({ theme }) => theme.sizeUnit}px;
}
`;
// Standard refresh frequency options used across modals
export const REFRESH_FREQUENCY_OPTIONS = [
{ value: 0, label: t("Don't refresh") },
{ value: 10, label: t('10 seconds') },
{ value: 30, label: t('30 seconds') },
{ value: 60, label: t('1 minute') },
{ value: 300, label: t('5 minutes') },
{ value: 1800, label: t('30 minutes') },
{ value: 3600, label: t('1 hour') },
{ value: 21600, label: t('6 hours') },
{ value: 43200, label: t('12 hours') },
{ value: 86400, label: t('24 hours') },
{ value: -1, label: t('Custom') },
];
interface RefreshFrequencySelectProps {
value: number;
onChange: (value: number) => void;
ariaLabel?: string;
}
/**
* Shared refresh frequency select component
* Used in both PropertiesModal and RefreshIntervalModal
*/
export const RefreshFrequencySelect = ({
value,
onChange,
ariaLabel = t('Refresh frequency'),
}: RefreshFrequencySelectProps) => {
// Separate radio selection state from value state
const [radioSelection, setRadioSelection] = useState(() =>
REFRESH_FREQUENCY_OPTIONS.find(opt => opt.value === value) ? value : -1,
);
const [customValue, setCustomValue] = useState(() =>
REFRESH_FREQUENCY_OPTIONS.find(opt => opt.value === value)
? ''
: value.toString(),
);
const handleRadioChange = (e: any) => {
const selectedValue = parseInt(e.target.value, 10);
setRadioSelection(selectedValue);
if (selectedValue === -1) {
// Custom selected - use current custom value or minimum
const numValue = parseInt(customValue, 10) || MINIMUM_REFRESH_INTERVAL;
onChange(numValue);
if (!customValue) {
setCustomValue(MINIMUM_REFRESH_INTERVAL.toString());
}
} else {
onChange(selectedValue);
}
};
const handleCustomInputChange = (e: any) => {
const inputValue = e.target.value;
setCustomValue(inputValue);
const numValue = parseInt(inputValue, 10);
if (numValue >= MINIMUM_REFRESH_INTERVAL) {
onChange(numValue);
}
};
return (
<StyledRadioGroup value={radioSelection} onChange={handleRadioChange}>
{REFRESH_FREQUENCY_OPTIONS.slice(0, -1).map(option => (
<Radio key={option.value} value={option.value}>
{option.label}
</Radio>
))}
<Radio value={-1}>
<CustomContent>
{t('Custom')}
<Input
type="number"
min={MINIMUM_REFRESH_INTERVAL}
value={customValue}
onChange={handleCustomInputChange}
placeholder={`${MINIMUM_REFRESH_INTERVAL}+`}
disabled={radioSelection !== -1}
onClick={e => e.stopPropagation()}
/>
<span>{t('seconds')}</span>
</CustomContent>
</Radio>
</StyledRadioGroup>
);
};
/**
* Validates refresh frequency against minimum limit
*/
export const validateRefreshFrequency = (
frequency: number,
refreshLimit?: number,
): string[] => {
const errors = [];
if (refreshLimit && frequency > 0 && frequency < refreshLimit) {
errors.push(
t('Refresh frequency must be at least %s seconds', refreshLimit / 1000),
);
}
return errors;
};
/**
* Generates warning message for low refresh frequencies
*/
export const getRefreshWarningMessage = (
frequency: number,
refreshLimit?: number,
refreshWarning?: string,
): string | null => {
if (
frequency > 0 &&
refreshLimit &&
frequency < refreshLimit &&
refreshWarning
) {
return refreshWarning;
}
return null;
};