[v9.4.x] DateTimePicker: Can now select time correctly (#65431)
This commit is contained in:
+29
@@ -1,4 +1,5 @@
|
|||||||
import { fireEvent, render, screen } from '@testing-library/react';
|
import { fireEvent, render, screen } from '@testing-library/react';
|
||||||
|
import userEvent from '@testing-library/user-event';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import { dateTime } from '@grafana/data';
|
import { dateTime } from '@grafana/data';
|
||||||
@@ -38,4 +39,32 @@ describe('Date time picker', () => {
|
|||||||
|
|
||||||
expect(dateTimeInput).toHaveDisplayValue('2021-07-31 12:30:30');
|
expect(dateTimeInput).toHaveDisplayValue('2021-07-31 12:30:30');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should be able to select values in TimeOfDayPicker without blurring the element', async () => {
|
||||||
|
renderDatetimePicker();
|
||||||
|
|
||||||
|
// open the calendar + time picker
|
||||||
|
await userEvent.click(screen.getByLabelText('Time picker'));
|
||||||
|
|
||||||
|
// open the time of day overlay
|
||||||
|
await userEvent.click(screen.getAllByRole('textbox')[1]);
|
||||||
|
|
||||||
|
// check the hour element is visible
|
||||||
|
const hourElement = screen.getAllByRole('button', {
|
||||||
|
name: '00',
|
||||||
|
})[0];
|
||||||
|
expect(hourElement).toBeVisible();
|
||||||
|
|
||||||
|
// select the hour value and check it's still visible
|
||||||
|
await userEvent.click(hourElement);
|
||||||
|
expect(hourElement).toBeVisible();
|
||||||
|
|
||||||
|
// click outside the overlay and check the hour element is no longer visible
|
||||||
|
await userEvent.click(document.body);
|
||||||
|
expect(
|
||||||
|
screen.queryByRole('button', {
|
||||||
|
name: '00',
|
||||||
|
})
|
||||||
|
).not.toBeInTheDocument();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
+10
-2
@@ -12,7 +12,7 @@ import { dateTimeFormat, DateTime, dateTime, GrafanaTheme2, isDateTime } from '@
|
|||||||
import { Button, HorizontalGroup, Icon, InlineField, Input, Portal } from '../..';
|
import { Button, HorizontalGroup, Icon, InlineField, Input, Portal } from '../..';
|
||||||
import { useStyles2, useTheme2 } from '../../../themes';
|
import { useStyles2, useTheme2 } from '../../../themes';
|
||||||
import { getModalStyles } from '../../Modal/getModalStyles';
|
import { getModalStyles } from '../../Modal/getModalStyles';
|
||||||
import { TimeOfDayPicker } from '../TimeOfDayPicker';
|
import { TimeOfDayPicker, POPUP_CLASS_NAME } from '../TimeOfDayPicker';
|
||||||
import { getBodyStyles } from '../TimeRangePicker/CalendarBody';
|
import { getBodyStyles } from '../TimeRangePicker/CalendarBody';
|
||||||
import { isValid } from '../utils';
|
import { isValid } from '../utils';
|
||||||
|
|
||||||
@@ -32,7 +32,15 @@ export const DateTimePicker = ({ date, maxDate, label, onChange }: Props) => {
|
|||||||
|
|
||||||
const ref = useRef<HTMLDivElement>(null);
|
const ref = useRef<HTMLDivElement>(null);
|
||||||
const { overlayProps, underlayProps } = useOverlay(
|
const { overlayProps, underlayProps } = useOverlay(
|
||||||
{ onClose: () => setOpen(false), isDismissable: true, isOpen },
|
{
|
||||||
|
onClose: () => setOpen(false),
|
||||||
|
isDismissable: true,
|
||||||
|
isOpen,
|
||||||
|
shouldCloseOnInteractOutside: (element) => {
|
||||||
|
const popupElement = document.getElementsByClassName(POPUP_CLASS_NAME)[0];
|
||||||
|
return !(popupElement && popupElement.contains(element));
|
||||||
|
},
|
||||||
|
},
|
||||||
ref
|
ref
|
||||||
);
|
);
|
||||||
const { dialogProps } = useDialog({}, ref);
|
const { dialogProps } = useDialog({}, ref);
|
||||||
|
|||||||
@@ -19,6 +19,8 @@ export interface Props {
|
|||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const POPUP_CLASS_NAME = 'time-of-day-picker-panel';
|
||||||
|
|
||||||
export const TimeOfDayPicker = ({
|
export const TimeOfDayPicker = ({
|
||||||
minuteStep = 1,
|
minuteStep = 1,
|
||||||
showHour = true,
|
showHour = true,
|
||||||
@@ -33,7 +35,7 @@ export const TimeOfDayPicker = ({
|
|||||||
return (
|
return (
|
||||||
<RcTimePicker
|
<RcTimePicker
|
||||||
className={cx(inputSizes()[size], styles.input)}
|
className={cx(inputSizes()[size], styles.input)}
|
||||||
popupClassName={styles.picker}
|
popupClassName={cx(styles.picker, POPUP_CLASS_NAME)}
|
||||||
defaultValue={dateTimeAsMoment()}
|
defaultValue={dateTimeAsMoment()}
|
||||||
onChange={(value: any) => onChange(dateTime(value))}
|
onChange={(value: any) => onChange(dateTime(value))}
|
||||||
allowEmpty={false}
|
allowEmpty={false}
|
||||||
|
|||||||
Reference in New Issue
Block a user