in superset-frontend/src/explore/components/controls/DateFilterControl/DateFilterLabel.tsx [147:429]
export default function DateFilterLabel(props: DateFilterControlProps) {
const {
name,
onChange,
onOpenPopover = noOp,
onClosePopover = noOp,
overlayStyle = 'Popover',
isOverflowingFilterBar = false,
} = props;
const defaultTimeFilter = useDefaultTimeFilter();
const value = props.value ?? defaultTimeFilter;
const [actualTimeRange, setActualTimeRange] = useState<string>(value);
const [show, setShow] = useState<boolean>(false);
const guessedFrame = useMemo(() => guessFrame(value), [value]);
const [frame, setFrame] = useState<FrameType>(guessedFrame);
const [lastFetchedTimeRange, setLastFetchedTimeRange] = useState(value);
const [timeRangeValue, setTimeRangeValue] = useState(value);
const [validTimeRange, setValidTimeRange] = useState<boolean>(false);
const [evalResponse, setEvalResponse] = useState<string>(value);
const [tooltipTitle, setTooltipTitle] = useState<ReactNode | null>(value);
const theme = useTheme();
const [labelRef, labelIsTruncated] = useCSSTextTruncation<HTMLSpanElement>();
useEffect(() => {
if (value === NO_TIME_RANGE) {
setActualTimeRange(NO_TIME_RANGE);
setTooltipTitle(null);
setValidTimeRange(true);
return;
}
fetchTimeRange(value).then(({ value: actualRange, error }) => {
if (error) {
setEvalResponse(error || '');
setValidTimeRange(false);
setTooltipTitle(value || null);
} else {
/*
HRT == human readable text
ADR == actual datetime range
+--------------+------+----------+--------+----------+-----------+
| | Last | Previous | Custom | Advanced | No Filter |
+--------------+------+----------+--------+----------+-----------+
| control pill | HRT | HRT | ADR | ADR | HRT |
+--------------+------+----------+--------+----------+-----------+
| tooltip | ADR | ADR | HRT | HRT | ADR |
+--------------+------+----------+--------+----------+-----------+
*/
if (
guessedFrame === 'Common' ||
guessedFrame === 'Calendar' ||
guessedFrame === 'Current' ||
guessedFrame === 'No filter'
) {
setActualTimeRange(value);
setTooltipTitle(
getTooltipTitle(labelIsTruncated, value, actualRange),
);
} else {
setActualTimeRange(actualRange || '');
setTooltipTitle(
getTooltipTitle(labelIsTruncated, actualRange, value),
);
}
setValidTimeRange(true);
}
setLastFetchedTimeRange(value);
setEvalResponse(actualRange || value);
});
}, [guessedFrame, labelIsTruncated, labelRef, value]);
useDebouncedEffect(
() => {
if (timeRangeValue === NO_TIME_RANGE) {
setEvalResponse(NO_TIME_RANGE);
setLastFetchedTimeRange(NO_TIME_RANGE);
setValidTimeRange(true);
return;
}
if (lastFetchedTimeRange !== timeRangeValue) {
fetchTimeRange(timeRangeValue).then(({ value: actualRange, error }) => {
if (error) {
setEvalResponse(error || '');
setValidTimeRange(false);
} else {
setEvalResponse(actualRange || '');
setValidTimeRange(true);
}
setLastFetchedTimeRange(timeRangeValue);
});
}
},
SLOW_DEBOUNCE,
[timeRangeValue],
);
function onSave() {
onChange(timeRangeValue);
setShow(false);
onClosePopover();
}
function onOpen() {
setTimeRangeValue(value);
setFrame(guessedFrame);
setShow(true);
onOpenPopover();
}
function onHide() {
setTimeRangeValue(value);
setFrame(guessedFrame);
setShow(false);
onClosePopover();
}
const toggleOverlay = () => {
if (show) {
onHide();
} else {
onOpen();
}
};
function onChangeFrame(value: FrameType) {
if (value === NO_TIME_RANGE) {
setTimeRangeValue(NO_TIME_RANGE);
}
setFrame(value);
}
const overlayContent = (
<ContentStyleWrapper>
<div className="control-label">{t('RANGE TYPE')}</div>
<StyledRangeType
ariaLabel={t('RANGE TYPE')}
options={FRAME_OPTIONS}
value={frame}
onChange={onChangeFrame}
/>
{frame !== 'No filter' && <Divider />}
{frame === 'Common' && (
<CommonFrame value={timeRangeValue} onChange={setTimeRangeValue} />
)}
{frame === 'Calendar' && (
<CalendarFrame value={timeRangeValue} onChange={setTimeRangeValue} />
)}
{frame === 'Current' && (
<CurrentCalendarFrame
value={timeRangeValue}
onChange={setTimeRangeValue}
/>
)}
{frame === 'Advanced' && (
<AdvancedFrame value={timeRangeValue} onChange={setTimeRangeValue} />
)}
{frame === 'Custom' && (
<CustomFrame
value={timeRangeValue}
onChange={setTimeRangeValue}
isOverflowingFilterBar={isOverflowingFilterBar}
/>
)}
{frame === 'No filter' && <div data-test={DateFilterTestKey.NoFilter} />}
<Divider />
<div>
<div className="section-title">{t('Actual time range')}</div>
{validTimeRange && (
<div>
{evalResponse === 'No filter' ? t('No filter') : evalResponse}
</div>
)}
{!validTimeRange && (
<IconWrapper className="warning">
<Icons.ExclamationCircleOutlined
iconColor={theme.colors.error.base}
/>
<span className="text error">{evalResponse}</span>
</IconWrapper>
)}
</div>
<Divider />
<div className="footer">
<Button
buttonStyle="secondary"
cta
key="cancel"
onClick={onHide}
data-test={DateFilterTestKey.CancelButton}
>
{t('CANCEL')}
</Button>
<Button
buttonStyle="primary"
cta
disabled={!validTimeRange}
key="apply"
onClick={onSave}
data-test={DateFilterTestKey.ApplyButton}
>
{t('APPLY')}
</Button>
</div>
</ContentStyleWrapper>
);
const title = (
<IconWrapper>
<Icons.EditOutlined />
<span className="text">{t('Edit time range')}</span>
</IconWrapper>
);
const popoverContent = (
<ControlPopover
autoAdjustOverflow={false}
trigger="click"
placement="right"
content={overlayContent}
title={title}
defaultOpen={show}
open={show}
onOpenChange={toggleOverlay}
overlayStyle={{ width: '600px' }}
destroyTooltipOnHide
getPopupContainer={nodeTrigger =>
isOverflowingFilterBar
? (nodeTrigger.parentNode as HTMLElement)
: document.body
}
overlayClassName="time-range-popover"
>
<Tooltip placement="top" title={tooltipTitle}>
<DateLabel
name={name}
aria-labelledby={`filter-name-${props.name}`}
aria-describedby={`date-label-${props.name}`}
label={actualTimeRange}
isActive={show}
isPlaceholder={actualTimeRange === NO_TIME_RANGE}
data-test={DateFilterTestKey.PopoverOverlay}
ref={labelRef}
/>
</Tooltip>
</ControlPopover>
);
const modalContent = (
<>
<Tooltip placement="top" title={tooltipTitle}>
<DateLabel
name={name}
aria-labelledby={`filter-name-${props.name}`}
aria-describedby={`date-label-${props.name}`}
onClick={toggleOverlay}
label={actualTimeRange}
isActive={show}
isPlaceholder={actualTimeRange === NO_TIME_RANGE}
data-test={DateFilterTestKey.ModalOverlay}
ref={labelRef}
/>
</Tooltip>
{/* the zIndex value is from trying so that the Modal doesn't overlay the AdhocFilter */}
<Modal
title={title}
show={show}
onHide={toggleOverlay}
width="600px"
hideFooter
zIndex={1030}
>
{overlayContent}
</Modal>
</>
);
return (
<>
<ControlHeader {...props} />
{overlayStyle === 'Modal' ? modalContent : popoverContent}
</>
);
}