change(ui): remove webhook reducer
This commit is contained in:
parent
ef090aa696
commit
8d7d183041
13 changed files with 297 additions and 283 deletions
|
|
@ -2,9 +2,7 @@ import React, { useEffect, useState } from 'react';
|
|||
import { SlideModal } from 'UI';
|
||||
import { useStore } from 'App/mstore'
|
||||
import { observer } from 'mobx-react-lite'
|
||||
import { fetchList as fetchWebhooks } from 'Duck/webhook';
|
||||
import AlertForm from '../AlertForm';
|
||||
import { connect } from 'react-redux';
|
||||
import { SLACK, TEAMS, WEBHOOK } from 'App/constants/schedule';
|
||||
import { confirm } from 'UI';
|
||||
|
||||
|
|
@ -18,16 +16,14 @@ interface Props {
|
|||
showModal?: boolean;
|
||||
metricId?: number;
|
||||
onClose?: () => void;
|
||||
webhooks: any;
|
||||
fetchWebhooks: Function;
|
||||
}
|
||||
function AlertFormModal(props: Props) {
|
||||
const { alertsStore } = useStore()
|
||||
const { metricId = null, showModal = false, webhooks } = props;
|
||||
const { alertsStore, settingsStore } = useStore()
|
||||
const { metricId = null, showModal = false } = props;
|
||||
const [showForm, setShowForm] = useState(false);
|
||||
|
||||
const webhooks = settingsStore.webhooks
|
||||
useEffect(() => {
|
||||
props.fetchWebhooks();
|
||||
settingsStore.fetchWebhooks();
|
||||
}, []);
|
||||
|
||||
|
||||
|
|
@ -110,9 +106,4 @@ function AlertFormModal(props: Props) {
|
|||
);
|
||||
}
|
||||
|
||||
export default connect(
|
||||
(state) => ({
|
||||
webhooks: state.getIn(['webhooks', 'list']),
|
||||
}),
|
||||
{ fetchWebhooks }
|
||||
)(observer(AlertFormModal));
|
||||
export default observer(AlertFormModal);
|
||||
|
|
|
|||
|
|
@ -1,94 +1,74 @@
|
|||
import React from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { edit, save } from 'Duck/webhook';
|
||||
import { Form, Button, Input } from 'UI';
|
||||
import styles from './webhookForm.module.css';
|
||||
import { useStore } from 'App/mstore'
|
||||
import { observer } from 'mobx-react-lite'
|
||||
|
||||
@connect(
|
||||
(state) => ({
|
||||
webhook: state.getIn(['webhooks', 'instance']),
|
||||
loading: state.getIn(['webhooks', 'saveRequest', 'loading']),
|
||||
}),
|
||||
{
|
||||
edit,
|
||||
save,
|
||||
}
|
||||
)
|
||||
class WebhookForm extends React.PureComponent {
|
||||
setFocus = () => this.focusElement.focus();
|
||||
onChangeSelect = (event, { name, value }) => this.props.edit({ [name]: value });
|
||||
write = ({ target: { value, name } }) => this.props.edit({ [name]: value });
|
||||
function WebhookForm(props) {
|
||||
const { settingsStore } = useStore()
|
||||
const { webhookInst: webhook, hooksLoading: loading, saveWebhook, editWebhook } = settingsStore
|
||||
const write = ({ target: { value, name } }) => editWebhook({ [name]: value });
|
||||
|
||||
save = () => {
|
||||
this.props.save(this.props.webhook).then(() => {
|
||||
this.props.onClose();
|
||||
const save = () => {
|
||||
saveWebhook(webhook).then(() => {
|
||||
props.onClose();
|
||||
});
|
||||
};
|
||||
|
||||
render() {
|
||||
const { webhook, loading } = this.props;
|
||||
return (
|
||||
<div className="bg-white h-screen overflow-y-auto" style={{ width: '350px' }}>
|
||||
<h3 className="p-5 text-2xl">{webhook.exists() ? 'Update' : 'Add'} Webhook</h3>
|
||||
<Form className={styles.wrapper}>
|
||||
<Form.Field>
|
||||
<label>{'Name'}</label>
|
||||
<Input
|
||||
ref={(ref) => {
|
||||
this.focusElement = ref;
|
||||
}}
|
||||
name="name"
|
||||
value={webhook.name}
|
||||
onChange={this.write}
|
||||
placeholder="Name"
|
||||
/>
|
||||
</Form.Field>
|
||||
|
||||
<Form.Field>
|
||||
<label>{'Endpoint'}</label>
|
||||
<Input
|
||||
ref={(ref) => {
|
||||
this.focusElement = ref;
|
||||
}}
|
||||
name="endpoint"
|
||||
value={webhook.endpoint}
|
||||
onChange={this.write}
|
||||
placeholder="Endpoint"
|
||||
/>
|
||||
</Form.Field>
|
||||
return (
|
||||
<div className="bg-white h-screen overflow-y-auto" style={{ width: '350px' }}>
|
||||
<h3 className="p-5 text-2xl">{webhook.exists() ? 'Update' : 'Add'} Webhook</h3>
|
||||
<Form className={styles.wrapper}>
|
||||
<Form.Field>
|
||||
<label>{'Name'}</label>
|
||||
<Input
|
||||
name="name"
|
||||
value={webhook.name}
|
||||
onChange={write}
|
||||
placeholder="Name"
|
||||
/>
|
||||
</Form.Field>
|
||||
|
||||
<Form.Field>
|
||||
<label>{'Auth Header (optional)'}</label>
|
||||
<Input
|
||||
ref={(ref) => {
|
||||
this.focusElement = ref;
|
||||
}}
|
||||
name="authHeader"
|
||||
value={webhook.authHeader}
|
||||
onChange={this.write}
|
||||
placeholder="Auth Header"
|
||||
/>
|
||||
</Form.Field>
|
||||
<Form.Field>
|
||||
<label>{'Endpoint'}</label>
|
||||
<Input
|
||||
name="endpoint"
|
||||
value={webhook.endpoint}
|
||||
onChange={write}
|
||||
placeholder="Endpoint"
|
||||
/>
|
||||
</Form.Field>
|
||||
|
||||
<div className="flex justify-between">
|
||||
<div className="flex items-center">
|
||||
<Button
|
||||
onClick={this.save}
|
||||
disabled={!webhook.validate()}
|
||||
loading={loading}
|
||||
variant="primary"
|
||||
className="float-left mr-2"
|
||||
>
|
||||
{webhook.exists() ? 'Update' : 'Add'}
|
||||
</Button>
|
||||
{webhook.exists() && <Button onClick={this.props.onClose}>{'Cancel'}</Button>}
|
||||
</div>
|
||||
{webhook.exists() && <Button icon="trash" variant="text" onClick={() => this.props.onDelete(webhook.webhookId)}></Button>}
|
||||
<Form.Field>
|
||||
<label>{'Auth Header (optional)'}</label>
|
||||
<Input
|
||||
name="authHeader"
|
||||
value={webhook.authHeader}
|
||||
onChange={write}
|
||||
placeholder="Auth Header"
|
||||
/>
|
||||
</Form.Field>
|
||||
|
||||
<div className="flex justify-between">
|
||||
<div className="flex items-center">
|
||||
<Button
|
||||
onClick={save}
|
||||
disabled={!webhook.validate()}
|
||||
loading={loading}
|
||||
variant="primary"
|
||||
className="float-left mr-2"
|
||||
>
|
||||
{webhook.exists() ? 'Update' : 'Add'}
|
||||
</Button>
|
||||
{webhook.exists() && <Button onClick={props.onClose}>{'Cancel'}</Button>}
|
||||
</div>
|
||||
</Form>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
{webhook.exists() &&
|
||||
<Button icon="trash" variant="text" onClick={() => props.onDelete(webhook.webhookId)}></Button>}
|
||||
</div>
|
||||
</Form>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default WebhookForm;
|
||||
export default observer(WebhookForm);
|
||||
|
|
|
|||
|
|
@ -1,9 +1,7 @@
|
|||
import React, { useEffect } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import cn from 'classnames';
|
||||
import withPageTitle from 'HOCs/withPageTitle';
|
||||
import { Button, Loader, NoContent, Icon } from 'UI';
|
||||
import { init, fetchList, remove } from 'Duck/webhook';
|
||||
import WebhookForm from './WebhookForm';
|
||||
import ListItem from './ListItem';
|
||||
import styles from './webhooks.module.css';
|
||||
|
|
@ -11,79 +9,71 @@ import AnimatedSVG, { ICONS } from 'Shared/AnimatedSVG/AnimatedSVG';
|
|||
import { confirm } from 'UI';
|
||||
import { toast } from 'react-toastify';
|
||||
import { useModal } from 'App/components/Modal';
|
||||
import { useStore } from 'App/mstore';
|
||||
import { observer } from 'mobx-react-lite'
|
||||
|
||||
function Webhooks(props) {
|
||||
const { webhooks, loading } = props;
|
||||
const { showModal, hideModal } = useModal();
|
||||
function Webhooks() {
|
||||
const { settingsStore } = useStore()
|
||||
const { webhooks, hooksLoading: loading } = settingsStore;
|
||||
const { showModal, hideModal } = useModal();
|
||||
|
||||
const noSlackWebhooks = webhooks.filter((hook) => hook.type === 'webhook');
|
||||
useEffect(() => {
|
||||
props.fetchList();
|
||||
}, []);
|
||||
const noSlackWebhooks = webhooks.filter((hook) => hook.type === 'webhook');
|
||||
useEffect(() => {
|
||||
void settingsStore.fetchWebhooks();
|
||||
}, []);
|
||||
|
||||
const init = (v) => {
|
||||
props.init(v);
|
||||
showModal(<WebhookForm onClose={hideModal} onDelete={removeWebhook} />);
|
||||
};
|
||||
const init = (v) => {
|
||||
settingsStore.initWebhook(v);
|
||||
showModal(<WebhookForm onClose={hideModal} onDelete={removeWebhook} />);
|
||||
};
|
||||
|
||||
const removeWebhook = async (id) => {
|
||||
if (
|
||||
await confirm({
|
||||
header: 'Confirm',
|
||||
confirmButton: 'Yes, delete',
|
||||
confirmation: `Are you sure you want to remove this webhook?`,
|
||||
})
|
||||
) {
|
||||
props.remove(id).then(() => {
|
||||
toast.success('Webhook removed successfully');
|
||||
});
|
||||
hideModal();
|
||||
}
|
||||
};
|
||||
const removeWebhook = async (id) => {
|
||||
if (
|
||||
await confirm({
|
||||
header: 'Confirm',
|
||||
confirmButton: 'Yes, delete',
|
||||
confirmation: `Are you sure you want to remove this webhook?`,
|
||||
})
|
||||
) {
|
||||
settingsStore.removeWebhook(id).then(() => {
|
||||
toast.success('Webhook removed successfully');
|
||||
});
|
||||
hideModal();
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className={cn(styles.tabHeader, 'px-5 pt-5')}>
|
||||
<h3 className={cn(styles.tabTitle, 'text-2xl')}>{'Webhooks'}</h3>
|
||||
{/* <Button rounded={true} icon="plus" variant="outline" onClick={() => init()} /> */}
|
||||
<Button className="ml-auto" variant="primary" onClick={() => init()}>Add Webhook</Button>
|
||||
</div>
|
||||
|
||||
<div className="text-base text-disabled-text flex items-center my-3 px-5">
|
||||
<Icon name="info-circle-fill" className="mr-2" size={16} />
|
||||
Leverage webhooks to push OpenReplay data to other systems.
|
||||
</div>
|
||||
|
||||
<Loader loading={loading}>
|
||||
<NoContent
|
||||
title={
|
||||
<div className="flex flex-col items-center justify-center">
|
||||
<AnimatedSVG name={ICONS.NO_WEBHOOKS} size={80} />
|
||||
<div className="text-center text-gray-600 my-4">None added yet</div>
|
||||
return (
|
||||
<div>
|
||||
<div className={cn(styles.tabHeader, 'px-5 pt-5')}>
|
||||
<h3 className={cn(styles.tabTitle, 'text-2xl')}>{'Webhooks'}</h3>
|
||||
<Button className="ml-auto" variant="primary" onClick={() => init()}>Add Webhook</Button>
|
||||
</div>
|
||||
}
|
||||
size="small"
|
||||
show={noSlackWebhooks.size === 0}
|
||||
>
|
||||
<div className="cursor-pointer">
|
||||
{noSlackWebhooks.map((webhook) => (
|
||||
<ListItem key={webhook.key} webhook={webhook} onEdit={() => init(webhook)} />
|
||||
))}
|
||||
</div>
|
||||
</NoContent>
|
||||
</Loader>
|
||||
</div>
|
||||
);
|
||||
|
||||
<div className="text-base text-disabled-text flex items-center my-3 px-5">
|
||||
<Icon name="info-circle-fill" className="mr-2" size={16} />
|
||||
Leverage webhooks to push OpenReplay data to other systems.
|
||||
</div>
|
||||
|
||||
<Loader loading={loading}>
|
||||
<NoContent
|
||||
title={
|
||||
<div className="flex flex-col items-center justify-center">
|
||||
<AnimatedSVG name={ICONS.NO_WEBHOOKS} size={80} />
|
||||
<div className="text-center text-gray-600 my-4">None added yet</div>
|
||||
</div>
|
||||
}
|
||||
size="small"
|
||||
show={noSlackWebhooks.length === 0}
|
||||
>
|
||||
<div className="cursor-pointer">
|
||||
{noSlackWebhooks.map((webhook) => (
|
||||
<ListItem key={webhook.key} webhook={webhook} onEdit={() => init(webhook)} />
|
||||
))}
|
||||
</div>
|
||||
</NoContent>
|
||||
</Loader>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default connect(
|
||||
(state) => ({
|
||||
webhooks: state.getIn(['webhooks', 'list']),
|
||||
loading: state.getIn(['webhooks', 'loading']),
|
||||
}),
|
||||
{
|
||||
init,
|
||||
fetchList,
|
||||
remove,
|
||||
}
|
||||
)(withPageTitle('Webhooks - OpenReplay Preferences')(Webhooks));
|
||||
export default withPageTitle('Webhooks - OpenReplay Preferences')(observer(Webhooks));
|
||||
|
|
|
|||
|
|
@ -1,25 +1,21 @@
|
|||
import React from 'react';
|
||||
import { NoContent, Pagination, Icon } from 'UI';
|
||||
import { NoContent, Pagination } from 'UI';
|
||||
import { filterList } from 'App/utils';
|
||||
import { sliceListPerPage } from 'App/utils';
|
||||
import { connect } from 'react-redux';
|
||||
import { fetchList as fetchWebhooks } from 'Duck/webhook';
|
||||
import AnimatedSVG, { ICONS } from 'Shared/AnimatedSVG/AnimatedSVG';
|
||||
import AlertListItem from './AlertListItem'
|
||||
import { useStore } from 'App/mstore'
|
||||
import { observer } from 'mobx-react-lite'
|
||||
import Alert from 'Types/alert'
|
||||
|
||||
const pageSize = 10;
|
||||
|
||||
interface Props {
|
||||
siteId: string;
|
||||
webhooks: Array<any>;
|
||||
fetchWebhooks: () => void;
|
||||
}
|
||||
|
||||
function AlertsList({ siteId, fetchWebhooks, webhooks }: Props) {
|
||||
const { alertsStore } = useStore();
|
||||
function AlertsList({ siteId }: Props) {
|
||||
const { alertsStore, settingsStore } = useStore();
|
||||
const { fetchWebhooks, webhooks } = settingsStore
|
||||
const { alerts: alertsList, alertsSearch, fetchList, init } = alertsStore
|
||||
|
||||
React.useEffect(() => { fetchList(); fetchWebhooks() }, []);
|
||||
|
|
@ -72,10 +68,4 @@ function AlertsList({ siteId, fetchWebhooks, webhooks }: Props) {
|
|||
);
|
||||
}
|
||||
|
||||
export default connect(
|
||||
(state) => ({
|
||||
// @ts-ignore
|
||||
webhooks: state.getIn(['webhooks', 'list']),
|
||||
}),
|
||||
{ fetchWebhooks }
|
||||
)(observer(AlertsList));
|
||||
export default observer(AlertsList);
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ import { validateEmail } from 'App/validate';
|
|||
import { confirm } from 'UI';
|
||||
import { toast } from 'react-toastify';
|
||||
import { SLACK, WEBHOOK, TEAMS } from 'App/constants/schedule';
|
||||
import { fetchList as fetchWebhooks } from 'Duck/webhook';
|
||||
import Breadcrumb from 'Shared/Breadcrumb';
|
||||
import { withSiteId, alerts } from 'App/routes';
|
||||
import { withRouter, RouteComponentProps } from 'react-router-dom';
|
||||
|
|
@ -57,17 +56,15 @@ interface Select {
|
|||
interface IProps extends RouteComponentProps {
|
||||
siteId: string;
|
||||
slackChannels: any[];
|
||||
webhooks: any[];
|
||||
loading: boolean;
|
||||
deleting: boolean;
|
||||
triggerOptions: any[];
|
||||
list: any;
|
||||
onSubmit: (instance: Alert) => void;
|
||||
fetchWebhooks: () => void;
|
||||
}
|
||||
|
||||
const NewAlert = (props: IProps) => {
|
||||
const { alertsStore } = useStore();
|
||||
const { alertsStore, settingsStore } = useStore();
|
||||
const {
|
||||
fetchTriggerOptions,
|
||||
init,
|
||||
|
|
@ -81,11 +78,10 @@ const NewAlert = (props: IProps) => {
|
|||
loading,
|
||||
} = alertsStore
|
||||
const deleting = loading
|
||||
|
||||
const webhooks = settingsStore.webhooks
|
||||
const fetchWebhooks = settingsStore.fetchWebhooks
|
||||
const {
|
||||
siteId,
|
||||
webhooks,
|
||||
fetchWebhooks,
|
||||
} = props;
|
||||
|
||||
useEffect(() => {
|
||||
|
|
@ -288,12 +284,4 @@ const NewAlert = (props: IProps) => {
|
|||
);
|
||||
};
|
||||
|
||||
export default withRouter(
|
||||
connect(
|
||||
(state) => ({
|
||||
// @ts-ignore
|
||||
webhooks: state.getIn(['webhooks', 'list']),
|
||||
}),
|
||||
{ fetchWebhooks }
|
||||
)(observer(NewAlert))
|
||||
);
|
||||
export default withRouter(observer(NewAlert))
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@ import sources from './sources';
|
|||
import members from './member';
|
||||
import site from './site';
|
||||
import customFields from './customField';
|
||||
import webhooks from './webhook';
|
||||
import integrations from './integrations';
|
||||
import rehydrate from './rehydrate';
|
||||
import errors from './errors';
|
||||
|
|
@ -36,7 +35,6 @@ const rootReducer = combineReducers({
|
|||
members,
|
||||
site,
|
||||
customFields,
|
||||
webhooks,
|
||||
rehydrate,
|
||||
errors,
|
||||
funnels,
|
||||
|
|
|
|||
|
|
@ -1,7 +0,0 @@
|
|||
import Webhook from 'Types/webhook';
|
||||
import crudDuckGenerator from './tools/crudDuck';
|
||||
|
||||
const crudDuck = crudDuckGenerator('webhook', Webhook, { idKey: 'webhookId' });
|
||||
export const { fetchList, init, edit, save, remove } = crudDuck.actions;
|
||||
|
||||
export default crudDuck.reducer;
|
||||
|
|
@ -6,17 +6,7 @@ import RoleStore from './roleStore';
|
|||
import APIClient from 'App/api_client';
|
||||
import FunnelStore from './funnelStore';
|
||||
import {
|
||||
dashboardService,
|
||||
metricService,
|
||||
sessionService,
|
||||
userService,
|
||||
auditService,
|
||||
funnelService,
|
||||
errorService,
|
||||
notesService,
|
||||
recordingsService,
|
||||
configService,
|
||||
alertsService,
|
||||
services
|
||||
} from 'App/services';
|
||||
import SettingsStore from './settingsStore';
|
||||
import AuditStore from './auditStore';
|
||||
|
|
@ -69,17 +59,9 @@ export class RootStore {
|
|||
|
||||
initClient() {
|
||||
const client = new APIClient();
|
||||
dashboardService.initClient(client);
|
||||
metricService.initClient(client);
|
||||
funnelService.initClient(client);
|
||||
sessionService.initClient(client);
|
||||
userService.initClient(client);
|
||||
auditService.initClient(client);
|
||||
errorService.initClient(client);
|
||||
notesService.initClient(client)
|
||||
recordingsService.initClient(client);
|
||||
configService.initClient(client);
|
||||
alertsService.initClient(client)
|
||||
services.forEach(service => {
|
||||
service.initClient(client);
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,44 +2,89 @@ import { makeAutoObservable, observable, action } from "mobx"
|
|||
import SessionSettings from "./types/sessionSettings"
|
||||
import { sessionService } from "App/services"
|
||||
import { toast } from 'react-toastify';
|
||||
import Webhook, { IWebhook } from 'Types/webhook';
|
||||
import {
|
||||
webhookService
|
||||
} from 'App/services';
|
||||
import Alert, { IAlert } from "Types/alert";
|
||||
|
||||
export default class SettingsStore {
|
||||
loadingCaptureRate: boolean = false;
|
||||
sessionSettings: SessionSettings = new SessionSettings()
|
||||
captureRateFetched: boolean = false;
|
||||
limits: any = null;
|
||||
loadingCaptureRate: boolean = false;
|
||||
sessionSettings: SessionSettings = new SessionSettings()
|
||||
captureRateFetched: boolean = false;
|
||||
limits: any = null;
|
||||
|
||||
constructor() {
|
||||
makeAutoObservable(this, {
|
||||
sessionSettings: observable,
|
||||
webhooks: Webhook[] = []
|
||||
webhookInst = new Webhook()
|
||||
|
||||
hooksLoading = false
|
||||
|
||||
constructor() {
|
||||
makeAutoObservable(this, {
|
||||
sessionSettings: observable,
|
||||
})
|
||||
}
|
||||
|
||||
saveCaptureRate(data: any) {
|
||||
return sessionService.saveCaptureRate(data)
|
||||
.then(data => data.json())
|
||||
.then(({ data }) => {
|
||||
this.sessionSettings.merge({
|
||||
captureRate: data.rate,
|
||||
captureAll: data.captureAll
|
||||
})
|
||||
}
|
||||
toast.success("Settings updated successfully");
|
||||
}).catch(err => {
|
||||
toast.error("Error saving capture rate");
|
||||
})
|
||||
}
|
||||
|
||||
saveCaptureRate(data: any) {
|
||||
return sessionService.saveCaptureRate(data)
|
||||
.then(data => data.json())
|
||||
.then(({ data }) => {
|
||||
this.sessionSettings.merge({
|
||||
captureRate: data.rate,
|
||||
captureAll: data.captureAll
|
||||
})
|
||||
toast.success("Settings updated successfully");
|
||||
}).catch(err => {
|
||||
toast.error("Error saving capture rate");
|
||||
})
|
||||
}
|
||||
fetchCaptureRate(): Promise<any> {
|
||||
this.loadingCaptureRate = true;
|
||||
return sessionService.fetchCaptureRate()
|
||||
.then(data => {
|
||||
this.sessionSettings.merge({
|
||||
captureRate: data.rate,
|
||||
captureAll: data.captureAll
|
||||
})
|
||||
this.captureRateFetched = true;
|
||||
}).finally(() => {
|
||||
this.loadingCaptureRate = false;
|
||||
})
|
||||
}
|
||||
|
||||
fetchCaptureRate(): Promise<any> {
|
||||
this.loadingCaptureRate = true;
|
||||
return sessionService.fetchCaptureRate()
|
||||
.then(data => {
|
||||
this.sessionSettings.merge({
|
||||
captureRate: data.rate,
|
||||
captureAll: data.captureAll
|
||||
})
|
||||
this.captureRateFetched = true;
|
||||
}).finally(() => {
|
||||
this.loadingCaptureRate = false;
|
||||
})
|
||||
}
|
||||
fetchWebhooks = () => {
|
||||
this.hooksLoading = true
|
||||
return webhookService.fetchList()
|
||||
.then(data => {
|
||||
this.webhooks = data.map(hook => new Webhook(hook))
|
||||
this.hooksLoading = false
|
||||
})
|
||||
}
|
||||
|
||||
initWebhook = (inst: Partial<IWebhook> | Webhook) => {
|
||||
this.webhookInst = inst instanceof Webhook ? inst : new Webhook(inst)
|
||||
}
|
||||
|
||||
saveWebhook = (inst: Webhook) => {
|
||||
this.hooksLoading = true
|
||||
return webhookService.saveWebhook(inst)
|
||||
.then(data => {
|
||||
this.webhookInst = new Webhook(data)
|
||||
this.hooksLoading = false
|
||||
})
|
||||
}
|
||||
|
||||
removeWebhook = (hookId: string) => {
|
||||
this.hooksLoading = true
|
||||
return webhookService.removeWebhook(hookId)
|
||||
.then(() => {
|
||||
this.webhooks = this.webhooks.filter(hook => hook.webhookId!== hookId)
|
||||
this.hooksLoading = false
|
||||
})
|
||||
}
|
||||
|
||||
editWebhook = (diff: Partial<IWebhook>) => {
|
||||
Object.assign(this.webhookInst, diff)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
25
frontend/app/services/WebhookService.ts
Normal file
25
frontend/app/services/WebhookService.ts
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
import BaseService from './BaseService';
|
||||
import Webhook, { IWebhook } from "Types/webhook";
|
||||
|
||||
export default class WebhookService extends BaseService {
|
||||
fetchList(): Promise<IWebhook[]> {
|
||||
return this.client.get('/webhooks')
|
||||
.then(r => r.json())
|
||||
.then(j => j.data || [])
|
||||
.catch(Promise.reject)
|
||||
}
|
||||
|
||||
saveWebhook(inst: Webhook) {
|
||||
return this.client.put('/webhooks', inst)
|
||||
.then(r => r.json())
|
||||
.then(j => j.data || {})
|
||||
.catch(Promise.reject)
|
||||
}
|
||||
|
||||
removeWebhook(id: Webhook["webhookId"]) {
|
||||
return this.client.delete('/webhooks/' + id)
|
||||
.then(r => r.json())
|
||||
.then(j => j.data || {})
|
||||
.catch(Promise.reject)
|
||||
}
|
||||
}
|
||||
|
|
@ -9,6 +9,8 @@ import NotesService from "./NotesService";
|
|||
import RecordingsService from "./RecordingsService";
|
||||
import ConfigService from './ConfigService'
|
||||
import AlertsService from './AlertsService'
|
||||
import WebhookService from './WebhookService'
|
||||
|
||||
export const dashboardService = new DashboardService();
|
||||
export const metricService = new MetricService();
|
||||
export const sessionService = new SessionSerivce();
|
||||
|
|
@ -19,4 +21,20 @@ export const errorService = new ErrorService();
|
|||
export const notesService = new NotesService();
|
||||
export const recordingsService = new RecordingsService();
|
||||
export const configService = new ConfigService();
|
||||
export const alertsService = new AlertsService();
|
||||
export const alertsService = new AlertsService();
|
||||
export const webhookService = new WebhookService();
|
||||
|
||||
export const services = [
|
||||
dashboardService,
|
||||
metricService,
|
||||
sessionService,
|
||||
userService,
|
||||
funnelService,
|
||||
auditService,
|
||||
errorService,
|
||||
notesService,
|
||||
recordingsService,
|
||||
configService,
|
||||
alertsService,
|
||||
webhookService,
|
||||
]
|
||||
|
|
@ -1,22 +0,0 @@
|
|||
import Record from 'Types/Record';
|
||||
import { validateName, validateURL } from 'App/validate';
|
||||
|
||||
export default Record({
|
||||
webhookId: undefined,
|
||||
type: undefined,
|
||||
name: '',
|
||||
endpoint: '',
|
||||
authHeader: '',
|
||||
}, {
|
||||
idKey: 'webhookId',
|
||||
methods: {
|
||||
validate() {
|
||||
return !!this.name && validateName(this.name) && !!this.endpoint && validateURL(this.endpoint);
|
||||
},
|
||||
toData() {
|
||||
const js = this.toJS();
|
||||
delete js.key;
|
||||
return js;
|
||||
},
|
||||
},
|
||||
});
|
||||
36
frontend/app/types/webhook.ts
Normal file
36
frontend/app/types/webhook.ts
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
import { validateName, validateURL } from 'App/validate';
|
||||
import { makeAutoObservable } from 'mobx'
|
||||
|
||||
export interface IWebhook {
|
||||
webhookId: string
|
||||
type: string
|
||||
name: string
|
||||
endpoint: string
|
||||
authHeader: string
|
||||
}
|
||||
|
||||
export default class Webhook {
|
||||
webhookId: IWebhook["webhookId"]
|
||||
type: IWebhook["type"]
|
||||
name: IWebhook["name"] = ''
|
||||
endpoint: IWebhook["endpoint"] = ''
|
||||
authHeader: IWebhook["authHeader"] = ''
|
||||
|
||||
constructor(data: Partial<IWebhook> = {}) {
|
||||
Object.assign(this, data)
|
||||
|
||||
makeAutoObservable(this)
|
||||
}
|
||||
|
||||
toData() {
|
||||
return { ...this };
|
||||
}
|
||||
|
||||
validate() {
|
||||
return !!this.name && validateName(this.name) && !!this.endpoint && validateURL(this.endpoint);
|
||||
}
|
||||
|
||||
exists() {
|
||||
return !!this.webhookId
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue