mirror of
https://git.mirrors.martin98.com/https://github.com/SigNoz/signoz
synced 2025-07-24 00:24:25 +08:00
feat: [SIG-543]: add time selection in the custom date selection (#4658)
* feat: [SIG-543]: inital commit * feat: [SIG-543]: refactor date time modal to separate component * feat: [SIG-543]: refactor date time modal to separate component * feat: add back the time support according to the older designs in the date time picker * fix: custom time picker minor UI fixes
This commit is contained in:
parent
9ace374855
commit
49aba4fb1c
@ -115,6 +115,9 @@ function CustomTimePicker({
|
|||||||
|
|
||||||
const handleOpenChange = (newOpen: boolean): void => {
|
const handleOpenChange = (newOpen: boolean): void => {
|
||||||
setOpen(newOpen);
|
setOpen(newOpen);
|
||||||
|
if (!newOpen) {
|
||||||
|
setCustomDTPickerVisible?.(false);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const debouncedHandleInputChange = debounce((inputValue): void => {
|
const debouncedHandleInputChange = debounce((inputValue): void => {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import './CustomTimePicker.styles.scss';
|
import './CustomTimePicker.styles.scss';
|
||||||
|
|
||||||
import { Button, DatePicker } from 'antd';
|
import { Button } from 'antd';
|
||||||
import cx from 'classnames';
|
import cx from 'classnames';
|
||||||
import ROUTES from 'constants/routes';
|
import ROUTES from 'constants/routes';
|
||||||
import { DateTimeRangeType } from 'container/TopNav/CustomDateTimeModal';
|
import { DateTimeRangeType } from 'container/TopNav/CustomDateTimeModal';
|
||||||
@ -9,12 +9,10 @@ import {
|
|||||||
Option,
|
Option,
|
||||||
RelativeDurationSuggestionOptions,
|
RelativeDurationSuggestionOptions,
|
||||||
} from 'container/TopNav/DateTimeSelectionV2/config';
|
} from 'container/TopNav/DateTimeSelectionV2/config';
|
||||||
import dayjs, { Dayjs } from 'dayjs';
|
|
||||||
import { Dispatch, SetStateAction, useMemo } from 'react';
|
import { Dispatch, SetStateAction, useMemo } from 'react';
|
||||||
import { useSelector } from 'react-redux';
|
|
||||||
import { useLocation } from 'react-router-dom';
|
import { useLocation } from 'react-router-dom';
|
||||||
import { AppState } from 'store/reducers';
|
|
||||||
import { GlobalReducer } from 'types/reducer/globalTime';
|
import RangePickerModal from './RangePickerModal';
|
||||||
|
|
||||||
interface CustomTimePickerPopoverContentProps {
|
interface CustomTimePickerPopoverContentProps {
|
||||||
options: any[];
|
options: any[];
|
||||||
@ -40,35 +38,12 @@ function CustomTimePickerPopoverContent({
|
|||||||
handleGoLive,
|
handleGoLive,
|
||||||
selectedTime,
|
selectedTime,
|
||||||
}: CustomTimePickerPopoverContentProps): JSX.Element {
|
}: CustomTimePickerPopoverContentProps): JSX.Element {
|
||||||
const { RangePicker } = DatePicker;
|
|
||||||
const { pathname } = useLocation();
|
const { pathname } = useLocation();
|
||||||
|
|
||||||
const { maxTime, minTime } = useSelector<AppState, GlobalReducer>(
|
|
||||||
(state) => state.globalTime,
|
|
||||||
);
|
|
||||||
|
|
||||||
const isLogsExplorerPage = useMemo(() => pathname === ROUTES.LOGS_EXPLORER, [
|
const isLogsExplorerPage = useMemo(() => pathname === ROUTES.LOGS_EXPLORER, [
|
||||||
pathname,
|
pathname,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const disabledDate = (current: Dayjs): boolean => {
|
|
||||||
const currentDay = dayjs(current);
|
|
||||||
return currentDay.isAfter(dayjs());
|
|
||||||
};
|
|
||||||
|
|
||||||
const onPopoverClose = (visible: boolean): void => {
|
|
||||||
if (!visible) {
|
|
||||||
setCustomDTPickerVisible(false);
|
|
||||||
}
|
|
||||||
setIsOpen(visible);
|
|
||||||
};
|
|
||||||
|
|
||||||
const onModalOkHandler = (date_time: any): void => {
|
|
||||||
if (date_time?.[1]) {
|
|
||||||
onPopoverClose(false);
|
|
||||||
}
|
|
||||||
onCustomDateHandler(date_time, LexicalContext.CUSTOM_DATE_PICKER);
|
|
||||||
};
|
|
||||||
function getTimeChips(options: Option[]): JSX.Element {
|
function getTimeChips(options: Option[]): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<div className="relative-date-time-section">
|
<div className="relative-date-time-section">
|
||||||
@ -105,7 +80,9 @@ function CustomTimePickerPopoverContent({
|
|||||||
}}
|
}}
|
||||||
className={cx(
|
className={cx(
|
||||||
'date-time-options-btn',
|
'date-time-options-btn',
|
||||||
selectedTime === option.value && 'active',
|
customDateTimeVisible
|
||||||
|
? option.value === 'custom' && 'active'
|
||||||
|
: selectedTime === option.value && 'active',
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
{option.label}
|
{option.label}
|
||||||
@ -121,14 +98,11 @@ function CustomTimePickerPopoverContent({
|
|||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
{selectedTime === 'custom' || customDateTimeVisible ? (
|
{selectedTime === 'custom' || customDateTimeVisible ? (
|
||||||
<RangePicker
|
<RangePickerModal
|
||||||
disabledDate={disabledDate}
|
setCustomDTPickerVisible={setCustomDTPickerVisible}
|
||||||
allowClear
|
setIsOpen={setIsOpen}
|
||||||
onCalendarChange={onModalOkHandler}
|
onCustomDateHandler={onCustomDateHandler}
|
||||||
// eslint-disable-next-line react/jsx-props-no-spreading
|
selectedTime={selectedTime}
|
||||||
{...(selectedTime === 'custom' && {
|
|
||||||
defaultValue: [dayjs(minTime / 1000000), dayjs(maxTime / 1000000)],
|
|
||||||
})}
|
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<div className="relative-times-container">
|
<div className="relative-times-container">
|
||||||
|
@ -0,0 +1,4 @@
|
|||||||
|
.custom-date-picker {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
@ -0,0 +1,68 @@
|
|||||||
|
import './RangePickerModal.styles.scss';
|
||||||
|
|
||||||
|
import { DatePicker } from 'antd';
|
||||||
|
import { DateTimeRangeType } from 'container/TopNav/CustomDateTimeModal';
|
||||||
|
import { LexicalContext } from 'container/TopNav/DateTimeSelectionV2/config';
|
||||||
|
import dayjs, { Dayjs } from 'dayjs';
|
||||||
|
import { Dispatch, SetStateAction } from 'react';
|
||||||
|
import { useSelector } from 'react-redux';
|
||||||
|
import { AppState } from 'store/reducers';
|
||||||
|
import { GlobalReducer } from 'types/reducer/globalTime';
|
||||||
|
|
||||||
|
interface RangePickerModalProps {
|
||||||
|
setCustomDTPickerVisible: Dispatch<SetStateAction<boolean>>;
|
||||||
|
setIsOpen: Dispatch<SetStateAction<boolean>>;
|
||||||
|
onCustomDateHandler: (
|
||||||
|
dateTimeRange: DateTimeRangeType,
|
||||||
|
lexicalContext?: LexicalContext | undefined,
|
||||||
|
) => void;
|
||||||
|
selectedTime: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
function RangePickerModal(props: RangePickerModalProps): JSX.Element {
|
||||||
|
const {
|
||||||
|
setCustomDTPickerVisible,
|
||||||
|
setIsOpen,
|
||||||
|
onCustomDateHandler,
|
||||||
|
selectedTime,
|
||||||
|
} = props;
|
||||||
|
const { RangePicker } = DatePicker;
|
||||||
|
const { maxTime, minTime } = useSelector<AppState, GlobalReducer>(
|
||||||
|
(state) => state.globalTime,
|
||||||
|
);
|
||||||
|
|
||||||
|
const disabledDate = (current: Dayjs): boolean => {
|
||||||
|
const currentDay = dayjs(current);
|
||||||
|
return currentDay.isAfter(dayjs());
|
||||||
|
};
|
||||||
|
|
||||||
|
const onPopoverClose = (visible: boolean): void => {
|
||||||
|
if (!visible) {
|
||||||
|
setCustomDTPickerVisible(false);
|
||||||
|
}
|
||||||
|
setIsOpen(visible);
|
||||||
|
};
|
||||||
|
|
||||||
|
const onModalOkHandler = (date_time: any): void => {
|
||||||
|
if (date_time?.[1]) {
|
||||||
|
onPopoverClose(false);
|
||||||
|
}
|
||||||
|
onCustomDateHandler(date_time, LexicalContext.CUSTOM_DATE_PICKER);
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
<div className="custom-date-picker">
|
||||||
|
<RangePicker
|
||||||
|
disabledDate={disabledDate}
|
||||||
|
allowClear
|
||||||
|
showTime
|
||||||
|
onOk={onModalOkHandler}
|
||||||
|
// eslint-disable-next-line react/jsx-props-no-spreading
|
||||||
|
{...(selectedTime === 'custom' && {
|
||||||
|
defaultValue: [dayjs(minTime / 1000000), dayjs(maxTime / 1000000)],
|
||||||
|
})}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default RangePickerModal;
|
@ -133,8 +133,8 @@
|
|||||||
padding: 13px 14px;
|
padding: 13px 14px;
|
||||||
|
|
||||||
&.date-picker {
|
&.date-picker {
|
||||||
width: 340px;
|
width: 480px;
|
||||||
height: 380px;
|
height: 430px;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.relative-times {
|
&.relative-times {
|
||||||
|
@ -44,7 +44,6 @@ import { DateTimeRangeType } from '../CustomDateTimeModal';
|
|||||||
import {
|
import {
|
||||||
getDefaultOption,
|
getDefaultOption,
|
||||||
getOptions,
|
getOptions,
|
||||||
LexicalContext,
|
|
||||||
LocalStorageTimeRange,
|
LocalStorageTimeRange,
|
||||||
Time,
|
Time,
|
||||||
TimeRange,
|
TimeRange,
|
||||||
@ -319,22 +318,12 @@ function DateTimeSelection({
|
|||||||
onLastRefreshHandler();
|
onLastRefreshHandler();
|
||||||
};
|
};
|
||||||
|
|
||||||
const onCustomDateHandler = (
|
const onCustomDateHandler = (dateTimeRange: DateTimeRangeType): void => {
|
||||||
dateTimeRange: DateTimeRangeType,
|
|
||||||
lexicalContext?: LexicalContext,
|
|
||||||
): void => {
|
|
||||||
if (dateTimeRange !== null) {
|
if (dateTimeRange !== null) {
|
||||||
const [startTimeMoment, endTimeMoment] = dateTimeRange;
|
const [startTimeMoment, endTimeMoment] = dateTimeRange;
|
||||||
if (startTimeMoment && endTimeMoment) {
|
if (startTimeMoment && endTimeMoment) {
|
||||||
let startTime = startTimeMoment;
|
const startTime = startTimeMoment;
|
||||||
let endTime = endTimeMoment;
|
const endTime = endTimeMoment;
|
||||||
if (
|
|
||||||
lexicalContext &&
|
|
||||||
lexicalContext === LexicalContext.CUSTOM_DATE_PICKER
|
|
||||||
) {
|
|
||||||
startTime = startTime.startOf('day');
|
|
||||||
endTime = endTime.endOf('day');
|
|
||||||
}
|
|
||||||
setCustomDTPickerVisible(false);
|
setCustomDTPickerVisible(false);
|
||||||
updateTimeInterval('custom', [
|
updateTimeInterval('custom', [
|
||||||
startTime.toDate().getTime(),
|
startTime.toDate().getTime(),
|
||||||
|
Loading…
x
Reference in New Issue
Block a user