mirror of
https://github.com/strapi/strapi.git
synced 2025-08-02 22:07:11 +00:00
Merge pull request #9942 from strapi/chore/fix-error-plugins
Improve CM error management
This commit is contained in:
commit
54b51d9d51
@ -1,49 +0,0 @@
|
||||
/**
|
||||
*
|
||||
* ErrorBoundary
|
||||
*
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
class ErrorBoundary extends React.Component {
|
||||
// eslint-disable-line react/prefer-stateless-function
|
||||
state = { error: null, errorInfo: null };
|
||||
|
||||
componentDidCatch(error, errorInfo) {
|
||||
this.setState({
|
||||
error,
|
||||
errorInfo,
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
const { error, errorInfo } = this.state;
|
||||
|
||||
if (errorInfo) {
|
||||
return (
|
||||
<div style={{ background: '#ffff' }}>
|
||||
<h2>Something went wrong.</h2>
|
||||
<details style={{ whiteSpace: 'pre-wrap' }}>
|
||||
{error && error.toString()}
|
||||
<br />
|
||||
{errorInfo.componentStack}
|
||||
</details>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return this.props.children;
|
||||
}
|
||||
}
|
||||
|
||||
ErrorBoundary.defaultProps = {
|
||||
children: null,
|
||||
};
|
||||
|
||||
ErrorBoundary.propTypes = {
|
||||
children: PropTypes.node,
|
||||
};
|
||||
|
||||
export default ErrorBoundary;
|
@ -1,22 +0,0 @@
|
||||
import React from 'react';
|
||||
import { shallow } from 'enzyme';
|
||||
|
||||
import ErrorBoundary from '../index';
|
||||
|
||||
describe('<ErrorBoundary />', () => {
|
||||
it('should not crash', () => {
|
||||
shallow(<ErrorBoundary />);
|
||||
});
|
||||
|
||||
it('should render its child', () => {
|
||||
const Child = () => <div>test</div>;
|
||||
|
||||
const wrapper = shallow(
|
||||
<ErrorBoundary>
|
||||
<Child />
|
||||
</ErrorBoundary>,
|
||||
);
|
||||
|
||||
expect(wrapper.find(Child)).toHaveLength(1);
|
||||
});
|
||||
});
|
@ -8,12 +8,10 @@ import React, { memo } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Redirect } from 'react-router-dom';
|
||||
import { get } from 'lodash';
|
||||
|
||||
import { BlockerComponent } from 'strapi-helper-plugin';
|
||||
import { ErrorBoundary } from 'react-error-boundary';
|
||||
import { BlockerComponent, ErrorFallback } from 'strapi-helper-plugin';
|
||||
import PageTitle from '../../components/PageTitle';
|
||||
|
||||
import { LOGIN_LOGO } from '../../config';
|
||||
import ErrorBoundary from '../ErrorBoundary';
|
||||
|
||||
export function PluginDispatcher(props) {
|
||||
const {
|
||||
@ -46,7 +44,7 @@ export function PluginDispatcher(props) {
|
||||
return (
|
||||
<div>
|
||||
<PageTitle title={`Strapi - ${name}`} />
|
||||
<ErrorBoundary>
|
||||
<ErrorBoundary FallbackComponent={ErrorFallback}>
|
||||
<PluginEntryComponent
|
||||
{...props}
|
||||
{...blockerComponentProps}
|
||||
|
@ -79,6 +79,7 @@
|
||||
"react-dnd": "^10.0.2",
|
||||
"react-dnd-html5-backend": "^10.0.2",
|
||||
"react-dom": "^16.9.0",
|
||||
"react-error-boundary": "3.1.1",
|
||||
"react-fast-compare": "^3.2.0",
|
||||
"react-helmet": "^6.1.0",
|
||||
"react-intl": "4.5.0",
|
||||
|
@ -27,6 +27,7 @@ const alias = [
|
||||
'react-dnd',
|
||||
'react-dnd-html5-backend',
|
||||
'react-dom',
|
||||
'react-error-boundary',
|
||||
'react-fast-compare',
|
||||
'react-helmet',
|
||||
'react-is',
|
||||
|
@ -0,0 +1,27 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
// https://github.com/bvaughn/react-error-boundary#usage
|
||||
|
||||
function ErrorFallback({ error }) {
|
||||
return (
|
||||
<div style={{ background: '#ffff' }}>
|
||||
<h2>Something went wrong.</h2>
|
||||
<details style={{ whiteSpace: 'pre-wrap' }}>
|
||||
{error.message}
|
||||
<br />
|
||||
{error.stack}
|
||||
</details>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
ErrorFallback.defaultProps = {
|
||||
error: { message: null },
|
||||
};
|
||||
|
||||
ErrorFallback.propTypes = {
|
||||
error: PropTypes.shape({ message: PropTypes.string }),
|
||||
};
|
||||
|
||||
export default ErrorFallback;
|
@ -17,6 +17,7 @@ export { default as CircleButton } from './components/CircleButton';
|
||||
export { default as ContainerFluid } from './components/ContainerFluid';
|
||||
export { default as ErrorBoundary } from './components/ErrorBoundary';
|
||||
export { default as ExtendComponent } from './components/ExtendComponent';
|
||||
export { default as ErrorFallback } from './components/ErrorFallback';
|
||||
export { default as FilterButton } from './components/FilterButton';
|
||||
export { default as GlobalPagination } from './components/GlobalPagination';
|
||||
export { default as HeaderNav } from './components/HeaderNav';
|
||||
|
@ -13,6 +13,7 @@ import PropTypes from 'prop-types';
|
||||
import isEqual from 'react-fast-compare';
|
||||
import { createDefaultForm, getTrad, removePasswordFieldsFromData } from '../../utils';
|
||||
import pluginId from '../../pluginId';
|
||||
import { useFindRedirectionLink } from '../../hooks';
|
||||
import {
|
||||
getData,
|
||||
getDataSucceeded,
|
||||
@ -23,8 +24,8 @@ import {
|
||||
submitSucceeded,
|
||||
} from '../../sharedReducers/crudReducer/actions';
|
||||
import selectCrudReducer from '../../sharedReducers/crudReducer/selectors';
|
||||
import { getRedirectionLink, getRequestUrl } from './utils';
|
||||
import selectMenuLinks from './selectors';
|
||||
import { getRequestUrl } from './utils';
|
||||
|
||||
// This container is used to handle the CRUD
|
||||
const CollectionTypeFormWrapper = ({ allLayoutData, children, slug, id, origin }) => {
|
||||
const { emitEvent } = useGlobalContext();
|
||||
@ -38,8 +39,7 @@ const CollectionTypeFormWrapper = ({ allLayoutData, children, slug, id, origin }
|
||||
isLoading,
|
||||
status,
|
||||
} = useSelector(selectCrudReducer);
|
||||
const collectionTypesMenuLinks = useSelector(selectMenuLinks);
|
||||
const redirectionLink = getRedirectionLink(collectionTypesMenuLinks, slug, rawQuery);
|
||||
const redirectionLink = useFindRedirectionLink(slug);
|
||||
|
||||
const isMounted = useRef(true);
|
||||
const emitEventRef = useRef(emitEvent);
|
||||
|
@ -1,2 +1,2 @@
|
||||
export { default as getRedirectionLink } from './getRedirectionLink';
|
||||
// eslint-disable-next-line import/prefer-default-export
|
||||
export { default as getRequestUrl } from './getRequestUrl';
|
||||
|
@ -1,8 +1,9 @@
|
||||
import React, { memo, useMemo } from 'react';
|
||||
import { Switch, Route } from 'react-router-dom';
|
||||
import { ErrorBoundary } from 'react-error-boundary';
|
||||
import { get } from 'lodash';
|
||||
import PropTypes from 'prop-types';
|
||||
import { LoadingIndicatorPage, CheckPagePermissions } from 'strapi-helper-plugin';
|
||||
import { ErrorFallback, LoadingIndicatorPage, CheckPagePermissions } from 'strapi-helper-plugin';
|
||||
import pluginPermissions from '../../permissions';
|
||||
import { ContentTypeLayoutContext } from '../../contexts';
|
||||
import { useFetchContentTypeLayout } from '../../hooks';
|
||||
@ -82,31 +83,33 @@ const CollectionTypeRecursivePath = ({
|
||||
));
|
||||
|
||||
return (
|
||||
<ContentTypeLayoutContext.Provider value={layout}>
|
||||
<Switch>
|
||||
<Route path={`${url}/configurations/list`}>
|
||||
<CheckPagePermissions permissions={pluginPermissions.collectionTypesConfigurations}>
|
||||
<ListSettingsView
|
||||
layout={rawContentTypeLayout}
|
||||
slug={slug}
|
||||
updateLayout={updateLayout}
|
||||
/>
|
||||
</CheckPagePermissions>
|
||||
</Route>
|
||||
<Route path={`${url}/configurations/edit`}>
|
||||
<CheckPagePermissions permissions={pluginPermissions.collectionTypesConfigurations}>
|
||||
<EditSettingsView
|
||||
components={rawComponentsLayouts}
|
||||
isContentTypeView
|
||||
mainLayout={rawContentTypeLayout}
|
||||
slug={slug}
|
||||
updateLayout={updateLayout}
|
||||
/>
|
||||
</CheckPagePermissions>
|
||||
</Route>
|
||||
{routes}
|
||||
</Switch>
|
||||
</ContentTypeLayoutContext.Provider>
|
||||
<ErrorBoundary FallbackComponent={ErrorFallback}>
|
||||
<ContentTypeLayoutContext.Provider value={layout}>
|
||||
<Switch>
|
||||
<Route path={`${url}/configurations/list`}>
|
||||
<CheckPagePermissions permissions={pluginPermissions.collectionTypesConfigurations}>
|
||||
<ListSettingsView
|
||||
layout={rawContentTypeLayout}
|
||||
slug={slug}
|
||||
updateLayout={updateLayout}
|
||||
/>
|
||||
</CheckPagePermissions>
|
||||
</Route>
|
||||
<Route path={`${url}/configurations/edit`}>
|
||||
<CheckPagePermissions permissions={pluginPermissions.collectionTypesConfigurations}>
|
||||
<EditSettingsView
|
||||
components={rawComponentsLayouts}
|
||||
isContentTypeView
|
||||
mainLayout={rawContentTypeLayout}
|
||||
slug={slug}
|
||||
updateLayout={updateLayout}
|
||||
/>
|
||||
</CheckPagePermissions>
|
||||
</Route>
|
||||
{routes}
|
||||
</Switch>
|
||||
</ContentTypeLayoutContext.Provider>
|
||||
</ErrorBoundary>
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -10,14 +10,14 @@ import { Flex, Padded } from '@buffetjs/core';
|
||||
import isEqual from 'react-fast-compare';
|
||||
import { stringify } from 'qs';
|
||||
import {
|
||||
PopUpWarning,
|
||||
request,
|
||||
CheckPermissions,
|
||||
useGlobalContext,
|
||||
InjectionZone,
|
||||
InjectionZoneList,
|
||||
PopUpWarning,
|
||||
useGlobalContext,
|
||||
useQueryParams,
|
||||
useUser,
|
||||
request,
|
||||
} from 'strapi-helper-plugin';
|
||||
import pluginId from '../../pluginId';
|
||||
import pluginPermissions from '../../permissions';
|
||||
|
@ -1,15 +1,25 @@
|
||||
import React, { useEffect } from 'react';
|
||||
import { useDispatch } from 'react-redux';
|
||||
import PropTypes from 'prop-types';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
import { useQueryParams } from 'strapi-helper-plugin';
|
||||
import { useFindRedirectionLink } from '../../hooks';
|
||||
import { resetProps, setLayout } from '../ListView/actions';
|
||||
import useSyncRbac from '../RBACManager/useSyncRbac';
|
||||
import Permissions from './Permissions';
|
||||
|
||||
const ListViewLayout = ({ layout, ...props }) => {
|
||||
const dispatch = useDispatch();
|
||||
const [{ query }] = useQueryParams();
|
||||
const { replace } = useHistory();
|
||||
const [{ query, rawQuery }] = useQueryParams();
|
||||
const permissions = useSyncRbac(query, props.slug, 'listView');
|
||||
const redirectionLink = useFindRedirectionLink(props.slug);
|
||||
|
||||
useEffect(() => {
|
||||
if (!rawQuery) {
|
||||
replace(redirectionLink);
|
||||
}
|
||||
}, [rawQuery, replace, redirectionLink]);
|
||||
|
||||
useEffect(() => {
|
||||
dispatch(setLayout(layout.contentType));
|
||||
|
@ -1,5 +1,6 @@
|
||||
export { default as useContentTypeLayout } from './useContentTypeLayout';
|
||||
export { default as useFetchContentTypeLayout } from './useFetchContentTypeLayout';
|
||||
export { default as useFindRedirectionLink } from './useFindRedirectionLink';
|
||||
export { default as useLayoutDnd } from './useLayoutDnd';
|
||||
export { default as useListView } from './useListView';
|
||||
export { default as useWysiwyg } from './useWysiwyg';
|
||||
|
@ -0,0 +1,14 @@
|
||||
import { useSelector } from 'react-redux';
|
||||
import { useQueryParams } from 'strapi-helper-plugin';
|
||||
import selectMenuLinks from './selectors';
|
||||
import getRedirectionLink from './utils/getRedirectionLink';
|
||||
|
||||
const useFindRedirectionLink = slug => {
|
||||
const [{ rawQuery }] = useQueryParams();
|
||||
const collectionTypesMenuLinks = useSelector(selectMenuLinks);
|
||||
const redirectionLink = getRedirectionLink(collectionTypesMenuLinks, slug, rawQuery);
|
||||
|
||||
return redirectionLink;
|
||||
};
|
||||
|
||||
export default useFindRedirectionLink;
|
@ -15,7 +15,7 @@ const VALID_REST_OPERATORS = [
|
||||
'null',
|
||||
];
|
||||
|
||||
// from strapi-utims/convert-rest-query-params
|
||||
// from strapi-utils/convert-rest-query-params
|
||||
const findAppliedFilter = whereClause => {
|
||||
// Useful to remove the mainField of relation fields.
|
||||
const formattedWhereClause = whereClause.split('.')[0];
|
||||
|
@ -16285,6 +16285,13 @@ react-dom@^16.9.0:
|
||||
prop-types "^15.6.2"
|
||||
scheduler "^0.19.1"
|
||||
|
||||
react-error-boundary@3.1.1:
|
||||
version "3.1.1"
|
||||
resolved "https://registry.yarnpkg.com/react-error-boundary/-/react-error-boundary-3.1.1.tgz#932c5ca5cbab8ec4fe37fd7b415aa5c3a47597e7"
|
||||
integrity sha512-W3xCd9zXnanqrTUeViceufD3mIW8Ut29BUD+S2f0eO2XCOU8b6UrJfY46RDGe5lxCJzfe4j0yvIfh0RbTZhKJw==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.12.5"
|
||||
|
||||
react-fast-compare@^2.0.1:
|
||||
version "2.0.4"
|
||||
resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-2.0.4.tgz#e84b4d455b0fec113e0402c329352715196f81f9"
|
||||
|
Loading…
x
Reference in New Issue
Block a user