diff --git a/src/components/Header/SubHeader.tsx b/src/components/Header/SubHeader.tsx index 4c9b34d9..e29bd09d 100644 --- a/src/components/Header/SubHeader.tsx +++ b/src/components/Header/SubHeader.tsx @@ -1,7 +1,7 @@ import useMountedState from '@/hooks/useMountedState'; import { Box, Breadcrumbs, Button, Menu, Text, TextInput, UnstyledButton, px } from '@mantine/core'; import { DateTimePicker } from '@mantine/dates'; -import { IconClock, IconRefresh, IconRefreshOff, IconSearch } from '@tabler/icons-react'; +import { IconClock,IconRefresh, IconReload , IconRefreshOff, IconSearch } from '@tabler/icons-react'; import dayjs from 'dayjs'; import ms from 'ms'; import type { ChangeEvent, FC, KeyboardEvent } from 'react'; @@ -35,18 +35,16 @@ const SubHeader: FC = () => { Streams {streamName} - {useMatch("/:streamName/logs")? "Logs": "Query" } + {useMatch("/:streamName/logs") ? "Logs" : "Query"} - - {useMatch("/:streamName/logs") - && - - } - + + {useMatch("/:streamName/logs") && } + {useMatch("/:streamName/logs") && } + @@ -105,6 +103,33 @@ const Search: FC = () => { ); }; +const RefreshNow: FC = () => { + const { + state: { subLogQuery, subLogSelectedTimeRange }, + } = useHeaderContext(); + + + const onRefresh = () => { + if (subLogSelectedTimeRange.get().includes('Past')) { + const now = dayjs(); + const timeDiff = subLogQuery.get().endTime.getTime() - subLogQuery.get().startTime.getTime(); + subLogQuery.set((state) => { + state.startTime = now.subtract(timeDiff).toDate(); + state.endTime = now.toDate(); + }); + } + }; + const { classes } = useLogQueryStyles(); + const { refreshNowBtn } = classes; + + return ( + + + ); +}; + const RefreshInterval: FC = () => { const { state: { subRefreshInterval }, @@ -195,7 +220,7 @@ const TimeRange: FC = () => { } = classes; return ( - + - - - - + + + + + + + + + ); }; diff --git a/src/pages/Query/QueryResultEditor.tsx b/src/pages/Query/QueryResultEditor.tsx index 5bed4bc7..b07f4a87 100644 --- a/src/pages/Query/QueryResultEditor.tsx +++ b/src/pages/Query/QueryResultEditor.tsx @@ -3,7 +3,7 @@ import Editor from '@monaco-editor/react'; import { useQueryPageContext } from './Context'; import useMountedState from '@/hooks/useMountedState'; import { Box, Button, Text, px } from '@mantine/core'; -import { IconCopy, IconSearch, IconCheck } from '@tabler/icons-react'; +import { IconClipboard , IconSearch, IconCheck } from '@tabler/icons-react'; import { notifications } from '@mantine/notifications'; import { useQueryResultEditorStyles } from './styles'; @@ -63,8 +63,8 @@ const QueryResultEditor: FC = () => { Result - - + + diff --git a/src/pages/Query/QuerySchemaList.tsx b/src/pages/Query/QuerySchemaList.tsx index 058df05c..74ebdced 100644 --- a/src/pages/Query/QuerySchemaList.tsx +++ b/src/pages/Query/QuerySchemaList.tsx @@ -1,13 +1,15 @@ import { FC, useEffect } from 'react'; import { useGetLogStreamSchema } from '@/hooks/useGetLogStreamSchema'; import { useHeaderContext } from '@/layouts/MainLayout/Context'; -import { Table, Box, Title } from '@mantine/core'; - - +import { Table, Box, Title, Button, ScrollArea } from '@mantine/core'; +import { IconX } from '@tabler/icons-react'; +import { useQuerySchemaListStyles } from './styles'; +import { useQueryPageContext } from './Context'; const QuerySchemaList: FC = () => { const { data: querySchema, getDataSchema, resetData, loading, error: logStreamSchemaError } = useGetLogStreamSchema(); const { state: { subLogQuery } } = useHeaderContext(); + const { state: { subSchemaToggle } } = useQueryPageContext(); useEffect(() => { if (subLogQuery.get().streamName) { @@ -36,23 +38,30 @@ const QuerySchemaList: FC = () => { } }); - return ( - - - Schema for {subLogQuery.get().streamName} +const {classes} = useQuerySchemaListStyles(); + const {actionBtn ,container ,textContext ,theadSt ,tbodySt ,innercontainer,scrollAreaSt}=classes; + return ( + + + Schema for {subLogQuery.get().streamName} + + + {!(logStreamSchemaError) ? ( !loading && Boolean(querySchema) ? ( (querySchema?.fields.length) ? ( + - + - {renderList} + {renderList}
Feild Type
+
) : (

No Data

) diff --git a/src/pages/Query/SecondaryHeader.tsx b/src/pages/Query/SecondaryHeader.tsx deleted file mode 100644 index 00b15e19..00000000 --- a/src/pages/Query/SecondaryHeader.tsx +++ /dev/null @@ -1,236 +0,0 @@ -import useMountedState from '@/hooks/useMountedState'; -import { Box, Button, Menu, Text, UnstyledButton, px } from '@mantine/core'; -import { DateTimePicker } from '@mantine/dates'; -import { IconClock, IconRefresh, IconRefreshOff, } from '@tabler/icons-react'; -import dayjs from 'dayjs'; -import ms from 'ms'; -import type { FC } from 'react'; -import { Fragment, useEffect, useMemo } from 'react'; -import { FIXED_DURATIONS, REFRESH_INTERVALS, useQueryPageContext } from './Context'; -import { useQueryStyles } from './styles'; - -const SecondaryHeader: FC = () => { - const { classes } = useQueryStyles(); - const { container, innerContainer, labelStyle } = classes; - - return ( - - - Time Range - - - - - - - - ); -}; - - -const RefreshInterval: FC = () => { - const { - state: { subRefreshInterval }, - } = useQueryPageContext(); - - const [selectedInterval, setSelectedInterval] = useMountedState(subRefreshInterval.get()); - - useEffect(() => { - const listener = subRefreshInterval.subscribe((interval) => { - setSelectedInterval(interval); - }); - - return () => listener(); - }, []); - - const Icon = useMemo(() => (selectedInterval ? IconRefresh : IconRefreshOff), [selectedInterval]); - - const onSelectedInterval = (interval: number | null) => { - subRefreshInterval.set(interval); - }; - - const { classes } = useQueryStyles(); - const { intervalBtn } = classes; - - return ( - - - - - - {REFRESH_INTERVALS.map((interval) => { - if (interval === selectedInterval) return null; - - return ( - onSelectedInterval(interval)}> - {ms(interval)} - - ); - })} - - {selectedInterval !== null && ( - onSelectedInterval(null)}> - Off - - )} - - - ); -}; - -type FixedDurations = (typeof FIXED_DURATIONS)[number]; - -const TimeRange: FC = () => { - const { - state: { subLogQuery, subLogSelectedTimeRange }, - } = useQueryPageContext(); - - const [selectedRange, setSelectedRange] = useMountedState(subLogSelectedTimeRange.get()); - - useEffect(() => { - const listener = subLogSelectedTimeRange.subscribe((state) => { - setSelectedRange(state); - }); - - return () => listener(); - }, []); - - const onDurationSelect = (duration: FixedDurations) => { - subLogSelectedTimeRange.set(duration.name); - const now = dayjs(); - - subLogQuery.set((query) => { - query.startTime = now.subtract(duration.milliseconds, 'milliseconds').toDate(); - query.endTime = now.toDate(); - }); - return; - }; - - const { classes, cx } = useQueryStyles(); - const { - timeRangeBTn, - timeRangeContainer, - fixedRangeContainer, - fixedRangeBtn, - fixedRangeBtnSelected, - customRangeContainer, - } = classes; - - return ( - - - - - - - - {FIXED_DURATIONS.map((duration) => { - return ( - onDurationSelect(duration)}> - {duration.name} - - ); - })} - - - - - - - - ); -}; - -const CustomTimeRange: FC = () => { - const { - state: { subLogQuery, subLogSelectedTimeRange }, - } = useQueryPageContext(); - - const [selectedRange, setSelectedRange] = useMountedState({ - startTime: subLogQuery.get().startTime, - endTime: subLogQuery.get().endTime, - }); - - const onRangeSelect = (key: keyof typeof selectedRange, date: Date) => { - setSelectedRange((state) => { - state[key] = date; - return { ...state }; - }); - }; - - const onApply = () => { - subLogQuery.set((query) => { - query.startTime = selectedRange.startTime; - query.endTime = selectedRange.endTime; - }); - const startTime = dayjs(selectedRange.startTime).format('DD-MM-YY HH:mm'); - const endTime = dayjs(selectedRange.endTime).format('DD-MM-YY HH:mm'); - subLogSelectedTimeRange.set(`${startTime} - ${endTime}`); - }; - - const { classes } = useQueryStyles(); - const { customTimeRangeFooter, customTimeRangeApplyBtn } = classes; - - const isApplicable = useMemo(() => { - return ( - dayjs(selectedRange.startTime).isSame(subLogQuery.get().startTime, 'seconds') && - dayjs(selectedRange.endTime).isSame(subLogQuery.get().endTime, 'seconds') - ); - }, [selectedRange]); - - const isStartTimeMoreThenEndTime = useMemo(() => { - return dayjs(selectedRange.startTime).isAfter(selectedRange.endTime, 'seconds'); - }, [selectedRange]); - - return ( - - { - if (date) { - onRangeSelect('startTime', date); - } - }} - valueFormat="DD-MM-YY HH:mm" - label="From" - placeholder="Pick date and time" - /> - { - if (date) { - onRangeSelect('endTime', date); - } - }} - valueFormat="DD-MM-YY HH:mm" - label="To" - placeholder="Pick date and time" - mt="md" - /> - - - - - ); -}; - -export default SecondaryHeader; diff --git a/src/pages/Query/index.tsx b/src/pages/Query/index.tsx index a92436d6..ec29c773 100644 --- a/src/pages/Query/index.tsx +++ b/src/pages/Query/index.tsx @@ -1,22 +1,33 @@ import { Box } from '@mantine/core'; import { useDocumentTitle } from '@mantine/hooks'; -import { FC } from 'react'; +import { FC, useEffect } from 'react'; import { useQueryStyles } from './styles'; import { Panel, PanelGroup, PanelResizeHandle } from "react-resizable-panels"; import QueryCodeEditor from './QueryCodeEditor'; import QueryResultEditor from './QueryResultEditor'; -// import QuerySchemaList from './QuerySchemaList'; +import QuerySchemaList from './QuerySchemaList'; +import { useQueryPageContext } from './Context'; +import useMountedState from '@/hooks/useMountedState'; const Logs: FC = () => { useDocumentTitle('Parseable | Query'); const { classes } = useQueryStyles(); - const { container,innerContainer1 } = classes; + const { container,innerContainer,schemaContainer } = classes; + const { state: { subSchemaToggle } } = useQueryPageContext(); + const [isSchemaOpen, setIsSchemaOpen] = useMountedState(false); + + useEffect(() => { + const listener = subSchemaToggle.subscribe(setIsSchemaOpen); + return () => { + listener(); + }; + }, [subSchemaToggle.get()]); return ( - + @@ -39,7 +50,9 @@ const Logs: FC = () => { - + + + diff --git a/src/pages/Query/styles.tsx b/src/pages/Query/styles.tsx index 90dc5202..4957c71d 100644 --- a/src/pages/Query/styles.tsx +++ b/src/pages/Query/styles.tsx @@ -3,7 +3,7 @@ import { HEADER_HEIGHT, NAVBAR_WIDTH } from '@/constants/theme'; import { createStyles } from '@mantine/core'; export const useQueryStyles = createStyles((theme) => { - const { colors, spacing } = theme; + const { colors ,shadows } = theme; const { heights, widths, } = theme.other; const sColor = colors.brandSecondary[0]; const pColor = colors.brandPrimary[0]; @@ -15,7 +15,7 @@ export const useQueryStyles = createStyles((theme) => { display: 'flex', position: 'relative', }, - innerContainer1: { + innerContainer: { position: 'relative', flex: 1, maxHeight: `calc(${heights.screen} - ${HEADER_HEIGHT}px)`, @@ -39,11 +39,11 @@ export const useQueryStyles = createStyles((theme) => { }, height: "25px", marginRight: "5px" }, - innerContainer: { - display: 'flex', - paddingTop: spacing.xxs, - marginRight: spacing.md, - }, + schemaContainer:{ + border: `${widths.px} ${colors.gray[1]} solid`, + boxShadow: shadows.sm, + maxWidth: "500px" + } }; }); @@ -60,21 +60,25 @@ export const useQueryCodeEditorStyles = createStyles((theme) => { alignItems: "center", height: "55px", padding: `${spacing.xs} ${spacing.md}` , + width:"100%" }, runQueryBtn: { color: pColor, - border: "none", - height: "40px", - marginLeft: "auto", + borderColor: colors.gray[2], + height: "34px", + width: "34px", + padding: "0px", '&:hover': { color: sColor, }, + marginInlineEnd: spacing.xs, + }, textContext: { marginRight: spacing.md, fontSize: fontSizes.md, fontFamily: fontFamily, - fontWeight: fontWeights.bold, + fontWeight: fontWeights.semibold, } }; @@ -101,15 +105,82 @@ export const useQueryResultEditorStyles = createStyles((theme) => { color: sColor, }, height: "34px", + width: "34px", + padding: "0px", marginInlineEnd: spacing.xs, color: colors.gray[5], - borderColor:colors.gray[5] + borderColor:colors.gray[2] + }, + textContext: { + marginRight: spacing.md, + fontSize: fontSizes.md, + fontFamily: fontFamily, + fontWeight: fontWeights.semibold, + } + }; +}); + + +export const useQuerySchemaListStyles = createStyles((theme) => { + const { colors ,spacing ,fontFamily,fontSizes} = theme; + const {fontWeights } = theme.other; + const sColor = colors.brandSecondary[0]; + + return { + container: { + maxWidth: "500px", + height: "100%", + overflow: "auto", + }, + innercontainer: { + display: "flex", + alignItems: "center", + borderBottom: `solid 1px ${colors.gray[2]}`, + height: "55px", + padding: `${spacing.xs} ${spacing.md}` , + justifyContent:"space-between" + ,paddingRight:0, + }, + + actionBtn: { + color: colors.gray[3], + height: "34px", + width: "34px", + padding: "0px", + borderColor:colors.gray[2], + '&:hover': { + color: sColor, + }, }, textContext: { marginRight: spacing.md, fontSize: fontSizes.md, fontFamily: fontFamily, - fontWeight: fontWeights.bold, + fontWeight: fontWeights.semibold, + }, + theadSt:{ + "& tr>th":{ + backgroundColor:colors.gray[0], + fontSize: fontSizes.md, + fontFamily: fontFamily, + fontWeight: fontWeights.semibold, + color:colors.gray[3], + height: "34px" + } + }, + tbodySt:{ + "& tr>td":{ + fontSize: fontSizes.md, + fontFamily: fontFamily, + borderTop:`solid 1px ${colors.gray[2]} !important`, + color:colors.gray[6], + height: "34px" + } + }, + scrollAreaSt:{ + maxWidth: "500px", + height: "calc(100% - 55px)", + overflow: "auto", } }; -}); \ No newline at end of file +});