1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-09-24 17:51:14 +02:00
unleash.unleash/frontend/src/component/incomingWebhooks/IncomingWebhooksModal/IncomingWebhooksModal.tsx
Nuno Góis 5b56fac66f
Chore inc webhooks modal form (#5938)
https://linear.app/unleash/issue/2-1818/ui-create-incoming-webhook-newedit-modal

Adds the incoming webhooks modal form, which allows users to create and
edit incoming webhooks, along with their respective tokens.

Follows a logic similar to service accounts and their tokens, and tries
to use the newest form validation flow that we implemented in the roles
form.


![image](https://github.com/Unleash/unleash/assets/14320932/5d37a72e-2777-4c8b-b71b-3c0610959a52)
2024-01-18 11:38:05 +00:00

185 lines
6.2 KiB
TypeScript

import { FormEvent, useEffect } from 'react';
import { Button, styled } from '@mui/material';
import { SidebarModal } from 'component/common/SidebarModal/SidebarModal';
import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
import FormTemplate from 'component/common/FormTemplate/FormTemplate';
import useToast from 'hooks/useToast';
import { formatUnknownError } from 'utils/formatUnknownError';
import { IIncomingWebhook } from 'interfaces/incomingWebhook';
import { useIncomingWebhooks } from 'hooks/api/getters/useIncomingWebhooks/useIncomingWebhooks';
import {
IncomingWebhookPayload,
useIncomingWebhooksApi,
} from 'hooks/api/actions/useIncomingWebhooksApi/useIncomingWebhooksApi';
import { useIncomingWebhookTokensApi } from 'hooks/api/actions/useIncomingWebhookTokensApi/useIncomingWebhookTokensApi';
import { IncomingWebhooksForm } from './IncomingWebhooksForm/IncomingWebhooksForm';
import {
TokenGeneration,
useIncomingWebhooksForm,
} from './IncomingWebhooksForm/useIncomingWebhooksForm';
const StyledForm = styled('form')(() => ({
display: 'flex',
flexDirection: 'column',
height: '100%',
}));
const StyledButtonContainer = styled('div')(({ theme }) => ({
marginTop: 'auto',
display: 'flex',
justifyContent: 'flex-end',
paddingTop: theme.spacing(4),
}));
const StyledCancelButton = styled(Button)(({ theme }) => ({
marginLeft: theme.spacing(3),
}));
interface IIncomingWebhooksModalProps {
incomingWebhook?: IIncomingWebhook;
open: boolean;
setOpen: React.Dispatch<React.SetStateAction<boolean>>;
newToken: (token: string) => void;
}
export const IncomingWebhooksModal = ({
incomingWebhook,
open,
setOpen,
newToken,
}: IIncomingWebhooksModalProps) => {
const { refetch } = useIncomingWebhooks();
const { addIncomingWebhook, updateIncomingWebhook, loading } =
useIncomingWebhooksApi();
const { addIncomingWebhookToken } = useIncomingWebhookTokensApi();
const { setToastData, setToastApiError } = useToast();
const { uiConfig } = useUiConfig();
const {
enabled,
setEnabled,
name,
setName,
description,
setDescription,
tokenGeneration,
setTokenGeneration,
tokenName,
setTokenName,
errors,
validateName,
validateTokenName,
validate,
validated,
reloadForm,
} = useIncomingWebhooksForm(incomingWebhook);
useEffect(() => {
reloadForm();
}, [open]);
const editing = incomingWebhook !== undefined;
const title = `${editing ? 'Edit' : 'New'} incoming webhook`;
const payload: IncomingWebhookPayload = {
enabled,
name,
description,
};
const formatApiCode = () => `curl --location --request ${
editing ? 'PUT' : 'POST'
} '${uiConfig.unleashUrl}/api/admin/incoming-webhooks${
editing ? `/${incomingWebhook.id}` : ''
}' \\
--header 'Authorization: INSERT_API_KEY' \\
--header 'Content-Type: application/json' \\
--data-raw '${JSON.stringify(payload, undefined, 2)}'`;
const onSubmit = async (e: FormEvent<HTMLFormElement>) => {
e.preventDefault();
if (!validate()) return;
try {
if (editing) {
await updateIncomingWebhook(incomingWebhook.id, payload);
} else {
const { id } = await addIncomingWebhook(payload);
if (tokenGeneration === TokenGeneration.NOW) {
const { token } = await addIncomingWebhookToken(id, {
name: tokenName,
});
newToken(token);
}
}
setToastData({
title: `Incoming webhook ${
editing ? 'updated' : 'added'
} successfully`,
type: 'success',
});
refetch();
setOpen(false);
} catch (error: unknown) {
setToastApiError(formatUnknownError(error));
}
};
return (
<SidebarModal
open={open}
onClose={() => {
setOpen(false);
}}
label={title}
>
<FormTemplate
loading={loading}
modal
title={title}
description='Incoming Webhooks allow third-party services to send observable events to Unleash.'
documentationLink='https://docs.getunleash.io/reference/incoming-webhooks'
documentationLinkLabel='Incoming webhooks documentation'
formatApiCode={formatApiCode}
>
<StyledForm onSubmit={onSubmit}>
<IncomingWebhooksForm
incomingWebhook={incomingWebhook}
enabled={enabled}
setEnabled={setEnabled}
name={name}
setName={setName}
description={description}
setDescription={setDescription}
tokenGeneration={tokenGeneration}
setTokenGeneration={setTokenGeneration}
tokenName={tokenName}
setTokenName={setTokenName}
errors={errors}
validateName={validateName}
validateTokenName={validateTokenName}
validated={validated}
/>
<StyledButtonContainer>
<Button
type='submit'
variant='contained'
color='primary'
>
{editing ? 'Save' : 'Add'} incoming webhook
</Button>
<StyledCancelButton
onClick={() => {
setOpen(false);
}}
>
Cancel
</StyledCancelButton>
</StyledButtonContainer>
</StyledForm>
</FormTemplate>
</SidebarModal>
);
};