clean code

This commit is contained in:
Virginie Ky 2020-01-10 15:17:36 +01:00
parent 177fdb6c5d
commit d98215c10b
22 changed files with 247 additions and 334 deletions

View File

@ -14,11 +14,11 @@ const EventRow = ({
);
const hasSomeCheckboxSelected = events.some(e => inputValue.indexOf(e) >= 0);
const handleChangeMultiple = ({ target: { name } }) => {
const onChangeAll = ({ target: { name } }) => {
const valueToSet = !areAllCheckboxesSelected;
handleChangeAll({
target: { name: name, value: valueToSet },
target: { name, value: valueToSet },
});
};
@ -27,7 +27,7 @@ const EventRow = ({
<td>
<Checkbox
name={name}
onChange={handleChangeMultiple}
onChange={onChangeAll}
message={name}
someChecked={hasSomeCheckboxSelected && !areAllCheckboxesSelected}
value={areAllCheckboxesSelected}

View File

@ -17,22 +17,22 @@ const Wrapper = styled.div`
tr {
&:before {
content: '-';
display: inline-block;
line-height: 1.1em;
color: transparent;
background-color: #f6f6f6;
position: absolute;
left: 20px;
display: inline-block;
width: calc(100% - 40px);
height: 1px;
margin-top: -1px;
line-height: 1.1em;
color: transparent;
background-color: #f6f6f6;
}
&:first-of-type:before {
background-color: #fafafb;
z-index: 1;
left: 0;
height: 2px;
width: 100%;
left: 0;
background-color: #fafafb;
z-index: 1;
}
}
thead {
@ -48,14 +48,13 @@ const Wrapper = styled.div`
border-bottom-left-radius: 3px;
border-bottom-right-radius: 3px;
box-shadow: inset 0px 0px 0px 1px #f6f6f6;
td {
height: 54px;
padding-bottom: 3px;
&:first-of-type {
width: 200px;
padding-left: 30px;
text-transform: capitalize;
width: 200px;
label {
width: fit-content;
margin-top: -1px;
@ -64,9 +63,9 @@ const Wrapper = styled.div`
}
}
&:not(:first-of-type) > div {
margin: 0 auto;
display: block;
width: fit-content;
margin: 0 auto;
}
}
}

View File

@ -19,44 +19,35 @@ const EventInput = ({ onChange, name: inputName, value: inputValue }) => {
media: ['media.create', 'media.update', 'media.delete'],
};
const handleChange = ({ target: { name, value } }) => {
let newValue = inputValue;
const formatValue = (name, value, newValue = inputValue) => {
if (value) {
if (!inputValue.includes(name)) {
if (!newValue.includes(name)) {
newValue.push(name);
}
} else {
if (inputValue.includes(name)) {
const index = inputValue.indexOf(name);
if (newValue.includes(name)) {
const index = newValue.indexOf(name);
if (index > -1) {
newValue.splice(index, 1);
}
}
}
return newValue;
};
const handleChange = ({ target: { name, value } }) => {
const newValue = formatValue(name, value);
onChange({ target: { name: inputName, value: newValue } });
};
const handleChangeAll = ({ target: { name, value } }) => {
let newValue = inputValue;
if (value) {
events[name].map(event => {
if (!inputValue.includes(event)) {
newValue.push(event);
}
});
} else {
events[name].map(event => {
const index = inputValue.indexOf(event);
if (index > -1) {
newValue.splice(index, 1);
}
});
}
events[name].map(event => {
newValue = formatValue(event, value, newValue);
});
onChange({ target: { name: inputName, value: newValue } });
onChange({ target: { name: inputName, value: inputValue } });
};
return (

View File

@ -7,19 +7,19 @@
import styled from 'styled-components';
const Wrapper = styled.div`
background-color: #fafafb;
padding: 23px 24px 26px 24px;
margin-top: 12px;
padding: 23px 24px 26px 24px;
background-color: #fafafb;
border-radius: 3px;
ul {
list-style-type: none;
padding: 0;
margin-bottom: 0;
padding: 0;
list-style-type: none;
& + button {
padding: 0;
color: #007eff;
font-size: 13px;
font-weight: 500;
padding: 0;
outline: 0;
svg,
span {
@ -40,8 +40,8 @@ const Wrapper = styled.div`
margin-bottom: 6px;
}
> section {
width: 50%;
display: inline-block;
width: 50%;
vertical-align: top;
&:nth-child(odd) {
padding-right: 15px;

View File

@ -7,19 +7,23 @@ import { CircleButton } from 'strapi-helper-plugin';
import { InputText } from '@buffetjs/core';
import { Plus } from '@buffetjs/icons';
import keys from './keys';
import Wrapper from './Wrapper';
import keys from './keys';
const HeadersInput = ({
errors,
name,
onBlur,
onClick,
onChange,
name,
value,
onRemove,
errors,
value,
}) => {
const optionFormat = value => ({ value: value, label: value });
const options = keys.map(key => optionFormat(key));
const handleBlur = () => onBlur({ target: { name, value } });
const handleChangeKey = (selected, name) => {
if (selected === null) {
onChange({ target: { name, value: '' } });
@ -29,24 +33,11 @@ const HeadersInput = ({
}
};
const optionFormat = value => {
return { value: value, label: value };
};
const options = keys.map(key => {
return optionFormat(key);
});
const handleClick = () => {
onClick(name);
};
const handleClick = () => onClick(name);
const handleRemoveItem = index => {
if (index === 0 && value.length === 1) {
onRemove({ event: 'clear', index });
} else {
onRemove({ event: 'remove', index });
}
const event = index === 0 && value.length === 1 ? 'clear' : 'remove';
onRemove({ event, index });
};
const customStyles = hasError => {
@ -95,10 +86,6 @@ const HeadersInput = ({
};
};
const handleBlur = () => {
onBlur({ target: { name, value } });
};
return (
<Wrapper>
<ul>
@ -125,20 +112,19 @@ const HeadersInput = ({
isClearable
onBlur={handleBlur}
onChange={e => handleChangeKey(e, `${name}.${index}.key`)}
options={options}
name={`${name}.${index}.key`}
value={optionFormat(key)}
options={options}
styles={customStyles(entryErrors && entryErrors.key)}
value={optionFormat(key)}
/>
</section>
<section>
<InputText
onBlur={handleBlur}
className={entryErrors && entryErrors.value && 'bordered'}
error={entryErrors && entryErrors.value}
value={value}
name={`${name}.${index}.value`}
onChange={onChange}
name={`${name}.${index}.value`}
value={value}
/>
</section>
<div>

View File

@ -16,13 +16,13 @@ const Wrapper = styled.div`
}
> p {
width 100%;
margin-bottom: -8px;
padding-top: 10px;
font-size: 13px;
line-height: normal;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
margin-bottom: -8px;
}
${({ error }) =>
!!error &&

View File

@ -5,102 +5,103 @@
import React from 'react';
import PropTypes from 'prop-types';
import { FormattedMessage } from 'react-intl';
import { ErrorMessage, Label } from '@buffetjs/styles';
import { Error, InputText } from '@buffetjs/core';
import Wrapper from './Wrapper';
import HeadersInput from '../HeadersInput';
import EventInput from '../EventInput';
import Wrapper from './Wrapper';
function Inputs({
error: inputError,
label,
name,
onChange,
onBlur: handleBlur,
onBlur,
onClick,
onRemove,
type,
validations,
value,
}) {
if (type === 'headers') {
return (
<Wrapper>
<Label htmlFor={name}>{label}</Label>
<HeadersInput
value={value}
name={name}
onBlur={handleBlur}
onClick={onClick}
onChange={onChange}
onRemove={onRemove}
errors={inputError}
/>
{inputError && <ErrorMessage>This value is required</ErrorMessage>}
</Wrapper>
);
}
return (
<Error
inputError={inputError}
name={name}
type="text"
validations={validations}
>
{({ canCheck, error, dispatch }) => {
const hasError = error && error !== null;
<Wrapper>
<Label htmlFor={name}>{label}</Label>
{type === 'headers' ? (
<>
<HeadersInput
errors={inputError}
name={name}
onBlur={onBlur}
onClick={onClick}
onChange={onChange}
onRemove={onRemove}
value={value}
/>
{inputError && (
<ErrorMessage>
<FormattedMessage id="components.Input.error.validation.required" />
</ErrorMessage>
)}
</>
) : (
<Error
inputError={inputError}
name={name}
type="text"
validations={validations}
>
{({ canCheck, error, dispatch }) => {
const hasError = error && error !== null;
const handleChange = e => {
if (!canCheck) {
dispatch({
type: 'SET_CHECK',
});
}
const handleChange = e => {
if (!canCheck) {
dispatch({
type: 'SET_CHECK',
});
}
dispatch({
type: 'SET_ERROR',
error: null,
});
dispatch({
type: 'SET_ERROR',
error: null,
});
onChange(e);
};
onChange(e);
};
return (
<Wrapper>
<Label htmlFor={name}>{label}</Label>
{type === 'events' ? (
<EventInput
value={value}
name={name}
onChange={e => {
handleChange(e);
handleBlur(e);
}}
/>
) : (
<InputText
error={hasError}
onBlur={handleBlur}
onChange={handleChange}
value={value}
name={name}
/>
)}
{hasError && <ErrorMessage>{error}</ErrorMessage>}
</Wrapper>
);
}}
</Error>
return (
<>
{type === 'events' ? (
<EventInput
name={name}
onChange={e => {
handleChange(e);
onBlur(e);
}}
value={value}
/>
) : (
<InputText
error={hasError}
name={name}
onBlur={onBlur}
onChange={handleChange}
value={value}
/>
)}
{hasError && <ErrorMessage>{error}</ErrorMessage>}
</>
);
}}
</Error>
)}
</Wrapper>
);
}
Inputs.defaultProps = {
error: null,
label: '',
onBlur: () => {},
onClick: () => {},
onRemove: () => {},
type: 'text',
@ -110,7 +111,7 @@ Inputs.defaultProps = {
Inputs.propTypes = {
error: PropTypes.oneOfType([PropTypes.string, PropTypes.object]),
label: PropTypes.oneOfType([PropTypes.string]),
label: PropTypes.string,
name: PropTypes.string.isRequired,
onBlur: PropTypes.func.isRequired,
onChange: PropTypes.func.isRequired,
@ -118,11 +119,7 @@ Inputs.propTypes = {
onRemove: PropTypes.func,
type: PropTypes.string,
validations: PropTypes.object,
value: PropTypes.oneOfType([
PropTypes.string,
PropTypes.object,
PropTypes.array,
]),
value: PropTypes.oneOfType([PropTypes.string, PropTypes.array]),
};
export default Inputs;

View File

@ -16,8 +16,8 @@ const StyledListRow = styled(Row)`
white-space: nowrap;
}
&:first-of-type {
padding-left: 30px;
width: 65px;
padding-left: 30px;
}
&:nth-of-type(2) {
max-width: 158px;

View File

@ -28,9 +28,7 @@ function ListRow({
const links = [
{
icon: 'pencil',
onClick: e => {
handleEditClick(e);
},
onClick: () => handleEditClick(),
},
{
icon: 'trash',
@ -43,17 +41,12 @@ function ListRow({
const isChecked = itemsToDelete.includes(id);
const handleEditClick = () => {
onEditClick(id);
};
const handleEditClick = () => onEditClick(id);
const handleEnabledChange = ({ target: { value } }) => {
const handleEnabledChange = ({ target: { value } }) =>
onEnabledChange(value, id);
};
const handleCheckChange = ({ target: { value } }) => {
onCheckChange(value, id);
};
const handleCheckChange = ({ target: { value } }) => onCheckChange(value, id);
const handleDeleteConfirm = () => {
onDeleteCLick(id);
@ -61,44 +54,42 @@ function ListRow({
};
return (
<>
<StyledListRow onClick={handleEditClick}>
<td>
<Checkbox
<StyledListRow onClick={handleEditClick}>
<td>
<Checkbox
name={name}
value={isChecked}
onClick={e => e.stopPropagation()}
onChange={handleCheckChange}
/>
</td>
<td>
<p>{name}</p>
</td>
<td>
<p title={url}>{url}</p>
</td>
<td>
<div onClick={e => e.stopPropagation()}>
<Switch
name={name}
value={isChecked}
onClick={e => e.stopPropagation()}
onChange={handleCheckChange}
value={isEnabled}
onChange={handleEnabledChange}
></Switch>
</div>
</td>
<td>
<IconLinks links={links} />
<div className="popup-wrapper">
<PopUpWarning
isOpen={showModal}
toggleModal={() => setShowModal(!showModal)}
popUpWarningType="danger"
onConfirm={handleDeleteConfirm}
/>
</td>
<td>
<p>{name}</p>
</td>
<td>
<p title={url}>{url}</p>
</td>
<td>
<div onClick={e => e.stopPropagation()}>
<Switch
name={name}
value={isEnabled}
onChange={handleEnabledChange}
></Switch>
</div>
</td>
<td>
<IconLinks links={links} />
<div className="popup-wrapper">
<PopUpWarning
isOpen={showModal}
toggleModal={() => setShowModal(!showModal)}
popUpWarningType="danger"
onConfirm={handleDeleteConfirm}
/>
</div>
</td>
</StyledListRow>
</>
</div>
</td>
</StyledListRow>
);
}
@ -111,8 +102,6 @@ ListRow.defaultProps = {
onEditClick: () => {},
onEnabledChange: () => {},
url: null,
headers: {},
hooks: [],
};
ListRow.propTypes = {
@ -125,8 +114,6 @@ ListRow.propTypes = {
onEditClick: PropTypes.func,
onEnabledChange: PropTypes.func,
url: PropTypes.string,
headers: PropTypes.object,
hooks: PropTypes.instanceOf(Array),
};
export default ListRow;

View File

@ -11,10 +11,10 @@ const Toggle = styled.input`
position: absolute;
top: 0;
left: 0;
margin: 0;
width: 100%;
height: 100%;
cursor: pointer;
margin: 0;
opacity: 0;
`;

View File

@ -9,29 +9,28 @@ import styled from 'styled-components';
const Wrapper = styled.div`
position: relative;
.button {
width: 30px;
height: 18px;
position: relative;
z-index: 2;
width: 30px;
height: 18px;
margin-right: 12px;
.button-rect {
position: relative;
z-index: -2;
margin-top: 3px;
width: 30px;
height: 12px;
background-color: #faa684;
border-radius: 6px;
margin-top: 3px;
z-index: -2;
}
.button-circle {
background-color: #f1f1f1;
position: absolute;
top: 0;
right: -1px;
width: 17px;
height: 17px;
border-radius: 9px;
background-color: #f1f1f1;
&:before {
content: '';
position: absolute;

View File

@ -19,9 +19,9 @@ function Switch({ name, value, onChange }) {
<Toggle
checked={value}
name={name}
onChange={e => {
onChange({ target: { name, value: e.target.checked } });
}}
onChange={({ target: { checked } }) =>
onChange({ target: { name, value: checked } })
}
/>
<div className="button">
<div className="button-rect"></div>

View File

@ -29,10 +29,8 @@ const Wrapper = styled.div`
display: inline-block;
vertical-align: bottom;
}
svg {
& + span {
margin-left: 10px;
}
svg + span {
margin-left: 10px;
}
&.success-label {
svg {
@ -46,8 +44,8 @@ const Wrapper = styled.div`
}
}
&:last-of-type {
text-align: right;
max-width: 400px;
text-align: right;
button {
color: #b4b6ba;
&,

View File

@ -17,13 +17,16 @@ const TriggerContainer = ({ isPending, onCancel, response }) => {
<td>
<p>Test-trigger</p>
</td>
{isPending ? (
<>
<td>
<p>
<Pending fill="#6DBB1A" width="15px" height="15px" />
<span>Pending...</span>
<span>
{formatMessage({
id: `Settings.webhooks.trigger.pending`,
})}
</span>
</p>
</td>
<td>
@ -38,11 +41,19 @@ const TriggerContainer = ({ isPending, onCancel, response }) => {
<td>
<p className="success-label">
<Success fill="#6DBB1A" width="19px" height="19px" />
<span>Success!</span>
<span>
{formatMessage({
id: `Settings.webhooks.trigger.success`,
})}
</span>
</p>
</td>
<td>
<p>Trigger succeded</p>
<p>
{formatMessage({
id: `Settings.webhooks.trigger.success.label`,
})}
</p>
</td>
</>
) : (
@ -68,6 +79,7 @@ const TriggerContainer = ({ isPending, onCancel, response }) => {
TriggerContainer.defaultProps = {
isPending: false,
onCancel: () => {},
response: {},
};
TriggerContainer.propTypes = {

View File

@ -17,18 +17,18 @@ const Wrapper = styled.div`
}
.header-title + div {
button: first-of-type {
margin-right: 30px;
position: relative;
margin-right: 30px;
overflow: initial;
&::after {
content: '-';
position: absolute;
top: 5px;
right: -20px;
width: 1px;
height: 20px;
background-color: #e9eaeb;
color: transparent;
position: absolute;
top: 5px;
right: -20px;
}
span svg {
margin-top: -2px;
@ -39,17 +39,17 @@ const Wrapper = styled.div`
padding-top: 4px;
}
.form-card {
margin-bottom: 30px;
padding: 21px 25px 0px 25px;
background-color: #ffffff;
border-radius: 2px;
box-shadow: 0 2px 4px 0 #e3e9f3;
margin-bottom: 30px;
}
.row {
> div {
position: relative;
margin-bottom: 4px;
z-index: 0;
margin-bottom: 4px;
&:nth-of-type(3) {
z-index: 1;
}

View File

@ -6,7 +6,7 @@
import React, { useEffect, useReducer, useCallback, useState } from 'react';
import { useHistory, useLocation } from 'react-router-dom';
import { cloneDeep, get, isEmpty, isEqual, set, setWith } from 'lodash';
import { get, isEmpty, isEqual, set, setWith } from 'lodash';
import { Header } from '@buffetjs/custom';
import { Play } from '@buffetjs/icons';
import {
@ -18,7 +18,7 @@ import {
import reducer, { initialState } from './reducer';
import form from './utils/form';
import { createYupSchema, createYupSchemaEntry } from './utils/schema';
import createYupSchema from './utils/schema';
import Inputs from '../../../components/Inputs';
import TriggerContainer from '../../../components/TriggerContainer';
@ -29,7 +29,7 @@ function EditView() {
const [submittedOnce, setSubmittedOnce] = useState(false);
const [reducerState, dispatch] = useReducer(reducer, initialState);
const location = useLocation();
const { goBack, push } = useHistory();
const { push } = useHistory();
const {
formErrors,
@ -43,17 +43,17 @@ function EditView() {
const { name } = modifiedWebhook;
const id = location.pathname.split('/')[3];
const isCreatingWebhook = id === 'create';
const isCreating = id === 'create';
const abortController = new AbortController();
const { signal } = abortController;
useEffect(() => {
if (!isCreatingWebhook || (!isCreatingWebhook && shouldRefetchData)) {
if (!isCreating || (!isCreating && shouldRefetchData)) {
fetchData();
}
}, [fetchData, isCreatingWebhook, shouldRefetchData]);
}, [fetchData, isCreating, shouldRefetchData]);
const fetchData = useCallback(async () => {
try {
@ -72,8 +72,7 @@ function EditView() {
}
}, [id]);
// Header props
const headerTitle = isCreatingWebhook
const headerTitle = isCreating
? formatMessage({
id: `Settings.webhooks.create`,
})
@ -84,7 +83,7 @@ function EditView() {
Object.keys(formErrors).length > 0;
const triggerActionIsDisabled =
isCreatingWebhook || (!isCreatingWebhook && !actionsAreDisabled);
isCreating || (!isCreating && !actionsAreDisabled);
const handleTrigger = async () => {
dispatch({
@ -116,17 +115,15 @@ function EditView() {
});
};
const handleReset = () => {
const handleReset = () =>
dispatch({
type: 'RESET',
});
};
const actions = [
{
color: 'primary',
disabled: triggerActionIsDisabled,
type: 'button',
label: formatMessage({
id: `Settings.webhooks.trigger`,
}),
@ -134,14 +131,14 @@ function EditView() {
handleTrigger();
},
style: {
paddingRight: 15,
paddingLeft: 15,
padding: '0 15px',
},
title: triggerActionIsDisabled
? formatMessage({
id: `Settings.webhooks.trigger.save`,
})
: null,
type: 'button',
icon: (
<Play
width="6px"
@ -151,30 +148,27 @@ function EditView() {
),
},
{
onClick: () => {
handleReset();
},
color: 'cancel',
disabled: actionsAreDisabled,
type: 'button',
label: formatMessage({
id: `app.components.Button.reset`,
}),
onClick: () => handleReset(),
style: {
paddingRight: 20,
paddingLeft: 20,
padding: '0 20px',
},
type: 'button',
},
{
color: 'success',
disabled: actionsAreDisabled,
type: 'submit',
label: formatMessage({
id: `app.components.Button.save`,
}),
style: {
minWidth: 140,
},
type: 'submit',
},
];
@ -185,8 +179,8 @@ function EditView() {
actions: actions,
};
const handleBlur = ({ target }) => {
if (submittedOnce) checkFormError(target);
const handleBlur = () => {
if (submittedOnce) checkFormErrors();
};
const handleChange = ({ target: { name, value } }) => {
@ -216,34 +210,19 @@ function EditView() {
const handleSubmit = e => {
e.preventDefault();
setSubmittedOnce(true);
checkFormErrors();
checkFormErrors(true);
};
const submitForm = () => {
if (!isCreatingWebhook) {
if (!isCreating) {
updateWebhook();
} else {
createWebhooks();
}
};
const checkFormError = async target => {
const { name, value } = target;
const { type, validations } = form[name];
try {
await createYupSchemaEntry(type, validations).validate(value, {
abortEarly: false,
});
resetError(name);
} catch (err) {
setError(err, name);
}
};
const checkFormErrors = async () => {
const webhookToCheck = cloneDeep(modifiedWebhook);
const checkFormErrors = async (submit = false) => {
const webhookToCheck = modifiedWebhook;
set(webhookToCheck, 'headers', cleanHeaders());
try {
@ -251,13 +230,11 @@ function EditView() {
abortEarly: false,
});
resetErrors();
submitForm();
setErrors({});
if (submit) submitForm();
} catch (err) {
strapi.notification.error('notification.form.error.fields');
const errors = getYupInnerErrors(err);
setErrors(errors);
setErrors(getYupInnerErrors(err));
if (submit) strapi.notification.error('notification.form.error.fields');
}
};
@ -271,43 +248,17 @@ function EditView() {
return headers;
};
const goBack = () => push('/settings/webhooks');
const resetError = name => {
const errors = formErrors;
if (errors[name]) {
delete errors[name];
resetErrors(errors);
setErrors(errors);
}
};
const resetErrors = (errors = {}) => {
dispatch({
type: 'SET_ERRORS',
errors: errors,
});
};
const setError = (errors, name) => {
const err =
name === 'headers'
? getYupInnerErrors(errors)
: { [name]: errors.message };
const formattedErrors = formErrors;
const newErrors = Object.keys(err).reduce((acc, curr) => {
const path = name === 'headers' ? `${name}${curr}` : name;
setWith(acc, path, err[curr], Object);
return acc;
}, {});
set(formattedErrors, name, newErrors[name]);
setErrors(formattedErrors);
};
const setErrors = errors => {
const newErrors = Object.keys(errors).reduce((acc, curr) => {
const { id } = errors[curr];
@ -323,12 +274,6 @@ function EditView() {
});
};
const formatWebhook = () => {
const webhooks = cloneDeep(modifiedWebhook);
set(webhooks, 'headers', unformatLayout(cleanHeaders()));
return webhooks;
};
const createWebhooks = async () => {
try {
await request(`/admin/webhooks`, {
@ -363,7 +308,13 @@ function EditView() {
};
// utils
const unformatLayout = headers => {
const formatWebhook = () => {
const webhooks = modifiedWebhook;
set(webhooks, 'headers', unformatHeaders(cleanHeaders()));
return webhooks;
};
const unformatHeaders = headers => {
return headers.reduce((obj, item) => {
const { key, value } = item;
return {
@ -375,7 +326,7 @@ function EditView() {
return (
<Wrapper>
<BackHeader onClick={() => push('/settings/webhooks')} />
<BackHeader onClick={goBack} />
<form onSubmit={handleSubmit}>
<Header {...headerProps} />
{(isTriggering || !isEmpty(triggerResponse)) && (

View File

@ -29,7 +29,6 @@ const reducer = (state, action) => {
return { key: key, value: headers[key] };
})
);
set(data, ['headers'], newHeaders);
} else {
set(data, ['headers'], get(initialWebhook, 'headers'));
@ -40,19 +39,16 @@ const reducer = (state, action) => {
.update('modifiedWebhook', () => fromJS(data))
.update('shouldRefetchData', () => false);
}
case 'TRIGGER_SUCCEEDED': {
case 'TRIGGER_SUCCEEDED':
return state
.update('triggerResponse', () => fromJS(action.response))
.update('isTriggering', () => false);
}
case 'ON_TRIGGER': {
case 'ON_TRIGGER':
return state.update('isTriggering', () => true);
}
case 'ON_TRIGGER_CANCELED': {
case 'ON_TRIGGER_CANCELED':
return state
.update('isTriggering', () => false)
.update('triggerResponse', () => {});
}
case 'ON_CHANGE':
return state.updateIn(
['modifiedWebhook', ...action.keys],
@ -74,17 +70,14 @@ const reducer = (state, action) => {
);
}
}
case 'RESET': {
case 'RESET':
return state.update('modifiedWebhook', () =>
fromJS(state.get('initialWebhook'))
);
}
case 'SET_ERRORS': {
case 'SET_ERRORS':
return state.update('formErrors', () => fromJS(action.errors));
}
case 'SUBMIT_SUCCEEDED': {
case 'SUBMIT_SUCCEEDED':
return state.update('shouldRefetchData', () => true);
}
default:
return state;
}

View File

@ -7,8 +7,8 @@ const translatedErrors = {
string: 'This is not a string',
};
const createYupSchema = form => {
const validation = yup.object().shape(
const createYupSchema = form =>
yup.object().shape(
Object.keys(form).reduce((acc, current) => {
const { type, validations } = form[current];
acc[current] = createYupSchemaEntry(type, validations);
@ -17,9 +17,6 @@ const createYupSchema = form => {
}, {})
);
return validation;
};
const createYupSchemaEntry = (type, validations) => {
let schema = yup.mixed();
@ -38,6 +35,7 @@ const createYupSchemaEntry = (type, validations) => {
)
.nullable();
}
if (['events'].includes(type)) {
schema = yup.array();
}
@ -59,4 +57,4 @@ const createYupSchemaEntry = (type, validations) => {
return schema;
};
export { createYupSchema, createYupSchemaEntry };
export default createYupSchema;

View File

@ -13,11 +13,10 @@ const reducer = (state, action) => {
.update('shouldRefetchData', () => false);
case 'SET_WEBHOOK_ENABLED':
return state.updateIn(['webhooks', ...action.keys], () => action.value);
case 'WEBHOOK_DELETED': {
case 'WEBHOOK_DELETED':
return state.update('webhooks', webhooks =>
webhooks.splice(action.index, 1)
);
}
case 'WEBHOOKS_DELETED':
return state.update('shouldRefetchData', v => !v);
default:

View File

@ -238,6 +238,9 @@
"Settings.webhooks.trigger": "Trigger",
"Settings.webhooks.trigger.title": "Save before Trigger",
"Settings.webhooks.trigger.cancel": "Cancel trigger",
"Settings.webhooks.trigger.pending": "Pending…",
"Settings.webhooks.trigger.success": "Success!",
"Settings.webhooks.trigger.success.label": "Trigger succeded",
"Settings.webhooks.trigger.save": "Please save to trigger",
"Settings.webhooks.events.create": "Create",
"Settings.webhooks.events.edit": "Edit",

View File

@ -20,10 +20,10 @@ function LeftMenuHeader({ count, search, searchable, setSearch, title }) {
const getTitle = () => {
if (searchable) {
return count > 1 ? (
<FormattedMessage id={`${title.id}plural`} />
) : (
<FormattedMessage id={`${title.id}singular`} />
return (
<FormattedMessage
id={`${title.id}${count > 1 ? 'plural' : 'singular'}`}
/>
);
}

View File

@ -2,13 +2,13 @@ import styled from 'styled-components';
const ListButton = styled.div`
button {
background-color: #e6f0fb;
width: 100%;
height: 54px;
border-top: 1px solid #aed4fb;
color: #007eff;
font-weight: 500;
text-transform: uppercase;
background-color: #e6f0fb;
border-top-left-radius: 0;
border-top-right-radius: 0;
border-bottom-left-radius: 2px;