diff --git a/packages/main/src/components/LabelBrowser/components/QueryBar/QueryBar.tsx b/packages/main/src/components/LabelBrowser/components/QueryBar/QueryBar.tsx index ce942fa8..8962c133 100644 --- a/packages/main/src/components/LabelBrowser/components/QueryBar/QueryBar.tsx +++ b/packages/main/src/components/LabelBrowser/components/QueryBar/QueryBar.tsx @@ -205,140 +205,6 @@ const QueryBar: React.FC = (props) => { // force single view from small width - useEffect(() => { - setQueryInput(data.expr); - setQueryValue([{ children: [{ text: sanitizeWithSigns(data.expr) }] }]); - }, [data.expr]); - - useEffect(() => { - let queryText = queryValue[0].children[0].text; - setQueryInput(queryText); - }, [queryValue]); - - useEffect(() => { - if (isTabletOrMobile && isSplit) { - dispatch(setSplitView(false)); - } - }, [isTabletOrMobile]); - - useEffect(() => { - let { expr } = getLocalQueryItem(dataSourceId, id); - let actLocalDs = getLocalDataSources(dataSourceId); - setQueryInput(expr); - setQueryValue([{ children: [{ text: sanitizeWithSigns(expr) }] }]); - - if (isLogsVolume && logsVolumeQuery) { - setLogsLevel(expr, isLogsVolume); - } - const dataSource: any = dataSources?.find( - (f: any) => f.id === dataSourceId - ); - - let currentDataSource: any = {}; - - if ( - actLocalDs && - actLocalDs?.url !== initialDefault && - actLocalDs?.url !== "" - ) { - currentDataSource = { ...actLocalDs }; - - const panelCP = [...panelData]; - - panelCP.forEach((query) => { - if (query.id === id) { - query.dataSourceId = currentDataSource.id; - query.dataSourceType = currentDataSource.type; - query.dataSourceURL = currentDataSource.url; - } - }); - - dispatch(panelAction(name, panelCP)); - - const dsCopy = [...dataSources]; - dsCopy.forEach((ds) => { - if (ds.id === dataSourceId) { - ds = currentDataSource; - } - }); - - dispatch(setDataSources(dsCopy)); - } else if (dataSource && dataSource.url !== "") { - currentDataSource = { ...dataSource }; - } - - let { isMatrix } = getIntvalData(expr); - if (expr !== "" && expr?.length > 6) { - dispatch( - getData( - dataSourceType, - expr, - queryType, - limit, - name, - id, - direction, - dataSourceId, - currentDataSource?.url - ) - ); - } - - // setLogsLevel(queryInput, isLogsVolume); - if ( - isLogsVolume && - logsVolumeQuery?.query && - logsVolumeQuery?.query !== "" && - dataSourceType === "logs" && - !isMatrix - ) { - dispatch( - getData( - dataSourceType, - logsVolumeQuery.query, - queryType, - limit, - name, - id, - direction, - dataSourceId, - currentDataSource.url, - logsVolumeQuery.customStep, - true // isLogsVolume - ) - ); - } - }, [dataSourceId, id]); - - useEffect(() => { - if (typeof queryInput === "string") { - setQueryInput(queryInput); - setQueryValue([ - { children: [{ text: sanitizeWithSigns(queryInput) }] }, - ]); - saveQuery(); - if (isLogsVolume) { - setLogsLevel(queryInput, true); - } - } - }, [queryInput]); - - useEffect(() => { - if (typeof launchQuery === "string" && launchQuery !== "") { - setQueryInput(launchQuery); - setQueryValue([ - { children: [{ text: sanitizeWithSigns(launchQuery) }] }, - ]); - saveQuery(); - if (isLogsVolume) { - setLogsLevel(launchQuery, true); - } - } - }, [launchQuery]); - - useEffect(() => { - setLogsLevel(queryInput, isLogsVolume); - }, [queryInput]); function setLogsLevel(queryInput: string, isLogsVolume: boolean) { if (isLogsVolume && queryInput !== "") { @@ -423,8 +289,8 @@ const QueryBar: React.FC = (props) => { saveLogsVolumeQuery({ query, customStep }); }; - const onSubmit = (e: any) => { - e.preventDefault(); + const onSubmit = (e?: any) => { + e?.preventDefault(); const ds: any = dataSources.find((f: any) => f.id === dataSourceId); if (onQueryValid(queryInput) && ds) { try { @@ -778,10 +644,6 @@ const QueryBar: React.FC = (props) => { return null; }; - if (isEmbed) { - return null; - } - const queryTypeRenderer = ( type: any, traceSearch: any, @@ -834,6 +696,150 @@ const QueryBar: React.FC = (props) => { return querySearch; }; + + useEffect(() => { + setQueryInput(data.expr); + setQueryValue([{ children: [{ text: sanitizeWithSigns(data.expr) }] }]); + }, [data.expr]); + + useEffect(() => { + let queryText = queryValue[0].children[0].text; + setQueryInput(queryText); + }, [queryValue]); + + useEffect(() => { + if (isTabletOrMobile && isSplit) { + dispatch(setSplitView(false)); + } + }, [isTabletOrMobile]); + + useEffect(() => { + let { expr } = getLocalQueryItem(dataSourceId, id); + let actLocalDs = getLocalDataSources(dataSourceId); + setQueryInput(expr); + setQueryValue([{ children: [{ text: sanitizeWithSigns(expr) }] }]); + + if (isLogsVolume && logsVolumeQuery) { + setLogsLevel(expr, isLogsVolume); + } + const dataSource: any = dataSources?.find( + (f: any) => f.id === dataSourceId + ); + + let currentDataSource: any = {}; + + if ( + actLocalDs && + actLocalDs?.url !== initialDefault && + actLocalDs?.url !== "" + ) { + currentDataSource = { ...actLocalDs }; + + const panelCP = [...panelData]; + + panelCP.forEach((query) => { + if (query.id === id) { + query.dataSourceId = currentDataSource.id; + query.dataSourceType = currentDataSource.type; + query.dataSourceURL = currentDataSource.url; + } + }); + + dispatch(panelAction(name, panelCP)); + + const dsCopy = [...dataSources]; + dsCopy.forEach((ds) => { + if (ds.id === dataSourceId) { + ds = currentDataSource; + } + }); + + dispatch(setDataSources(dsCopy)); + } else if (dataSource && dataSource.url !== "") { + currentDataSource = { ...dataSource }; + } + + let { isMatrix } = getIntvalData(expr); + if (expr !== "" && expr?.length > 6) { + dispatch( + getData( + dataSourceType, + expr, + queryType, + limit, + name, + id, + direction, + dataSourceId, + currentDataSource?.url + ) + ); + } + + // setLogsLevel(queryInput, isLogsVolume); + if ( + isLogsVolume && + logsVolumeQuery?.query && + logsVolumeQuery?.query !== "" && + dataSourceType === "logs" && + !isMatrix + ) { + dispatch( + getData( + dataSourceType, + logsVolumeQuery.query, + queryType, + limit, + name, + id, + direction, + dataSourceId, + currentDataSource.url, + logsVolumeQuery.customStep, + true // isLogsVolume + ) + ); + } + }, [dataSourceId, id]); + + useEffect(() => { + if (typeof queryInput === "string") { + setQueryInput(queryInput); + setQueryValue([ + { children: [{ text: sanitizeWithSigns(queryInput) }] }, + ]); + saveQuery(); + if (isLogsVolume) { + setLogsLevel(queryInput, true); + } + } + }, [queryInput]); + + useEffect(() => { + if (typeof launchQuery === "string" && launchQuery !== "") { + setQueryInput(launchQuery); + setQueryValue([ + { children: [{ text: sanitizeWithSigns(launchQuery) }] }, + ]); + saveQuery(); + if (isLogsVolume) { + setLogsLevel(launchQuery, true); + } + } + }, [launchQuery]); + + useEffect(() => { + setLogsLevel(queryInput, isLogsVolume); + }, [queryInput]); + + useEffect(()=>{ + if(data?.start && data?.stop){ + onSubmit() + } + + },[data.start, data.stop]) + + // render if (isEmbed) { diff --git a/packages/main/src/components/StatusBar/components/daterangepicker/components/Nav.tsx b/packages/main/src/components/StatusBar/components/daterangepicker/components/Nav.tsx index 7111bc13..109c4aac 100644 --- a/packages/main/src/components/StatusBar/components/daterangepicker/components/Nav.tsx +++ b/packages/main/src/components/StatusBar/components/daterangepicker/components/Nav.tsx @@ -1,4 +1,4 @@ -import React, { useState, useEffect } from "react"; +import { useState, useEffect, forwardRef } from "react"; import Paper from "@mui/material/Paper"; import Grid from "@mui/material/Grid"; @@ -26,7 +26,6 @@ import { findRangeByLabel } from "../utils"; import AbsoluteSelector from "./AbsoluteSelector"; import { useMediaQuery } from "react-responsive"; import styled from "@emotion/styled"; -import { ThemeProvider } from "@emotion/react"; import useTheme from "@ui/theme/useTheme"; import { QrynTheme } from "@ui/theme/types"; @@ -82,7 +81,7 @@ const StyledNav = styled.div<{theme:QrynTheme}>` `; // open month only at -export const PickerNav = (props: any) => { +export const PickerNav = forwardRef((props: any, ref:any) => { const { ranges, dateRange, @@ -197,9 +196,8 @@ export const PickerNav = (props: any) => { }; return ( - - + {calendarOpen && isBigScreen && ( @@ -394,6 +392,6 @@ export const PickerNav = (props: any) => { - + ); -}; +}); diff --git a/packages/main/src/components/StatusBar/components/daterangepicker/consts.ts b/packages/main/src/components/StatusBar/components/daterangepicker/consts.ts index 422f1a69..b1750288 100644 --- a/packages/main/src/components/StatusBar/components/daterangepicker/consts.ts +++ b/packages/main/src/components/StatusBar/components/daterangepicker/consts.ts @@ -16,8 +16,8 @@ export const MONTHS = [ export const WEEK_DAYS = ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"]; export const MARKERS = { - FIRST_MONTH: Symbol("firstMonth"), - SECOND_MONTH: Symbol("secondMonth"), + FIRST_MONTH: "firstMonth", + SECOND_MONTH: "secondMonth", }; export const DATE_TIME_RANGE = "dateTimeRange"; diff --git a/packages/main/src/components/StatusBar/components/daterangepicker/hooks/useOutsideRef.tsx b/packages/main/src/components/StatusBar/components/daterangepicker/hooks/useOutsideRef.tsx index 0c7f3c56..aace292f 100644 --- a/packages/main/src/components/StatusBar/components/daterangepicker/hooks/useOutsideRef.tsx +++ b/packages/main/src/components/StatusBar/components/daterangepicker/hooks/useOutsideRef.tsx @@ -1,19 +1,16 @@ -import { useEffect, useRef } from "react"; -import { setRangeOpen } from '@ui/store/actions/setRangeOpen'; -import { useDispatch } from 'react-redux'; +import React, { useEffect } from "react"; -export default function useOutsideRef() { - const dispatch: any = useDispatch() - const ref = useRef(null); +export default function useOutsideRef(onOpen: (value: boolean) => void) { + const ref = React.createRef(); - const handleHideDateRange = (event:any) => { + const handleHideDateRange = (event: any) => { if (event.key === "Escape") { - dispatch(setRangeOpen(false)); + onOpen(false); } }; - const handleClickOutside = (event:any) => { + const handleClickOutside = (event: any) => { if (ref.current && !ref.current.contains(event.target)) { - dispatch(setRangeOpen(false)); + onOpen(false); } }; useEffect(() => { diff --git a/packages/main/src/components/StatusBar/components/daterangepicker/index.tsx b/packages/main/src/components/StatusBar/components/daterangepicker/index.tsx index 04bc4942..c19fc037 100644 --- a/packages/main/src/components/StatusBar/components/daterangepicker/index.tsx +++ b/packages/main/src/components/StatusBar/components/daterangepicker/index.tsx @@ -16,6 +16,8 @@ import { add, sub, intervalToDuration, + startOfDay, + endOfDay, } from "date-fns"; import { PickerNav } from "./components/Nav"; @@ -37,7 +39,7 @@ import MenuItem from "@mui/material/MenuItem"; import { Tooltip } from "@mui/material"; import TimeLabel from "./components/TimeLabel"; import { DatePickerButton } from "../../styled"; -import useTheme from "@ui/theme/useTheme" +import useTheme from "@ui/theme/useTheme"; import { useMediaQuery } from "react-responsive"; import { useSelector } from "react-redux"; @@ -147,37 +149,36 @@ export function DateRangePickerMain(props: DateRangePickerProps) { pickerOpen, onPickerOpen, } = props; + const [localLabel, setLocalLabel] = useState(label); const isTabletOrMobile = useMediaQuery({ query: "(max-width: 1013px)" }); - const isSplit = useSelector((store:any)=> store.isSplit); + const isSplit = useSelector((store: any) => store.isSplit); const isFullWidth = useMemo(() => { - return !isTabletOrMobile && !isSplit - },[isTabletOrMobile, isSplit]); - + return !isTabletOrMobile && !isSplit; + }, [isTabletOrMobile, isSplit]); const theme = useTheme(); const defaultRange = { - label: 'Last 5 minutes', - dateStart: new Date(Date.now()-5 * 60000), - dateEnd: new Date(Date.now()) - } + label: "Last 5 minutes", + dateStart: new Date(Date.now() - 5 * 60000), + dateEnd: new Date(Date.now()), + }; const initialDateRange = () => { - try { - if(defaultRange.label !== label) { + if (defaultRange.label !== label) { return { dateStart: startTs, - dateEnd: stopTs, - label - } + dateEnd: stopTs, + label, + }; } - return defaultRange - + return defaultRange; } catch (e) { if (isDate(startTs) && isDate(stopTs)) { return { dateStart: startTs, dateEnd: stopTs }; } + console.log(e); } }; @@ -208,7 +209,7 @@ export function DateRangePickerMain(props: DateRangePickerProps) { const { dateStart, dateEnd } = dateRange; - const { ref } = useOutsideRef(); + const { ref } = useOutsideRef(onPickerOpen); const setFirstMonthValidated = (date: any) => { if (isBefore(date, secondMonth)) { @@ -223,12 +224,13 @@ export function DateRangePickerMain(props: DateRangePickerProps) { }; const setDateRangeValidated = (range: any) => { - let { label, dateStart: newStart, dateEnd: newEnd } = range; + let { label: newLabel, dateStart: newStart, dateEnd: newEnd } = range; if (newStart && newEnd) { - range.label = label; + range.label = newLabel; range.dateStart = newStart = max([newStart, minDateValid]); range.dateEnd = newEnd = min([newEnd, maxDateValid]); setDateRange(range); + setLocalLabel(newLabel || ""); // Update local label saveDateRange(range); onChange(range); setFirstMonth(newStart); @@ -242,15 +244,21 @@ export function DateRangePickerMain(props: DateRangePickerProps) { }; const onDayClick = (day: any) => { if (dateStart && !dateEnd && !isBefore(day, dateStart)) { - const newRange: any = { dateStart, dateEnd: day }; + const newRange: any = { + dateStart: startOfDay(dateStart), // Set to beginning of start day + dateEnd: endOfDay(day), // Set to end of end day + }; onChange(newRange); saveDateRange(newRange); setDateRange(newRange); - - onLabelChange(""); + setLocalLabel(""); // Clear local label for custom range + onLabelChange(""); // Still notify parent about label change onClose(); } else { - setDateRange({ dateStart: day, dateEnd: undefined }); + setDateRange({ + dateStart: startOfDay(day), // Set to beginning of day + dateEnd: undefined, + }); } setHoverDay(day); }; @@ -304,10 +312,10 @@ export function DateRangePickerMain(props: DateRangePickerProps) { const { dateStart, dateEnd, label } = range; const isStart = isDate(dateStart); const isEnd = isDate(dateEnd); - const isLabel = typeof label !== "undefined"; - if (isStart) onStartChange(dateStart); //dispatch(setStartTime(dateStart)); - if (isEnd) onStopChange(dateEnd); //dispatch(setStopTime(dateEnd)); - if (isLabel) onLabelChange(label); //dispatch(setTimeRangeLabel(label)); + const isLabel = !!label; + if (isStart) onStartChange(dateStart); + if (isEnd) onStopChange(dateEnd); + onLabelChange(isLabel ? label : ""); } const openButtonHandler = (e: any) => { @@ -375,13 +383,13 @@ export function DateRangePickerMain(props: DateRangePickerProps) { return (
- {(isFullWidth) && ( + {isFullWidth && ( <> { adjustTimeRange("backward"); }} - side={'left'} + side={"left"} attachedside={"r"} emptySide={"l"} className={cx(DTStyles)} @@ -391,7 +399,7 @@ export function DateRangePickerMain(props: DateRangePickerProps) { - {label !== "" - ? label + {localLabel !== "" + ? localLabel : (isValid(dateRange.dateStart) ? format( dateRange.dateStart, @@ -447,19 +455,19 @@ export function DateRangePickerMain(props: DateRangePickerProps) { "yyyy/MM/dd HH:mm:ss" ) : typeof dateRange.dateEnd !== "undefined" - ? dateRange.dateEnd - : "")} + ? dateRange.dateEnd + : "")} - {(isFullWidth) && ( + {isFullWidth && ( <> { adjustTimeRange("forward"); }} - side={'right'} + side={"right"} attachedside={"l"} className={cx(DTStyles)} > @@ -503,9 +511,10 @@ export function DateRangePickerMain(props: DateRangePickerProps) { )} {pickerOpen ? ( -
+
void; +removeRangeItem: (id: string) => void; +updateRangeItem: (id: string, rangeItem: DateRangeItem) => void; +selectRangeItem: (id: string) => void; +} + +export const initialStore = { + rangeItems: [ + { + start: 0, + end: 0, + label: "Last 1 hour", + rageOpen: false, + } + ], +}; + +export const dateRangePickerStore = create((set) => ({ +...initialStore, +addRangeItem: (rangeItem: DateRangeItem) => set((state) => ({ + rangeItems: [...state.rangeItems, rangeItem] +})), +removeRangeItem: (id: string) => set((state) => ({ + rangeItems: state.rangeItems.filter((item) => item.id !== id) +})), +updateRangeItem: (id: string, rangeItem: DateRangeItem) => set((state) => ({ + rangeItems: state.rangeItems.map((item) => item.id === id ? rangeItem : item) +})), +selectRangeItem: (id: string) => set((state) => ({ + rangeItems: state.rangeItems.map((item) => item.id === id ? { ...item, rangeOpen: !item.rangeOpen } : item) +})), +})); \ No newline at end of file diff --git a/packages/main/src/components/StatusBar/components/daterangepicker/utils.ts b/packages/main/src/components/StatusBar/components/daterangepicker/utils.ts index d2f57dde..fa5f57fd 100644 --- a/packages/main/src/components/StatusBar/components/daterangepicker/utils.ts +++ b/packages/main/src/components/StatusBar/components/daterangepicker/utils.ts @@ -20,7 +20,7 @@ import { min, max, } from "date-fns"; -import isSameMinute from "date-fns/isSameMinute"; +import isSameMinute from "date-fns/isSameMinute"; export const chunks = (array: any, size: any) => { return Array.from({ length: Math.ceil(array.length / size) }, (v, i) => @@ -61,23 +61,29 @@ export const inDateRange = ( isSameDay(day, dateStart) || isSameDay(day, dateEnd)); -export const isRangeSameDay = ({ dateStart, dateEnd }:{ dateStart:any; dateEnd:any }) => { +export const isRangeSameDay = ({ + dateStart, + dateEnd, +}: { + dateStart: any; + dateEnd: any; +}) => { if (dateStart && dateEnd) { return isSameDay(dateStart, dateEnd); } return false; }; -export const findRange = (dateRange:any) => { +export const findRange = (dateRange: any) => { return getDefaultRanges(new Date()).find((range) => isSameRange(dateRange, range) )?.label; }; -export const findRangeByLabel = (label:any) => { +export const findRangeByLabel = (label: any) => { return getDefaultRanges(new Date()).find((range) => range.label === label); }; -export const parseOptionalDate = (date:any, defaultValue:any) => { +export const parseOptionalDate = (date: any, defaultValue: any) => { if (date instanceof Date) { const parsed = toDate(date); if (isValid(parsed)) { @@ -95,25 +101,28 @@ export const parseOptionalDate = (date:any, defaultValue:any) => { } }; -export const generateYears = (relativeTo:any, count:any) => { +export const generateYears = (relativeTo: any, count: any) => { const half = Math.floor(count / 2); return Array(count) ?.fill(0) ?.map((y, i) => relativeTo?.getFullYear() - half + i); }; -export const isSameRange = (first:any, second:any) => { +export const isSameRange = (first: any, second: any) => { const { dateStart: fStart, dateEnd: fEnd, label: fLabel } = first; const { dateStart: sStart, dateEnd: sEnd, label: sLabel } = second; if (fLabel === sLabel) { return true; } else if (fStart && sStart && fEnd && sEnd) { - return isSameMinute(fStart, sStart) && isSameMinute(fEnd, sEnd); + return ( + isSameMinute(parseISO(fStart), parseISO(sStart)) && + isSameMinute(parseISO(fEnd), parseISO(sEnd)) + ); } return false; }; -export const getValidatedMonths = (range:any, minDate:any, maxDate:any) => { +export const getValidatedMonths = (range: any, minDate: any, maxDate: any) => { let { dateStart, dateEnd } = range; if (dateStart && dateEnd) { const newStart = max([dateStart, minDate]); @@ -128,7 +137,7 @@ export const getValidatedMonths = (range:any, minDate:any, maxDate:any) => { } }; -export const getDefaultRanges = (date:any) => [ +export const getDefaultRanges = (date: Date | number) => [ { label: "Last 5 minutes", dateStart: addMinutes(date, -5),