mirror of
https://github.com/strapi/strapi.git
synced 2025-11-09 06:40:42 +00:00
Merge pull request #16700 from strapi/webhooks/list-view
This commit is contained in:
commit
ee413187df
@ -1 +1 @@
|
|||||||
export const MARKETPLACE_API_URL = 'https://market-api.strapi.io';
|
export const MARKETPLACE_API_URL = 'https://market-api.strapi.io';
|
||||||
|
|||||||
@ -5,7 +5,18 @@ import { useFormikContext } from 'formik';
|
|||||||
import { useIntl } from 'react-intl';
|
import { useIntl } from 'react-intl';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
import EventRow from './EventRow';
|
import EventRow from './EventRow';
|
||||||
import formatValue from './utils/formatValue';
|
|
||||||
|
export const formatValue = (value) =>
|
||||||
|
value.reduce((acc, curr) => {
|
||||||
|
const key = curr.split('.')[0];
|
||||||
|
|
||||||
|
if (!acc[key]) {
|
||||||
|
acc[key] = [];
|
||||||
|
}
|
||||||
|
acc[key].push(curr);
|
||||||
|
|
||||||
|
return acc;
|
||||||
|
}, {});
|
||||||
|
|
||||||
const StyledTable = styled.table`
|
const StyledTable = styled.table`
|
||||||
td {
|
td {
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import formatValue from '../utils/formatValue';
|
import { formatValue } from '..';
|
||||||
|
|
||||||
describe('utils | formatValue', () => {
|
describe('utils | formatValue', () => {
|
||||||
it('should format array to object', () => {
|
it('should format array to object', () => {
|
||||||
|
|||||||
@ -1,13 +0,0 @@
|
|||||||
const formatValue = (value) =>
|
|
||||||
value.reduce((acc, curr) => {
|
|
||||||
const key = curr.split('.')[0];
|
|
||||||
|
|
||||||
if (!acc[key]) {
|
|
||||||
acc[key] = [];
|
|
||||||
}
|
|
||||||
acc[key].push(curr);
|
|
||||||
|
|
||||||
return acc;
|
|
||||||
}, {});
|
|
||||||
|
|
||||||
export default formatValue;
|
|
||||||
@ -1,13 +1,9 @@
|
|||||||
/* eslint-disable no-nested-ternary */
|
/* eslint-disable no-nested-ternary */
|
||||||
/**
|
import React, { useState, useEffect } from 'react';
|
||||||
*
|
|
||||||
* ListView
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
import React, { useEffect, useReducer, useRef, useState } from 'react';
|
|
||||||
import { useHistory, useLocation } from 'react-router-dom';
|
import { useHistory, useLocation } from 'react-router-dom';
|
||||||
import { useIntl } from 'react-intl';
|
import { useIntl } from 'react-intl';
|
||||||
|
import { useQuery, useMutation } from 'react-query';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
useFetchClient,
|
useFetchClient,
|
||||||
useRBAC,
|
useRBAC,
|
||||||
@ -19,6 +15,7 @@ import {
|
|||||||
onRowClick,
|
onRowClick,
|
||||||
stopPropagation,
|
stopPropagation,
|
||||||
LinkButton,
|
LinkButton,
|
||||||
|
useAPIErrorHandler,
|
||||||
} from '@strapi/helper-plugin';
|
} from '@strapi/helper-plugin';
|
||||||
import {
|
import {
|
||||||
HeaderLayout,
|
HeaderLayout,
|
||||||
@ -45,212 +42,124 @@ import {
|
|||||||
VisuallyHidden,
|
VisuallyHidden,
|
||||||
} from '@strapi/design-system';
|
} from '@strapi/design-system';
|
||||||
import { Plus, Pencil, Trash, EmptyDocuments } from '@strapi/icons';
|
import { Plus, Pencil, Trash, EmptyDocuments } from '@strapi/icons';
|
||||||
import reducer, { initialState } from './reducer';
|
|
||||||
import adminPermissions from '../../../../../permissions';
|
import adminPermissions from '../../../../../permissions';
|
||||||
|
|
||||||
const ListView = () => {
|
const ListView = () => {
|
||||||
const {
|
|
||||||
isLoading,
|
|
||||||
allowedActions: { canCreate, canRead, canUpdate, canDelete },
|
|
||||||
} = useRBAC(adminPermissions.settings.webhooks);
|
|
||||||
const toggleNotification = useNotification();
|
|
||||||
const isMounted = useRef(true);
|
|
||||||
const { formatMessage } = useIntl();
|
|
||||||
const [showModal, setShowModal] = useState(false);
|
const [showModal, setShowModal] = useState(false);
|
||||||
const [{ webhooks, webhooksToDelete, webhookToDelete, loadingWebhooks }, dispatch] = useReducer(
|
const [webhooksToDelete, setWebhooksToDelete] = useState([]);
|
||||||
reducer,
|
|
||||||
initialState
|
|
||||||
);
|
|
||||||
const { notifyStatus } = useNotifyAT();
|
|
||||||
|
|
||||||
const { get, del, post, put } = useFetchClient();
|
|
||||||
|
|
||||||
|
const { formatMessage } = useIntl();
|
||||||
|
const { formatAPIError } = useAPIErrorHandler();
|
||||||
|
const toggleNotification = useNotification();
|
||||||
useFocusWhenNavigate();
|
useFocusWhenNavigate();
|
||||||
const { push } = useHistory();
|
const { push } = useHistory();
|
||||||
const { pathname } = useLocation();
|
const { pathname } = useLocation();
|
||||||
const rowsCount = webhooks.length;
|
|
||||||
const webhooksToDeleteLength = webhooksToDelete.length;
|
const {
|
||||||
const getWebhookIndex = (id) => webhooks.findIndex((webhook) => webhook.id === id);
|
isLoading: isRBACLoading,
|
||||||
|
allowedActions: { canCreate, canUpdate, canDelete },
|
||||||
|
} = useRBAC(adminPermissions.settings.webhooks);
|
||||||
|
const { get, post, put } = useFetchClient();
|
||||||
|
const { notifyStatus } = useNotifyAT();
|
||||||
|
|
||||||
|
const QUERY_KEY = 'webhooks';
|
||||||
|
const {
|
||||||
|
isLoading: isWebhooksLoading,
|
||||||
|
data: webhooks,
|
||||||
|
error: webhooksError,
|
||||||
|
refetch: refetchWebhooks,
|
||||||
|
} = useQuery(QUERY_KEY, async () => {
|
||||||
|
const {
|
||||||
|
data: { data },
|
||||||
|
} = await get('/admin/webhooks');
|
||||||
|
|
||||||
|
return data;
|
||||||
|
});
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
isMounted.current = true;
|
if (webhooksError) {
|
||||||
|
toggleNotification({
|
||||||
return () => {
|
type: 'warning',
|
||||||
isMounted.current = false;
|
message: formatAPIError(webhooksError),
|
||||||
};
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* TODO: refactor this, but actually refactor
|
|
||||||
* the whole component. Needs some love.
|
|
||||||
*/
|
|
||||||
useEffect(() => {
|
|
||||||
const fetchWebHooks = async () => {
|
|
||||||
try {
|
|
||||||
const {
|
|
||||||
data: { data },
|
|
||||||
} = await get('/admin/webhooks');
|
|
||||||
|
|
||||||
if (isMounted.current) {
|
|
||||||
dispatch({
|
|
||||||
type: 'GET_DATA_SUCCEEDED',
|
|
||||||
data,
|
|
||||||
});
|
|
||||||
notifyStatus('webhooks have been loaded');
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
console.log(err);
|
|
||||||
|
|
||||||
if (isMounted.current) {
|
|
||||||
if (err.code !== 20) {
|
|
||||||
toggleNotification({
|
|
||||||
type: 'warning',
|
|
||||||
message: { id: 'notification.error' },
|
|
||||||
});
|
|
||||||
}
|
|
||||||
dispatch({
|
|
||||||
type: 'TOGGLE_LOADING',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if (canRead) {
|
|
||||||
fetchWebHooks();
|
|
||||||
}
|
|
||||||
}, [canRead, get, notifyStatus, toggleNotification]);
|
|
||||||
|
|
||||||
const handleToggleModal = () => {
|
|
||||||
setShowModal((prev) => !prev);
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleConfirmDelete = () => {
|
|
||||||
if (webhookToDelete) {
|
|
||||||
handleConfirmDeleteOne();
|
|
||||||
} else {
|
|
||||||
handleConfirmDeleteAll();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleConfirmDeleteOne = async () => {
|
|
||||||
try {
|
|
||||||
await del(`/admin/webhooks/${webhookToDelete}`);
|
|
||||||
|
|
||||||
dispatch({
|
|
||||||
type: 'WEBHOOK_DELETED',
|
|
||||||
index: getWebhookIndex(webhookToDelete),
|
|
||||||
});
|
});
|
||||||
} catch (err) {
|
|
||||||
/**
|
return;
|
||||||
* TODO: especially this.
|
}
|
||||||
*/
|
if (webhooks) {
|
||||||
if (err.code !== 20) {
|
notifyStatus(
|
||||||
|
formatMessage({
|
||||||
|
id: 'Settings.webhooks.list.loading.success',
|
||||||
|
defaultMessage: 'Webhooks have been loaded',
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}, [webhooks, webhooksError, toggleNotification, formatMessage, notifyStatus, formatAPIError]);
|
||||||
|
|
||||||
|
const deleteMutation = useMutation(
|
||||||
|
async () => {
|
||||||
|
await post('/admin/webhooks/batch-delete', {
|
||||||
|
ids: webhooksToDelete,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
{
|
||||||
|
onError(error) {
|
||||||
toggleNotification({
|
toggleNotification({
|
||||||
type: 'warning',
|
type: 'warning',
|
||||||
message: { id: 'notification.error' },
|
message: formatAPIError(error),
|
||||||
});
|
});
|
||||||
}
|
setShowModal(false);
|
||||||
|
},
|
||||||
|
onSuccess() {
|
||||||
|
setWebhooksToDelete([]);
|
||||||
|
setShowModal(false);
|
||||||
|
refetchWebhooks();
|
||||||
|
},
|
||||||
}
|
}
|
||||||
setShowModal(false);
|
);
|
||||||
};
|
|
||||||
|
|
||||||
const handleConfirmDeleteAll = async () => {
|
const enabledMutation = useMutation(
|
||||||
const body = {
|
async ({ isEnabled, id }) => {
|
||||||
ids: webhooksToDelete,
|
const { id: _, ...webhook } = webhooks.find((webhook) => webhook.id === id) ?? {};
|
||||||
};
|
const body = {
|
||||||
|
...webhook,
|
||||||
try {
|
isEnabled,
|
||||||
await post('/admin/webhooks/batch-delete', body);
|
};
|
||||||
|
|
||||||
if (isMounted.current) {
|
|
||||||
dispatch({
|
|
||||||
type: 'WEBHOOKS_DELETED',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
if (isMounted.current) {
|
|
||||||
if (err.code !== 20) {
|
|
||||||
toggleNotification({
|
|
||||||
type: 'warning',
|
|
||||||
message: { id: 'notification.error' },
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
setShowModal(false);
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleDeleteClick = (id) => {
|
|
||||||
setShowModal(true);
|
|
||||||
|
|
||||||
if (id !== 'all') {
|
|
||||||
dispatch({
|
|
||||||
type: 'SET_WEBHOOK_TO_DELETE',
|
|
||||||
id,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleEnabledChange = async (value, id) => {
|
|
||||||
const webhookIndex = getWebhookIndex(id);
|
|
||||||
const initialWebhookProps = webhooks[webhookIndex];
|
|
||||||
const keys = [webhookIndex, 'isEnabled'];
|
|
||||||
|
|
||||||
const body = {
|
|
||||||
...initialWebhookProps,
|
|
||||||
isEnabled: value,
|
|
||||||
};
|
|
||||||
|
|
||||||
delete body.id;
|
|
||||||
|
|
||||||
try {
|
|
||||||
dispatch({
|
|
||||||
type: 'SET_WEBHOOK_ENABLED',
|
|
||||||
keys,
|
|
||||||
value,
|
|
||||||
});
|
|
||||||
|
|
||||||
await put(`/admin/webhooks/${id}`, body);
|
await put(`/admin/webhooks/${id}`, body);
|
||||||
} catch (err) {
|
},
|
||||||
if (isMounted.current) {
|
{
|
||||||
dispatch({
|
onError(error) {
|
||||||
type: 'SET_WEBHOOK_ENABLED',
|
toggleNotification({
|
||||||
keys,
|
type: 'warning',
|
||||||
value: !value,
|
message: formatAPIError(error),
|
||||||
});
|
});
|
||||||
|
},
|
||||||
if (err.code !== 20) {
|
onSuccess() {
|
||||||
toggleNotification({
|
refetchWebhooks();
|
||||||
type: 'warning',
|
},
|
||||||
message: { id: 'notification.error' },
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
);
|
||||||
|
|
||||||
const handleSelectAllCheckbox = () => {
|
const confirmDelete = () => deleteMutation.mutate();
|
||||||
dispatch({
|
|
||||||
type: 'SET_ALL_WEBHOOKS_TO_DELETE',
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleSelectOneCheckbox = (value, id) => {
|
const selectAllCheckbox = (selected) =>
|
||||||
dispatch({
|
selected ? setWebhooksToDelete(webhooks.map((webhook) => webhook.id)) : setWebhooksToDelete([]);
|
||||||
type: 'SET_WEBHOOKS_TO_DELETE',
|
|
||||||
value,
|
|
||||||
id,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleGoTo = (to) => {
|
const selectOneCheckbox = (selected, id) =>
|
||||||
push(`${pathname}/${to}`);
|
selected
|
||||||
};
|
? setWebhooksToDelete((prev) => [...prev, id])
|
||||||
|
: setWebhooksToDelete((prev) => prev.filter((webhookId) => webhookId !== id));
|
||||||
|
|
||||||
|
const goTo = (to) => push(`${pathname}/${to}`);
|
||||||
|
|
||||||
|
const isLoading = isRBACLoading || isWebhooksLoading;
|
||||||
|
const numberOfWebhooks = webhooks?.length ?? 0;
|
||||||
|
const webhooksToDeleteLength = webhooksToDelete.length;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Layout>
|
<Layout>
|
||||||
<SettingsPageTitle name="Webhooks" />
|
<SettingsPageTitle name="Webhooks" />
|
||||||
<Main aria-busy={isLoading || loadingWebhooks}>
|
<Main aria-busy={isLoading}>
|
||||||
<HeaderLayout
|
<HeaderLayout
|
||||||
title={formatMessage({ id: 'Settings.webhooks.title', defaultMessage: 'Webhooks' })}
|
title={formatMessage({ id: 'Settings.webhooks.title', defaultMessage: 'Webhooks' })}
|
||||||
subtitle={formatMessage({
|
subtitle={formatMessage({
|
||||||
@ -259,7 +168,7 @@ const ListView = () => {
|
|||||||
})}
|
})}
|
||||||
primaryAction={
|
primaryAction={
|
||||||
canCreate &&
|
canCreate &&
|
||||||
!loadingWebhooks && (
|
!isLoading && (
|
||||||
<LinkButton startIcon={<Plus />} variant="default" to={`${pathname}/create`} size="S">
|
<LinkButton startIcon={<Plus />} variant="default" to={`${pathname}/create`} size="S">
|
||||||
{formatMessage({
|
{formatMessage({
|
||||||
id: 'Settings.webhooks.list.button.add',
|
id: 'Settings.webhooks.list.button.add',
|
||||||
@ -278,13 +187,13 @@ const ListView = () => {
|
|||||||
{
|
{
|
||||||
id: 'Settings.webhooks.to.delete',
|
id: 'Settings.webhooks.to.delete',
|
||||||
defaultMessage:
|
defaultMessage:
|
||||||
'{webhooksToDeleteLength, plural, one {# asset} other {# assets}} selected',
|
'{webhooksToDeleteLength, plural, one {# webhook} other {# webhooks}} selected',
|
||||||
},
|
},
|
||||||
{ webhooksToDeleteLength }
|
{ webhooksToDeleteLength }
|
||||||
)}
|
)}
|
||||||
</Typography>
|
</Typography>
|
||||||
<Button
|
<Button
|
||||||
onClick={() => handleDeleteClick('all')}
|
onClick={() => setShowModal(true)}
|
||||||
startIcon={<Trash />}
|
startIcon={<Trash />}
|
||||||
size="L"
|
size="L"
|
||||||
variant="danger-light"
|
variant="danger-light"
|
||||||
@ -299,16 +208,16 @@ const ListView = () => {
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
<ContentLayout>
|
<ContentLayout>
|
||||||
{isLoading || loadingWebhooks ? (
|
{isLoading ? (
|
||||||
<Box background="neutral0" padding={6} shadow="filterShadow" hasRadius>
|
<Box background="neutral0" padding={6} shadow="filterShadow" hasRadius>
|
||||||
<LoadingIndicatorPage />
|
<LoadingIndicatorPage />
|
||||||
</Box>
|
</Box>
|
||||||
) : rowsCount > 0 ? (
|
) : numberOfWebhooks > 0 ? (
|
||||||
<Table
|
<Table
|
||||||
colCount={5}
|
colCount={5}
|
||||||
rowCount={rowsCount + 1}
|
rowCount={numberOfWebhooks + 1}
|
||||||
footer={
|
footer={
|
||||||
<TFooter onClick={() => (canCreate ? handleGoTo('create') : {})} icon={<Plus />}>
|
<TFooter onClick={() => (canCreate ? goTo('create') : {})} icon={<Plus />}>
|
||||||
{formatMessage({
|
{formatMessage({
|
||||||
id: 'Settings.webhooks.list.button.add',
|
id: 'Settings.webhooks.list.button.add',
|
||||||
defaultMessage: 'Create new webhook',
|
defaultMessage: 'Create new webhook',
|
||||||
@ -325,10 +234,10 @@ const ListView = () => {
|
|||||||
defaultMessage: 'Select all entries',
|
defaultMessage: 'Select all entries',
|
||||||
})}
|
})}
|
||||||
indeterminate={
|
indeterminate={
|
||||||
webhooksToDeleteLength > 0 && webhooksToDeleteLength < rowsCount
|
webhooksToDeleteLength > 0 && webhooksToDeleteLength < numberOfWebhooks
|
||||||
}
|
}
|
||||||
value={webhooksToDeleteLength === rowsCount}
|
value={webhooksToDeleteLength === numberOfWebhooks}
|
||||||
onValueChange={handleSelectAllCheckbox}
|
onValueChange={selectAllCheckbox}
|
||||||
/>
|
/>
|
||||||
</Th>
|
</Th>
|
||||||
<Th width="20%">
|
<Th width="20%">
|
||||||
@ -370,7 +279,7 @@ const ListView = () => {
|
|||||||
<Tr
|
<Tr
|
||||||
key={webhook.id}
|
key={webhook.id}
|
||||||
{...onRowClick({
|
{...onRowClick({
|
||||||
fn: () => handleGoTo(webhook.id),
|
fn: () => goTo(webhook.id),
|
||||||
condition: canUpdate,
|
condition: canUpdate,
|
||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
@ -381,8 +290,7 @@ const ListView = () => {
|
|||||||
defaultMessage: 'Select',
|
defaultMessage: 'Select',
|
||||||
})} ${webhook.name}`}
|
})} ${webhook.name}`}
|
||||||
value={webhooksToDelete?.includes(webhook.id)}
|
value={webhooksToDelete?.includes(webhook.id)}
|
||||||
onValueChange={(value) => handleSelectOneCheckbox(value, webhook.id)}
|
onValueChange={(selected) => selectOneCheckbox(selected, webhook.id)}
|
||||||
id="select"
|
|
||||||
name="select"
|
name="select"
|
||||||
/>
|
/>
|
||||||
</Td>
|
</Td>
|
||||||
@ -395,7 +303,7 @@ const ListView = () => {
|
|||||||
<Typography textColor="neutral800">{webhook.url}</Typography>
|
<Typography textColor="neutral800">{webhook.url}</Typography>
|
||||||
</Td>
|
</Td>
|
||||||
<Td>
|
<Td>
|
||||||
<Flex {...stopPropagation}>
|
<Flex>
|
||||||
<Switch
|
<Switch
|
||||||
onLabel={formatMessage({
|
onLabel={formatMessage({
|
||||||
id: 'global.enabled',
|
id: 'global.enabled',
|
||||||
@ -410,18 +318,21 @@ const ListView = () => {
|
|||||||
defaultMessage: 'Status',
|
defaultMessage: 'Status',
|
||||||
})}`}
|
})}`}
|
||||||
selected={webhook.isEnabled}
|
selected={webhook.isEnabled}
|
||||||
onChange={() => handleEnabledChange(!webhook.isEnabled, webhook.id)}
|
onChange={(e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
enabledMutation.mutate({
|
||||||
|
isEnabled: !webhook.isEnabled,
|
||||||
|
id: webhook.id,
|
||||||
|
});
|
||||||
|
}}
|
||||||
visibleLabels
|
visibleLabels
|
||||||
/>
|
/>
|
||||||
</Flex>
|
</Flex>
|
||||||
</Td>
|
</Td>
|
||||||
<Td>
|
<Td>
|
||||||
<Flex gap={1} {...stopPropagation}>
|
<Flex gap={1}>
|
||||||
{canUpdate && (
|
{canUpdate && (
|
||||||
<IconButton
|
<IconButton
|
||||||
onClick={() => {
|
|
||||||
handleGoTo(webhook.id);
|
|
||||||
}}
|
|
||||||
label={formatMessage({
|
label={formatMessage({
|
||||||
id: 'Settings.webhooks.events.update',
|
id: 'Settings.webhooks.events.update',
|
||||||
defaultMessage: 'Update',
|
defaultMessage: 'Update',
|
||||||
@ -432,14 +343,17 @@ const ListView = () => {
|
|||||||
)}
|
)}
|
||||||
{canDelete && (
|
{canDelete && (
|
||||||
<IconButton
|
<IconButton
|
||||||
onClick={() => handleDeleteClick(webhook.id)}
|
onClick={(e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
setWebhooksToDelete([webhook.id]);
|
||||||
|
setShowModal(true);
|
||||||
|
}}
|
||||||
label={formatMessage({
|
label={formatMessage({
|
||||||
id: 'global.delete',
|
id: 'Settings.webhooks.events.delete',
|
||||||
defaultMessage: 'Delete',
|
defaultMessage: 'Delete webhook',
|
||||||
})}
|
})}
|
||||||
icon={<Trash />}
|
icon={<Trash />}
|
||||||
noBorder
|
noBorder
|
||||||
id={`delete-${webhook.id}`}
|
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</Flex>
|
</Flex>
|
||||||
@ -459,7 +373,7 @@ const ListView = () => {
|
|||||||
<Button
|
<Button
|
||||||
variant="secondary"
|
variant="secondary"
|
||||||
startIcon={<Plus />}
|
startIcon={<Plus />}
|
||||||
onClick={() => (canCreate ? handleGoTo('create') : {})}
|
onClick={() => (canCreate ? goTo('create') : {})}
|
||||||
>
|
>
|
||||||
{formatMessage({
|
{formatMessage({
|
||||||
id: 'Settings.webhooks.list.button.add',
|
id: 'Settings.webhooks.list.button.add',
|
||||||
@ -473,8 +387,9 @@ const ListView = () => {
|
|||||||
</Main>
|
</Main>
|
||||||
<ConfirmDialog
|
<ConfirmDialog
|
||||||
isOpen={showModal}
|
isOpen={showModal}
|
||||||
onToggleDialog={handleToggleModal}
|
onToggleDialog={() => setShowModal((prev) => !prev)}
|
||||||
onConfirm={handleConfirmDelete}
|
onConfirm={confirmDelete}
|
||||||
|
isConfirmButtonLoading={deleteMutation.isLoading}
|
||||||
/>
|
/>
|
||||||
</Layout>
|
</Layout>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -1,72 +0,0 @@
|
|||||||
import produce from 'immer';
|
|
||||||
import set from 'lodash/set';
|
|
||||||
|
|
||||||
const initialState = {
|
|
||||||
webhooks: [],
|
|
||||||
webhooksToDelete: [],
|
|
||||||
webhookToDelete: null,
|
|
||||||
loadingWebhooks: true,
|
|
||||||
};
|
|
||||||
|
|
||||||
const reducer = (state, action) =>
|
|
||||||
// eslint-disable-next-line consistent-return
|
|
||||||
produce(state, (draftState) => {
|
|
||||||
switch (action.type) {
|
|
||||||
case 'GET_DATA_SUCCEEDED': {
|
|
||||||
draftState.webhooks = action.data;
|
|
||||||
draftState.loadingWebhooks = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case 'TOGGLE_LOADING': {
|
|
||||||
draftState.loadingWebhooks = !state.loadingWebhooks;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case 'SET_WEBHOOK_ENABLED': {
|
|
||||||
set(draftState, ['webhooks', ...action.keys], action.value);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case 'SET_WEBHOOK_TO_DELETE': {
|
|
||||||
draftState.webhookToDelete = action.id;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'SET_WEBHOOKS_TO_DELETE': {
|
|
||||||
if (action.value) {
|
|
||||||
draftState.webhooksToDelete.push(action.id);
|
|
||||||
} else {
|
|
||||||
draftState.webhooksToDelete = state.webhooksToDelete.filter((id) => id !== action.id);
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'SET_ALL_WEBHOOKS_TO_DELETE': {
|
|
||||||
if (state.webhooksToDelete.length === 0) {
|
|
||||||
draftState.webhooksToDelete = state.webhooks.map((webhook) => webhook.id);
|
|
||||||
} else {
|
|
||||||
draftState.webhooksToDelete = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'WEBHOOKS_DELETED': {
|
|
||||||
draftState.webhooks = state.webhooks.filter(
|
|
||||||
(webhook) => !state.webhooksToDelete.includes(webhook.id)
|
|
||||||
);
|
|
||||||
draftState.webhooksToDelete = [];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'WEBHOOK_DELETED': {
|
|
||||||
draftState.webhooks = state.webhooks.filter((_, index) => index !== action.index);
|
|
||||||
draftState.webhookToDelete = null;
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
return draftState;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
export default reducer;
|
|
||||||
export { initialState };
|
|
||||||
File diff suppressed because it is too large
Load Diff
@ -1,370 +0,0 @@
|
|||||||
import reducer from '../reducer';
|
|
||||||
|
|
||||||
describe('Admin | containers | Webhooks | ListView | reducer', () => {
|
|
||||||
const initialState = {
|
|
||||||
webhooks: [],
|
|
||||||
webhooksToDelete: [],
|
|
||||||
webhookToDelete: null,
|
|
||||||
loadingWebhooks: true,
|
|
||||||
};
|
|
||||||
|
|
||||||
describe('Load webhooks', () => {
|
|
||||||
it('should update webhooks with received data', () => {
|
|
||||||
const state = initialState;
|
|
||||||
const receivedData = [
|
|
||||||
{
|
|
||||||
id: 1,
|
|
||||||
name: 'webhook 1',
|
|
||||||
url: 'http://localhost:5000',
|
|
||||||
headers: {},
|
|
||||||
events: ['entry.create', 'entry.update', 'entry.delete'],
|
|
||||||
isEnabled: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 2,
|
|
||||||
name: 'webhook 2',
|
|
||||||
url: 'http://localhost:4000',
|
|
||||||
headers: {},
|
|
||||||
events: ['media.create', 'media.update'],
|
|
||||||
isEnabled: false,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
const action = {
|
|
||||||
type: 'GET_DATA_SUCCEEDED',
|
|
||||||
data: receivedData,
|
|
||||||
};
|
|
||||||
|
|
||||||
const expectedState = { ...state, webhooks: receivedData, loadingWebhooks: false };
|
|
||||||
|
|
||||||
expect(reducer(state, action)).toEqual(expectedState);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('Update webhook', () => {
|
|
||||||
it('should toggle isEnabled parameter', () => {
|
|
||||||
const webhooks = [
|
|
||||||
{
|
|
||||||
id: 1,
|
|
||||||
name: 'webhook 1',
|
|
||||||
url: 'http://localhost:5000',
|
|
||||||
headers: {},
|
|
||||||
events: ['entry.create', 'entry.update', 'entry.delete'],
|
|
||||||
isEnabled: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 2,
|
|
||||||
name: 'webhook 2',
|
|
||||||
url: 'http://localhost:4000',
|
|
||||||
headers: {},
|
|
||||||
events: ['media.create', 'media.update'],
|
|
||||||
isEnabled: false,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
const state = { ...initialState, webhooks };
|
|
||||||
|
|
||||||
const action = {
|
|
||||||
type: 'SET_WEBHOOK_ENABLED',
|
|
||||||
keys: [1, 'isEnabled'],
|
|
||||||
value: true,
|
|
||||||
};
|
|
||||||
|
|
||||||
const expectedState = {
|
|
||||||
...state,
|
|
||||||
webhooks: [
|
|
||||||
{
|
|
||||||
id: 1,
|
|
||||||
name: 'webhook 1',
|
|
||||||
url: 'http://localhost:5000',
|
|
||||||
headers: {},
|
|
||||||
events: ['entry.create', 'entry.update', 'entry.delete'],
|
|
||||||
isEnabled: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 2,
|
|
||||||
name: 'webhook 2',
|
|
||||||
url: 'http://localhost:4000',
|
|
||||||
headers: {},
|
|
||||||
events: ['media.create', 'media.update'],
|
|
||||||
isEnabled: true,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
||||||
|
|
||||||
expect(reducer(state, action)).toEqual(expectedState);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('Delete webhooks', () => {
|
|
||||||
it('should set a webhook id to webhookToDelete', () => {
|
|
||||||
const webhooks = [
|
|
||||||
{
|
|
||||||
id: 1,
|
|
||||||
name: 'webhook 1',
|
|
||||||
url: 'http://localhost:5000',
|
|
||||||
headers: {},
|
|
||||||
events: ['entry.create', 'entry.update', 'entry.delete'],
|
|
||||||
isEnabled: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 2,
|
|
||||||
name: 'webhook 2',
|
|
||||||
url: 'http://localhost:4000',
|
|
||||||
headers: {},
|
|
||||||
events: ['media.create', 'media.update'],
|
|
||||||
isEnabled: false,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
const state = { ...initialState, webhooks };
|
|
||||||
const action = {
|
|
||||||
type: 'SET_WEBHOOK_TO_DELETE',
|
|
||||||
id: 1,
|
|
||||||
};
|
|
||||||
|
|
||||||
const expectedState = { ...state, webhookToDelete: 1 };
|
|
||||||
|
|
||||||
expect(reducer(state, action)).toEqual(expectedState);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should add a webhook id to webhooksToDelete if value is true', () => {
|
|
||||||
const webhooks = [
|
|
||||||
{
|
|
||||||
id: 1,
|
|
||||||
name: 'webhook 1',
|
|
||||||
url: 'http://localhost:5000',
|
|
||||||
headers: {},
|
|
||||||
events: ['entry.create', 'entry.update', 'entry.delete'],
|
|
||||||
isEnabled: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 2,
|
|
||||||
name: 'webhook 2',
|
|
||||||
url: 'http://localhost:4000',
|
|
||||||
headers: {},
|
|
||||||
events: ['media.create', 'media.update'],
|
|
||||||
isEnabled: false,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
const state = { ...initialState, webhooks };
|
|
||||||
const action = {
|
|
||||||
type: 'SET_WEBHOOKS_TO_DELETE',
|
|
||||||
id: 1,
|
|
||||||
value: true,
|
|
||||||
};
|
|
||||||
|
|
||||||
const expectedState = { ...state, webhooksToDelete: [1] };
|
|
||||||
|
|
||||||
expect(reducer(state, action)).toEqual(expectedState);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should remove a webhook id to webhooksToDelete if value is false', () => {
|
|
||||||
const webhooks = [
|
|
||||||
{
|
|
||||||
id: 1,
|
|
||||||
name: 'webhook 1',
|
|
||||||
url: 'http://localhost:5000',
|
|
||||||
headers: {},
|
|
||||||
events: ['entry.create', 'entry.update', 'entry.delete'],
|
|
||||||
isEnabled: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 2,
|
|
||||||
name: 'webhook 2',
|
|
||||||
url: 'http://localhost:4000',
|
|
||||||
headers: {},
|
|
||||||
events: ['media.create', 'media.update'],
|
|
||||||
isEnabled: false,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
const state = { ...initialState, webhooks, webhooksToDelete: [1, 2] };
|
|
||||||
|
|
||||||
const action = {
|
|
||||||
type: 'SET_WEBHOOKS_TO_DELETE',
|
|
||||||
id: 1,
|
|
||||||
value: false,
|
|
||||||
};
|
|
||||||
|
|
||||||
const expectedState = { ...state, webhooksToDelete: [2] };
|
|
||||||
|
|
||||||
expect(reducer(state, action)).toEqual(expectedState);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should update webhooks and clear webhooksToDelete', () => {
|
|
||||||
const webhooks = [
|
|
||||||
{
|
|
||||||
id: 1,
|
|
||||||
name: 'webhook 1',
|
|
||||||
url: 'http://localhost:5000',
|
|
||||||
headers: {},
|
|
||||||
events: ['entry.create', 'entry.update', 'entry.delete'],
|
|
||||||
isEnabled: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 2,
|
|
||||||
name: 'webhook 2',
|
|
||||||
url: 'http://localhost:4000',
|
|
||||||
headers: {},
|
|
||||||
events: ['media.create', 'media.update'],
|
|
||||||
isEnabled: false,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
const updatedWebhooks = [
|
|
||||||
{
|
|
||||||
id: 2,
|
|
||||||
name: 'webhook 2',
|
|
||||||
url: 'http://localhost:4000',
|
|
||||||
headers: {},
|
|
||||||
events: ['media.create', 'media.update'],
|
|
||||||
isEnabled: false,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
const state = { ...initialState, webhooksToDelete: [1], webhooks };
|
|
||||||
const action = {
|
|
||||||
type: 'WEBHOOKS_DELETED',
|
|
||||||
};
|
|
||||||
|
|
||||||
const expectedState = { ...state, webhooks: updatedWebhooks, webhooksToDelete: [] };
|
|
||||||
|
|
||||||
expect(reducer(state, action)).toEqual(expectedState);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should update webhooks and clear webhookToDelete', () => {
|
|
||||||
const webhooks = [
|
|
||||||
{
|
|
||||||
id: 3,
|
|
||||||
name: 'webhook 1',
|
|
||||||
url: 'http://localhost:5000',
|
|
||||||
headers: {},
|
|
||||||
events: ['entry.create', 'entry.update', 'entry.delete'],
|
|
||||||
isEnabled: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 4,
|
|
||||||
name: 'webhook 2',
|
|
||||||
url: 'http://localhost:4000',
|
|
||||||
headers: {},
|
|
||||||
events: ['media.create', 'media.update'],
|
|
||||||
isEnabled: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 5,
|
|
||||||
name: 'webhook 2',
|
|
||||||
url: 'http://localhost:4000',
|
|
||||||
headers: {},
|
|
||||||
events: ['media.create', 'media.update'],
|
|
||||||
isEnabled: false,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
const updatedWebhooks = [
|
|
||||||
{
|
|
||||||
id: 3,
|
|
||||||
name: 'webhook 1',
|
|
||||||
url: 'http://localhost:5000',
|
|
||||||
headers: {},
|
|
||||||
events: ['entry.create', 'entry.update', 'entry.delete'],
|
|
||||||
isEnabled: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 5,
|
|
||||||
name: 'webhook 2',
|
|
||||||
url: 'http://localhost:4000',
|
|
||||||
headers: {},
|
|
||||||
events: ['media.create', 'media.update'],
|
|
||||||
isEnabled: false,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
const webhookIdToDelete = 4;
|
|
||||||
|
|
||||||
const state = { ...initialState, webhookToDelete: webhookIdToDelete, webhooks };
|
|
||||||
|
|
||||||
const action = {
|
|
||||||
type: 'WEBHOOK_DELETED',
|
|
||||||
index: 1,
|
|
||||||
};
|
|
||||||
|
|
||||||
const expectedState = { ...state, webhooks: updatedWebhooks, webhookToDelete: null };
|
|
||||||
|
|
||||||
expect(reducer(state, action)).toEqual(expectedState);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should clear webhooksToDelete when webhooksToDelete length > 0', () => {
|
|
||||||
const webhooks = [
|
|
||||||
{
|
|
||||||
id: 3,
|
|
||||||
name: 'webhook 1',
|
|
||||||
url: 'http://localhost:5000',
|
|
||||||
headers: {},
|
|
||||||
events: ['entry.create', 'entry.update', 'entry.delete'],
|
|
||||||
isEnabled: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 4,
|
|
||||||
name: 'webhook 2',
|
|
||||||
url: 'http://localhost:4000',
|
|
||||||
headers: {},
|
|
||||||
events: ['media.create', 'media.update'],
|
|
||||||
isEnabled: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 5,
|
|
||||||
name: 'webhook 2',
|
|
||||||
url: 'http://localhost:4000',
|
|
||||||
headers: {},
|
|
||||||
events: ['media.create', 'media.update'],
|
|
||||||
isEnabled: false,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
const state = { ...initialState, webhooks, webhooksToDelete: [3] };
|
|
||||||
|
|
||||||
const action = {
|
|
||||||
type: 'SET_ALL_WEBHOOKS_TO_DELETE',
|
|
||||||
};
|
|
||||||
|
|
||||||
const expectedState = { ...state, webhooks, webhooksToDelete: [] };
|
|
||||||
|
|
||||||
expect(reducer(state, action)).toEqual(expectedState);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should add all webhooks in webhooksToDelete when webhooksToDelete length === 0', () => {
|
|
||||||
const webhooks = [
|
|
||||||
{
|
|
||||||
id: 3,
|
|
||||||
name: 'webhook 1',
|
|
||||||
url: 'http://localhost:5000',
|
|
||||||
headers: {},
|
|
||||||
events: ['entry.create', 'entry.update', 'entry.delete'],
|
|
||||||
isEnabled: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 4,
|
|
||||||
name: 'webhook 2',
|
|
||||||
url: 'http://localhost:4000',
|
|
||||||
headers: {},
|
|
||||||
events: ['media.create', 'media.update'],
|
|
||||||
isEnabled: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 5,
|
|
||||||
name: 'webhook 2',
|
|
||||||
url: 'http://localhost:4000',
|
|
||||||
headers: {},
|
|
||||||
events: ['media.create', 'media.update'],
|
|
||||||
isEnabled: false,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
const state = { ...initialState, webhooks, webhooksToDelete: [] };
|
|
||||||
|
|
||||||
const action = {
|
|
||||||
type: 'SET_ALL_WEBHOOKS_TO_DELETE',
|
|
||||||
};
|
|
||||||
|
|
||||||
const expectedState = { ...state, webhooks, webhooksToDelete: [3, 4, 5] };
|
|
||||||
|
|
||||||
expect(reducer(state, action)).toEqual(expectedState);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@ -1,16 +1,48 @@
|
|||||||
import { setupServer } from 'msw/node';
|
import { setupServer } from 'msw/node';
|
||||||
import { rest } from 'msw';
|
import { rest } from 'msw';
|
||||||
|
|
||||||
|
const initialWebhooks = [
|
||||||
|
{ id: 1, isEnabled: true, name: 'test', url: 'http:://strapi.io' },
|
||||||
|
{ id: 2, isEnabled: false, name: 'test2', url: 'http://me.io' },
|
||||||
|
];
|
||||||
|
|
||||||
|
let webhooks = initialWebhooks;
|
||||||
|
export const resetWebhooks = () => {
|
||||||
|
webhooks = initialWebhooks;
|
||||||
|
};
|
||||||
|
|
||||||
const handlers = [
|
const handlers = [
|
||||||
rest.get('*/webhooks', (req, res, ctx) => {
|
rest.get('*/webhooks', (req, res, ctx) => {
|
||||||
return res(
|
return res(
|
||||||
ctx.delay(100),
|
ctx.delay(100),
|
||||||
ctx.status(200),
|
ctx.status(200),
|
||||||
ctx.json({
|
ctx.json({
|
||||||
data: [
|
data: webhooks,
|
||||||
{ id: 1, isEnabled: true, name: 'test', url: 'http:://strapi.io' },
|
})
|
||||||
{ id: 2, isEnabled: false, name: 'test2', url: 'http://me.io' },
|
);
|
||||||
],
|
}),
|
||||||
|
rest.post('*/webhooks/batch-delete', (req, res, ctx) => {
|
||||||
|
webhooks = webhooks.filter((webhook) => !req.body.ids.includes(webhook.id));
|
||||||
|
|
||||||
|
return res(
|
||||||
|
ctx.status(200),
|
||||||
|
ctx.json({
|
||||||
|
data: webhooks,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
rest.put('*/webhooks/:id', (req, res, ctx) => {
|
||||||
|
const { id } = req.params;
|
||||||
|
const { isEnabled } = req.body;
|
||||||
|
|
||||||
|
webhooks = webhooks.map((webhook) =>
|
||||||
|
webhook.id === Number(id) ? { ...webhook, isEnabled } : webhook
|
||||||
|
);
|
||||||
|
|
||||||
|
return res(
|
||||||
|
ctx.status(200),
|
||||||
|
ctx.json({
|
||||||
|
data: webhooks,
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
}),
|
}),
|
||||||
|
|||||||
@ -287,6 +287,7 @@
|
|||||||
"Settings.webhooks.event.publish-tooltip": "This event only exists for contents with Draft/Publish system enabled",
|
"Settings.webhooks.event.publish-tooltip": "This event only exists for contents with Draft/Publish system enabled",
|
||||||
"Settings.webhooks.events.create": "Create",
|
"Settings.webhooks.events.create": "Create",
|
||||||
"Settings.webhooks.events.update": "Update",
|
"Settings.webhooks.events.update": "Update",
|
||||||
|
"Settings.webhooks.events.delete": "Delete webhook",
|
||||||
"Settings.webhooks.form.events": "Events",
|
"Settings.webhooks.form.events": "Events",
|
||||||
"Settings.webhooks.form.headers": "Headers",
|
"Settings.webhooks.form.headers": "Headers",
|
||||||
"Settings.webhooks.form.url": "URL",
|
"Settings.webhooks.form.url": "URL",
|
||||||
@ -299,9 +300,10 @@
|
|||||||
"Settings.webhooks.list.empty.title": "There are no webhooks yet",
|
"Settings.webhooks.list.empty.title": "There are no webhooks yet",
|
||||||
"Settings.webhooks.list.th.actions": "actions",
|
"Settings.webhooks.list.th.actions": "actions",
|
||||||
"Settings.webhooks.list.th.status": "status",
|
"Settings.webhooks.list.th.status": "status",
|
||||||
|
"Settings.webhooks.list.loading.success": "Webhooks have been loaded",
|
||||||
"Settings.webhooks.singular": "webhook",
|
"Settings.webhooks.singular": "webhook",
|
||||||
"Settings.webhooks.title": "Webhooks",
|
"Settings.webhooks.title": "Webhooks",
|
||||||
"Settings.webhooks.to.delete": "{webhooksToDeleteLength, plural, one {# asset} other {# assets}} selected",
|
"Settings.webhooks.to.delete": "{webhooksToDeleteLength, plural, one {# webhook} other {# webhooks}} selected",
|
||||||
"Settings.webhooks.trigger": "Trigger",
|
"Settings.webhooks.trigger": "Trigger",
|
||||||
"Settings.webhooks.trigger.cancel": "Cancel trigger",
|
"Settings.webhooks.trigger.cancel": "Cancel trigger",
|
||||||
"Settings.webhooks.trigger.pending": "Pending…",
|
"Settings.webhooks.trigger.pending": "Pending…",
|
||||||
|
|||||||
@ -9,7 +9,7 @@ const createContentTypeSchema = ({
|
|||||||
reservedModels = [],
|
reservedModels = [],
|
||||||
singularNames = [],
|
singularNames = [],
|
||||||
pluralNames = [],
|
pluralNames = [],
|
||||||
collectionNames = []
|
collectionNames = [],
|
||||||
}) => {
|
}) => {
|
||||||
const shape = {
|
const shape = {
|
||||||
displayName: yup
|
displayName: yup
|
||||||
|
|||||||
@ -157,7 +157,6 @@ const forms = {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
contentType: {
|
contentType: {
|
||||||
|
|
||||||
schema(alreadyTakenNames, isEditing, ctUid, reservedNames, extensions, contentTypes) {
|
schema(alreadyTakenNames, isEditing, ctUid, reservedNames, extensions, contentTypes) {
|
||||||
const singularNames = Object.values(contentTypes).map((contentType) => {
|
const singularNames = Object.values(contentTypes).map((contentType) => {
|
||||||
return contentType.schema.singularName;
|
return contentType.schema.singularName;
|
||||||
@ -197,7 +196,7 @@ const forms = {
|
|||||||
reservedModels: reservedNames.models,
|
reservedModels: reservedNames.models,
|
||||||
singularNames: takenSingularNames,
|
singularNames: takenSingularNames,
|
||||||
pluralNames: takenPluralNames,
|
pluralNames: takenPluralNames,
|
||||||
collectionNames
|
collectionNames,
|
||||||
});
|
});
|
||||||
|
|
||||||
// FIXME
|
// FIXME
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user