diff --git a/dashboard/src/components/AddWebhookModal.tsx b/dashboard/src/components/UpdateWebhookModal.tsx similarity index 80% rename from dashboard/src/components/AddWebhookModal.tsx rename to dashboard/src/components/UpdateWebhookModal.tsx index 4310681..80df822 100644 --- a/dashboard/src/components/AddWebhookModal.tsx +++ b/dashboard/src/components/UpdateWebhookModal.tsx @@ -1,4 +1,4 @@ -import React, { useState } from 'react'; +import React, { useEffect, useState } from 'react'; import { Button, Center, @@ -6,6 +6,7 @@ import { Input, InputGroup, InputRightElement, + MenuItem, Modal, ModalBody, ModalCloseButton, @@ -24,13 +25,14 @@ import { ArrayInputOperations, WebhookInputDataFields, WebhookInputHeaderFields, + UpdateWebhookModalViews, } from '../constants'; import { capitalizeFirstLetter, validateEventName, validateURI, } from '../utils'; -import { AddWebhook } from '../graphql/mutation'; +import { AddWebhook, EditWebhook } from '../graphql/mutation'; interface headersDataType { [WebhookInputHeaderFields.KEY]: string; @@ -42,6 +44,20 @@ interface headersValidatorDataType { [WebhookInputHeaderFields.VALUE]: boolean; } +interface selecetdWebhookDataTypes { + [WebhookInputDataFields.ID]: string; + [WebhookInputDataFields.EVENT_NAME]: string; + [WebhookInputDataFields.ENDPOINT]: string; + [WebhookInputDataFields.ENABLED]: boolean; + [WebhookInputDataFields.HEADERS]?: Record; +} + +interface UpdateWebhookModalInputPropTypes { + view: UpdateWebhookModalViews; + selectedWebhook?: selecetdWebhookDataTypes; + fetchWebookData: Function; +} + const initHeadersData: headersDataType = { [WebhookInputHeaderFields.KEY]: '', [WebhookInputHeaderFields.VALUE]: '', @@ -78,7 +94,11 @@ const initWebhookValidatorData: validatorDataType = { [WebhookInputDataFields.HEADERS]: [{ ...initHeadersValidatorData }], }; -const AddWebhookModal = () => { +const UpdateWebhookModal = ({ + view, + selectedWebhook, + fetchWebookData, +}: UpdateWebhookModalInputPropTypes) => { const client = useClient(); const toast = useToast(); const { isOpen, onOpen, onClose } = useDisclosure(); @@ -201,7 +221,13 @@ const AddWebhookModal = () => { const saveData = async () => { if (!validateData()) return; setLoading(true); - let { [WebhookInputDataFields.HEADERS]: _, ...params }: any = webhook; + let params: any = { + [WebhookInputDataFields.EVENT_NAME]: + webhook[WebhookInputDataFields.EVENT_NAME], + [WebhookInputDataFields.ENDPOINT]: + webhook[WebhookInputDataFields.ENDPOINT], + [WebhookInputDataFields.ENABLED]: webhook[WebhookInputDataFields.ENABLED], + }; if (webhook[WebhookInputDataFields.HEADERS].length) { const headers = webhook[WebhookInputDataFields.HEADERS].reduce( (acc, data) => { @@ -213,7 +239,22 @@ const AddWebhookModal = () => { params[WebhookInputDataFields.HEADERS] = headers; } } - const res = await client.mutation(AddWebhook, { params }).toPromise(); + let res: any = {}; + if ( + view === UpdateWebhookModalViews.Edit && + selectedWebhook?.[WebhookInputDataFields.ID] + ) { + res = await client + .mutation(EditWebhook, { + params: { + ...params, + id: selectedWebhook[WebhookInputDataFields.ID], + }, + }) + .toPromise(); + } else { + res = await client.mutation(AddWebhook, { params }).toPromise(); + } if (res.error) { toast({ title: capitalizeFirstLetter(res.error.message), @@ -223,9 +264,11 @@ const AddWebhookModal = () => { }); setLoading(false); return; - } else if (res.data?._add_webhook) { + } else if (res.data?._add_webhook || res.data?._update_webhook) { toast({ - title: capitalizeFirstLetter(res.data?._add_webhook.message), + title: capitalizeFirstLetter( + res.data?._add_webhook?.message || res.data?._update_webhook?.message + ), isClosable: true, status: 'success', position: 'bottom-right', @@ -236,25 +279,66 @@ const AddWebhookModal = () => { }); setValidator({ ...initWebhookValidatorData }); onClose(); + fetchWebookData(); } setLoading(false); }; + useEffect(() => { + if ( + view === UpdateWebhookModalViews.Edit && + selectedWebhook && + Object.keys(selectedWebhook || {}).length + ) { + const { headers, ...rest } = selectedWebhook; + const headerItems = Object.entries(headers || {}); + if (headerItems.length) { + let formattedHeadersData = headerItems.map((headerData) => { + return { + [WebhookInputHeaderFields.KEY]: headerData[0], + [WebhookInputHeaderFields.VALUE]: headerData[1], + }; + }); + setWebhook({ + ...rest, + [WebhookInputDataFields.HEADERS]: formattedHeadersData, + }); + setValidator({ + ...validator, + [WebhookInputDataFields.HEADERS]: new Array( + formattedHeadersData.length + ) + .fill({}) + .map(() => ({ ...initHeadersValidatorData })), + }); + } else { + setWebhook({ ...rest, [WebhookInputDataFields.HEADERS]: [] }); + } + } + }, [view]); return ( <> - + {view === UpdateWebhookModalViews.ADD ? ( + + ) : ( + Edit + )} - Add New Webhook + + {view === UpdateWebhookModalViews.ADD + ? 'Add New Webhook' + : 'Edit Webhook'} + { ); }; -export default AddWebhookModal; +export default UpdateWebhookModal; diff --git a/dashboard/src/constants.ts b/dashboard/src/constants.ts index f68aa8b..fb00802 100644 --- a/dashboard/src/constants.ts +++ b/dashboard/src/constants.ts @@ -167,4 +167,9 @@ export enum WebhookInputHeaderFields { VALUE = 'value', } +export enum UpdateWebhookModalViews { + ADD = 'add', + Edit = 'edit', +} + export const pageLimits: number[] = [5, 10, 15]; diff --git a/dashboard/src/graphql/mutation/index.ts b/dashboard/src/graphql/mutation/index.ts index 36cea16..ebb7d48 100644 --- a/dashboard/src/graphql/mutation/index.ts +++ b/dashboard/src/graphql/mutation/index.ts @@ -87,3 +87,11 @@ export const AddWebhook = ` } } `; + +export const EditWebhook = ` + mutation editWebhook($params: UpdateWebhookRequest!) { + _update_webhook(params: $params) { + message + } + } +`; diff --git a/dashboard/src/pages/Webhooks.tsx b/dashboard/src/pages/Webhooks.tsx index eaaffa2..5c81cb2 100644 --- a/dashboard/src/pages/Webhooks.tsx +++ b/dashboard/src/pages/Webhooks.tsx @@ -36,8 +36,12 @@ import { FaAngleRight, FaExclamationCircle, } from 'react-icons/fa'; -import AddWebhookModal from '../components/AddWebhookModal'; -import { pageLimits, WebhookInputDataFields } from '../constants'; +import UpdateWebhookModal from '../components/UpdateWebhookModal'; +import { + pageLimits, + WebhookInputDataFields, + UpdateWebhookModalViews, +} from '../constants'; import { WebhooksDataQuery } from '../graphql/queries'; interface paginationPropTypes { @@ -115,14 +119,16 @@ const Webhooks = () => { React.useEffect(() => { fetchWebookData(); }, [paginationProps.page, paginationProps.limit]); - console.log('webhookData ==>> ', webhookData); return ( Webhooks - + {!loading ? ( webhookData.length ? ( @@ -161,10 +167,13 @@ const Webhooks = () => {
{ - {}}>Edit + {}}>Delete {}}>View Logs