2019-12-16 21:53:30 +01:00
|
|
|
/**
|
|
|
|
|
*
|
|
|
|
|
* EditView
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
|
2020-01-06 11:02:11 +01:00
|
|
|
import React, { useEffect, useReducer, useCallback } from 'react';
|
|
|
|
|
import { useHistory, useLocation } from 'react-router-dom';
|
2020-01-07 16:00:11 +01:00
|
|
|
import { cloneDeep, get, isEmpty, isEqual, set } from 'lodash';
|
2019-12-18 18:13:24 +01:00
|
|
|
import { Header } from '@buffetjs/custom';
|
2020-01-06 01:52:26 +01:00
|
|
|
import { Play } from '@buffetjs/icons';
|
2020-01-07 16:00:11 +01:00
|
|
|
import {
|
|
|
|
|
request,
|
|
|
|
|
useGlobalContext,
|
|
|
|
|
getYupInnerErrors,
|
|
|
|
|
} from 'strapi-helper-plugin';
|
2019-12-18 18:13:24 +01:00
|
|
|
|
|
|
|
|
import reducer, { initialState } from './reducer';
|
2020-01-02 09:55:26 +01:00
|
|
|
import form from './utils/form';
|
2020-01-07 16:00:11 +01:00
|
|
|
import createYupSchema from './utils/schema';
|
2020-01-02 09:55:26 +01:00
|
|
|
|
|
|
|
|
import Inputs from '../../../components/Inputs';
|
2020-01-06 01:52:26 +01:00
|
|
|
import TriggerContainer from '../../../components/TriggerContainer';
|
2020-01-02 09:55:26 +01:00
|
|
|
import Wrapper from './Wrapper';
|
2019-12-16 21:53:30 +01:00
|
|
|
|
|
|
|
|
function EditView() {
|
2019-12-18 18:13:24 +01:00
|
|
|
const { formatMessage } = useGlobalContext();
|
|
|
|
|
const [reducerState, dispatch] = useReducer(reducer, initialState);
|
|
|
|
|
const location = useLocation();
|
2020-01-06 11:02:11 +01:00
|
|
|
const { goBack } = useHistory();
|
2019-12-18 18:13:24 +01:00
|
|
|
|
2020-01-06 01:52:26 +01:00
|
|
|
const {
|
2020-01-07 16:00:11 +01:00
|
|
|
formErrors,
|
2020-01-06 01:52:26 +01:00
|
|
|
modifiedWebhook,
|
|
|
|
|
initialWebhook,
|
|
|
|
|
isTriggering,
|
|
|
|
|
triggerResponse,
|
2020-01-06 11:02:11 +01:00
|
|
|
shouldRefetchData,
|
2020-01-06 01:52:26 +01:00
|
|
|
} = reducerState.toJS();
|
2019-12-18 18:13:24 +01:00
|
|
|
|
|
|
|
|
const { name } = modifiedWebhook;
|
|
|
|
|
|
|
|
|
|
const id = location.pathname.split('/')[3];
|
|
|
|
|
const isCreatingWebhook = id === 'create';
|
|
|
|
|
|
2020-01-06 16:01:42 +01:00
|
|
|
const abortController = new AbortController();
|
|
|
|
|
|
|
|
|
|
const { signal } = abortController;
|
|
|
|
|
|
2019-12-18 18:13:24 +01:00
|
|
|
useEffect(() => {
|
2020-01-07 16:00:11 +01:00
|
|
|
if (!isCreatingWebhook || (!isCreatingWebhook && shouldRefetchData)) {
|
2020-01-06 11:02:11 +01:00
|
|
|
fetchData();
|
|
|
|
|
}
|
2020-01-07 16:00:11 +01:00
|
|
|
}, [fetchData, isCreatingWebhook, shouldRefetchData]);
|
2020-01-06 11:02:11 +01:00
|
|
|
|
|
|
|
|
const fetchData = useCallback(async () => {
|
2019-12-18 18:13:24 +01:00
|
|
|
try {
|
|
|
|
|
const { data } = await request(`/admin/webhooks/${id}`, {
|
|
|
|
|
method: 'GET',
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
dispatch({
|
|
|
|
|
type: 'GET_DATA_SUCCEEDED',
|
|
|
|
|
data,
|
|
|
|
|
});
|
|
|
|
|
} catch (err) {
|
|
|
|
|
if (err.code !== 20) {
|
|
|
|
|
strapi.notification.error('notification.error');
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-01-06 11:02:11 +01:00
|
|
|
}, [id]);
|
2019-12-18 18:13:24 +01:00
|
|
|
|
|
|
|
|
// Header props
|
|
|
|
|
const headerTitle = isCreatingWebhook
|
|
|
|
|
? formatMessage({
|
|
|
|
|
id: `Settings.webhooks.create`,
|
|
|
|
|
})
|
|
|
|
|
: name;
|
|
|
|
|
|
2020-01-06 01:52:26 +01:00
|
|
|
const actionsAreDisabled = isEqual(initialWebhook, modifiedWebhook);
|
2020-01-06 10:48:34 +01:00
|
|
|
const triggerActionIsDisabled =
|
|
|
|
|
isCreatingWebhook || (!isCreatingWebhook && !actionsAreDisabled);
|
2020-01-06 01:52:26 +01:00
|
|
|
|
|
|
|
|
const handleTrigger = async () => {
|
|
|
|
|
dispatch({
|
|
|
|
|
type: 'ON_TRIGGER',
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
try {
|
2020-01-06 16:01:42 +01:00
|
|
|
const { data } = await request(`/admin/webhooks/${id}/trigger`, {
|
2020-01-06 01:52:26 +01:00
|
|
|
method: 'POST',
|
2020-01-06 16:01:42 +01:00
|
|
|
signal,
|
2020-01-06 01:52:26 +01:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
dispatch({
|
|
|
|
|
type: 'TRIGGER_SUCCEEDED',
|
2020-01-06 16:01:42 +01:00
|
|
|
response: data,
|
2020-01-06 01:52:26 +01:00
|
|
|
});
|
|
|
|
|
} catch (err) {
|
|
|
|
|
if (err.code !== 20) {
|
|
|
|
|
strapi.notification.error('notification.error');
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
2019-12-18 18:13:24 +01:00
|
|
|
|
2020-01-06 16:01:42 +01:00
|
|
|
const onCancelTrigger = () => {
|
|
|
|
|
abortController.abort();
|
|
|
|
|
|
|
|
|
|
dispatch({
|
|
|
|
|
type: 'ON_TRIGGER_CANCELED',
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const handleReset = () => {
|
|
|
|
|
dispatch({
|
|
|
|
|
type: 'RESET',
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
2019-12-18 18:13:24 +01:00
|
|
|
const actions = [
|
|
|
|
|
{
|
|
|
|
|
color: 'primary',
|
2020-01-06 10:48:34 +01:00
|
|
|
disabled: triggerActionIsDisabled,
|
2019-12-18 18:13:24 +01:00
|
|
|
type: 'button',
|
2020-01-06 01:52:26 +01:00
|
|
|
label: formatMessage({
|
2019-12-18 18:13:24 +01:00
|
|
|
id: `Settings.webhooks.trigger`,
|
|
|
|
|
}),
|
2020-01-06 01:52:26 +01:00
|
|
|
onClick: () => {
|
|
|
|
|
handleTrigger();
|
|
|
|
|
},
|
2019-12-18 18:13:24 +01:00
|
|
|
style: {
|
|
|
|
|
paddingRight: 15,
|
|
|
|
|
paddingLeft: 15,
|
|
|
|
|
},
|
2020-01-06 10:48:34 +01:00
|
|
|
title: triggerActionIsDisabled
|
|
|
|
|
? formatMessage({
|
|
|
|
|
id: `Settings.webhooks.trigger.save`,
|
|
|
|
|
})
|
|
|
|
|
: null,
|
|
|
|
|
icon: (
|
|
|
|
|
<Play
|
|
|
|
|
width="6px"
|
|
|
|
|
height="7px"
|
|
|
|
|
fill={triggerActionIsDisabled ? '#b4b6ba' : '#ffffff'}
|
|
|
|
|
/>
|
|
|
|
|
),
|
2019-12-18 18:13:24 +01:00
|
|
|
},
|
|
|
|
|
{
|
2020-01-06 16:01:42 +01:00
|
|
|
onClick: () => {
|
|
|
|
|
handleReset();
|
|
|
|
|
},
|
2019-12-18 18:13:24 +01:00
|
|
|
color: 'cancel',
|
|
|
|
|
disabled: actionsAreDisabled,
|
|
|
|
|
type: 'button',
|
2020-01-06 01:52:26 +01:00
|
|
|
label: formatMessage({
|
2019-12-18 18:13:24 +01:00
|
|
|
id: `app.components.Button.reset`,
|
|
|
|
|
}),
|
|
|
|
|
style: {
|
|
|
|
|
paddingRight: 20,
|
|
|
|
|
paddingLeft: 20,
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
color: 'success',
|
|
|
|
|
disabled: actionsAreDisabled,
|
|
|
|
|
type: 'submit',
|
2020-01-06 01:52:26 +01:00
|
|
|
label: formatMessage({
|
2019-12-18 18:13:24 +01:00
|
|
|
id: `app.components.Button.save`,
|
|
|
|
|
}),
|
|
|
|
|
style: {
|
|
|
|
|
minWidth: 140,
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
];
|
2020-01-07 16:00:11 +01:00
|
|
|
|
2019-12-18 18:13:24 +01:00
|
|
|
const headerProps = {
|
|
|
|
|
title: {
|
|
|
|
|
label: headerTitle,
|
|
|
|
|
},
|
|
|
|
|
actions: actions,
|
|
|
|
|
};
|
|
|
|
|
|
2020-01-02 09:55:26 +01:00
|
|
|
const handleChange = ({ target: { name, value } }) => {
|
|
|
|
|
dispatch({
|
|
|
|
|
type: 'ON_CHANGE',
|
|
|
|
|
keys: name.split('.'),
|
|
|
|
|
value,
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
2020-01-03 10:53:58 +01:00
|
|
|
const handleClick = () => {
|
|
|
|
|
dispatch({
|
|
|
|
|
type: 'ADD_NEW_HEADER',
|
|
|
|
|
keys: ['headers'],
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
2020-01-07 16:00:11 +01:00
|
|
|
const handleRemove = ({ event, index }) => {
|
|
|
|
|
dispatch({
|
|
|
|
|
type: 'ON_HEADER_REMOVE',
|
|
|
|
|
index,
|
|
|
|
|
event,
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
2020-01-06 10:48:34 +01:00
|
|
|
const handleSubmit = e => {
|
|
|
|
|
e.preventDefault();
|
2020-01-07 16:00:11 +01:00
|
|
|
checkFormErrors();
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const submitForm = () => {
|
2020-01-06 11:02:11 +01:00
|
|
|
if (!isCreatingWebhook) {
|
|
|
|
|
updateWebhook();
|
|
|
|
|
} else {
|
|
|
|
|
createWebhooks();
|
|
|
|
|
}
|
2020-01-06 10:48:34 +01:00
|
|
|
};
|
|
|
|
|
|
2020-01-07 16:00:11 +01:00
|
|
|
const checkFormErrors = async () => {
|
|
|
|
|
const webhookToCheck = cloneDeep(modifiedWebhook);
|
|
|
|
|
set(webhookToCheck, 'headers', cleanHeaders());
|
2020-01-06 10:48:34 +01:00
|
|
|
|
|
|
|
|
try {
|
2020-01-07 16:00:11 +01:00
|
|
|
await createYupSchema(form).validate(webhookToCheck, {
|
|
|
|
|
abortEarly: false,
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
resetErrors();
|
|
|
|
|
submitForm();
|
|
|
|
|
} catch (err) {
|
2020-01-08 14:55:37 +01:00
|
|
|
strapi.notification.error('notification.form.error.fields');
|
2020-01-07 16:00:11 +01:00
|
|
|
|
2020-01-08 14:55:37 +01:00
|
|
|
const errors = getYupInnerErrors(err);
|
2020-01-07 16:00:11 +01:00
|
|
|
setErrors(errors);
|
|
|
|
|
}
|
|
|
|
|
};
|
2020-01-06 10:48:34 +01:00
|
|
|
|
2020-01-07 16:00:11 +01:00
|
|
|
const cleanHeaders = () => {
|
|
|
|
|
const { headers } = modifiedWebhook;
|
|
|
|
|
|
|
|
|
|
if (Object.keys(headers).length === 1) {
|
|
|
|
|
const { key, value } = headers[0];
|
|
|
|
|
if (key.length === 0 && value.length === 0) return [];
|
|
|
|
|
}
|
|
|
|
|
return headers;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const resetErrors = () => {
|
|
|
|
|
dispatch({
|
|
|
|
|
type: 'SET_ERRORS',
|
|
|
|
|
errors: null,
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const setErrors = errors => {
|
|
|
|
|
dispatch({
|
|
|
|
|
type: 'SET_ERRORS',
|
|
|
|
|
errors,
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const formatWebhook = () => {
|
|
|
|
|
const webhooks = cloneDeep(modifiedWebhook);
|
|
|
|
|
set(webhooks, 'headers', unformatLayout(cleanHeaders()));
|
|
|
|
|
return webhooks;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const createWebhooks = async () => {
|
|
|
|
|
try {
|
2020-01-06 10:48:34 +01:00
|
|
|
await request(`/admin/webhooks`, {
|
|
|
|
|
method: 'POST',
|
2020-01-07 16:00:11 +01:00
|
|
|
body: formatWebhook(),
|
2020-01-06 10:48:34 +01:00
|
|
|
});
|
|
|
|
|
|
2020-01-07 16:00:11 +01:00
|
|
|
strapi.notification.success(`notification.success`);
|
2020-01-06 11:02:11 +01:00
|
|
|
goBack();
|
|
|
|
|
} catch (err) {
|
|
|
|
|
strapi.notification.error('notification.error');
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const updateWebhook = async () => {
|
|
|
|
|
try {
|
2020-01-07 16:00:11 +01:00
|
|
|
const body = formatWebhook();
|
2020-01-06 16:01:42 +01:00
|
|
|
delete body.id;
|
2020-01-06 11:02:11 +01:00
|
|
|
|
|
|
|
|
await request(`/admin/webhooks/${id}`, {
|
|
|
|
|
method: 'PUT',
|
|
|
|
|
body,
|
|
|
|
|
});
|
|
|
|
|
|
2020-01-06 10:48:34 +01:00
|
|
|
dispatch({
|
|
|
|
|
type: 'SUBMIT_SUCCEEDED',
|
|
|
|
|
});
|
2020-01-07 16:00:11 +01:00
|
|
|
strapi.notification.success(`notification.success`);
|
2020-01-06 10:48:34 +01:00
|
|
|
} catch (err) {
|
|
|
|
|
strapi.notification.error('notification.error');
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// utils
|
|
|
|
|
const unformatLayout = headers => {
|
2020-01-07 16:00:11 +01:00
|
|
|
return headers.reduce((obj, item) => {
|
2020-01-06 10:48:34 +01:00
|
|
|
const { key, value } = item;
|
|
|
|
|
return {
|
|
|
|
|
...obj,
|
|
|
|
|
[key]: value,
|
|
|
|
|
};
|
|
|
|
|
}, {});
|
2020-01-06 16:01:42 +01:00
|
|
|
};
|
|
|
|
|
|
2019-12-16 21:53:30 +01:00
|
|
|
return (
|
2019-12-18 18:13:24 +01:00
|
|
|
<Wrapper>
|
2020-01-06 10:48:34 +01:00
|
|
|
<form onSubmit={handleSubmit}>
|
|
|
|
|
<Header {...headerProps} />
|
|
|
|
|
{(isTriggering || !isEmpty(triggerResponse)) && (
|
|
|
|
|
<div className="trigger-wrapper">
|
|
|
|
|
<TriggerContainer
|
|
|
|
|
isPending={isTriggering}
|
|
|
|
|
response={triggerResponse}
|
2020-01-06 16:01:42 +01:00
|
|
|
onCancel={onCancelTrigger}
|
2020-01-06 10:48:34 +01:00
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
)}
|
|
|
|
|
<div className="form-wrapper">
|
|
|
|
|
<div className="form-card">
|
|
|
|
|
<div className="row">
|
|
|
|
|
{Object.keys(form).map(key => {
|
|
|
|
|
return (
|
|
|
|
|
<div key={key} className={form[key].styleName}>
|
|
|
|
|
<Inputs
|
|
|
|
|
{...form[key]}
|
2020-01-07 16:00:11 +01:00
|
|
|
error={get(formErrors, [key, 'id'], null)}
|
2020-01-06 10:48:34 +01:00
|
|
|
name={key}
|
|
|
|
|
onChange={handleChange}
|
|
|
|
|
onClick={handleClick}
|
2020-01-06 16:46:30 +01:00
|
|
|
onRemove={handleRemove}
|
2020-01-06 10:48:34 +01:00
|
|
|
validations={form[key].validations}
|
|
|
|
|
value={modifiedWebhook[key] || form[key].value}
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
})}
|
|
|
|
|
</div>
|
2020-01-03 10:53:58 +01:00
|
|
|
</div>
|
2020-01-02 09:55:26 +01:00
|
|
|
</div>
|
2020-01-06 10:48:34 +01:00
|
|
|
</form>
|
2019-12-18 18:13:24 +01:00
|
|
|
</Wrapper>
|
2019-12-16 21:53:30 +01:00
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export default EditView;
|