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

chore: integrate react query #175

Merged
merged 12 commits into from
Jan 17, 2024
30 changes: 15 additions & 15 deletions src/api/users.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,26 @@
import { Axios } from "./axios";
import { USERS_LIST_URL, USER_PASSWORD_URL, USER_ROLES_URL, USER_URL } from "./constants";
import { Axios } from './axios';
import { USERS_LIST_URL, USER_PASSWORD_URL, USER_ROLES_URL, USER_URL } from './constants';

export const getUsers = () => {
return Axios().get(USERS_LIST_URL);
}
return Axios().get(USERS_LIST_URL);
};

export const postUser = (username: string, roles?: object[]) => {
return Axios().post(USER_URL(username), roles );
}
return Axios().post(USER_URL(username), roles);
};

export const deleteUser = (username: string) => {
return Axios().delete(USER_URL(username));
}
return Axios().delete(USER_URL(username));
};

export const putUserRoles = (username: string, roles: object[]) => {
return Axios().put(USER_ROLES_URL(username), roles);
}
export const putUserRoles = (username: string, roles: string[]) => {
return Axios().put(USER_ROLES_URL(username), roles);
};

export const getUserRoles = (username: string) => {
return Axios().get(USER_ROLES_URL(username));
}
return Axios().get(USER_ROLES_URL(username));
};

export const postUserResetPassword = (username: string) => {
return Axios().post(USER_PASSWORD_URL(username));
}
return Axios().post(USER_PASSWORD_URL(username));
};
10 changes: 6 additions & 4 deletions src/components/Header/RefreshInterval.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import useMountedState from '@/hooks/useMountedState';
import { REFRESH_INTERVALS, useHeaderContext } from '@/layouts/MainLayout/Context';
import { useHeaderContext } from '@/layouts/MainLayout/Context';
import { Button, Menu, Text, px } from '@mantine/core';
import { IconRefresh, IconRefreshOff } from '@tabler/icons-react';
import ms from 'ms';
import type { FC } from 'react';
import { useEffect, useMemo } from 'react';
import { useLogQueryStyles } from './styles';
import { REFRESH_INTERVALS } from '@/constants/timeConstants';

const RefreshInterval: FC = () => {
const {
Expand Down Expand Up @@ -38,9 +39,10 @@ const RefreshInterval: FC = () => {
<Text>{selectedInterval ? ms(selectedInterval) : 'Off'}</Text>
</Button>
</Menu.Target>
<Menu.Dropdown sx={{
zIndex: 1000,
}}>
<Menu.Dropdown
sx={{
zIndex: 1000,
}}>
{REFRESH_INTERVALS.map((interval) => {
if (interval === selectedInterval) return null;

Expand Down
3 changes: 2 additions & 1 deletion src/components/Header/TimeRange.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import useMountedState from '@/hooks/useMountedState';
import { FIXED_DURATIONS, useHeaderContext } from '@/layouts/MainLayout/Context';
import { useHeaderContext } from '@/layouts/MainLayout/Context';
import { Box, Button, Menu, Text, UnstyledButton, px } from '@mantine/core';
import { DateTimePicker } from '@mantine/dates';
import { IconClock } from '@tabler/icons-react';
import dayjs from 'dayjs';
import type { FC } from 'react';
import { Fragment, useEffect, useMemo } from 'react';
import { useLogQueryStyles } from './styles';
import { FIXED_DURATIONS } from '@/constants/timeConstants';

type FixedDurations = (typeof FIXED_DURATIONS)[number];

Expand Down
57 changes: 23 additions & 34 deletions src/components/Navbar/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,21 +18,20 @@ import {
import { FC, useEffect } from 'react';
import { useNavbarStyles } from './styles';
import { useLocation, useParams } from 'react-router-dom';
import { useGetLogStreamList } from '@/hooks/useGetLogStreamList';
import { notifications } from '@mantine/notifications';
import { useNavigate } from 'react-router-dom';
import { DEFAULT_FIXED_DURATIONS, useHeaderContext } from '@/layouts/MainLayout/Context';
import useMountedState from '@/hooks/useMountedState';
import dayjs from 'dayjs';
import { useDisclosure } from '@mantine/hooks';
import { USERS_MANAGEMENT_ROUTE } from '@/constants/routes';
import { useDeleteLogStream } from '@/hooks/useDeleteLogStream';
import InfoModal from './infoModal';
import { useGetUserRole } from '@/hooks/useGetUserRoles';
import { getStreamsSepcificAccess, getUserSepcificStreams } from './rolesHandler';
import { LogStreamData } from '@/@types/parseable/api/stream';
import Cookies from 'js-cookie';
import { NAVBAR_WIDTH } from '@/constants/theme';
import { useUser } from '@/hooks/useUser';
import { useLogStream } from '@/hooks/useLogStream';
const baseURL = import.meta.env.VITE_PARSEABLE_URL ?? '/';

const links = [
Expand Down Expand Up @@ -68,8 +67,11 @@ const Navbar: FC<NavbarProps> = (props) => {
const [opened, { open, close }] = useDisclosure(false);
const [openedDelete, { close: closeDelete, open: openDelete }] = useDisclosure();

const { data: streams, error, getData, resetData: resetStreamArray } = useGetLogStreamList();
const { data: deleteData, deleteLogStreamFun } = useDeleteLogStream();
const { deleteLogStreamMutation, getLogStreamListData, getLogStreamListIsError, getLogStreamListRefetch } =
useLogStream();

const { getUserRolesData, getUserRolesMutation } = useUser();

useEffect(() => {
const listener = subNavbarTogle.subscribe(setIsSubNavbarOpen);
return () => {
Expand Down Expand Up @@ -103,7 +105,7 @@ const Navbar: FC<NavbarProps> = (props) => {
handleChange(userSepecficStreams[0].name);
} else if (userSepecficStreams && !userSepecficStreams.find((stream: any) => stream.name === streamName)) {
notifications.show({
id: 'error-data',
id: 'getLogStreamListIsError-data',
color: 'red',
title: 'Error occurred',
message: `${streamName} stream not found`,
Expand All @@ -130,17 +132,18 @@ const Navbar: FC<NavbarProps> = (props) => {
navigate(`/${value}${page}`);
}
};

const handleChangeWithoutRiderection = (value: string, page: string = currentPage) => {
setActiveStream(value);
setSearchValue(value);
setCurrentPage(page);
const now = dayjs();
setUserSepecficAccess(getStreamsSepcificAccess(roles, value));
setUserSepecficAccess(getStreamsSepcificAccess(getUserRolesData?.data, value));
subLogQuery.set((state) => {
state.streamName = value || '';
state.startTime = now.subtract(DEFAULT_FIXED_DURATIONS.milliseconds, 'milliseconds').toDate();
state.endTime = now.toDate();
state.access = getStreamsSepcificAccess(roles, value);
state.access = getStreamsSepcificAccess(getUserRolesData?.data, value);
});
subLogSelectedTimeRange.set((state) => {
state.state = 'fixed';
Expand All @@ -159,37 +162,23 @@ const Navbar: FC<NavbarProps> = (props) => {
};

const handleDelete = () => {
deleteLogStreamFun(deleteStream);
deleteLogStreamMutation({ deleteStream });
closeDelete();
};

useEffect(() => {
if (deleteData) {
resetStreamArray();
getData();
return;
}
}, [deleteData]);

const { data: roles, getRoles, resetData } = useGetUserRole();
useEffect(() => {
if (username) {
getRoles(username);
}
return () => {
resetData();
};
}, [username]);

useEffect(() => {
if (streams && streams.length > 0 && roles) {
const userStreams = getUserSepcificStreams(roles, streams as any);
if (getLogStreamListData?.data && getLogStreamListData?.data.length > 0 && getUserRolesData?.data) {
const userStreams = getUserSepcificStreams(getUserRolesData?.data, getLogStreamListData?.data as any);
setUserSepecficStreams(userStreams as any);
} else {
setUserSepecficStreams([]);
setUserSepecficAccess(getStreamsSepcificAccess(roles));
setUserSepecficAccess(getStreamsSepcificAccess(getUserRolesData?.data));
}
}, [roles, streams]);
}, [getUserRolesData?.data, getLogStreamListData?.data]);

useEffect(() => {
getUserRolesMutation({ userName: username ? username : '' });
}, [username]);

const { classes } = useNavbarStyles();
const {
Expand Down Expand Up @@ -231,13 +220,13 @@ const Navbar: FC<NavbarProps> = (props) => {
required
className={selectStreambtn}
/>
{error && <div>{error}</div>}
{error && (
{getLogStreamListIsError && <div>{getLogStreamListIsError}</div>}
{getLogStreamListIsError && (
<NavLink
label="Retry"
icon={<IconReload size="1rem" stroke={1.5} />}
component="button"
onClick={getData}
onClick={() => getLogStreamListRefetch()}
sx={{ paddingLeft: 0 }}
/>
)}
Expand Down
57 changes: 24 additions & 33 deletions src/components/Navbar/infoModal.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Box, Button, Modal, Text, Tooltip, px } from '@mantine/core';
import { FC, useEffect, useMemo } from 'react';
import { useInfoModalStyles } from './styles';
import { useGetAbout } from '@/hooks/useGetAbout';
import { useAbout } from '@/hooks/useGetAbout';
import { IconAlertCircle, IconBook2, IconBrandGithub, IconBrandSlack, IconBusinessplan } from '@tabler/icons-react';
import { useHeaderContext } from '@/layouts/MainLayout/Context';

Expand Down Expand Up @@ -62,30 +62,21 @@ const InfoModal: FC<InfoModalProps> = (props) => {
state: { subInstanceConfig },
} = useHeaderContext();

const { data, loading, error, getAbout, resetData } = useGetAbout();
useEffect(() => {
if (data) {
resetData();
}
getAbout();
return () => {
resetData();
};
}, []);
const { getAboutData, getAboutIsError, getAboutIsLoading } = useAbout();

const llmStatus = useMemo(() => {
let status = 'LLM API Key not set';
if (data?.llmActive) {
status = `${data.llmProvider} configured`;
if (getAboutData?.data?.llmActive) {
status = `${getAboutData?.data.llmProvider} configured`;
}
return status;
}, [data?.llmActive]);
}, [getAboutData?.data?.llmActive]);

useEffect(() => {
if (data) {
subInstanceConfig.set(data);
if (getAboutData?.data) {
subInstanceConfig.set(getAboutData?.data);
}
}, [data]);
}, [getAboutData?.data]);

const { classes } = useInfoModalStyles();
const {
Expand All @@ -108,16 +99,16 @@ const InfoModal: FC<InfoModalProps> = (props) => {
<Text className={aboutDescription} id="info-modal-description">
Important info about your Parseable deployment
</Text>
{error ? (
{getAboutIsError ? (
<Text className={aboutDescription}>Error...</Text>
) : loading ? (
) : getAboutIsLoading ? (
<Text className={aboutDescription}>Loading...</Text>
) : data ? (
) : getAboutData?.data ? (
<>
<Box className={aboutTextBox}>
<Box className={aboutTextInnerBox}>
<Text className={aboutTextKey}> License: </Text>
<Text className={aboutTextValue}> {data.license} </Text>
<Text className={aboutTextValue}> {getAboutData?.data.license} </Text>
<Button
variant="outline"
component={'a'}
Expand All @@ -131,49 +122,49 @@ const InfoModal: FC<InfoModalProps> = (props) => {
<Box className={aboutTextBox}>
<Box className={aboutTextInnerBox}>
<Text className={aboutTextKey}> Commit: </Text>
<Text className={aboutTextValue}> {data.commit} </Text>
<Text className={aboutTextValue}> {getAboutData?.data.commit} </Text>
</Box>
<Box className={aboutTextInnerBox}>
<Text className={aboutTextKey}> Version: </Text>
<Text className={aboutTextValue}> {data.version} </Text>
{data.updateAvailable ? (
<Text className={aboutTextValue}> {getAboutData?.data.version} </Text>
{getAboutData?.data.updateAvailable ? (
<Button
variant="outline"
component={'a'}
href="https://github.com/parseablehq/parseable/releases/latest"
target="_blank"
className={actionBtnRed}
leftIcon={<IconAlertCircle size={px('1.2rem')} stroke={1.5} />}>
Upgrade to latest version {data.latestVersion}
Upgrade to latest version {getAboutData?.data.latestVersion}
</Button>
) : null}
</Box>
<Box className={aboutTextInnerBox}>
<Text className={aboutTextKey}> UI Version: </Text>
<Text className={aboutTextValue}> {data.uiVersion} </Text>
<Text className={aboutTextValue}> {getAboutData?.data.uiVersion} </Text>
</Box>
</Box>
<Box className={aboutTextBox}>
<Box className={aboutTextInnerBox}>
<Text className={aboutTextKey}> Deployment Id: </Text>
<Text className={aboutTextValue}> {data.deploymentId} </Text>
<Text className={aboutTextValue}> {getAboutData?.data.deploymentId} </Text>
</Box>
<Box className={aboutTextInnerBox}>
<Text className={aboutTextKey}>Mode</Text>
<Text className={aboutTextValue}>{data.mode}</Text>
<Text className={aboutTextValue}>{getAboutData?.data.mode}</Text>
</Box>
<Box className={aboutTextInnerBox}>
<Text className={aboutTextKey}>Staging</Text>
<Text className={aboutTextValue}>{data.staging}</Text>
<Text className={aboutTextValue}>{getAboutData?.data.staging}</Text>
</Box>
<Box className={aboutTextInnerBox}>
<Text className={aboutTextKey}>Store</Text>
<Text className={aboutTextValue}>{data.store}</Text>
<Text className={aboutTextValue}>{getAboutData?.data.store}</Text>
</Box>
<Box className={aboutTextInnerBox}>
<Text className={aboutTextKey}>Cache</Text>
<Text className={aboutTextValue}>{data.cache}</Text>
</Box>
<Text className={aboutTextKey}>Cache</Text>
<Text className={aboutTextValue}>{getAboutData?.data.cache}</Text>
</Box>
<Box className={aboutTextInnerBox}>
<Text className={aboutTextKey}>LLM Status</Text>
<Text className={aboutTextValue}>{llmStatus}</Text>
Expand Down
35 changes: 35 additions & 0 deletions src/constants/timeConstants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import dayjs from 'dayjs';

type FixedDuration = {
name: string;
milliseconds: number;
};

export const REFRESH_INTERVALS: number[] = [10000, 30000, 60000, 300000, 600000, 1200000];

export const FIXED_DURATIONS: ReadonlyArray<FixedDuration> = [
{
name: 'last 10 minutes',
milliseconds: dayjs.duration({ minutes: 10 }).asMilliseconds(),
},
{
name: 'last 1 hour',
milliseconds: dayjs.duration({ hours: 1 }).asMilliseconds(),
},
{
name: 'last 5 hours',
milliseconds: dayjs.duration({ hours: 5 }).asMilliseconds(),
},
{
name: 'last 24 hours',
milliseconds: dayjs.duration({ days: 1 }).asMilliseconds(),
},
{
name: 'last 3 days',
milliseconds: dayjs.duration({ days: 3 }).asMilliseconds(),
},
{
name: 'last 7 days',
milliseconds: dayjs.duration({ days: 7 }).asMilliseconds(),
},
] as const;
Loading