100 lines
3.7 KiB
TypeScript
100 lines
3.7 KiB
TypeScript
import React, { useEffect } from 'react';
|
|
import { Loader, NoContent, Icon } from 'UI';
|
|
import WebhookForm from './WebhookForm';
|
|
import AnimatedSVG, { ICONS } from 'Shared/AnimatedSVG/AnimatedSVG';
|
|
import { toast } from 'react-toastify';
|
|
import { useStore } from 'App/mstore';
|
|
import { observer } from 'mobx-react-lite';
|
|
import { IWebhook } from 'Types/webhook';
|
|
import { App, List, Button, Typography, Space } from 'antd';
|
|
import { PencilIcon } from '.store/lucide-react-virtual-b029c146a4/package';
|
|
import usePageTitle from '@/hooks/usePageTitle';
|
|
import { useModal } from 'Components/ModalContext';
|
|
|
|
function Webhooks() {
|
|
const { settingsStore } = useStore();
|
|
const { webhooks, hooksLoading: loading } = settingsStore;
|
|
const { openModal, closeModal } = useModal();
|
|
const { modal } = App.useApp();
|
|
usePageTitle('Webhooks - OpenReplay Preferences');
|
|
const customWebhooks = webhooks.filter((h) => h.type === 'webhook');
|
|
|
|
useEffect(() => {
|
|
void settingsStore.fetchWebhooks();
|
|
}, []);
|
|
|
|
const init = (w?: Partial<IWebhook>) => {
|
|
settingsStore.initWebhook({...w});
|
|
openModal(<WebhookForm onClose={closeModal}
|
|
onDelete={removeWebhook} />, { title: w ? 'Edit Webhook' : 'Add Webhook' });
|
|
};
|
|
|
|
const removeWebhook = async (id: string) => {
|
|
modal.confirm({
|
|
title: 'Confirm',
|
|
content: 'Are you sure you want to remove this webhook?',
|
|
onOk: () => {
|
|
settingsStore.removeWebhook(id).then(() => toast.success('Webhook removed successfully'));
|
|
closeModal();
|
|
}
|
|
});
|
|
};
|
|
|
|
return (
|
|
<div className="bg-white rounded-lg shadow-sm border p-5">
|
|
<div className="flex items-center justify-between mb-4">
|
|
<div>
|
|
<Typography.Title level={4} style={{ marginBottom: 0 }}>Webhooks</Typography.Title>
|
|
<Typography.Text type="secondary">
|
|
<Space><Icon name="info-circle-fill" size={16} />
|
|
Leverage webhook notifications on alerts to trigger custom callbacks.</Space>
|
|
</Typography.Text>
|
|
</div>
|
|
<Button type="primary" onClick={() => init()}>Add Webhook</Button>
|
|
</div>
|
|
|
|
<Loader loading={loading}>
|
|
<NoContent
|
|
title={
|
|
<div className="flex flex-col items-center justify-center">
|
|
<AnimatedSVG name={ICONS.NO_WEBHOOKS} size={60} />
|
|
<div className="text-center my-4">None added yet</div>
|
|
</div>
|
|
}
|
|
size="small"
|
|
show={customWebhooks.length === 0}
|
|
>
|
|
<List
|
|
size="small"
|
|
dataSource={customWebhooks}
|
|
renderItem={(w) => (
|
|
<List.Item
|
|
onClick={() => init(w)}
|
|
className="p-2! group flex justify-between items-center cursor-pointer hover:bg-active-blue transition"
|
|
>
|
|
<Space direction="vertical" className="overflow-hidden w-full">
|
|
<Typography.Text style={{ textTransform: 'capitalize' }}>{w.name}</Typography.Text>
|
|
<Typography.Text
|
|
type="secondary"
|
|
ellipsis={{ tooltip: w.endpoint }}
|
|
style={{
|
|
width: '90%',
|
|
display: 'inline-block',
|
|
overflow: 'hidden',
|
|
whiteSpace: 'nowrap'
|
|
}}
|
|
>
|
|
{w.endpoint}
|
|
</Typography.Text>
|
|
</Space>
|
|
<Button type="text" className="invisible group-hover:visible" icon={<PencilIcon size={16} />} />
|
|
</List.Item>
|
|
)}
|
|
/>
|
|
</NoContent>
|
|
</Loader>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
export default observer(Webhooks);
|