authorizer/dashboard/src/pages/Webhooks.tsx

370 lines
9.3 KiB
TypeScript
Raw Normal View History

2022-07-15 16:42:08 +00:00
import React, { useEffect, useState } from 'react';
import { useClient } from 'urql';
import {
Box,
Button,
Center,
Flex,
IconButton,
Menu,
MenuButton,
MenuList,
NumberDecrementStepper,
NumberIncrementStepper,
NumberInput,
NumberInputField,
NumberInputStepper,
Select,
Spinner,
Table,
TableCaption,
Tag,
Tbody,
Td,
Text,
Th,
Thead,
Tooltip,
Tr,
} from '@chakra-ui/react';
import {
FaAngleDoubleLeft,
FaAngleDoubleRight,
FaAngleDown,
FaAngleLeft,
FaAngleRight,
FaExclamationCircle,
} from 'react-icons/fa';
2022-07-16 09:54:50 +00:00
import UpdateWebhookModal from '../components/UpdateWebhookModal';
import {
pageLimits,
WebhookInputDataFields,
UpdateModalViews,
2022-07-16 09:54:50 +00:00
} from '../constants';
2022-07-15 16:42:08 +00:00
import { WebhooksDataQuery } from '../graphql/queries';
2022-07-16 10:29:21 +00:00
import DeleteWebhookModal from '../components/DeleteWebhookModal';
2022-07-16 17:40:05 +00:00
import ViewWebhookLogsModal from '../components/ViewWebhookLogsModal';
2022-07-15 16:42:08 +00:00
interface paginationPropTypes {
limit: number;
page: number;
offset: number;
total: number;
maxPages: number;
}
interface webhookDataTypes {
[WebhookInputDataFields.ID]: string;
[WebhookInputDataFields.EVENT_NAME]: string;
[WebhookInputDataFields.ENDPOINT]: string;
[WebhookInputDataFields.ENABLED]: boolean;
[WebhookInputDataFields.HEADERS]?: Record<string, string>;
}
2022-07-14 18:11:44 +00:00
const Webhooks = () => {
2022-07-15 16:42:08 +00:00
const client = useClient();
const [loading, setLoading] = useState<boolean>(false);
const [webhookData, setWebhookData] = useState<webhookDataTypes[]>([]);
const [paginationProps, setPaginationProps] = useState<paginationPropTypes>({
limit: 5,
page: 1,
offset: 0,
total: 0,
maxPages: 1,
});
const getMaxPages = (pagination: paginationPropTypes) => {
const { limit, total } = pagination;
if (total > 1) {
return total % limit === 0
? total / limit
: parseInt(`${total / limit}`) + 1;
} else return 1;
};
const fetchWebookData = async () => {
setLoading(true);
2022-07-16 04:23:29 +00:00
const res = await client
.query(WebhooksDataQuery, {
params: {
pagination: {
limit: paginationProps.limit,
page: paginationProps.page,
},
},
})
.toPromise();
2022-07-15 16:42:08 +00:00
if (res.data?._webhooks) {
const { pagination, webhooks } = res.data?._webhooks;
const maxPages = getMaxPages(pagination);
if (webhooks?.length) {
setWebhookData(webhooks);
setPaginationProps({ ...paginationProps, ...pagination, maxPages });
} else {
if (paginationProps.page !== 1) {
setPaginationProps({
...paginationProps,
...pagination,
maxPages,
page: 1,
});
}
}
}
setLoading(false);
};
const paginationHandler = (value: Record<string, number>) => {
setPaginationProps({ ...paginationProps, ...value });
};
2022-07-16 17:40:05 +00:00
useEffect(() => {
2022-07-16 04:23:29 +00:00
fetchWebookData();
}, [paginationProps.page, paginationProps.limit]);
2022-07-14 18:11:44 +00:00
return (
<Box m="5" py="5" px="10" bg="white" rounded="md">
<Flex margin="2% 0" justifyContent="space-between" alignItems="center">
<Text fontSize="md" fontWeight="bold">
Webhooks
</Text>
2022-07-16 09:54:50 +00:00
<UpdateWebhookModal
view={UpdateModalViews.ADD}
2022-07-16 09:54:50 +00:00
fetchWebookData={fetchWebookData}
/>
2022-07-14 18:11:44 +00:00
</Flex>
2022-07-15 16:42:08 +00:00
{!loading ? (
webhookData.length ? (
<Table variant="simple">
<Thead>
<Tr>
<Th>Event Name</Th>
<Th>Endpoint</Th>
<Th>Enabled</Th>
<Th>Headers</Th>
<Th>Actions</Th>
</Tr>
</Thead>
<Tbody>
2022-07-16 17:40:05 +00:00
{webhookData.map((webhook: webhookDataTypes) => (
2022-07-15 16:42:08 +00:00
<Tr
key={webhook[WebhookInputDataFields.ID]}
style={{ fontSize: 14 }}
>
<Td maxW="300">
{webhook[WebhookInputDataFields.EVENT_NAME]}
</Td>
<Td>{webhook[WebhookInputDataFields.ENDPOINT]}</Td>
<Td>
<Tag
size="sm"
variant="outline"
colorScheme={
webhook[WebhookInputDataFields.ENABLED]
? 'green'
: 'yellow'
}
>
{webhook[WebhookInputDataFields.ENABLED].toString()}
</Tag>
</Td>
<Td>
2022-07-16 04:12:10 +00:00
<Tooltip
bg="gray.300"
color="black"
label={JSON.stringify(
2022-07-16 09:54:50 +00:00
webhook[WebhookInputDataFields.HEADERS],
null,
2022-10-02 17:06:57 +00:00
' ',
2022-07-16 04:12:10 +00:00
)}
>
2022-07-16 17:40:05 +00:00
<Tag size="sm" variant="outline" colorScheme="gray">
{Object.keys(
2022-10-02 17:06:57 +00:00
webhook[WebhookInputDataFields.HEADERS] || {},
2022-07-16 17:40:05 +00:00
)?.length.toString()}
</Tag>
2022-07-16 04:12:10 +00:00
</Tooltip>
2022-07-15 16:42:08 +00:00
</Td>
<Td>
<Menu>
<MenuButton as={Button} variant="unstyled" size="sm">
<Flex
justifyContent="space-between"
alignItems="center"
>
<Text fontSize="sm" fontWeight="light">
Menu
</Text>
<FaAngleDown style={{ marginLeft: 10 }} />
</Flex>
</MenuButton>
<MenuList>
2022-07-16 09:54:50 +00:00
<UpdateWebhookModal
view={UpdateModalViews.Edit}
2022-07-16 09:54:50 +00:00
selectedWebhook={webhook}
fetchWebookData={fetchWebookData}
/>
2022-07-16 10:29:21 +00:00
<DeleteWebhookModal
webhookId={webhook[WebhookInputDataFields.ID]}
eventName={webhook[WebhookInputDataFields.EVENT_NAME]}
fetchWebookData={fetchWebookData}
/>
2022-07-16 17:40:05 +00:00
<ViewWebhookLogsModal
webhookId={webhook[WebhookInputDataFields.ID]}
eventName={webhook[WebhookInputDataFields.EVENT_NAME]}
/>
2022-07-15 16:42:08 +00:00
</MenuList>
</Menu>
</Td>
</Tr>
))}
</Tbody>
{(paginationProps.maxPages > 1 || paginationProps.total >= 5) && (
<TableCaption>
<Flex
justifyContent="space-between"
alignItems="center"
m="2% 0"
>
<Flex flex="1">
<Tooltip label="First Page">
<IconButton
aria-label="icon button"
onClick={() =>
paginationHandler({
page: 1,
})
}
isDisabled={paginationProps.page <= 1}
mr={4}
icon={<FaAngleDoubleLeft />}
/>
</Tooltip>
<Tooltip label="Previous Page">
<IconButton
aria-label="icon button"
onClick={() =>
paginationHandler({
page: paginationProps.page - 1,
})
}
isDisabled={paginationProps.page <= 1}
icon={<FaAngleLeft />}
/>
</Tooltip>
</Flex>
<Flex
flex="8"
justifyContent="space-evenly"
alignItems="center"
>
<Text mr={8}>
Page{' '}
<Text fontWeight="bold" as="span">
{paginationProps.page}
</Text>{' '}
of{' '}
<Text fontWeight="bold" as="span">
{paginationProps.maxPages}
</Text>
</Text>
<Flex alignItems="center">
<Text flexShrink="0">Go to page:</Text>{' '}
<NumberInput
ml={2}
mr={8}
w={28}
min={1}
max={paginationProps.maxPages}
onChange={(value) =>
paginationHandler({
page: parseInt(value),
})
}
value={paginationProps.page}
>
<NumberInputField />
<NumberInputStepper>
<NumberIncrementStepper />
<NumberDecrementStepper />
</NumberInputStepper>
</NumberInput>
</Flex>
<Select
w={32}
value={paginationProps.limit}
onChange={(e) =>
paginationHandler({
page: 1,
limit: parseInt(e.target.value),
})
}
>
{pageLimits.map((pageSize) => (
<option key={pageSize} value={pageSize}>
Show {pageSize}
</option>
))}
</Select>
</Flex>
<Flex flex="1">
<Tooltip label="Next Page">
<IconButton
aria-label="icon button"
onClick={() =>
paginationHandler({
page: paginationProps.page + 1,
})
}
isDisabled={
paginationProps.page >= paginationProps.maxPages
}
icon={<FaAngleRight />}
/>
</Tooltip>
<Tooltip label="Last Page">
<IconButton
aria-label="icon button"
onClick={() =>
paginationHandler({
page: paginationProps.maxPages,
})
}
isDisabled={
paginationProps.page >= paginationProps.maxPages
}
ml={4}
icon={<FaAngleDoubleRight />}
/>
</Tooltip>
</Flex>
</Flex>
</TableCaption>
)}
</Table>
) : (
<Flex
flexDirection="column"
minH="25vh"
justifyContent="center"
alignItems="center"
>
<Center w="50px" marginRight="1.5%">
<FaExclamationCircle style={{ color: '#f0f0f0', fontSize: 70 }} />
</Center>
<Text
fontSize="2xl"
paddingRight="1%"
fontWeight="bold"
color="#d9d9d9"
>
No Data
</Text>
</Flex>
)
) : (
<Center minH="25vh">
<Spinner />
</Center>
)}
2022-07-14 18:11:44 +00:00
</Box>
);
};
export default Webhooks;