mirror of
https://git.mirrors.martin98.com/https://github.com/SigNoz/signoz
synced 2025-08-13 21:15:56 +08:00
feat: update time range selection flows to handle relative and absolu… (#4742)
* feat: update time range selection flows to handle relative and absolute times * fix: lint error * fix: lint error * feat: update logic to handle custom relative times on load and standardize relative time formats * fix: type issue * fix: handle light mode and on custom time range select * chore: update alert frequency corresponding times * chore: update copy URL * feat: update styles
This commit is contained in:
parent
7c2f5352d2
commit
6eced60bf5
@ -5,13 +5,14 @@ import './CustomTimePicker.styles.scss';
|
|||||||
import { Input, Popover, Tooltip, Typography } from 'antd';
|
import { Input, Popover, Tooltip, Typography } from 'antd';
|
||||||
import cx from 'classnames';
|
import cx from 'classnames';
|
||||||
import { DateTimeRangeType } from 'container/TopNav/CustomDateTimeModal';
|
import { DateTimeRangeType } from 'container/TopNav/CustomDateTimeModal';
|
||||||
import { Options } from 'container/TopNav/DateTimeSelection/config';
|
|
||||||
import {
|
import {
|
||||||
FixedDurationSuggestionOptions,
|
FixedDurationSuggestionOptions,
|
||||||
|
Options,
|
||||||
RelativeDurationSuggestionOptions,
|
RelativeDurationSuggestionOptions,
|
||||||
} from 'container/TopNav/DateTimeSelectionV2/config';
|
} from 'container/TopNav/DateTimeSelectionV2/config';
|
||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
import { defaultTo, noop } from 'lodash-es';
|
import { isValidTimeFormat } from 'lib/getMinMax';
|
||||||
|
import { defaultTo, isFunction, noop } from 'lodash-es';
|
||||||
import debounce from 'lodash-es/debounce';
|
import debounce from 'lodash-es/debounce';
|
||||||
import { CheckCircle, ChevronDown, Clock } from 'lucide-react';
|
import { CheckCircle, ChevronDown, Clock } from 'lucide-react';
|
||||||
import {
|
import {
|
||||||
@ -33,7 +34,14 @@ interface CustomTimePickerProps {
|
|||||||
onError: (value: boolean) => void;
|
onError: (value: boolean) => void;
|
||||||
selectedValue: string;
|
selectedValue: string;
|
||||||
selectedTime: string;
|
selectedTime: string;
|
||||||
onValidCustomDateChange: ([t1, t2]: any[]) => void;
|
onValidCustomDateChange: ({
|
||||||
|
time: [t1, t2],
|
||||||
|
timeStr,
|
||||||
|
}: {
|
||||||
|
time: [dayjs.Dayjs | null, dayjs.Dayjs | null];
|
||||||
|
timeStr: string;
|
||||||
|
}) => void;
|
||||||
|
onCustomTimeStatusUpdate?: (isValid: boolean) => void;
|
||||||
open: boolean;
|
open: boolean;
|
||||||
setOpen: Dispatch<SetStateAction<boolean>>;
|
setOpen: Dispatch<SetStateAction<boolean>>;
|
||||||
items: any[];
|
items: any[];
|
||||||
@ -53,6 +61,7 @@ function CustomTimePicker({
|
|||||||
open,
|
open,
|
||||||
setOpen,
|
setOpen,
|
||||||
onValidCustomDateChange,
|
onValidCustomDateChange,
|
||||||
|
onCustomTimeStatusUpdate,
|
||||||
newPopover,
|
newPopover,
|
||||||
customDateTimeVisible,
|
customDateTimeVisible,
|
||||||
setCustomDTPickerVisible,
|
setCustomDTPickerVisible,
|
||||||
@ -85,6 +94,7 @@ function CustomTimePicker({
|
|||||||
return Options[index].label;
|
return Options[index].label;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (
|
for (
|
||||||
let index = 0;
|
let index = 0;
|
||||||
index < RelativeDurationSuggestionOptions.length;
|
index < RelativeDurationSuggestionOptions.length;
|
||||||
@ -94,12 +104,17 @@ function CustomTimePicker({
|
|||||||
return RelativeDurationSuggestionOptions[index].label;
|
return RelativeDurationSuggestionOptions[index].label;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (let index = 0; index < FixedDurationSuggestionOptions.length; index++) {
|
for (let index = 0; index < FixedDurationSuggestionOptions.length; index++) {
|
||||||
if (FixedDurationSuggestionOptions[index].value === selectedTime) {
|
if (FixedDurationSuggestionOptions[index].value === selectedTime) {
|
||||||
return FixedDurationSuggestionOptions[index].label;
|
return FixedDurationSuggestionOptions[index].label;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isValidTimeFormat(selectedTime)) {
|
||||||
|
return selectedTime;
|
||||||
|
}
|
||||||
|
|
||||||
return '';
|
return '';
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -161,13 +176,22 @@ function CustomTimePicker({
|
|||||||
setInputStatus('error');
|
setInputStatus('error');
|
||||||
onError(true);
|
onError(true);
|
||||||
setInputErrorMessage('Please enter time less than 6 months');
|
setInputErrorMessage('Please enter time less than 6 months');
|
||||||
|
if (isFunction(onCustomTimeStatusUpdate)) {
|
||||||
|
onCustomTimeStatusUpdate(true);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
onValidCustomDateChange([minTime, currentTime]);
|
onValidCustomDateChange({
|
||||||
|
time: [minTime, currentTime],
|
||||||
|
timeStr: inputValue,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
setInputStatus('error');
|
setInputStatus('error');
|
||||||
onError(true);
|
onError(true);
|
||||||
setInputErrorMessage(null);
|
setInputErrorMessage(null);
|
||||||
|
if (isFunction(onCustomTimeStatusUpdate)) {
|
||||||
|
onCustomTimeStatusUpdate(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}, 300);
|
}, 300);
|
||||||
|
|
||||||
@ -320,4 +344,5 @@ CustomTimePicker.defaultProps = {
|
|||||||
setCustomDTPickerVisible: noop,
|
setCustomDTPickerVisible: noop,
|
||||||
onCustomDateHandler: noop,
|
onCustomDateHandler: noop,
|
||||||
handleGoLive: noop,
|
handleGoLive: noop,
|
||||||
|
onCustomTimeStatusUpdate: noop,
|
||||||
};
|
};
|
||||||
|
@ -29,4 +29,5 @@ export enum QueryParams {
|
|||||||
expandedWidgetId = 'expandedWidgetId',
|
expandedWidgetId = 'expandedWidgetId',
|
||||||
integration = 'integration',
|
integration = 'integration',
|
||||||
pagination = 'pagination',
|
pagination = 'pagination',
|
||||||
|
relativeTime = 'relativeTime',
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,10 @@ import GridPanelSwitch from 'container/GridPanelSwitch';
|
|||||||
import { getFormatNameByOptionId } from 'container/NewWidget/RightContainer/alertFomatCategories';
|
import { getFormatNameByOptionId } from 'container/NewWidget/RightContainer/alertFomatCategories';
|
||||||
import { timePreferenceType } from 'container/NewWidget/RightContainer/timeItems';
|
import { timePreferenceType } from 'container/NewWidget/RightContainer/timeItems';
|
||||||
import { Time } from 'container/TopNav/DateTimeSelection/config';
|
import { Time } from 'container/TopNav/DateTimeSelection/config';
|
||||||
import { Time as TimeV2 } from 'container/TopNav/DateTimeSelectionV2/config';
|
import {
|
||||||
|
CustomTimeType,
|
||||||
|
Time as TimeV2,
|
||||||
|
} from 'container/TopNav/DateTimeSelectionV2/config';
|
||||||
import { useGetQueryRange } from 'hooks/queryBuilder/useGetQueryRange';
|
import { useGetQueryRange } from 'hooks/queryBuilder/useGetQueryRange';
|
||||||
import { useIsDarkMode } from 'hooks/useDarkMode';
|
import { useIsDarkMode } from 'hooks/useDarkMode';
|
||||||
import { useResizeObserver } from 'hooks/useDimensions';
|
import { useResizeObserver } from 'hooks/useDimensions';
|
||||||
@ -39,7 +42,7 @@ export interface ChartPreviewProps {
|
|||||||
query: Query | null;
|
query: Query | null;
|
||||||
graphType?: PANEL_TYPES;
|
graphType?: PANEL_TYPES;
|
||||||
selectedTime?: timePreferenceType;
|
selectedTime?: timePreferenceType;
|
||||||
selectedInterval?: Time | TimeV2;
|
selectedInterval?: Time | TimeV2 | CustomTimeType;
|
||||||
headline?: JSX.Element;
|
headline?: JSX.Element;
|
||||||
alertDef?: AlertDef;
|
alertDef?: AlertDef;
|
||||||
userQueryKey?: string;
|
userQueryKey?: string;
|
||||||
@ -53,7 +56,7 @@ function ChartPreview({
|
|||||||
query,
|
query,
|
||||||
graphType = PANEL_TYPES.TIME_SERIES,
|
graphType = PANEL_TYPES.TIME_SERIES,
|
||||||
selectedTime = 'GLOBAL_TIME',
|
selectedTime = 'GLOBAL_TIME',
|
||||||
selectedInterval = '5min',
|
selectedInterval = '5m',
|
||||||
headline,
|
headline,
|
||||||
userQueryKey,
|
userQueryKey,
|
||||||
allowSelectedIntervalForStepGen = false,
|
allowSelectedIntervalForStepGen = false,
|
||||||
|
@ -12,22 +12,30 @@ import {
|
|||||||
// toChartInterval converts eval window to chart selection time interval
|
// toChartInterval converts eval window to chart selection time interval
|
||||||
export const toChartInterval = (evalWindow: string | undefined): Time => {
|
export const toChartInterval = (evalWindow: string | undefined): Time => {
|
||||||
switch (evalWindow) {
|
switch (evalWindow) {
|
||||||
|
case '1m0s':
|
||||||
|
return '1m';
|
||||||
case '5m0s':
|
case '5m0s':
|
||||||
return '5min';
|
return '5m';
|
||||||
case '10m0s':
|
case '10m0s':
|
||||||
return '10min';
|
return '10m';
|
||||||
case '15m0s':
|
case '15m0s':
|
||||||
return '15min';
|
return '15m';
|
||||||
case '30m0s':
|
case '30m0s':
|
||||||
return '30min';
|
return '30m';
|
||||||
case '1h0m0s':
|
case '1h0m0s':
|
||||||
return '1hr';
|
return '1h';
|
||||||
|
case '3h0m0s':
|
||||||
|
return '3h';
|
||||||
case '4h0m0s':
|
case '4h0m0s':
|
||||||
return '4hr';
|
return '4h';
|
||||||
|
case '6h0m0s':
|
||||||
|
return '6h';
|
||||||
|
case '12h0m0s':
|
||||||
|
return '12h';
|
||||||
case '24h0m0s':
|
case '24h0m0s':
|
||||||
return '1day';
|
return '1d';
|
||||||
default:
|
default:
|
||||||
return '5min';
|
return '5m';
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { DEFAULT_ENTITY_VERSION } from 'constants/app';
|
import { DEFAULT_ENTITY_VERSION } from 'constants/app';
|
||||||
import { QueryParams } from 'constants/query';
|
import { QueryParams } from 'constants/query';
|
||||||
import { PANEL_TYPES } from 'constants/queryBuilder';
|
import { PANEL_TYPES } from 'constants/queryBuilder';
|
||||||
|
import { CustomTimeType } from 'container/TopNav/DateTimeSelectionV2/config';
|
||||||
import { useGetQueryRange } from 'hooks/queryBuilder/useGetQueryRange';
|
import { useGetQueryRange } from 'hooks/queryBuilder/useGetQueryRange';
|
||||||
import { useStepInterval } from 'hooks/queryBuilder/useStepInterval';
|
import { useStepInterval } from 'hooks/queryBuilder/useStepInterval';
|
||||||
import { useIsDarkMode } from 'hooks/useDarkMode';
|
import { useIsDarkMode } from 'hooks/useDarkMode';
|
||||||
@ -81,8 +82,13 @@ function GridCardGraph({
|
|||||||
const searchParams = new URLSearchParams(window.location.search);
|
const searchParams = new URLSearchParams(window.location.search);
|
||||||
const startTime = searchParams.get(QueryParams.startTime);
|
const startTime = searchParams.get(QueryParams.startTime);
|
||||||
const endTime = searchParams.get(QueryParams.endTime);
|
const endTime = searchParams.get(QueryParams.endTime);
|
||||||
|
const relativeTime = searchParams.get(
|
||||||
|
QueryParams.relativeTime,
|
||||||
|
) as CustomTimeType;
|
||||||
|
|
||||||
if (startTime && endTime && startTime !== endTime) {
|
if (relativeTime) {
|
||||||
|
dispatch(UpdateTimeInterval(relativeTime));
|
||||||
|
} else if (startTime && endTime && startTime !== endTime) {
|
||||||
dispatch(
|
dispatch(
|
||||||
UpdateTimeInterval('custom', [
|
UpdateTimeInterval('custom', [
|
||||||
parseInt(getTimeString(startTime), 10),
|
parseInt(getTimeString(startTime), 10),
|
||||||
|
@ -2,6 +2,7 @@ import Graph from 'components/Graph';
|
|||||||
import Spinner from 'components/Spinner';
|
import Spinner from 'components/Spinner';
|
||||||
import { QueryParams } from 'constants/query';
|
import { QueryParams } from 'constants/query';
|
||||||
import { themeColors } from 'constants/theme';
|
import { themeColors } from 'constants/theme';
|
||||||
|
import { CustomTimeType } from 'container/TopNav/DateTimeSelectionV2/config';
|
||||||
import useUrlQuery from 'hooks/useUrlQuery';
|
import useUrlQuery from 'hooks/useUrlQuery';
|
||||||
import getChartData, { GetChartDataProps } from 'lib/getChartData';
|
import getChartData, { GetChartDataProps } from 'lib/getChartData';
|
||||||
import GetMinMax from 'lib/getMinMax';
|
import GetMinMax from 'lib/getMinMax';
|
||||||
@ -65,8 +66,13 @@ function LogsExplorerChart({
|
|||||||
const searchParams = new URLSearchParams(window.location.search);
|
const searchParams = new URLSearchParams(window.location.search);
|
||||||
const startTime = searchParams.get(QueryParams.startTime);
|
const startTime = searchParams.get(QueryParams.startTime);
|
||||||
const endTime = searchParams.get(QueryParams.endTime);
|
const endTime = searchParams.get(QueryParams.endTime);
|
||||||
|
const relativeTime = searchParams.get(
|
||||||
|
QueryParams.relativeTime,
|
||||||
|
) as CustomTimeType;
|
||||||
|
|
||||||
if (startTime && endTime && startTime !== endTime) {
|
if (relativeTime) {
|
||||||
|
dispatch(UpdateTimeInterval(relativeTime));
|
||||||
|
} else if (startTime && endTime && startTime !== endTime) {
|
||||||
dispatch(
|
dispatch(
|
||||||
UpdateTimeInterval('custom', [
|
UpdateTimeInterval('custom', [
|
||||||
parseInt(getTimeString(startTime), 10),
|
parseInt(getTimeString(startTime), 10),
|
||||||
|
@ -1,9 +1,12 @@
|
|||||||
import { Time } from 'container/TopNav/DateTimeSelection/config';
|
import { Time } from 'container/TopNav/DateTimeSelection/config';
|
||||||
import { Time as TimeV2 } from 'container/TopNav/DateTimeSelectionV2/config';
|
import {
|
||||||
|
CustomTimeType,
|
||||||
|
Time as TimeV2,
|
||||||
|
} from 'container/TopNav/DateTimeSelectionV2/config';
|
||||||
import { GetMinMaxPayload } from 'lib/getMinMax';
|
import { GetMinMaxPayload } from 'lib/getMinMax';
|
||||||
|
|
||||||
export const getGlobalTime = (
|
export const getGlobalTime = (
|
||||||
selectedTime: Time | TimeV2,
|
selectedTime: Time | TimeV2 | CustomTimeType,
|
||||||
globalTime: GetMinMaxPayload,
|
globalTime: GetMinMaxPayload,
|
||||||
): GetMinMaxPayload | undefined => {
|
): GetMinMaxPayload | undefined => {
|
||||||
if (selectedTime === 'custom') {
|
if (selectedTime === 'custom') {
|
||||||
|
@ -3,6 +3,7 @@ import { PANEL_TYPES } from 'constants/queryBuilder';
|
|||||||
import GridPanelSwitch from 'container/GridPanelSwitch';
|
import GridPanelSwitch from 'container/GridPanelSwitch';
|
||||||
import { ThresholdProps } from 'container/NewWidget/RightContainer/Threshold/types';
|
import { ThresholdProps } from 'container/NewWidget/RightContainer/Threshold/types';
|
||||||
import { timePreferance } from 'container/NewWidget/RightContainer/timeItems';
|
import { timePreferance } from 'container/NewWidget/RightContainer/timeItems';
|
||||||
|
import { CustomTimeType } from 'container/TopNav/DateTimeSelectionV2/config';
|
||||||
import { useQueryBuilder } from 'hooks/queryBuilder/useQueryBuilder';
|
import { useQueryBuilder } from 'hooks/queryBuilder/useQueryBuilder';
|
||||||
import { useIsDarkMode } from 'hooks/useDarkMode';
|
import { useIsDarkMode } from 'hooks/useDarkMode';
|
||||||
import { useResizeObserver } from 'hooks/useDimensions';
|
import { useResizeObserver } from 'hooks/useDimensions';
|
||||||
@ -97,8 +98,13 @@ function WidgetGraph({
|
|||||||
const searchParams = new URLSearchParams(window.location.search);
|
const searchParams = new URLSearchParams(window.location.search);
|
||||||
const startTime = searchParams.get(QueryParams.startTime);
|
const startTime = searchParams.get(QueryParams.startTime);
|
||||||
const endTime = searchParams.get(QueryParams.endTime);
|
const endTime = searchParams.get(QueryParams.endTime);
|
||||||
|
const relativeTime = searchParams.get(
|
||||||
|
QueryParams.relativeTime,
|
||||||
|
) as CustomTimeType;
|
||||||
|
|
||||||
if (startTime && endTime && startTime !== endTime) {
|
if (relativeTime) {
|
||||||
|
dispatch(UpdateTimeInterval(relativeTime));
|
||||||
|
} else if (startTime && endTime && startTime !== endTime) {
|
||||||
dispatch(
|
dispatch(
|
||||||
UpdateTimeInterval('custom', [
|
UpdateTimeInterval('custom', [
|
||||||
parseInt(getTimeString(startTime), 10),
|
parseInt(getTimeString(startTime), 10),
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
import { ServiceDataProps } from 'api/metrics/getTopLevelOperations';
|
import { ServiceDataProps } from 'api/metrics/getTopLevelOperations';
|
||||||
import { Time } from 'container/TopNav/DateTimeSelection/config';
|
import { Time } from 'container/TopNav/DateTimeSelection/config';
|
||||||
import { Time as TimeV2 } from 'container/TopNav/DateTimeSelectionV2/config';
|
import {
|
||||||
|
CustomTimeType,
|
||||||
|
Time as TimeV2,
|
||||||
|
} from 'container/TopNav/DateTimeSelectionV2/config';
|
||||||
import { GetQueryResultsProps } from 'lib/dashboard/getQueryResults';
|
import { GetQueryResultsProps } from 'lib/dashboard/getQueryResults';
|
||||||
import { UseQueryResult } from 'react-query';
|
import { UseQueryResult } from 'react-query';
|
||||||
import { SuccessResponse } from 'types/api';
|
import { SuccessResponse } from 'types/api';
|
||||||
@ -25,7 +28,7 @@ export interface GetQueryRangeRequestDataProps {
|
|||||||
topLevelOperations: [keyof ServiceDataProps, string[]][];
|
topLevelOperations: [keyof ServiceDataProps, string[]][];
|
||||||
maxTime: number;
|
maxTime: number;
|
||||||
minTime: number;
|
minTime: number;
|
||||||
globalSelectedInterval: Time | TimeV2;
|
globalSelectedInterval: Time | TimeV2 | CustomTimeType;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface GetServiceListFromQueryProps {
|
export interface GetServiceListFromQueryProps {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import GetMinMax, { GetMinMaxPayload } from 'lib/getMinMax';
|
import GetMinMax, { GetMinMaxPayload } from 'lib/getMinMax';
|
||||||
|
|
||||||
import { Time } from '../DateTimeSelection/config';
|
import { Time } from '../DateTimeSelection/config';
|
||||||
import { Time as TimeV2 } from '../DateTimeSelectionV2/config';
|
import { CustomTimeType, Time as TimeV2 } from '../DateTimeSelectionV2/config';
|
||||||
|
|
||||||
export const options: IOptions[] = [
|
export const options: IOptions[] = [
|
||||||
{
|
{
|
||||||
@ -68,7 +68,7 @@ export interface IOptions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const getMinMax = (
|
export const getMinMax = (
|
||||||
selectedTime: Time | TimeV2,
|
selectedTime: Time | TimeV2 | CustomTimeType,
|
||||||
minTime: number,
|
minTime: number,
|
||||||
maxTime: number,
|
maxTime: number,
|
||||||
): GetMinMaxPayload =>
|
): GetMinMaxPayload =>
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import GetMinMax, { GetMinMaxPayload } from 'lib/getMinMax';
|
import GetMinMax, { GetMinMaxPayload } from 'lib/getMinMax';
|
||||||
|
|
||||||
import { Time } from '../DateTimeSelection/config';
|
import { Time } from '../DateTimeSelection/config';
|
||||||
import { Time as TimeV2 } from '../DateTimeSelectionV2/config';
|
import { CustomTimeType, Time as TimeV2 } from '../DateTimeSelectionV2/config';
|
||||||
|
|
||||||
export const options: IOptions[] = [
|
export const options: IOptions[] = [
|
||||||
{
|
{
|
||||||
@ -68,7 +68,7 @@ export interface IOptions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const getMinMax = (
|
export const getMinMax = (
|
||||||
selectedTime: Time | TimeV2,
|
selectedTime: Time | TimeV2 | CustomTimeType,
|
||||||
minTime: number,
|
minTime: number,
|
||||||
maxTime: number,
|
maxTime: number,
|
||||||
): GetMinMaxPayload =>
|
): GetMinMaxPayload =>
|
||||||
|
@ -1,16 +1,18 @@
|
|||||||
import ROUTES from 'constants/routes';
|
import ROUTES from 'constants/routes';
|
||||||
|
|
||||||
type FiveMin = '5min';
|
type FiveMin = '5m';
|
||||||
type TenMin = '10min';
|
type TenMin = '10m';
|
||||||
type FifteenMin = '15min';
|
type FifteenMin = '15m';
|
||||||
type ThirtyMin = '30min';
|
type ThirtyMin = '30m';
|
||||||
type OneMin = '1min';
|
type OneMin = '1m';
|
||||||
type SixHour = '6hr';
|
type SixHour = '6h';
|
||||||
type OneHour = '1hr';
|
type OneHour = '1h';
|
||||||
type FourHour = '4hr';
|
type FourHour = '4h';
|
||||||
type OneDay = '1day';
|
type ThreeHour = '3h';
|
||||||
type ThreeDay = '3days';
|
type TwelveHour = '12h';
|
||||||
type OneWeek = '1week';
|
type OneDay = '1d';
|
||||||
|
type ThreeDay = '3d';
|
||||||
|
type OneWeek = '1w';
|
||||||
type Custom = 'custom';
|
type Custom = 'custom';
|
||||||
|
|
||||||
export type Time =
|
export type Time =
|
||||||
@ -22,37 +24,62 @@ export type Time =
|
|||||||
| FourHour
|
| FourHour
|
||||||
| SixHour
|
| SixHour
|
||||||
| OneHour
|
| OneHour
|
||||||
|
| ThreeHour
|
||||||
| Custom
|
| Custom
|
||||||
| OneWeek
|
| OneWeek
|
||||||
| OneDay
|
| OneDay
|
||||||
|
| TwelveHour
|
||||||
| ThreeDay;
|
| ThreeDay;
|
||||||
|
|
||||||
export const Options: Option[] = [
|
export const Options: Option[] = [
|
||||||
{ value: '5min', label: 'Last 5 min' },
|
{ value: '5m', label: 'Last 5 min' },
|
||||||
{ value: '15min', label: 'Last 15 min' },
|
{ value: '15m', label: 'Last 15 min' },
|
||||||
{ value: '30min', label: 'Last 30 min' },
|
{ value: '30m', label: 'Last 30 min' },
|
||||||
{ value: '1hr', label: 'Last 1 hour' },
|
{ value: '1h', label: 'Last 1 hour' },
|
||||||
{ value: '6hr', label: 'Last 6 hour' },
|
{ value: '6h', label: 'Last 6 hour' },
|
||||||
{ value: '1day', label: 'Last 1 day' },
|
{ value: '1d', label: 'Last 1 day' },
|
||||||
{ value: '3days', label: 'Last 3 days' },
|
{ value: '3d', label: 'Last 3 days' },
|
||||||
{ value: '1week', label: 'Last 1 week' },
|
{ value: '1w', label: 'Last 1 week' },
|
||||||
{ value: 'custom', label: 'Custom' },
|
{ value: 'custom', label: 'Custom' },
|
||||||
];
|
];
|
||||||
|
|
||||||
|
type TimeFrame = {
|
||||||
|
'5min': string;
|
||||||
|
'15min': string;
|
||||||
|
'30min': string;
|
||||||
|
'1hr': string;
|
||||||
|
'6hr': string;
|
||||||
|
'1day': string;
|
||||||
|
'3days': string;
|
||||||
|
'1week': string;
|
||||||
|
[key: string]: string; // Index signature to allow any string as index
|
||||||
|
};
|
||||||
|
|
||||||
|
export const RelativeTimeMap: TimeFrame = {
|
||||||
|
'5min': '5m',
|
||||||
|
'15min': '15m',
|
||||||
|
'30min': '30m',
|
||||||
|
'1hr': '1h',
|
||||||
|
'6hr': '6h',
|
||||||
|
'1day': '1d',
|
||||||
|
'3days': '3d',
|
||||||
|
'1week': '1w',
|
||||||
|
};
|
||||||
|
|
||||||
export interface Option {
|
export interface Option {
|
||||||
value: Time;
|
value: Time;
|
||||||
label: string;
|
label: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const RelativeDurationOptions: Option[] = [
|
export const RelativeDurationOptions: Option[] = [
|
||||||
{ value: '5min', label: 'Last 5 min' },
|
{ value: '5m', label: 'Last 5 min' },
|
||||||
{ value: '15min', label: 'Last 15 min' },
|
{ value: '15m', label: 'Last 15 min' },
|
||||||
{ value: '30min', label: 'Last 30 min' },
|
{ value: '30m', label: 'Last 30 min' },
|
||||||
{ value: '1hr', label: 'Last 1 hour' },
|
{ value: '1h', label: 'Last 1 hour' },
|
||||||
{ value: '6hr', label: 'Last 6 hour' },
|
{ value: '6h', label: 'Last 6 hour' },
|
||||||
{ value: '1day', label: 'Last 1 day' },
|
{ value: '1d', label: 'Last 1 day' },
|
||||||
{ value: '3days', label: 'Last 3 days' },
|
{ value: '3d', label: 'Last 3 days' },
|
||||||
{ value: '1week', label: 'Last 1 week' },
|
{ value: '1w', label: 'Last 1 week' },
|
||||||
];
|
];
|
||||||
|
|
||||||
export const getDefaultOption = (route: string): Time => {
|
export const getDefaultOption = (route: string): Time => {
|
||||||
|
@ -28,7 +28,7 @@ import { GlobalReducer } from 'types/reducer/globalTime';
|
|||||||
|
|
||||||
import AutoRefresh from '../AutoRefresh';
|
import AutoRefresh from '../AutoRefresh';
|
||||||
import CustomDateTimeModal, { DateTimeRangeType } from '../CustomDateTimeModal';
|
import CustomDateTimeModal, { DateTimeRangeType } from '../CustomDateTimeModal';
|
||||||
import { Time as TimeV2 } from '../DateTimeSelectionV2/config';
|
import { CustomTimeType, Time as TimeV2 } from '../DateTimeSelectionV2/config';
|
||||||
import {
|
import {
|
||||||
getDefaultOption,
|
getDefaultOption,
|
||||||
getOptions,
|
getOptions,
|
||||||
@ -122,7 +122,7 @@ function DateTimeSelection({
|
|||||||
const getInputLabel = (
|
const getInputLabel = (
|
||||||
startTime?: Dayjs,
|
startTime?: Dayjs,
|
||||||
endTime?: Dayjs,
|
endTime?: Dayjs,
|
||||||
timeInterval: Time | TimeV2 = '15min',
|
timeInterval: Time | TimeV2 | CustomTimeType = '15m',
|
||||||
): string | Time => {
|
): string | Time => {
|
||||||
if (startTime && endTime && timeInterval === 'custom') {
|
if (startTime && endTime && timeInterval === 'custom') {
|
||||||
const format = 'YYYY/MM/DD HH:mm';
|
const format = 'YYYY/MM/DD HH:mm';
|
||||||
@ -225,7 +225,7 @@ function DateTimeSelection({
|
|||||||
[location.pathname],
|
[location.pathname],
|
||||||
);
|
);
|
||||||
|
|
||||||
const onSelectHandler = (value: Time | TimeV2): void => {
|
const onSelectHandler = (value: Time | TimeV2 | CustomTimeType): void => {
|
||||||
if (value !== 'custom') {
|
if (value !== 'custom') {
|
||||||
updateTimeInterval(value);
|
updateTimeInterval(value);
|
||||||
updateLocalStorageForRoutes(value);
|
updateLocalStorageForRoutes(value);
|
||||||
@ -358,7 +358,7 @@ function DateTimeSelection({
|
|||||||
}}
|
}}
|
||||||
selectedTime={selectedTime}
|
selectedTime={selectedTime}
|
||||||
onValidCustomDateChange={(dateTime): void =>
|
onValidCustomDateChange={(dateTime): void =>
|
||||||
onCustomDateHandler(dateTime as DateTimeRangeType)
|
onCustomDateHandler(dateTime.time as DateTimeRangeType)
|
||||||
}
|
}
|
||||||
selectedValue={getInputLabel(
|
selectedValue={getInputLabel(
|
||||||
dayjs(minTime / 1000000),
|
dayjs(minTime / 1000000),
|
||||||
@ -406,7 +406,7 @@ function DateTimeSelection({
|
|||||||
|
|
||||||
interface DispatchProps {
|
interface DispatchProps {
|
||||||
updateTimeInterval: (
|
updateTimeInterval: (
|
||||||
interval: Time | TimeV2,
|
interval: Time | TimeV2 | CustomTimeType,
|
||||||
dateTimeRange?: [number, number],
|
dateTimeRange?: [number, number],
|
||||||
) => (dispatch: Dispatch<AppActions>) => void;
|
) => (dispatch: Dispatch<AppActions>) => void;
|
||||||
globalTimeLoading: () => void;
|
globalTimeLoading: () => void;
|
||||||
|
@ -54,9 +54,61 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.share-link-btn {
|
||||||
|
height: 34px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.shareable-link-popover {
|
||||||
|
margin-left: 8px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.date-time-root {
|
.share-modal-content {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 8px;
|
||||||
|
padding: 16px;
|
||||||
|
width: 420px;
|
||||||
|
|
||||||
|
.absolute-relative-time-toggler-container {
|
||||||
|
display: flex;
|
||||||
|
gap: 8px;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.absolute-relative-time-toggler {
|
||||||
|
display: flex;
|
||||||
|
gap: 4px;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.absolute-relative-time-error {
|
||||||
|
font-size: 12px;
|
||||||
|
color: var(--bg-amber-600);
|
||||||
|
}
|
||||||
|
|
||||||
|
.share-link {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
.share-url {
|
||||||
|
flex: 1;
|
||||||
|
border: 1px solid var(--bg-slate-400);
|
||||||
|
border-radius: 2px;
|
||||||
|
background: var(--bg-ink-300);
|
||||||
|
height: 32px;
|
||||||
|
padding: 6px 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.copy-url-btn {
|
||||||
|
width: 32px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.date-time-root,
|
||||||
|
.shareable-link-popover-root {
|
||||||
.ant-popover-inner {
|
.ant-popover-inner {
|
||||||
border-radius: 4px !important;
|
border-radius: 4px !important;
|
||||||
border: 1px solid var(--bg-slate-400);
|
border: 1px solid var(--bg-slate-400);
|
||||||
@ -185,7 +237,8 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.date-time-root {
|
.date-time-root,
|
||||||
|
.shareable-link-popover-root {
|
||||||
.ant-popover-inner {
|
.ant-popover-inner {
|
||||||
border: 1px solid var(--bg-vanilla-400);
|
border: 1px solid var(--bg-vanilla-400);
|
||||||
background: var(--bg-vanilla-100) !important;
|
background: var(--bg-vanilla-100) !important;
|
||||||
@ -234,4 +287,13 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.share-modal-content {
|
||||||
|
.share-link {
|
||||||
|
.share-url {
|
||||||
|
border: 1px solid var(--bg-vanilla-300);
|
||||||
|
background: var(--bg-vanilla-100);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,24 +1,24 @@
|
|||||||
/* eslint-disable sonarjs/no-duplicate-string */
|
/* eslint-disable sonarjs/no-duplicate-string */
|
||||||
import ROUTES from 'constants/routes';
|
import ROUTES from 'constants/routes';
|
||||||
|
|
||||||
type FiveMin = '5min';
|
type FiveMin = '5m';
|
||||||
type TenMin = '10min';
|
type TenMin = '10m';
|
||||||
type FifteenMin = '15min';
|
type FifteenMin = '15m';
|
||||||
type ThirtyMin = '30min';
|
type ThirtyMin = '30m';
|
||||||
type FortyFiveMin = '45min';
|
type FortyFiveMin = '45m';
|
||||||
type OneMin = '1min';
|
type OneMin = '1m';
|
||||||
type ThreeHour = '3hr';
|
type ThreeHour = '3h';
|
||||||
type SixHour = '6hr';
|
type SixHour = '6h';
|
||||||
type OneHour = '1hr';
|
type OneHour = '1h';
|
||||||
type FourHour = '4hr';
|
type FourHour = '4h';
|
||||||
type TwelveHour = '12hr';
|
type TwelveHour = '12h';
|
||||||
type OneDay = '1day';
|
type OneDay = '1d';
|
||||||
type ThreeDay = '3days';
|
type ThreeDay = '3d';
|
||||||
type FourDay = '4days';
|
type FourDay = '4d';
|
||||||
type TenDay = '10days';
|
type TenDay = '10d';
|
||||||
type OneWeek = '1week';
|
type OneWeek = '1w';
|
||||||
type TwoWeek = '2weeks';
|
type TwoWeek = '2w';
|
||||||
type SixWeek = '6weeks';
|
type SixWeek = '6w';
|
||||||
type TwoMonths = '2months';
|
type TwoMonths = '2months';
|
||||||
type Custom = 'custom';
|
type Custom = 'custom';
|
||||||
|
|
||||||
@ -44,15 +44,19 @@ export type Time =
|
|||||||
| TwoWeek
|
| TwoWeek
|
||||||
| TwoMonths;
|
| TwoMonths;
|
||||||
|
|
||||||
|
export type TimeUnit = 'm' | 'h' | 'd' | 'w';
|
||||||
|
|
||||||
|
export type CustomTimeType = `${string}${TimeUnit}`;
|
||||||
|
|
||||||
export const Options: Option[] = [
|
export const Options: Option[] = [
|
||||||
{ value: '5min', label: 'Last 5 minutes' },
|
{ value: '5m', label: 'Last 5 minutes' },
|
||||||
{ value: '15min', label: 'Last 15 minutes' },
|
{ value: '15m', label: 'Last 15 minutes' },
|
||||||
{ value: '30min', label: 'Last 30 minutes' },
|
{ value: '30m', label: 'Last 30 minutes' },
|
||||||
{ value: '1hr', label: 'Last 1 hour' },
|
{ value: '1h', label: 'Last 1 hour' },
|
||||||
{ value: '6hr', label: 'Last 6 hours' },
|
{ value: '6h', label: 'Last 6 hours' },
|
||||||
{ value: '1day', label: 'Last 1 day' },
|
{ value: '1d', label: 'Last 1 day' },
|
||||||
{ value: '3days', label: 'Last 3 days' },
|
{ value: '3d', label: 'Last 3 days' },
|
||||||
{ value: '1week', label: 'Last 1 week' },
|
{ value: '1w', label: 'Last 1 week' },
|
||||||
{ value: 'custom', label: 'Custom' },
|
{ value: 'custom', label: 'Custom' },
|
||||||
];
|
];
|
||||||
|
|
||||||
@ -61,36 +65,92 @@ export interface Option {
|
|||||||
label: string;
|
label: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const OLD_RELATIVE_TIME_VALUES = [
|
||||||
|
'1min',
|
||||||
|
'10min',
|
||||||
|
'15min',
|
||||||
|
'1hr',
|
||||||
|
'30min',
|
||||||
|
'45min',
|
||||||
|
'5min',
|
||||||
|
'1day',
|
||||||
|
'3days',
|
||||||
|
'4days',
|
||||||
|
'10days',
|
||||||
|
'1week',
|
||||||
|
'2weeks',
|
||||||
|
'6weeks',
|
||||||
|
'3hr',
|
||||||
|
'4hr',
|
||||||
|
'6hr',
|
||||||
|
'12hr',
|
||||||
|
];
|
||||||
|
|
||||||
export const RelativeDurationOptions: Option[] = [
|
export const RelativeDurationOptions: Option[] = [
|
||||||
{ value: '5min', label: 'Last 5 minutes' },
|
{ value: '5m', label: 'Last 5 minutes' },
|
||||||
{ value: '15min', label: 'Last 15 minutes' },
|
{ value: '15m', label: 'Last 15 minutes' },
|
||||||
{ value: '30min', label: 'Last 30 minutes' },
|
{ value: '30m', label: 'Last 30 minutes' },
|
||||||
{ value: '1hr', label: 'Last 1 hour' },
|
{ value: '1h', label: 'Last 1 hour' },
|
||||||
{ value: '6hr', label: 'Last 6 hour' },
|
{ value: '6h', label: 'Last 6 hour' },
|
||||||
{ value: '1day', label: 'Last 1 day' },
|
{ value: '1d', label: 'Last 1 day' },
|
||||||
{ value: '3days', label: 'Last 3 days' },
|
{ value: '3d', label: 'Last 3 days' },
|
||||||
{ value: '1week', label: 'Last 1 week' },
|
{ value: '1w', label: 'Last 1 week' },
|
||||||
];
|
];
|
||||||
|
|
||||||
export const RelativeDurationSuggestionOptions: Option[] = [
|
export const RelativeDurationSuggestionOptions: Option[] = [
|
||||||
{ value: '3hr', label: '3h' },
|
{ value: '3h', label: 'Last 3 hours' },
|
||||||
{ value: '4days', label: '4d' },
|
{ value: '4d', label: 'Last 4 days' },
|
||||||
{ value: '6weeks', label: '6w' },
|
{ value: '6w', label: 'Last 6 weeks' },
|
||||||
{ value: '12hr', label: '12 hours' },
|
{ value: '12h', label: 'Last 12 hours' },
|
||||||
{ value: '10days', label: '10d' },
|
{ value: '10d', label: 'Last 10 days' },
|
||||||
{ value: '2weeks', label: '2 weeks' },
|
{ value: '2w', label: 'Last 2 weeks' },
|
||||||
{ value: '2months', label: 'Last 2 months' },
|
{ value: '2months', label: 'Last 2 months' },
|
||||||
{ value: '1day', label: 'today' },
|
{ value: '1d', label: 'today' },
|
||||||
];
|
];
|
||||||
export const FixedDurationSuggestionOptions: Option[] = [
|
export const FixedDurationSuggestionOptions: Option[] = [
|
||||||
{ value: '45min', label: '45m' },
|
{ value: '45m', label: 'Last 45 mins' },
|
||||||
{ value: '12hr', label: '12 hours' },
|
{ value: '12h', label: 'Last 12 hours' },
|
||||||
{ value: '10days', label: '10d' },
|
{ value: '10d', label: 'Last 10 days' },
|
||||||
{ value: '2weeks', label: '2 weeks' },
|
{ value: '2w', label: 'Last 2 weeks' },
|
||||||
{ value: '2months', label: 'Last 2 months' },
|
{ value: '2months', label: 'Last 2 months' },
|
||||||
{ value: '1day', label: 'today' },
|
{ value: '1d', label: 'today' },
|
||||||
];
|
];
|
||||||
|
|
||||||
|
export const convertOldTimeToNewValidCustomTimeFormat = (
|
||||||
|
time: string,
|
||||||
|
): CustomTimeType => {
|
||||||
|
const regex = /^(\d+)([a-zA-Z]+)/;
|
||||||
|
const match = regex.exec(time);
|
||||||
|
|
||||||
|
if (match) {
|
||||||
|
let unit = 'm';
|
||||||
|
|
||||||
|
switch (match[2]) {
|
||||||
|
case 'min':
|
||||||
|
unit = 'm';
|
||||||
|
break;
|
||||||
|
case 'hr':
|
||||||
|
unit = 'h';
|
||||||
|
break;
|
||||||
|
case 'day':
|
||||||
|
case 'days':
|
||||||
|
unit = 'd';
|
||||||
|
break;
|
||||||
|
case 'week':
|
||||||
|
case 'weeks':
|
||||||
|
unit = 'w';
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return `${match[1]}${unit}` as CustomTimeType;
|
||||||
|
}
|
||||||
|
|
||||||
|
return '30m';
|
||||||
|
};
|
||||||
|
|
||||||
export const getDefaultOption = (route: string): Time => {
|
export const getDefaultOption = (route: string): Time => {
|
||||||
if (route === ROUTES.SERVICE_MAP) {
|
if (route === ROUTES.SERVICE_MAP) {
|
||||||
return RelativeDurationOptions[2].value;
|
return RelativeDurationOptions[2].value;
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
import './DateTimeSelectionV2.styles.scss';
|
import './DateTimeSelectionV2.styles.scss';
|
||||||
|
|
||||||
import { SyncOutlined } from '@ant-design/icons';
|
import { SyncOutlined } from '@ant-design/icons';
|
||||||
import { Button } from 'antd';
|
import { Color } from '@signozhq/design-tokens';
|
||||||
|
import { Button, Popover, Switch, Typography } from 'antd';
|
||||||
import getLocalStorageKey from 'api/browser/localstorage/get';
|
import getLocalStorageKey from 'api/browser/localstorage/get';
|
||||||
import setLocalStorageKey from 'api/browser/localstorage/set';
|
import setLocalStorageKey from 'api/browser/localstorage/set';
|
||||||
import CustomTimePicker from 'components/CustomTimePicker/CustomTimePicker';
|
import CustomTimePicker from 'components/CustomTimePicker/CustomTimePicker';
|
||||||
@ -26,10 +27,12 @@ import GetMinMax from 'lib/getMinMax';
|
|||||||
import getTimeString from 'lib/getTimeString';
|
import getTimeString from 'lib/getTimeString';
|
||||||
import history from 'lib/history';
|
import history from 'lib/history';
|
||||||
import { isObject } from 'lodash-es';
|
import { isObject } from 'lodash-es';
|
||||||
|
import { Check, Copy, Info, Send } from 'lucide-react';
|
||||||
import { useCallback, useEffect, useMemo, useState } from 'react';
|
import { useCallback, useEffect, useMemo, useState } from 'react';
|
||||||
import { useQueryClient } from 'react-query';
|
import { useQueryClient } from 'react-query';
|
||||||
import { connect, useSelector } from 'react-redux';
|
import { connect, useSelector } from 'react-redux';
|
||||||
import { RouteComponentProps, withRouter } from 'react-router-dom';
|
import { RouteComponentProps, withRouter } from 'react-router-dom';
|
||||||
|
import { useCopyToClipboard } from 'react-use';
|
||||||
import { bindActionCreators, Dispatch } from 'redux';
|
import { bindActionCreators, Dispatch } from 'redux';
|
||||||
import { ThunkDispatch } from 'redux-thunk';
|
import { ThunkDispatch } from 'redux-thunk';
|
||||||
import { GlobalTimeLoading, UpdateTimeInterval } from 'store/actions';
|
import { GlobalTimeLoading, UpdateTimeInterval } from 'store/actions';
|
||||||
@ -42,9 +45,12 @@ import { GlobalReducer } from 'types/reducer/globalTime';
|
|||||||
import AutoRefresh from '../AutoRefreshV2';
|
import AutoRefresh from '../AutoRefreshV2';
|
||||||
import { DateTimeRangeType } from '../CustomDateTimeModal';
|
import { DateTimeRangeType } from '../CustomDateTimeModal';
|
||||||
import {
|
import {
|
||||||
|
convertOldTimeToNewValidCustomTimeFormat,
|
||||||
|
CustomTimeType,
|
||||||
getDefaultOption,
|
getDefaultOption,
|
||||||
getOptions,
|
getOptions,
|
||||||
LocalStorageTimeRange,
|
LocalStorageTimeRange,
|
||||||
|
OLD_RELATIVE_TIME_VALUES,
|
||||||
Time,
|
Time,
|
||||||
TimeRange,
|
TimeRange,
|
||||||
} from './config';
|
} from './config';
|
||||||
@ -66,6 +72,10 @@ function DateTimeSelection({
|
|||||||
const searchStartTime = urlQuery.get('startTime');
|
const searchStartTime = urlQuery.get('startTime');
|
||||||
const searchEndTime = urlQuery.get('endTime');
|
const searchEndTime = urlQuery.get('endTime');
|
||||||
const queryClient = useQueryClient();
|
const queryClient = useQueryClient();
|
||||||
|
const [enableAbsoluteTime, setEnableAbsoluteTime] = useState(false);
|
||||||
|
const [isValidteRelativeTime, setIsValidteRelativeTime] = useState(false);
|
||||||
|
const [, handleCopyToClipboard] = useCopyToClipboard();
|
||||||
|
const [isURLCopied, setIsURLCopied] = useState(false);
|
||||||
|
|
||||||
const {
|
const {
|
||||||
localstorageStartTime,
|
localstorageStartTime,
|
||||||
@ -178,7 +188,7 @@ function DateTimeSelection({
|
|||||||
const getInputLabel = (
|
const getInputLabel = (
|
||||||
startTime?: Dayjs,
|
startTime?: Dayjs,
|
||||||
endTime?: Dayjs,
|
endTime?: Dayjs,
|
||||||
timeInterval: Time = '15min',
|
timeInterval: Time | CustomTimeType = '15m',
|
||||||
): string | Time => {
|
): string | Time => {
|
||||||
if (startTime && endTime && timeInterval === 'custom') {
|
if (startTime && endTime && timeInterval === 'custom') {
|
||||||
const format = 'DD/MM/YYYY HH:mm';
|
const format = 'DD/MM/YYYY HH:mm';
|
||||||
@ -284,28 +294,38 @@ function DateTimeSelection({
|
|||||||
[location.pathname],
|
[location.pathname],
|
||||||
);
|
);
|
||||||
|
|
||||||
const onSelectHandler = (value: Time): void => {
|
const onSelectHandler = (value: Time | CustomTimeType): void => {
|
||||||
if (value !== 'custom') {
|
if (value !== 'custom') {
|
||||||
setIsOpen(false);
|
setIsOpen(false);
|
||||||
updateTimeInterval(value);
|
updateTimeInterval(value);
|
||||||
updateLocalStorageForRoutes(value);
|
updateLocalStorageForRoutes(value);
|
||||||
|
setIsValidteRelativeTime(true);
|
||||||
if (refreshButtonHidden) {
|
if (refreshButtonHidden) {
|
||||||
setRefreshButtonHidden(false);
|
setRefreshButtonHidden(false);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
setRefreshButtonHidden(true);
|
setRefreshButtonHidden(true);
|
||||||
setCustomDTPickerVisible(true);
|
setCustomDTPickerVisible(true);
|
||||||
|
setIsValidteRelativeTime(false);
|
||||||
|
setEnableAbsoluteTime(false);
|
||||||
|
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { maxTime, minTime } = GetMinMax(value, getTime());
|
const { maxTime, minTime } = GetMinMax(value, getTime());
|
||||||
|
|
||||||
if (!isLogsExplorerPage) {
|
if (!isLogsExplorerPage) {
|
||||||
urlQuery.set(QueryParams.startTime, minTime.toString());
|
urlQuery.delete('startTime');
|
||||||
urlQuery.set(QueryParams.endTime, maxTime.toString());
|
urlQuery.delete('endTime');
|
||||||
|
|
||||||
|
urlQuery.set(QueryParams.relativeTime, value);
|
||||||
|
|
||||||
const generatedUrl = `${location.pathname}?${urlQuery.toString()}`;
|
const generatedUrl = `${location.pathname}?${urlQuery.toString()}`;
|
||||||
history.replace(generatedUrl);
|
history.replace(generatedUrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// For logs explorer - time range handling is managed in useCopyLogLink.ts:52
|
||||||
|
|
||||||
if (!stagedQuery) {
|
if (!stagedQuery) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -319,18 +339,22 @@ function DateTimeSelection({
|
|||||||
};
|
};
|
||||||
|
|
||||||
const onCustomDateHandler = (dateTimeRange: DateTimeRangeType): void => {
|
const onCustomDateHandler = (dateTimeRange: DateTimeRangeType): void => {
|
||||||
|
// console.log('dateTimeRange', dateTimeRange);
|
||||||
if (dateTimeRange !== null) {
|
if (dateTimeRange !== null) {
|
||||||
const [startTimeMoment, endTimeMoment] = dateTimeRange;
|
const [startTimeMoment, endTimeMoment] = dateTimeRange;
|
||||||
if (startTimeMoment && endTimeMoment) {
|
if (startTimeMoment && endTimeMoment) {
|
||||||
const startTime = startTimeMoment;
|
const startTime = startTimeMoment;
|
||||||
const endTime = endTimeMoment;
|
const endTime = endTimeMoment;
|
||||||
setCustomDTPickerVisible(false);
|
setCustomDTPickerVisible(false);
|
||||||
|
|
||||||
updateTimeInterval('custom', [
|
updateTimeInterval('custom', [
|
||||||
startTime.toDate().getTime(),
|
startTime.toDate().getTime(),
|
||||||
endTime.toDate().getTime(),
|
endTime.toDate().getTime(),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
setLocalStorageKey('startTime', startTime.toString());
|
setLocalStorageKey('startTime', startTime.toString());
|
||||||
setLocalStorageKey('endTime', endTime.toString());
|
setLocalStorageKey('endTime', endTime.toString());
|
||||||
|
|
||||||
updateLocalStorageForRoutes(JSON.stringify({ startTime, endTime }));
|
updateLocalStorageForRoutes(JSON.stringify({ startTime, endTime }));
|
||||||
|
|
||||||
if (!isLogsExplorerPage) {
|
if (!isLogsExplorerPage) {
|
||||||
@ -339,6 +363,7 @@ function DateTimeSelection({
|
|||||||
startTime?.toDate().getTime().toString(),
|
startTime?.toDate().getTime().toString(),
|
||||||
);
|
);
|
||||||
urlQuery.set(QueryParams.endTime, endTime?.toDate().getTime().toString());
|
urlQuery.set(QueryParams.endTime, endTime?.toDate().getTime().toString());
|
||||||
|
urlQuery.delete(QueryParams.relativeTime);
|
||||||
const generatedUrl = `${location.pathname}?${urlQuery.toString()}`;
|
const generatedUrl = `${location.pathname}?${urlQuery.toString()}`;
|
||||||
history.replace(generatedUrl);
|
history.replace(generatedUrl);
|
||||||
}
|
}
|
||||||
@ -346,6 +371,57 @@ function DateTimeSelection({
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const onValidCustomDateHandler = (dateTimeStr: CustomTimeType): void => {
|
||||||
|
setIsOpen(false);
|
||||||
|
updateTimeInterval(dateTimeStr);
|
||||||
|
updateLocalStorageForRoutes(dateTimeStr);
|
||||||
|
|
||||||
|
urlQuery.delete('startTime');
|
||||||
|
urlQuery.delete('endTime');
|
||||||
|
|
||||||
|
setIsValidteRelativeTime(true);
|
||||||
|
|
||||||
|
const { maxTime, minTime } = GetMinMax(dateTimeStr, getTime());
|
||||||
|
|
||||||
|
if (!isLogsExplorerPage) {
|
||||||
|
urlQuery.delete('startTime');
|
||||||
|
urlQuery.delete('endTime');
|
||||||
|
|
||||||
|
urlQuery.set(QueryParams.relativeTime, dateTimeStr);
|
||||||
|
|
||||||
|
const generatedUrl = `${location.pathname}?${urlQuery.toString()}`;
|
||||||
|
history.replace(generatedUrl);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!stagedQuery) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// the second boolean param directs the qb about the time change so to merge the query and retain the current state
|
||||||
|
initQueryBuilderData(updateStepInterval(stagedQuery, maxTime, minTime), true);
|
||||||
|
};
|
||||||
|
|
||||||
|
const getCustomOrIntervalTime = (
|
||||||
|
time: Time,
|
||||||
|
currentRoute: string,
|
||||||
|
): Time | CustomTimeType => {
|
||||||
|
if (searchEndTime !== null && searchStartTime !== null) {
|
||||||
|
return 'custom';
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
(localstorageEndTime === null || localstorageStartTime === null) &&
|
||||||
|
time === 'custom'
|
||||||
|
) {
|
||||||
|
return getDefaultOption(currentRoute);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (OLD_RELATIVE_TIME_VALUES.indexOf(time) > -1) {
|
||||||
|
return convertOldTimeToNewValidCustomTimeFormat(time);
|
||||||
|
}
|
||||||
|
|
||||||
|
return time;
|
||||||
|
};
|
||||||
|
|
||||||
// this is triggred when we change the routes and based on that we are changing the default options
|
// this is triggred when we change the routes and based on that we are changing the default options
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const metricsTimeDuration = getLocalStorageKey(
|
const metricsTimeDuration = getLocalStorageKey(
|
||||||
@ -365,21 +441,9 @@ function DateTimeSelection({
|
|||||||
const currentOptions = getOptions(currentRoute);
|
const currentOptions = getOptions(currentRoute);
|
||||||
setOptions(currentOptions);
|
setOptions(currentOptions);
|
||||||
|
|
||||||
const getCustomOrIntervalTime = (time: Time): Time => {
|
const updatedTime = getCustomOrIntervalTime(time, currentRoute);
|
||||||
if (searchEndTime !== null && searchStartTime !== null) {
|
|
||||||
return 'custom';
|
|
||||||
}
|
|
||||||
if (
|
|
||||||
(localstorageEndTime === null || localstorageStartTime === null) &&
|
|
||||||
time === 'custom'
|
|
||||||
) {
|
|
||||||
return getDefaultOption(currentRoute);
|
|
||||||
}
|
|
||||||
|
|
||||||
return time;
|
setIsValidteRelativeTime(updatedTime !== 'custom');
|
||||||
};
|
|
||||||
|
|
||||||
const updatedTime = getCustomOrIntervalTime(time);
|
|
||||||
|
|
||||||
const [preStartTime = 0, preEndTime = 0] = getTime() || [];
|
const [preStartTime = 0, preEndTime = 0] = getTime() || [];
|
||||||
|
|
||||||
@ -388,18 +452,113 @@ function DateTimeSelection({
|
|||||||
updateTimeInterval(updatedTime, [preStartTime, preEndTime]);
|
updateTimeInterval(updatedTime, [preStartTime, preEndTime]);
|
||||||
|
|
||||||
if (updatedTime !== 'custom') {
|
if (updatedTime !== 'custom') {
|
||||||
const { minTime, maxTime } = GetMinMax(updatedTime);
|
urlQuery.delete('startTime');
|
||||||
urlQuery.set(QueryParams.startTime, minTime.toString());
|
urlQuery.delete('endTime');
|
||||||
urlQuery.set(QueryParams.endTime, maxTime.toString());
|
|
||||||
|
urlQuery.set(QueryParams.relativeTime, updatedTime);
|
||||||
} else {
|
} else {
|
||||||
urlQuery.set(QueryParams.startTime, preStartTime.toString());
|
const startTime = preStartTime.toString();
|
||||||
urlQuery.set(QueryParams.endTime, preEndTime.toString());
|
const endTime = preEndTime.toString();
|
||||||
|
|
||||||
|
urlQuery.set(QueryParams.startTime, startTime);
|
||||||
|
urlQuery.set(QueryParams.endTime, endTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
const generatedUrl = `${location.pathname}?${urlQuery.toString()}`;
|
const generatedUrl = `${location.pathname}?${urlQuery.toString()}`;
|
||||||
|
|
||||||
history.replace(generatedUrl);
|
history.replace(generatedUrl);
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [location.pathname, updateTimeInterval, globalTimeLoading]);
|
}, [location.pathname, updateTimeInterval, globalTimeLoading]);
|
||||||
|
|
||||||
|
// eslint-disable-next-line sonarjs/cognitive-complexity
|
||||||
|
const shareModalContent = (): JSX.Element => {
|
||||||
|
let currentUrl = window.location.href;
|
||||||
|
|
||||||
|
const startTime = urlQuery.get(QueryParams.startTime);
|
||||||
|
const endTime = urlQuery.get(QueryParams.endTime);
|
||||||
|
const isCustomTime = !!(startTime && endTime && selectedTime === 'custom');
|
||||||
|
|
||||||
|
if (enableAbsoluteTime || isCustomTime) {
|
||||||
|
if (selectedTime === 'custom') {
|
||||||
|
if (searchStartTime && searchEndTime) {
|
||||||
|
urlQuery.set(QueryParams.startTime, searchStartTime.toString());
|
||||||
|
urlQuery.set(QueryParams.endTime, searchEndTime.toString());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const { minTime, maxTime } = GetMinMax(selectedTime);
|
||||||
|
|
||||||
|
urlQuery.set(QueryParams.startTime, minTime.toString());
|
||||||
|
urlQuery.set(QueryParams.endTime, maxTime.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
urlQuery.delete(QueryParams.relativeTime);
|
||||||
|
|
||||||
|
currentUrl = `${window.location.origin}${
|
||||||
|
location.pathname
|
||||||
|
}?${urlQuery.toString()}`;
|
||||||
|
} else {
|
||||||
|
urlQuery.delete(QueryParams.startTime);
|
||||||
|
urlQuery.delete(QueryParams.endTime);
|
||||||
|
|
||||||
|
urlQuery.set(QueryParams.relativeTime, selectedTime);
|
||||||
|
currentUrl = `${window.location.origin}${
|
||||||
|
location.pathname
|
||||||
|
}?${urlQuery.toString()}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="share-modal-content">
|
||||||
|
<div className="absolute-relative-time-toggler-container">
|
||||||
|
<div className="absolute-relative-time-toggler">
|
||||||
|
{(selectedTime === 'custom' || !isValidteRelativeTime) && (
|
||||||
|
<Info size={14} color={Color.BG_AMBER_600} />
|
||||||
|
)}
|
||||||
|
<Switch
|
||||||
|
checked={enableAbsoluteTime || isCustomTime}
|
||||||
|
disabled={selectedTime === 'custom' || !isValidteRelativeTime}
|
||||||
|
size="small"
|
||||||
|
onChange={(): void => {
|
||||||
|
setEnableAbsoluteTime(!enableAbsoluteTime);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Typography.Text>Enable Absolute Time</Typography.Text>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{(selectedTime === 'custom' || !isValidteRelativeTime) && (
|
||||||
|
<div className="absolute-relative-time-error">
|
||||||
|
Please select / enter valid relative time to toggle.
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<div className="share-link">
|
||||||
|
<Typography.Text ellipsis className="share-url">
|
||||||
|
{currentUrl}
|
||||||
|
</Typography.Text>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
className="periscope-btn copy-url-btn"
|
||||||
|
onClick={(): void => {
|
||||||
|
handleCopyToClipboard(currentUrl);
|
||||||
|
setIsURLCopied(true);
|
||||||
|
setTimeout(() => {
|
||||||
|
setIsURLCopied(false);
|
||||||
|
}, 1000);
|
||||||
|
}}
|
||||||
|
icon={
|
||||||
|
isURLCopied ? (
|
||||||
|
<Check size={14} color={Color.BG_FOREST_500} />
|
||||||
|
) : (
|
||||||
|
<Copy size={14} color={Color.BG_ROBIN_500} />
|
||||||
|
)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="date-time-selector">
|
<div className="date-time-selector">
|
||||||
{!hasSelectedTimeError && !refreshButtonHidden && (
|
{!hasSelectedTimeError && !refreshButtonHidden && (
|
||||||
@ -426,9 +585,12 @@ function DateTimeSelection({
|
|||||||
setHasSelectedTimeError(hasError);
|
setHasSelectedTimeError(hasError);
|
||||||
}}
|
}}
|
||||||
selectedTime={selectedTime}
|
selectedTime={selectedTime}
|
||||||
onValidCustomDateChange={(dateTime): void =>
|
onValidCustomDateChange={(dateTime): void => {
|
||||||
onCustomDateHandler(dateTime as DateTimeRangeType)
|
onValidCustomDateHandler(dateTime.timeStr as CustomTimeType);
|
||||||
}
|
}}
|
||||||
|
onCustomTimeStatusUpdate={(isValid: boolean): void => {
|
||||||
|
setIsValidteRelativeTime(isValid);
|
||||||
|
}}
|
||||||
selectedValue={getInputLabel(
|
selectedValue={getInputLabel(
|
||||||
dayjs(minTime / 1000000),
|
dayjs(minTime / 1000000),
|
||||||
dayjs(maxTime / 1000000),
|
dayjs(maxTime / 1000000),
|
||||||
@ -457,6 +619,22 @@ function DateTimeSelection({
|
|||||||
</FormItem>
|
</FormItem>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
<Popover
|
||||||
|
rootClassName="shareable-link-popover-root"
|
||||||
|
className="shareable-link-popover"
|
||||||
|
placement="bottomRight"
|
||||||
|
content={shareModalContent}
|
||||||
|
arrow={false}
|
||||||
|
trigger={['hover']}
|
||||||
|
>
|
||||||
|
<Button
|
||||||
|
className="share-link-btn periscope-btn"
|
||||||
|
icon={<Send size={14} />}
|
||||||
|
>
|
||||||
|
Share
|
||||||
|
</Button>
|
||||||
|
</Popover>
|
||||||
</FormContainer>
|
</FormContainer>
|
||||||
</Form>
|
</Form>
|
||||||
</div>
|
</div>
|
||||||
@ -468,7 +646,7 @@ interface DateTimeSelectionV2Props {
|
|||||||
}
|
}
|
||||||
interface DispatchProps {
|
interface DispatchProps {
|
||||||
updateTimeInterval: (
|
updateTimeInterval: (
|
||||||
interval: Time,
|
interval: Time | CustomTimeType,
|
||||||
dateTimeRange?: [number, number],
|
dateTimeRange?: [number, number],
|
||||||
) => (dispatch: Dispatch<AppActions>) => void;
|
) => (dispatch: Dispatch<AppActions>) => void;
|
||||||
globalTimeLoading: () => void;
|
globalTimeLoading: () => void;
|
||||||
|
@ -11,8 +11,11 @@ import {
|
|||||||
useMemo,
|
useMemo,
|
||||||
useState,
|
useState,
|
||||||
} from 'react';
|
} from 'react';
|
||||||
|
import { useSelector } from 'react-redux';
|
||||||
import { useLocation } from 'react-router-dom';
|
import { useLocation } from 'react-router-dom';
|
||||||
import { useCopyToClipboard } from 'react-use';
|
import { useCopyToClipboard } from 'react-use';
|
||||||
|
import { AppState } from 'store/reducers';
|
||||||
|
import { GlobalReducer } from 'types/reducer/globalTime';
|
||||||
|
|
||||||
import { HIGHLIGHTED_DELAY } from './configs';
|
import { HIGHLIGHTED_DELAY } from './configs';
|
||||||
import { LogTimeRange, UseCopyLogLink } from './types';
|
import { LogTimeRange, UseCopyLogLink } from './types';
|
||||||
@ -33,15 +36,30 @@ export const useCopyLogLink = (logId?: string): UseCopyLogLink => {
|
|||||||
null,
|
null,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const { selectedTime } = useSelector<AppState, GlobalReducer>(
|
||||||
|
(state) => state.globalTime,
|
||||||
|
);
|
||||||
|
|
||||||
const onTimeRangeChange = useCallback(
|
const onTimeRangeChange = useCallback(
|
||||||
(newTimeRange: LogTimeRange | null): void => {
|
(newTimeRange: LogTimeRange | null): void => {
|
||||||
urlQuery.set(QueryParams.timeRange, JSON.stringify(newTimeRange));
|
urlQuery.set(QueryParams.timeRange, JSON.stringify(newTimeRange));
|
||||||
|
|
||||||
|
if (selectedTime !== 'custom') {
|
||||||
|
urlQuery.delete(QueryParams.startTime);
|
||||||
|
urlQuery.delete(QueryParams.endTime);
|
||||||
|
|
||||||
|
urlQuery.set(QueryParams.relativeTime, selectedTime);
|
||||||
|
} else {
|
||||||
urlQuery.set(QueryParams.startTime, newTimeRange?.start.toString() || '');
|
urlQuery.set(QueryParams.startTime, newTimeRange?.start.toString() || '');
|
||||||
urlQuery.set(QueryParams.endTime, newTimeRange?.end.toString() || '');
|
urlQuery.set(QueryParams.endTime, newTimeRange?.end.toString() || '');
|
||||||
|
|
||||||
|
urlQuery.delete(QueryParams.relativeTime);
|
||||||
|
}
|
||||||
|
|
||||||
const generatedUrl = `${pathname}?${urlQuery.toString()}`;
|
const generatedUrl = `${pathname}?${urlQuery.toString()}`;
|
||||||
history.replace(generatedUrl);
|
history.replace(generatedUrl);
|
||||||
},
|
},
|
||||||
[pathname, urlQuery],
|
[pathname, urlQuery, selectedTime],
|
||||||
);
|
);
|
||||||
|
|
||||||
const isActiveLog = useMemo(() => activeLogId === logId, [activeLogId, logId]);
|
const isActiveLog = useMemo(() => activeLogId === logId, [activeLogId, logId]);
|
||||||
|
@ -1,7 +1,10 @@
|
|||||||
import getService from 'api/metrics/getService';
|
import getService from 'api/metrics/getService';
|
||||||
import { AxiosError } from 'axios';
|
import { AxiosError } from 'axios';
|
||||||
import { Time } from 'container/TopNav/DateTimeSelection/config';
|
import { Time } from 'container/TopNav/DateTimeSelection/config';
|
||||||
import { Time as TimeV2 } from 'container/TopNav/DateTimeSelectionV2/config';
|
import {
|
||||||
|
CustomTimeType,
|
||||||
|
Time as TimeV2,
|
||||||
|
} from 'container/TopNav/DateTimeSelectionV2/config';
|
||||||
import {
|
import {
|
||||||
QueryKey,
|
QueryKey,
|
||||||
useQuery,
|
useQuery,
|
||||||
@ -27,7 +30,7 @@ export const useQueryService = ({
|
|||||||
interface UseQueryServiceProps {
|
interface UseQueryServiceProps {
|
||||||
minTime: number;
|
minTime: number;
|
||||||
maxTime: number;
|
maxTime: number;
|
||||||
selectedTime: Time | TimeV2;
|
selectedTime: Time | TimeV2 | CustomTimeType;
|
||||||
selectedTags: Tags[];
|
selectedTags: Tags[];
|
||||||
options?: UseQueryOptions<PayloadProps, AxiosError, PayloadProps, QueryKey>;
|
options?: UseQueryOptions<PayloadProps, AxiosError, PayloadProps, QueryKey>;
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,10 @@ import { getMetricsQueryRange } from 'api/metrics/getQueryRange';
|
|||||||
import { PANEL_TYPES } from 'constants/queryBuilder';
|
import { PANEL_TYPES } from 'constants/queryBuilder';
|
||||||
import { timePreferenceType } from 'container/NewWidget/RightContainer/timeItems';
|
import { timePreferenceType } from 'container/NewWidget/RightContainer/timeItems';
|
||||||
import { Time } from 'container/TopNav/DateTimeSelection/config';
|
import { Time } from 'container/TopNav/DateTimeSelection/config';
|
||||||
import { Time as TimeV2 } from 'container/TopNav/DateTimeSelectionV2/config';
|
import {
|
||||||
|
CustomTimeType,
|
||||||
|
Time as TimeV2,
|
||||||
|
} from 'container/TopNav/DateTimeSelectionV2/config';
|
||||||
import { Pagination } from 'hooks/queryPagination';
|
import { Pagination } from 'hooks/queryPagination';
|
||||||
import { convertNewDataToOld } from 'lib/newQueryBuilder/convertNewDataToOld';
|
import { convertNewDataToOld } from 'lib/newQueryBuilder/convertNewDataToOld';
|
||||||
import { isEmpty } from 'lodash-es';
|
import { isEmpty } from 'lodash-es';
|
||||||
@ -67,7 +70,7 @@ export interface GetQueryResultsProps {
|
|||||||
query: Query;
|
query: Query;
|
||||||
graphType: PANEL_TYPES;
|
graphType: PANEL_TYPES;
|
||||||
selectedTime: timePreferenceType;
|
selectedTime: timePreferenceType;
|
||||||
globalSelectedInterval: Time | TimeV2;
|
globalSelectedInterval: Time | TimeV2 | CustomTimeType;
|
||||||
variables?: Record<string, unknown>;
|
variables?: Record<string, unknown>;
|
||||||
params?: Record<string, unknown>;
|
params?: Record<string, unknown>;
|
||||||
tableParams?: {
|
tableParams?: {
|
||||||
|
@ -1,63 +1,101 @@
|
|||||||
import { Time } from 'container/TopNav/DateTimeSelection/config';
|
import { Time } from 'container/TopNav/DateTimeSelection/config';
|
||||||
import { Time as TimeV2 } from 'container/TopNav/DateTimeSelectionV2/config';
|
import { Time as TimeV2 } from 'container/TopNav/DateTimeSelectionV2/config';
|
||||||
|
import { isString } from 'lodash-es';
|
||||||
import { GlobalReducer } from 'types/reducer/globalTime';
|
import { GlobalReducer } from 'types/reducer/globalTime';
|
||||||
|
|
||||||
import getMinAgo from './getStartAndEndTime/getMinAgo';
|
import getMinAgo from './getStartAndEndTime/getMinAgo';
|
||||||
|
|
||||||
|
const validCustomTimeRegex = /^(\d+)([mhdw])$/;
|
||||||
|
|
||||||
|
export const isValidTimeFormat = (time: string): boolean =>
|
||||||
|
validCustomTimeRegex.test(time);
|
||||||
|
|
||||||
|
const extractTimeAndUnit = (time: string): { time: number; unit: string } => {
|
||||||
|
// Match the pattern
|
||||||
|
const match = /^(\d+)([mhdw])$/.exec(time);
|
||||||
|
|
||||||
|
if (match) {
|
||||||
|
return { time: parseInt(match[1], 10), unit: match[2] };
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
time: 30,
|
||||||
|
unit: 'm',
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getMinTimeForRelativeTimes = (
|
||||||
|
time: number,
|
||||||
|
unit: string,
|
||||||
|
): number => {
|
||||||
|
switch (unit) {
|
||||||
|
case 'm':
|
||||||
|
return getMinAgo({ minutes: 1 * time }).getTime();
|
||||||
|
case 'h':
|
||||||
|
return getMinAgo({ minutes: 60 * time }).getTime();
|
||||||
|
case 'd':
|
||||||
|
return getMinAgo({ minutes: 24 * 60 * time }).getTime();
|
||||||
|
case 'w':
|
||||||
|
return getMinAgo({ minutes: 24 * 60 * 7 * time }).getTime();
|
||||||
|
default:
|
||||||
|
return getMinAgo({ minutes: 1 }).getTime();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const GetMinMax = (
|
const GetMinMax = (
|
||||||
interval: Time | TimeV2,
|
interval: Time | TimeV2 | string,
|
||||||
dateTimeRange?: [number, number],
|
dateTimeRange?: [number, number],
|
||||||
// eslint-disable-next-line sonarjs/cognitive-complexity
|
// eslint-disable-next-line sonarjs/cognitive-complexity
|
||||||
): GetMinMaxPayload => {
|
): GetMinMaxPayload => {
|
||||||
let maxTime = new Date().getTime();
|
let maxTime = new Date().getTime();
|
||||||
let minTime = 0;
|
let minTime = 0;
|
||||||
|
|
||||||
if (interval === '1min') {
|
if (interval === '1m') {
|
||||||
const minTimeAgo = getMinAgo({ minutes: 1 }).getTime();
|
const minTimeAgo = getMinAgo({ minutes: 1 }).getTime();
|
||||||
minTime = minTimeAgo;
|
minTime = minTimeAgo;
|
||||||
} else if (interval === '10min') {
|
} else if (interval === '10m') {
|
||||||
const minTimeAgo = getMinAgo({ minutes: 10 }).getTime();
|
const minTimeAgo = getMinAgo({ minutes: 10 }).getTime();
|
||||||
minTime = minTimeAgo;
|
minTime = minTimeAgo;
|
||||||
} else if (interval === '15min') {
|
} else if (interval === '15m') {
|
||||||
const minTimeAgo = getMinAgo({ minutes: 15 }).getTime();
|
const minTimeAgo = getMinAgo({ minutes: 15 }).getTime();
|
||||||
minTime = minTimeAgo;
|
minTime = minTimeAgo;
|
||||||
} else if (interval === '1hr') {
|
} else if (interval === '1h') {
|
||||||
const minTimeAgo = getMinAgo({ minutes: 60 }).getTime();
|
const minTimeAgo = getMinAgo({ minutes: 60 }).getTime();
|
||||||
minTime = minTimeAgo;
|
minTime = minTimeAgo;
|
||||||
} else if (interval === '30min') {
|
} else if (interval === '30m') {
|
||||||
const minTimeAgo = getMinAgo({ minutes: 30 }).getTime();
|
const minTimeAgo = getMinAgo({ minutes: 30 }).getTime();
|
||||||
minTime = minTimeAgo;
|
minTime = minTimeAgo;
|
||||||
} else if (interval === '45min') {
|
} else if (interval === '45m') {
|
||||||
const minTimeAgo = getMinAgo({ minutes: 45 }).getTime();
|
const minTimeAgo = getMinAgo({ minutes: 45 }).getTime();
|
||||||
minTime = minTimeAgo;
|
minTime = minTimeAgo;
|
||||||
} else if (interval === '5min') {
|
} else if (interval === '5m') {
|
||||||
const minTimeAgo = getMinAgo({ minutes: 5 }).getTime();
|
const minTimeAgo = getMinAgo({ minutes: 5 }).getTime();
|
||||||
minTime = minTimeAgo;
|
minTime = minTimeAgo;
|
||||||
} else if (interval === '1day') {
|
} else if (interval === '1d') {
|
||||||
// one day = 24*60(min)
|
// one day = 24*60(min)
|
||||||
const minTimeAgo = getMinAgo({ minutes: 24 * 60 }).getTime();
|
const minTimeAgo = getMinAgo({ minutes: 24 * 60 }).getTime();
|
||||||
minTime = minTimeAgo;
|
minTime = minTimeAgo;
|
||||||
} else if (interval === '3days') {
|
} else if (interval === '3d') {
|
||||||
// three day = one day * 3
|
// three day = one day * 3
|
||||||
const minTimeAgo = getMinAgo({ minutes: 24 * 60 * 3 }).getTime();
|
const minTimeAgo = getMinAgo({ minutes: 24 * 60 * 3 }).getTime();
|
||||||
minTime = minTimeAgo;
|
minTime = minTimeAgo;
|
||||||
} else if (interval === '4days') {
|
} else if (interval === '4d') {
|
||||||
// four day = one day * 4
|
// four day = one day * 4
|
||||||
const minTimeAgo = getMinAgo({ minutes: 24 * 60 * 4 }).getTime();
|
const minTimeAgo = getMinAgo({ minutes: 24 * 60 * 4 }).getTime();
|
||||||
minTime = minTimeAgo;
|
minTime = minTimeAgo;
|
||||||
} else if (interval === '10days') {
|
} else if (interval === '10d') {
|
||||||
// ten day = one day * 10
|
// ten day = one day * 10
|
||||||
const minTimeAgo = getMinAgo({ minutes: 24 * 60 * 10 }).getTime();
|
const minTimeAgo = getMinAgo({ minutes: 24 * 60 * 10 }).getTime();
|
||||||
minTime = minTimeAgo;
|
minTime = minTimeAgo;
|
||||||
} else if (interval === '1week') {
|
} else if (interval === '1w') {
|
||||||
// one week = one day * 7
|
// one week = one day * 7
|
||||||
const minTimeAgo = getMinAgo({ minutes: 24 * 60 * 7 }).getTime();
|
const minTimeAgo = getMinAgo({ minutes: 24 * 60 * 7 }).getTime();
|
||||||
minTime = minTimeAgo;
|
minTime = minTimeAgo;
|
||||||
} else if (interval === '2weeks') {
|
} else if (interval === '2w') {
|
||||||
// two week = one day * 14
|
// two week = one day * 14
|
||||||
const minTimeAgo = getMinAgo({ minutes: 24 * 60 * 14 }).getTime();
|
const minTimeAgo = getMinAgo({ minutes: 24 * 60 * 14 }).getTime();
|
||||||
minTime = minTimeAgo;
|
minTime = minTimeAgo;
|
||||||
} else if (interval === '6weeks') {
|
} else if (interval === '6w') {
|
||||||
// six week = one day * 42
|
// six week = one day * 42
|
||||||
const minTimeAgo = getMinAgo({ minutes: 24 * 60 * 42 }).getTime();
|
const minTimeAgo = getMinAgo({ minutes: 24 * 60 * 42 }).getTime();
|
||||||
minTime = minTimeAgo;
|
minTime = minTimeAgo;
|
||||||
@ -65,13 +103,17 @@ const GetMinMax = (
|
|||||||
// two months = one day * 60
|
// two months = one day * 60
|
||||||
const minTimeAgo = getMinAgo({ minutes: 24 * 60 * 60 }).getTime();
|
const minTimeAgo = getMinAgo({ minutes: 24 * 60 * 60 }).getTime();
|
||||||
minTime = minTimeAgo;
|
minTime = minTimeAgo;
|
||||||
} else if (['3hr', '4hr', '6hr', '12hr'].includes(interval)) {
|
} else if (['3h', '4h', '6h', '12h'].includes(interval)) {
|
||||||
const h = parseInt(interval.replace('hr', ''), 10);
|
const h = parseInt(interval.replace('h', ''), 10);
|
||||||
const minTimeAgo = getMinAgo({ minutes: h * 60 }).getTime();
|
const minTimeAgo = getMinAgo({ minutes: h * 60 }).getTime();
|
||||||
minTime = minTimeAgo;
|
minTime = minTimeAgo;
|
||||||
} else if (interval === 'custom') {
|
} else if (interval === 'custom') {
|
||||||
maxTime = (dateTimeRange || [])[1] || 0;
|
maxTime = (dateTimeRange || [])[1] || 0;
|
||||||
minTime = (dateTimeRange || [])[0] || 0;
|
minTime = (dateTimeRange || [])[0] || 0;
|
||||||
|
} else if (isString(interval) && isValidTimeFormat(interval)) {
|
||||||
|
const { time, unit } = extractTimeAndUnit(interval);
|
||||||
|
|
||||||
|
minTime = getMinTimeForRelativeTimes(time, unit);
|
||||||
} else {
|
} else {
|
||||||
throw new Error('invalid time type');
|
throw new Error('invalid time type');
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,10 @@
|
|||||||
import { PANEL_TYPES } from 'constants/queryBuilder';
|
import { PANEL_TYPES } from 'constants/queryBuilder';
|
||||||
import { timePreferenceType } from 'container/NewWidget/RightContainer/timeItems';
|
import { timePreferenceType } from 'container/NewWidget/RightContainer/timeItems';
|
||||||
import { Time } from 'container/TopNav/DateTimeSelection/config';
|
import { Time } from 'container/TopNav/DateTimeSelection/config';
|
||||||
import { Time as TimeV2 } from 'container/TopNav/DateTimeSelectionV2/config';
|
import {
|
||||||
|
CustomTimeType,
|
||||||
|
Time as TimeV2,
|
||||||
|
} from 'container/TopNav/DateTimeSelectionV2/config';
|
||||||
import store from 'store';
|
import store from 'store';
|
||||||
|
|
||||||
import getMaxMinTime from './getMaxMinTime';
|
import getMaxMinTime from './getMaxMinTime';
|
||||||
@ -38,7 +41,7 @@ const getStartEndRangeTime = ({
|
|||||||
interface GetStartEndRangeTimesProps {
|
interface GetStartEndRangeTimesProps {
|
||||||
type?: timePreferenceType;
|
type?: timePreferenceType;
|
||||||
graphType?: PANEL_TYPES | null;
|
graphType?: PANEL_TYPES | null;
|
||||||
interval?: Time | TimeV2;
|
interval?: Time | TimeV2 | CustomTimeType;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface GetStartEndRangeTimesPayload {
|
interface GetStartEndRangeTimesPayload {
|
||||||
|
@ -1,12 +1,15 @@
|
|||||||
import { Time } from 'container/TopNav/DateTimeSelection/config';
|
import { Time } from 'container/TopNav/DateTimeSelection/config';
|
||||||
import { Time as TimeV2 } from 'container/TopNav/DateTimeSelectionV2/config';
|
import {
|
||||||
|
CustomTimeType,
|
||||||
|
Time as TimeV2,
|
||||||
|
} from 'container/TopNav/DateTimeSelectionV2/config';
|
||||||
import GetMinMax from 'lib/getMinMax';
|
import GetMinMax from 'lib/getMinMax';
|
||||||
import { Dispatch } from 'redux';
|
import { Dispatch } from 'redux';
|
||||||
import AppActions from 'types/actions';
|
import AppActions from 'types/actions';
|
||||||
import { UPDATE_TIME_INTERVAL } from 'types/actions/globalTime';
|
import { UPDATE_TIME_INTERVAL } from 'types/actions/globalTime';
|
||||||
|
|
||||||
export const UpdateTimeInterval = (
|
export const UpdateTimeInterval = (
|
||||||
interval: Time | TimeV2,
|
interval: Time | TimeV2 | CustomTimeType,
|
||||||
dateTimeRange: [number, number] = [0, 0],
|
dateTimeRange: [number, number] = [0, 0],
|
||||||
): ((dispatch: Dispatch<AppActions>) => void) => (
|
): ((dispatch: Dispatch<AppActions>) => void) => (
|
||||||
dispatch: Dispatch<AppActions>,
|
dispatch: Dispatch<AppActions>,
|
||||||
|
@ -88,4 +88,7 @@ export const getFilter = (data: GetFilterPayload): TraceReducer['filter'] => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const stripTimestampsFromQuery = (query: string): string =>
|
export const stripTimestampsFromQuery = (query: string): string =>
|
||||||
query.replace(/(\?|&)startTime=\d+/, '').replace(/&endTime=\d+/, '');
|
query
|
||||||
|
.replace(/(\?|&)startTime=\d+/, '')
|
||||||
|
.replace(/&endTime=\d+/, '')
|
||||||
|
.replace(/[?&]relativeTime=[^&]+/g, '');
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
import { Time } from 'container/TopNav/DateTimeSelection/config';
|
import { Time } from 'container/TopNav/DateTimeSelection/config';
|
||||||
import { Time as TimeV2 } from 'container/TopNav/DateTimeSelectionV2/config';
|
import {
|
||||||
|
CustomTimeType,
|
||||||
|
Time as TimeV2,
|
||||||
|
} from 'container/TopNav/DateTimeSelectionV2/config';
|
||||||
|
|
||||||
import { ResetIdStartAndEnd, SetSearchQueryString } from './logs';
|
import { ResetIdStartAndEnd, SetSearchQueryString } from './logs';
|
||||||
|
|
||||||
@ -14,7 +17,7 @@ export type GlobalTime = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
interface UpdateTime extends GlobalTime {
|
interface UpdateTime extends GlobalTime {
|
||||||
selectedTime: Time | TimeV2;
|
selectedTime: Time | TimeV2 | CustomTimeType;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface UpdateTimeInterval {
|
interface UpdateTimeInterval {
|
||||||
|
@ -1,12 +1,15 @@
|
|||||||
import { Time } from 'container/TopNav/DateTimeSelection/config';
|
import { Time } from 'container/TopNav/DateTimeSelection/config';
|
||||||
import { Time as TimeV2 } from 'container/TopNav/DateTimeSelectionV2/config';
|
import {
|
||||||
|
CustomTimeType,
|
||||||
|
Time as TimeV2,
|
||||||
|
} from 'container/TopNav/DateTimeSelectionV2/config';
|
||||||
import { GlobalTime } from 'types/actions/globalTime';
|
import { GlobalTime } from 'types/actions/globalTime';
|
||||||
|
|
||||||
export interface GlobalReducer {
|
export interface GlobalReducer {
|
||||||
maxTime: GlobalTime['maxTime'];
|
maxTime: GlobalTime['maxTime'];
|
||||||
minTime: GlobalTime['minTime'];
|
minTime: GlobalTime['minTime'];
|
||||||
loading: boolean;
|
loading: boolean;
|
||||||
selectedTime: Time | TimeV2;
|
selectedTime: Time | TimeV2 | CustomTimeType;
|
||||||
isAutoRefreshDisabled: boolean;
|
isAutoRefreshDisabled: boolean;
|
||||||
selectedAutoRefreshInterval: string;
|
selectedAutoRefreshInterval: string;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user