Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pagination modification #158

Merged
merged 3 commits into from
Oct 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/api/query.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { LogsQuery } from '@/@types/parseable/api/query';
export const getQueryLogs = (logsQuery: LogsQuery) => {
const { startTime, endTime, streamName } = logsQuery;

const query = `SELECT * FROM ${streamName} ORDER BY p_timestamp DESC`;
const query = `SELECT * FROM ${streamName}`;

return Axios().post(
LOG_QUERY_URL,
Expand Down
88 changes: 79 additions & 9 deletions src/pages/Logs/CarouselSlide.tsx
Original file line number Diff line number Diff line change
@@ -1,25 +1,28 @@
import { useGetQueryCount } from '@/hooks/useGetQueryCount';
import { useHeaderContext } from '@/layouts/MainLayout/Context';
import { Box, Button, Tooltip } from '@mantine/core';
import { Box, Button, Modal, Text, Tooltip } from '@mantine/core';
import dayjs from 'dayjs';
import { useEffect } from 'react';
import { useLogsPageContext } from './Context';
import useMountedState from '@/hooks/useMountedState';
import { Carousel } from '@mantine/carousel';
import { useCarouselSlideStyle } from './styles';

type FillCarouselProps = {
gapMinute: number;
endtime: Date;
id: number;
zoomIn: () => void;
};
const FillCarousel = ({ gapMinute, endtime, id }: FillCarouselProps) => {
const FillCarousel = ({ gapMinute, endtime, id, zoomIn }: FillCarouselProps) => {
const {
state: { subLogQuery },
state: { subLogQuery, subLogSelectedTimeRange },
} = useHeaderContext();
const {
state: { subGapTime },
} = useLogsPageContext();
const [subID, setSubID] = useMountedState<number | null>(null);
const [overLimit, setOverLimit] = useMountedState<boolean>(false);

const { data: count, error, loading, getQueryCountData: getCount } = useGetQueryCount();

Expand All @@ -40,7 +43,7 @@ const FillCarousel = ({ gapMinute, endtime, id }: FillCarouselProps) => {
return () => {
subID();
};
}, []);
}, [gapMinute]);

useEffect(() => {
if (count && count[0].totalcurrentcount !== 0 && ((subGapTime.get()?.id ?? 0) > id || subGapTime.get() === null)) {
Expand All @@ -52,6 +55,8 @@ const FillCarousel = ({ gapMinute, endtime, id }: FillCarouselProps) => {
}
}, [count]);

const { classes } = useCarouselSlideStyle();

return (
<Carousel.Slide>
<Tooltip
Expand Down Expand Up @@ -89,17 +94,82 @@ const FillCarousel = ({ gapMinute, endtime, id }: FillCarouselProps) => {
}}
disabled={count && count[0].totalcurrentcount === 0}
onClick={() => {
subGapTime.set({
startTime: dayjs(parsedEndTime).subtract(gapMinute, 'minute').toDate(),
endTime: parsedEndTime,
id: id,
});
if ((count && count[0].totalcurrentcount < 30000) || gapMinute === 1) {
subGapTime.set({
startTime: dayjs(parsedEndTime).subtract(gapMinute, 'minute').toDate(),
endTime: parsedEndTime,
id: id,
});
}
if (count && count[0].totalcurrentcount >= 30000 && gapMinute !== 1) {
setOverLimit(true);
}
}}>
{dayjs(parsedEndTime).format('HH:mm')} -{' '}
{dayjs(parsedEndTime).subtract(gapMinute, 'minute').format('HH:mm')}
</Button>
</Box>
</Tooltip>
<Modal centered opened={overLimit} onClose={() => setOverLimit(false)} title="Over 30,000 events" size={'lg'}>
<Box pb="lg">
<Text mb="lg">
{dayjs(parsedEndTime).format('DD-MMM-YYYY HH:mm')} -{' '}
{dayjs(parsedEndTime).subtract(gapMinute, 'minute').format('DD-MMM-YYYY HH:mm')}
</Text>
<Text mb="lg">
You have reached the limit of 30,000 events per query zoom in to continue or view this time period. If you
load more than 30,000 events, the browser may become unresponsive.
</Text>
<Box>
<Button
className={classes.controlBtn}
onClick={() => {
setOverLimit(false);
}}>
Close
</Button>

<Button
className={classes.controlBtn}
onClick={() => {
zoomIn();
setOverLimit(false);
}}>
Zoom In
</Button>
<Button
className={classes.controlBtn}
onClick={() => {
subLogQuery.set({
...subLogQuery.get(),
startTime: dayjs(parsedEndTime).subtract(gapMinute, 'minute').toDate(),
endTime: parsedEndTime,
});
subLogSelectedTimeRange.set({
state: 'custom',
value: `${dayjs(parsedEndTime).subtract(gapMinute, 'minute').format('DD-MMM-YYYY HH:mm')} - ${dayjs(
parsedEndTime,
).format('DD-MMM-YYYY HH:mm')}`,
});
setOverLimit(false);
}}>
View this time period
</Button>
<Button
className={classes.controlBtn}
onClick={() => {
subGapTime.set({
startTime: dayjs(parsedEndTime).subtract(gapMinute, 'minute').toDate(),
endTime: parsedEndTime,
id: id,
});
setOverLimit(false);
}}>
Load anyway
</Button>
</Box>
</Box>
</Modal>
</Carousel.Slide>
);
};
Expand Down
104 changes: 62 additions & 42 deletions src/pages/Logs/HeaderPagination.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@ import { useGetQueryCount } from '@/hooks/useGetQueryCount';
import useMountedState from '@/hooks/useMountedState';
import { useHeaderContext } from '@/layouts/MainLayout/Context';
import { Carousel } from '@mantine/carousel';
import { Box, Button, Text } from '@mantine/core';
import { Box, Button, Text, Tooltip, px } from '@mantine/core';
import dayjs from 'dayjs';
import { useHeaderPaginationStyle } from './styles';

import { FC, useEffect, useRef } from 'react';
import { FC, useEffect } from 'react';
import FillCarousel from './CarouselSlide';
import { useLogsPageContext } from './Context';
import Loading from '@/components/Loading';
import { IconZoomIn, IconZoomOut } from '@tabler/icons-react';

const Limit = 10000;
const gapOptions = [1, 5, 10, 15, 20, 30, 60];
Expand All @@ -17,20 +19,19 @@ const HeaderPagination: FC = () => {
const {
state: { subLogQuery },
} = useHeaderContext();
const [headDate, setHeadDate] = useMountedState<Date | null>(null);

const [endDatePointer, setEndDatePointer] = useMountedState<Date | null>(null);
const [gapTemp, setGapTemp] = useMountedState<number>(0);
const [gapMinute, setGapMinute] = useMountedState<number>(0);
const [upperLimit, setUpperLimit] = useMountedState<number>(20);
const slots = useRef<
| {
gapMinute: number;
endtime: Date;
id: number;
}[]
| null
>(null);

const [slots, setSlots] = useMountedState<
{
gapMinute: number;
endtime: Date;
id: number;
}[]
>([]);

const {
data: queryCountRes,
Expand Down Expand Up @@ -66,7 +67,7 @@ const HeaderPagination: FC = () => {
subGapTime.set(null);
setGapTemp(0);
setGapMinute(0);
slots.current = null;
setSlots([]);
setUpperLimit(20);
setEndDatePointer(tempDate);
}
Expand Down Expand Up @@ -124,25 +125,24 @@ const HeaderPagination: FC = () => {
id: j,
});
}
slots.current = tempSlots;

setSlots(tempSlots);
}
}, [gapMinute]);

const loadMore = () => {
if (
subLogQuery.get().endTime &&
slots.current &&
slots.current.length > 0 &&
slots.current[slots.current.length - 1].endtime > subLogQuery.get().startTime
slots.length > 0 &&
slots[slots.length - 1].endtime > subLogQuery.get().startTime
) {
setUpperLimit(upperLimit + 20);
for (
let i = dayjs(slots.current[slots.current.length - 1].endtime).toDate(),
j = slots.current[slots.current.length - 1].id + 1;
let i = dayjs(slots[slots.length - 1].endtime).toDate(), j = slots[slots.length - 1].id + 1;
dayjs(i).subtract(gapMinute, 'minute').toDate() > subLogQuery.get().startTime && j <= upperLimit + 20;
i = dayjs(i).subtract(gapMinute, 'minute').toDate(), j++
) {
slots.current.push({
slots.push({
gapMinute: gapMinute,
endtime: i,
id: j,
Expand All @@ -151,51 +151,71 @@ const HeaderPagination: FC = () => {
}
};

const onSlideChange = (index: number) => {
if (slots.current && slots.current.length - 1 >= index * 9) {
setHeadDate(dayjs(slots.current[index * 9].endtime).toDate());
const zoomIn = () => {
if (gapTemp > 0 && gapTemp < gapOptions.length) {
setGapMinute(gapOptions[gapTemp - 1]);
setGapTemp(gapTemp - 1);
subGapTime.set(null);
}
};
const zoomOut = () => {
if (gapTemp < gapOptions.length - 1) {
setGapMinute(gapOptions[gapTemp + 1]);
setGapTemp(gapTemp + 1);
subGapTime.set(null);
}
};

const { classes } = useHeaderPaginationStyle();
return (
<Box
h={95}
h={105}
sx={{
overflow: 'hidden',
}}>
{gapMinute === 0 || queryCountLoading ? (
<Loading visible zIndex={0} />
) : (
<>
<Text
sx={{
fontSize: '1rem',
fontWeight: 500,
color: '#211F1F',
paddingTop: '10px',
}}
ta={'center'}>
{' '}
Loaded events for {dayjs(headDate).format('DD-MM-YYYY')}. Showing {gapMinute} minute intervals.
</Text>
<Box className={classes.controlContainer}>
<Text className={classes.controlText}>Showing events in blocks of {gapMinute} min</Text>
<Tooltip
label={gapOptions[gapTemp - 1] ? `Change Block time to ${gapOptions[gapTemp - 1]} min` : 'Loading...'}>
<Button className={classes.controlBtn} onClick={zoomIn} disabled={gapTemp === 0}>
<IconZoomIn size={px('1.2rem')} stroke={1.5} />
</Button>
</Tooltip>
<Tooltip
label={gapOptions[gapTemp + 1] ? `Change Block time to ${gapOptions[gapTemp + 1]} min` : 'Loading...'}>
<Button
className={classes.controlBtn}
onClick={zoomOut}
disabled={
gapTemp === gapOptions.length - 1 ||
gapOptions[gapTemp + 1] >=
dayjs(subLogQuery.get().endTime).diff(dayjs(subLogQuery.get().startTime), 'minute')
}>
<IconZoomOut size={px('1.2rem')} stroke={1.5} />
</Button>
</Tooltip>
</Box>

<Carousel
p={'sm'}
py={'sm'}
px={50}
height={36}
slideSize="11.1%"
slideGap="sm"
align="start"
slidesToScroll={9}
onSlideChange={onSlideChange}
styles={{
viewport: {
overflow: 'unset',
overflowX: 'clip',
},
}}>
{slots.current?.map((slot) => (
<FillCarousel key={slot.id} {...slot} />
{slots?.map((slot) => (
<FillCarousel key={slot.id} {...slot} zoomIn={zoomIn}/>
))}

<Carousel.Slide>
Expand All @@ -210,15 +230,15 @@ const HeaderPagination: FC = () => {
}}
disabled={Boolean(
subLogQuery.get().startTime &&
slots.current &&
dayjs(slots.current[slots.current.length - 1].endtime)
slots.length &&
dayjs(slots[slots.length - 1].endtime)
.subtract(gapMinute + 1, 'minute')
.toDate() <= subLogQuery.get().startTime,
)}
onClick={loadMore}>
{subLogQuery.get().endTime &&
slots.current &&
dayjs(slots.current[slots.current.length - 1].endtime)
slots.length &&
dayjs(slots[slots.length - 1].endtime)
.subtract(gapMinute + 1, 'minute')
.toDate() <= subLogQuery.get().startTime
? 'No More Data'
Expand Down
Loading
Loading