From c8fb3130042c9a06672b2289b5f9b04475445101 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nuno=20G=C3=B3is?= Date: Mon, 8 Jan 2024 15:43:24 +0000 Subject: [PATCH] chore: incoming webhook token hooks (#5790) https://linear.app/unleash/issue/2-1814/create-new-incoming-webhook-token-hooks-on-the-frontend Adds incoming webhook token hooks to help us with CRUD operations on the frontend. --- .../useIncomingWebhookTokensApi.ts | 77 +++++++++++++++++++ .../useIncomingWebhookTokens.ts | 36 +++++++++ frontend/src/interfaces/incomingWebhook.ts | 8 ++ 3 files changed, 121 insertions(+) create mode 100644 frontend/src/hooks/api/actions/useIncomingWebhookTokensApi/useIncomingWebhookTokensApi.ts create mode 100644 frontend/src/hooks/api/getters/useIncomingWebhookTokens/useIncomingWebhookTokens.ts diff --git a/frontend/src/hooks/api/actions/useIncomingWebhookTokensApi/useIncomingWebhookTokensApi.ts b/frontend/src/hooks/api/actions/useIncomingWebhookTokensApi/useIncomingWebhookTokensApi.ts new file mode 100644 index 0000000000..1e8b6ad179 --- /dev/null +++ b/frontend/src/hooks/api/actions/useIncomingWebhookTokensApi/useIncomingWebhookTokensApi.ts @@ -0,0 +1,77 @@ +import { IIncomingWebhookToken } from 'interfaces/incomingWebhook'; +import useAPI from '../useApi/useApi'; + +const ENDPOINT = 'api/admin/incoming-webhooks'; + +export type AddOrUpdateIncomingWebhookToken = Omit< + IIncomingWebhookToken, + 'id' | 'incomingWebhookId' | 'createdAt' | 'createdByUserId' +>; + +export type IncomingWebhookTokenWithTokenSecret = IIncomingWebhookToken & { + token: string; +}; + +export const useIncomingWebhookTokensApi = () => { + const { loading, makeRequest, createRequest, errors } = useAPI({ + propagateErrors: true, + }); + + const addIncomingWebhookToken = async ( + incomingWebhookId: number, + incomingWebhookToken: AddOrUpdateIncomingWebhookToken, + ): Promise => { + const requestId = 'addIncomingWebhookToken'; + const req = createRequest( + `${ENDPOINT}/${incomingWebhookId}/tokens`, + { + method: 'POST', + body: JSON.stringify(incomingWebhookToken), + }, + requestId, + ); + + const response = await makeRequest(req.caller, req.id); + return response.json(); + }; + + const updateIncomingWebhookToken = async ( + incomingWebhookId: number, + incomingWebhookTokenId: number, + incomingWebhookToken: AddOrUpdateIncomingWebhookToken, + ) => { + const requestId = 'updateIncomingWebhookToken'; + const req = createRequest( + `${ENDPOINT}/${incomingWebhookId}/tokens/${incomingWebhookTokenId}`, + { + method: 'PUT', + body: JSON.stringify(incomingWebhookToken), + }, + requestId, + ); + + await makeRequest(req.caller, req.id); + }; + + const removeIncomingWebhookToken = async ( + incomingWebhookId: number, + incomingWebhookTokenId: number, + ) => { + const requestId = 'removeIncomingWebhookToken'; + const req = createRequest( + `${ENDPOINT}/${incomingWebhookId}/tokens/${incomingWebhookTokenId}`, + { method: 'DELETE' }, + requestId, + ); + + await makeRequest(req.caller, req.id); + }; + + return { + addIncomingWebhookToken, + updateIncomingWebhookToken, + removeIncomingWebhookToken, + errors, + loading, + }; +}; diff --git a/frontend/src/hooks/api/getters/useIncomingWebhookTokens/useIncomingWebhookTokens.ts b/frontend/src/hooks/api/getters/useIncomingWebhookTokens/useIncomingWebhookTokens.ts new file mode 100644 index 0000000000..c9283c18d1 --- /dev/null +++ b/frontend/src/hooks/api/getters/useIncomingWebhookTokens/useIncomingWebhookTokens.ts @@ -0,0 +1,36 @@ +import { useMemo } from 'react'; +import { formatApiPath } from 'utils/formatPath'; +import handleErrorResponses from '../httpErrorResponseHandler'; +import { useConditionalSWR } from '../useConditionalSWR/useConditionalSWR'; +import useUiConfig from '../useUiConfig/useUiConfig'; +import { IIncomingWebhookToken } from 'interfaces/incomingWebhook'; + +const ENDPOINT = 'api/admin/incoming-webhooks'; + +export const useIncomingWebhookTokens = (incomingWebhookId: number) => { + const { isEnterprise } = useUiConfig(); + + const { data, error, mutate } = useConditionalSWR( + isEnterprise(), + { incomingWebhookTokens: [] }, + formatApiPath(`${ENDPOINT}/${incomingWebhookId}/tokens`), + fetcher, + ); + + return useMemo( + () => ({ + incomingWebhookTokens: (data?.incomingWebhooks ?? + []) as IIncomingWebhookToken[], + loading: !error && !data, + refetch: () => mutate(), + error, + }), + [data, error, mutate], + ); +}; + +const fetcher = (path: string) => { + return fetch(path) + .then(handleErrorResponses('Incoming webhook tokens')) + .then((res) => res.json()); +}; diff --git a/frontend/src/interfaces/incomingWebhook.ts b/frontend/src/interfaces/incomingWebhook.ts index 2fabb45686..d53c578be1 100644 --- a/frontend/src/interfaces/incomingWebhook.ts +++ b/frontend/src/interfaces/incomingWebhook.ts @@ -5,3 +5,11 @@ export interface IIncomingWebhook { createdAt: string; createdByUserId: number; } + +export interface IIncomingWebhookToken { + id: number; + name: string; + incomingWebhookId: number; + createdAt: string; + createdByUserId: number; +}