Move utils to old/utils, done trigger container

This commit is contained in:
bulby97 2021-09-03 11:42:17 +02:00
parent 5e9591edcf
commit b8a60d7d0e
51 changed files with 253 additions and 120 deletions

View File

@ -4,6 +4,25 @@ import { TextButton } from '@strapi/parts/TextButton';
import { Field, FieldArray, useFormikContext } from 'formik';
import React from 'react';
import { useIntl } from 'react-intl';
import styled from 'styled-components';
import { pxToRem } from '@strapi/helper-plugin';
const StyledIconButton = styled(IconButton)(
({ theme }) => `
border-radius: ${pxToRem(30)};
width: ${pxToRem(20)};
height: ${pxToRem(20)};
padding: ${pxToRem(3)};
align-items: center;
justify-content: center;
svg {
width: ${pxToRem(8)};
rect {
fill: ${theme.colors.primary600}
}
}
`
);
const HeadersInput = () => {
const { formatMessage } = useIntl();
@ -46,6 +65,7 @@ const HeadersInput = () => {
<Field
as={TextInput}
name={`headers.${i}.key`}
aria-label={`row ${i + 1} key`}
error={
errors.headers?.[i]?.key && formatMessage({ id: errors.headers[i]?.key })
}
@ -56,6 +76,7 @@ const HeadersInput = () => {
<Box style={{ flex: 1 }}>
<Field
as={TextInput}
aria-label={`row ${i + 1} value`}
name={`headers.${i}.value`}
error={
errors.headers?.[i]?.value &&
@ -64,13 +85,16 @@ const HeadersInput = () => {
/>
</Box>
<Box paddingLeft={2}>
<IconButton
<StyledIconButton
onClick={() => values.headers.length !== 1 && remove(i)}
label={formatMessage({
id: 'Settings.webhooks.events.update',
})}
label={formatMessage(
{
id: 'Settings.webhooks.headers.remove',
defaultMessage: 'Remove header row {number}',
},
{ number: i + 1 }
)}
icon={<Autoselect />}
noBorder
/>
</Box>
</Row>

View File

@ -1,36 +1,53 @@
import React from 'react';
import { CheckIcon, ClearField, Close, LoadingIcon } from '@strapi/icons';
import { Box, Grid, GridItem, Row, Stack, Text } from '@strapi/parts';
import PropTypes from 'prop-types';
import React from 'react';
import { FormattedMessage } from 'react-intl';
import { Fail, Success, Pending, Remove } from '@buffetjs/icons';
import { Grid, GridItem } from '@strapi/parts';
import styled from 'styled-components';
// Being discussed in Notion: create a <Icon /> component in Parts
const Icon = styled.svg(
({ theme, color }) => `
width: ${12 / 16}rem;
height: ${12 / 16}rem;
path {
fill: ${theme.colors[color]};
}
`
);
const Status = ({ isPending, statusCode }) => {
if (isPending) {
return (
<>
<Pending fill="#ffb500" width="15px" height="15px" />
<FormattedMessage id="Settings.webhooks.trigger.pending" defaultMessage="pending" />
</>
<Stack horizontal size={2} style={{ alignItems: 'center' }}>
<Icon as={LoadingIcon} />
<Text>
<FormattedMessage id="Settings.webhooks.trigger.pending" defaultMessage="pending" />
</Text>
</Stack>
);
}
if (statusCode >= 200 && statusCode < 300) {
return (
<>
<Success fill="#6DBB1A" width="19px" height="19px" />
<FormattedMessage id="Settings.webhooks.trigger.success" defaultMessage="success" />
</>
<Stack horizontal size={2} style={{ alignItems: 'center' }}>
<Icon as={CheckIcon} color="success700" />
<Text>
<FormattedMessage id="Settings.webhooks.trigger.success" defaultMessage="success" />
</Text>
</Stack>
);
}
if (statusCode >= 300) {
return (
<>
<Fail fill="#f64d0a" width="15px" height="15px" />
<FormattedMessage id="Settings.error" defaultMessage="error" />
&nbsp;
{statusCode}
</>
<Stack horizontal size={2} style={{ alignItems: 'center' }}>
<Icon as={Close} color="danger700" />
<Text>
<FormattedMessage id="Settings.error" defaultMessage="error" /> {statusCode}
</Text>
</Stack>
);
}
@ -47,31 +64,53 @@ Status.defaultProps = {
const Message = ({ statusCode, message }) => {
if (statusCode >= 200 && statusCode < 300) {
return (
<>
<FormattedMessage id="Settings.webhooks.trigger.success.label" defaultMessage="success" />
</>
<Row justifyContent="flex-end">
<Text>
<FormattedMessage id="Settings.webhooks.trigger.success.label" defaultMessage="success" />
</Text>
</Row>
);
}
if (statusCode >= 300) {
return <p title={message}>{message}</p>;
return (
<Row justifyContent="flex-end" title={message}>
<Text
// ! REMOVE THIS WHEN DS IS UPDATED WITH ELLIPSIS PROP
style={{
overflow: 'hidden',
whiteSpace: 'nowrap',
textOverflow: 'ellipsis',
}}
>
{message}
</Text>
</Row>
);
}
return null;
};
Message.propTypes = {
statusCode: PropTypes.number,
message: PropTypes.string.isRequired,
message: PropTypes.string,
};
Message.defaultProps = {
statusCode: undefined,
message: undefined,
};
const CancelButton = ({ onCancel }) => (
<button onClick={onCancel} type="button">
<FormattedMessage id="Settings.webhooks.trigger.cancel" defaultMessage="cancel" />
<Remove fill="#b4b6ba" />
</button>
<Row justifyContent="flex-end">
<button onClick={onCancel} type="button">
<Stack horizontal size={2} style={{ alignItems: 'center' }}>
<Text textColor="neutral400">
<FormattedMessage id="Settings.webhooks.trigger.cancel" defaultMessage="cancel" />
</Text>
<Icon as={ClearField} color="neutral400" />
</Stack>
</button>
</Row>
);
CancelButton.propTypes = { onCancel: PropTypes.func.isRequired };
@ -79,21 +118,25 @@ const TriggerContainer = ({ isPending, onCancel, response }) => {
const { statusCode, message } = response;
return (
<Grid gap={4}>
<GridItem col={3}>
<FormattedMessage id="Settings.webhooks.trigger.test" defaultMessage="test-trigger" />
</GridItem>
<GridItem col={3}>
<Status isPending={isPending} statusCode={statusCode} />
</GridItem>
<GridItem col={6}>
{!isPending ? (
<Message statusCode={statusCode} message={message} />
) : (
<CancelButton onCancel={onCancel} />
)}
</GridItem>
</Grid>
<Box background="neutral0" padding={5} shadow="filterShadow" hasRadius>
<Grid gap={4} style={{ alignItems: 'center' }}>
<GridItem col={3}>
<Text>
<FormattedMessage id="Settings.webhooks.trigger.test" defaultMessage="test-trigger" />
</Text>
</GridItem>
<GridItem col={3}>
<Status isPending={isPending} statusCode={statusCode} />
</GridItem>
<GridItem col={6}>
{!isPending ? (
<Message statusCode={statusCode} message={message} />
) : (
<CancelButton onCancel={onCancel} />
)}
</GridItem>
</Grid>
</Box>
);
};

View File

@ -41,6 +41,7 @@ const EditView = () => {
const {
params: { id },
} = useRouteMatch('/settings/webhooks/:id');
const { formatMessage } = useIntl();
const { replace } = useHistory();
const { lockApp, unlockApp } = useOverlayBlocker();
@ -74,9 +75,13 @@ const EditView = () => {
const triggerWebhookFn = useCallback(
async id => {
const abortController = new AbortController();
const { signal } = abortController;
const [err, { data }] = await to(
request(`/admin/webhooks/${id}/trigger`, {
method: 'POST',
signal,
})
);
@ -87,6 +92,8 @@ const EditView = () => {
});
}
data.cancel = () => abortController.abort();
return data;
},
[toggleNotification]
@ -237,45 +244,47 @@ const EditView = () => {
as="h1"
/>
<ContentLayout>
{(isTriggering || !isTriggerIdle) && (
<div className="trigger-wrapper">
<TriggerContainer
isPending={isTriggering}
response={triggerResponse}
onCancel={() => {}}
/>
</div>
)}
<Box background="neutral0" padding={8} shadow="filterShadow" hasRadius>
<Stack size={6}>
<Grid gap={6}>
<GridItem col={6}>
<Field
as={TextInput}
name="name"
error={errors.name && formatMessage({ id: errors.name })}
label={formatMessage({
id: 'Settings.webhooks.form.name',
defaultMessage: 'Name',
})}
/>
</GridItem>
<GridItem col={12}>
<Field
as={TextInput}
name="url"
error={errors.url && formatMessage({ id: errors.url })}
label={formatMessage({
id: 'Settings.roles.form.input.url',
defaultMessage: 'Url',
})}
/>
</GridItem>
</Grid>
<HeadersInput />
<EventInput isDraftAndPublish={isDraftAndPublishEvents} />
</Stack>
</Box>
<Stack size={4}>
{(isTriggering || !isTriggerIdle) && (
<div className="trigger-wrapper">
<TriggerContainer
isPending={isTriggering}
response={triggerResponse}
onCancel={triggerResponse?.cancel}
/>
</div>
)}
<Box background="neutral0" padding={8} shadow="filterShadow" hasRadius>
<Stack size={6}>
<Grid gap={6}>
<GridItem col={6}>
<Field
as={TextInput}
name="name"
error={errors.name && formatMessage({ id: errors.name })}
label={formatMessage({
id: 'Settings.webhooks.form.name',
defaultMessage: 'Name',
})}
/>
</GridItem>
<GridItem col={12}>
<Field
as={TextInput}
name="url"
error={errors.url && formatMessage({ id: errors.url })}
label={formatMessage({
id: 'Settings.roles.form.input.url',
defaultMessage: 'Url',
})}
/>
</GridItem>
</Grid>
<HeadersInput />
<EventInput isDraftAndPublish={isDraftAndPublishEvents} />
</Stack>
</Box>
</Stack>
</ContentLayout>
</Form>
)}

View File

@ -161,6 +161,7 @@
"Settings.sso.title": "Single Sign-On",
"Settings.webhooks.create": "Create a webhook",
"Settings.webhooks.create.header": "Create a new header",
"Settings.webhooks.headers.remove": "Remove header row {number}",
"Settings.webhooks.created": "Webhook created",
"Settings.webhooks.disabled": "Disabled",
"Settings.webhooks.enabled": "Enabled",

View File

@ -3,7 +3,7 @@ import { Redirect } from 'react-router-dom';
import PropTypes from 'prop-types';
import useNotification from '../../hooks/useNotification';
import useRBACProvider from '../../hooks/useRBACProvider';
import hasPermissions from '../../utils/hasPermissions';
import hasPermissions from '../../old/utils/hasPermissions';
import LoadingIndicatorPage from '../LoadingIndicatorPage';
const CheckPagePermissions = ({ permissions, children }) => {

View File

@ -2,7 +2,7 @@ import { useEffect, useRef, useState } from 'react';
import PropTypes from 'prop-types';
import useNotification from '../../hooks/useNotification';
import hasPermissions from '../../utils/hasPermissions';
import hasPermissions from '../../old/utils/hasPermissions';
import useRBACProvider from '../../hooks/useRBACProvider';
// NOTE: this component is very similar to the CheckPagePermissions

View File

@ -1,5 +1,5 @@
import { useCallback, useEffect, useMemo, useReducer, useRef } from 'react';
import hasPermissions from '../../utils/hasPermissions';
import hasPermissions from '../../old/utils/hasPermissions';
import generateResultsObject from './utils/generateResultsObject';
import reducer from './reducer';

View File

@ -134,33 +134,35 @@ export { default as NotificationsProvider } from './providers/NotificationsProvi
export { default as StrapiAppProvider } from './providers/StrapiAppProvider';
// Utils
export { default as auth } from './utils/auth';
export { default as cleanData } from './utils/cleanData';
export { default as difference } from './utils/difference';
export { default as auth } from './old/utils/auth';
export { default as cleanData } from './old/utils/cleanData';
export { default as difference } from './old/utils/difference';
export { default as contentManagementUtilRemoveFieldsFromData } from './content-manager/utils/contentManagementUtilRemoveFieldsFromData';
export { default as dateFormats } from './utils/dateFormats';
export { default as dateToUtcTime } from './utils/dateToUtcTime';
export { default as dateFormats } from './old/utils/dateFormats';
export { default as dateToUtcTime } from './old/utils/dateToUtcTime';
export { default as formatComponentData } from './content-manager/utils/formatComponentData';
export { default as hasPermissions } from './utils/hasPermissions';
export { findMatchingPermissions } from './utils/hasPermissions';
export { default as translatedErrors } from './utils/translatedErrors';
export { default as to } from './utils/await-to-js';
export { darken } from './utils/colors';
export { default as getFileExtension } from './utils/getFileExtension';
export { default as getFilterType } from './utils/getFilterType';
export { default as getQueryParameters } from './utils/getQueryParameters';
export { default as validateInput } from './utils/inputsValidations';
export { default as request } from './utils/request';
export { default as storeData } from './utils/storeData';
export { default as templateObject } from './utils/templateObject';
export { default as hasPermissions } from './old/utils/hasPermissions';
export { findMatchingPermissions } from './old/utils/hasPermissions';
export { default as translatedErrors } from './old/utils/translatedErrors';
export { darken } from './old/utils/colors';
export { default as getFileExtension } from './old/utils/getFileExtension';
export { default as getFilterType } from './old/utils/getFilterType';
export { default as getQueryParameters } from './old/utils/getQueryParameters';
export { default as validateInput } from './old/utils/inputsValidations';
export { default as request } from './old/utils/request';
export { default as storeData } from './old/utils/storeData';
export { default as templateObject } from './old/utils/templateObject';
export { getType };
export { getOtherInfos };
export { default as getYupInnerErrors } from './utils/getYupInnerErrors';
export { default as generateFiltersFromSearch } from './utils/generateFiltersFromSearch';
export { default as generateSearchFromFilters } from './utils/generateSearchFromFilters';
export { default as generateSearchFromObject } from './utils/generateSearchFromObject';
export { default as prefixFileUrlWithBackendUrl } from './utils/prefixFileUrlWithBackendUrl';
export { default as prefixPluginTranslations } from './utils/prefixPluginTranslations';
export { default as getYupInnerErrors } from './old/utils/getYupInnerErrors';
export { default as generateFiltersFromSearch } from './old/utils/generateFiltersFromSearch';
export { default as generateSearchFromFilters } from './old/utils/generateSearchFromFilters';
export { default as generateSearchFromObject } from './old/utils/generateSearchFromObject';
export { default as prefixFileUrlWithBackendUrl } from './old/utils/prefixFileUrlWithBackendUrl';
export { default as prefixPluginTranslations } from './old/utils/prefixPluginTranslations';
export { default as pxToRem } from './utils/pxToRem';
export { default as to } from './utils/await-to-js';
// SVGS
export { default as LayoutIcon } from './old/svgs/Layout';

View File

@ -11,7 +11,7 @@ import { map } from 'lodash';
import PropTypes from 'prop-types';
// Utils
import { darken } from '../../../utils/colors';
import { darken } from '../../utils/colors';
import Wrapper from './Wrapper';
function HeaderNav({ links, style }) {

View File

@ -10,7 +10,7 @@ import { isEmpty, isFunction } from 'lodash';
import cn from 'classnames';
// Utils
import validateInput from '../../../utils/inputsValidations';
import validateInput from '../../utils/inputsValidations';
// Design
import Label from '../Label';

View File

@ -10,7 +10,7 @@ import { isEmpty, isFunction } from 'lodash';
import cn from 'classnames';
// Utils
import validateInput from '../../../utils/inputsValidations';
import validateInput from '../../utils/inputsValidations';
// Design
import Label from '../Label';

View File

@ -4,7 +4,7 @@ import { isEmpty, isFunction } from 'lodash';
import cn from 'classnames';
// Utils
import validateInput from '../../../utils/inputsValidations';
import validateInput from '../../utils/inputsValidations';
// Design
import Label from '../Label';

View File

@ -10,7 +10,7 @@ import { isEmpty, isFunction } from 'lodash';
import cn from 'classnames';
// Utils
import validateInput from '../../../utils/inputsValidations';
import validateInput from '../../utils/inputsValidations';
// Design
import Label from '../Label';

View File

@ -10,7 +10,7 @@ import { isEmpty, isFunction } from 'lodash';
import cn from 'classnames';
// Utils
import validateInput from '../../../utils/inputsValidations';
import validateInput from '../../utils/inputsValidations';
// Design
import Label from '../Label';

View File

@ -4,7 +4,7 @@ import { isEmpty, isFunction } from 'lodash';
import cn from 'classnames';
// Utils
import validateInput from '../../../utils/inputsValidations';
import validateInput from '../../utils/inputsValidations';
// Design
import Label from '../Label';

View File

@ -4,7 +4,7 @@ import { isEmpty, isFunction } from 'lodash';
import cn from 'classnames';
// Utils
import validateInput from '../../../utils/inputsValidations';
import validateInput from '../../utils/inputsValidations';
// Design
import Label from '../Label';

View File

@ -3,7 +3,7 @@ import { useIntl } from 'react-intl';
import { Inputs } from '@buffetjs/custom';
import PropTypes from 'prop-types';
import { isObject } from 'lodash';
import translatedErrors from '../../../utils/translatedErrors';
import translatedErrors from '../../utils/translatedErrors';
const IntlInput = ({
description,

View File

@ -0,0 +1,24 @@
<!--- await-to-js.stories.mdx --->
import { Meta } from '@storybook/addon-docs';
<Meta title="utils/await-to-js" />
# await-to-js
Async await wrapper for easy error handling
## Usage
```
import { to } from '@strapi/helper-plugin';
const [err, response] = await to(promise);
if (err) {
throw new Error(err)
}
...else continue
```

View File

@ -0,0 +1,3 @@
const pxToRem = px => `${px / 16}rem`;
export default pxToRem;

View File

@ -0,0 +1,27 @@
<!--- pxToRem.stories.mdx --->
import { Meta } from '@storybook/addon-docs';
<Meta title="utils/pxToRem" />
# pxToRem
Converts px to rem.
## Usage
```
import { pxToRem } from '@strapi/helper-plugin';
import { Box } from '@strapi/parts';
import styled from 'styled-components'
const StyledBox = styled(Box)`
width: ${pxToRem}
`
const HomePage = () =>
return (
<StyledBox>I'm a sized box</StyledBox>
);
};
```