From b9333cc0b54af7502ff13fe2ea5368c83926bf46 Mon Sep 17 00:00:00 2001 From: HichamELBSI Date: Tue, 18 Jan 2022 17:55:10 +0100 Subject: [PATCH 1/3] Migrate 404 page and init 500 page Signed-off-by: HichamELBSI --- .../core/admin/admin/src/pages/Admin/index.js | 2 + .../src/pages/InternalErrorPage/index.js | 53 ++ .../InternalErrorPage/tests/index.test.js | 462 ++++++++++++++++++ .../admin/src/pages/NotFoundPage/index.js | 47 +- .../pages/NotFoundPage/tests/index.test.js | 462 ++++++++++++++++++ .../core/admin/admin/src/translations/en.json | 1 + 6 files changed, 1025 insertions(+), 2 deletions(-) create mode 100644 packages/core/admin/admin/src/pages/InternalErrorPage/index.js create mode 100644 packages/core/admin/admin/src/pages/InternalErrorPage/tests/index.test.js create mode 100644 packages/core/admin/admin/src/pages/NotFoundPage/tests/index.test.js diff --git a/packages/core/admin/admin/src/pages/Admin/index.js b/packages/core/admin/admin/src/pages/Admin/index.js index d2b3a319b7..f1195fa0d5 100644 --- a/packages/core/admin/admin/src/pages/Admin/index.js +++ b/packages/core/admin/admin/src/pages/Admin/index.js @@ -27,6 +27,7 @@ const MarketplacePage = lazy(() => import(/* webpackChunkName: "Admin_marketplace" */ '../MarketplacePage') ); const NotFoundPage = lazy(() => import('../NotFoundPage')); +const InternalErrorPage = lazy(() => import('../InternalErrorPage')); const ProfilePage = lazy(() => import(/* webpackChunkName: "Admin_profilePage" */ '../ProfilePage') @@ -87,6 +88,7 @@ const Admin = () => { + diff --git a/packages/core/admin/admin/src/pages/InternalErrorPage/index.js b/packages/core/admin/admin/src/pages/InternalErrorPage/index.js new file mode 100644 index 0000000000..e51c6ca941 --- /dev/null +++ b/packages/core/admin/admin/src/pages/InternalErrorPage/index.js @@ -0,0 +1,53 @@ +/** + * InternalErrorPage + * + * This is the page we show when the user gets a 500 error + * + */ +import React from 'react'; +import { useFocusWhenNavigate } from '@strapi/helper-plugin'; +import { Main } from '@strapi/design-system/Main'; +import { LinkButton } from '@strapi/design-system/LinkButton'; +import { ContentLayout, HeaderLayout } from '@strapi/design-system/Layout'; +import { EmptyStateLayout } from '@strapi/design-system/EmptyStateLayout'; +import EmptyPictures from '@strapi/icons/EmptyPictures'; +import ArrowRight from '@strapi/icons/ArrowRight'; +import { useIntl } from 'react-intl'; + +const InternalErrorPage = () => { + const { formatMessage } = useIntl(); + useFocusWhenNavigate(); + + return ( +
+ + + } to="/"> + {formatMessage({ + id: 'app.components.NotFoundPage.back', + defaultMessage: 'Back to homepage', + })} + + } + content={formatMessage({ + id: 'notification.error', + defaultMessage: 'An error occured', + })} + hasRadius + icon={} + shadow="tableShadow" + /> + +
+ ); +}; + +export default InternalErrorPage; diff --git a/packages/core/admin/admin/src/pages/InternalErrorPage/tests/index.test.js b/packages/core/admin/admin/src/pages/InternalErrorPage/tests/index.test.js new file mode 100644 index 0000000000..c1897ef983 --- /dev/null +++ b/packages/core/admin/admin/src/pages/InternalErrorPage/tests/index.test.js @@ -0,0 +1,462 @@ +import React from 'react'; +import { render } from '@testing-library/react'; +import { Router } from 'react-router-dom'; +import { createMemoryHistory } from 'history'; +import { IntlProvider } from 'react-intl'; +import { ThemeProvider, lightTheme } from '@strapi/design-system'; +import InternalErrorPage from '../index'; +import { useModels } from '../../../hooks'; + +jest.mock('../../../hooks', () => ({ + useModels: jest.fn(), +})); + +const history = createMemoryHistory(); + +const App = ( + + + + + + + +); + +describe('InternalErrorPage', () => { + useModels.mockImplementation(() => ({ + isLoading: false, + collectionTypes: [], + singleTypes: [], + })); + + it('renders and matches the snapshot', () => { + const { + container: { firstChild }, + } = render(App); + + expect(firstChild).toMatchInlineSnapshot(` + .c12 { + color: #666687; + font-weight: 500; + font-size: 1rem; + line-height: 1.25; + } + + .c7 { + background: #ffffff; + padding: 64px; + border-radius: 4px; + box-shadow: 0px 1px 4px rgba(33,33,52,0.1); + } + + .c9 { + padding-bottom: 24px; + } + + .c11 { + padding-bottom: 16px; + } + + .c8 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + text-align: center; + } + + .c10 svg { + height: 5.5rem; + } + + .c0:focus-visible { + outline: none; + } + + .c16 { + font-weight: 600; + color: #32324d; + font-size: 0.875rem; + line-height: 1.43; + } + + .c18 { + padding-left: 8px; + } + + .c13 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + cursor: pointer; + padding: 8px; + border-radius: 4px; + background: #ffffff; + border: 1px solid #dcdce4; + position: relative; + outline: none; + } + + .c13 svg { + height: 12px; + width: 12px; + } + + .c13 svg > g, + .c13 svg path { + fill: #ffffff; + } + + .c13[aria-disabled='true'] { + pointer-events: none; + } + + .c13:after { + -webkit-transition-property: all; + transition-property: all; + -webkit-transition-duration: 0.2s; + transition-duration: 0.2s; + border-radius: 8px; + content: ''; + position: absolute; + top: -4px; + bottom: -4px; + left: -4px; + right: -4px; + border: 2px solid transparent; + } + + .c13:focus-visible { + outline: none; + } + + .c13:focus-visible:after { + border-radius: 8px; + content: ''; + position: absolute; + top: -5px; + bottom: -5px; + left: -5px; + right: -5px; + border: 2px solid #4945ff; + } + + .c14 { + padding: 10px 16px; + background: #4945ff; + border: none; + border-radius: 4px; + border: 1px solid #d9d8ff; + background: #f0f0ff; + display: -webkit-inline-box; + display: -webkit-inline-flex; + display: -ms-inline-flexbox; + display: inline-flex; + -webkit-text-decoration: none; + text-decoration: none; + } + + .c14 .c17 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + } + + .c14 .c15 { + color: #ffffff; + } + + .c14[aria-disabled='true'] { + border: 1px solid #dcdce4; + background: #eaeaef; + } + + .c14[aria-disabled='true'] .c15 { + color: #666687; + } + + .c14[aria-disabled='true'] svg > g, + .c14[aria-disabled='true'] svg path { + fill: #666687; + } + + .c14[aria-disabled='true']:active { + border: 1px solid #dcdce4; + background: #eaeaef; + } + + .c14[aria-disabled='true']:active .c15 { + color: #666687; + } + + .c14[aria-disabled='true']:active svg > g, + .c14[aria-disabled='true']:active svg path { + fill: #666687; + } + + .c14:hover { + background-color: #ffffff; + } + + .c14:active { + background-color: #ffffff; + border: 1px solid #4945ff; + } + + .c14:active .c15 { + color: #4945ff; + } + + .c14:active svg > g, + .c14:active svg path { + fill: #4945ff; + } + + .c14 .c15 { + color: #271fe0; + } + + .c14 svg > g, + .c14 svg path { + fill: #271fe0; + } + + .c1 { + background: #f6f6f9; + padding-top: 40px; + padding-right: 56px; + padding-bottom: 40px; + padding-left: 56px; + } + + .c6 { + padding-right: 56px; + padding-left: 56px; + } + + .c2 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-flex-direction: row; + -ms-flex-direction: row; + flex-direction: row; + -webkit-box-pack: justify; + -webkit-justify-content: space-between; + -ms-flex-pack: justify; + justify-content: space-between; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + } + + .c3 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-flex-direction: row; + -ms-flex-direction: row; + flex-direction: row; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + } + + .c4 { + color: #32324d; + font-weight: 600; + font-size: 2rem; + line-height: 1.25; + } + + .c5 { + color: #666687; + font-size: 1rem; + line-height: 1.5; + } + +
+
+
+
+
+

+ Page not found +

+
+
+

+

+
+
+
+ +
+

+ An error occured +

+
+ + + Back to homepage + + + +
+
+
+ `); + }); +}); diff --git a/packages/core/admin/admin/src/pages/NotFoundPage/index.js b/packages/core/admin/admin/src/pages/NotFoundPage/index.js index 47fea7054a..190b4ff6a1 100644 --- a/packages/core/admin/admin/src/pages/NotFoundPage/index.js +++ b/packages/core/admin/admin/src/pages/NotFoundPage/index.js @@ -4,7 +4,50 @@ * This is the page we show when the user visits a url that doesn't have a route * */ +import React from 'react'; +import { useFocusWhenNavigate } from '@strapi/helper-plugin'; +import { Main } from '@strapi/design-system/Main'; +import { LinkButton } from '@strapi/design-system/LinkButton'; +import { ContentLayout, HeaderLayout } from '@strapi/design-system/Layout'; +import { EmptyStateLayout } from '@strapi/design-system/EmptyStateLayout'; +import EmptyPictures from '@strapi/icons/EmptyPictures'; +import ArrowRight from '@strapi/icons/ArrowRight'; +import { useIntl } from 'react-intl'; -const NotFoundPage = () => 'TODO NOT FOUND'; +const NoContentType = () => { + const { formatMessage } = useIntl(); + useFocusWhenNavigate(); -export default NotFoundPage; + return ( +
+ + + } to="/"> + {formatMessage({ + id: 'app.components.NotFoundPage.back', + defaultMessage: 'Back to homepage', + })} + + } + content={formatMessage({ + id: 'app.page.not.found', + defaultMessage: "Oops! We can't seem to find the page you're looging for...", + })} + hasRadius + icon={} + shadow="tableShadow" + /> + +
+ ); +}; + +export default NoContentType; diff --git a/packages/core/admin/admin/src/pages/NotFoundPage/tests/index.test.js b/packages/core/admin/admin/src/pages/NotFoundPage/tests/index.test.js new file mode 100644 index 0000000000..11aadf0e69 --- /dev/null +++ b/packages/core/admin/admin/src/pages/NotFoundPage/tests/index.test.js @@ -0,0 +1,462 @@ +import React from 'react'; +import { render } from '@testing-library/react'; +import { Router } from 'react-router-dom'; +import { createMemoryHistory } from 'history'; +import { IntlProvider } from 'react-intl'; +import { ThemeProvider, lightTheme } from '@strapi/design-system'; +import NotFoundPage from '../index'; +import { useModels } from '../../../hooks'; + +jest.mock('../../../hooks', () => ({ + useModels: jest.fn(), +})); + +const history = createMemoryHistory(); + +const App = ( + + + + + + + +); + +describe('NotFoundPage', () => { + useModels.mockImplementation(() => ({ + isLoading: false, + collectionTypes: [], + singleTypes: [], + })); + + it('renders and matches the snapshot', () => { + const { + container: { firstChild }, + } = render(App); + + expect(firstChild).toMatchInlineSnapshot(` + .c12 { + color: #666687; + font-weight: 500; + font-size: 1rem; + line-height: 1.25; + } + + .c7 { + background: #ffffff; + padding: 64px; + border-radius: 4px; + box-shadow: 0px 1px 4px rgba(33,33,52,0.1); + } + + .c9 { + padding-bottom: 24px; + } + + .c11 { + padding-bottom: 16px; + } + + .c8 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + text-align: center; + } + + .c10 svg { + height: 5.5rem; + } + + .c0:focus-visible { + outline: none; + } + + .c16 { + font-weight: 600; + color: #32324d; + font-size: 0.75rem; + line-height: 1.33; + } + + .c18 { + padding-left: 8px; + } + + .c13 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + cursor: pointer; + padding: 8px; + border-radius: 4px; + background: #ffffff; + border: 1px solid #dcdce4; + position: relative; + outline: none; + } + + .c13 svg { + height: 12px; + width: 12px; + } + + .c13 svg > g, + .c13 svg path { + fill: #ffffff; + } + + .c13[aria-disabled='true'] { + pointer-events: none; + } + + .c13:after { + -webkit-transition-property: all; + transition-property: all; + -webkit-transition-duration: 0.2s; + transition-duration: 0.2s; + border-radius: 8px; + content: ''; + position: absolute; + top: -4px; + bottom: -4px; + left: -4px; + right: -4px; + border: 2px solid transparent; + } + + .c13:focus-visible { + outline: none; + } + + .c13:focus-visible:after { + border-radius: 8px; + content: ''; + position: absolute; + top: -5px; + bottom: -5px; + left: -5px; + right: -5px; + border: 2px solid #4945ff; + } + + .c14 { + padding: 8px 16px; + background: #4945ff; + border: none; + border-radius: 4px; + border: 1px solid #d9d8ff; + background: #f0f0ff; + display: -webkit-inline-box; + display: -webkit-inline-flex; + display: -ms-inline-flexbox; + display: inline-flex; + -webkit-text-decoration: none; + text-decoration: none; + } + + .c14 .c17 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + } + + .c14 .c15 { + color: #ffffff; + } + + .c14[aria-disabled='true'] { + border: 1px solid #dcdce4; + background: #eaeaef; + } + + .c14[aria-disabled='true'] .c15 { + color: #666687; + } + + .c14[aria-disabled='true'] svg > g, + .c14[aria-disabled='true'] svg path { + fill: #666687; + } + + .c14[aria-disabled='true']:active { + border: 1px solid #dcdce4; + background: #eaeaef; + } + + .c14[aria-disabled='true']:active .c15 { + color: #666687; + } + + .c14[aria-disabled='true']:active svg > g, + .c14[aria-disabled='true']:active svg path { + fill: #666687; + } + + .c14:hover { + background-color: #ffffff; + } + + .c14:active { + background-color: #ffffff; + border: 1px solid #4945ff; + } + + .c14:active .c15 { + color: #4945ff; + } + + .c14:active svg > g, + .c14:active svg path { + fill: #4945ff; + } + + .c14 .c15 { + color: #271fe0; + } + + .c14 svg > g, + .c14 svg path { + fill: #271fe0; + } + + .c1 { + background: #f6f6f9; + padding-top: 40px; + padding-right: 56px; + padding-bottom: 40px; + padding-left: 56px; + } + + .c6 { + padding-right: 56px; + padding-left: 56px; + } + + .c2 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-flex-direction: row; + -ms-flex-direction: row; + flex-direction: row; + -webkit-box-pack: justify; + -webkit-justify-content: space-between; + -ms-flex-pack: justify; + justify-content: space-between; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + } + + .c3 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-flex-direction: row; + -ms-flex-direction: row; + flex-direction: row; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + } + + .c4 { + color: #32324d; + font-weight: 600; + font-size: 2rem; + line-height: 1.25; + } + + .c5 { + color: #666687; + font-size: 1rem; + line-height: 1.5; + } + +
+
+
+
+
+

+ Page not found +

+
+
+

+

+
+
+
+ +
+

+ Oops! We can't seem to find the page you're looging for... +

+
+ + + Back to homepage + + + +
+
+
+ `); + }); +}); diff --git a/packages/core/admin/admin/src/translations/en.json b/packages/core/admin/admin/src/translations/en.json index a7c3802140..39dd5a0f00 100644 --- a/packages/core/admin/admin/src/translations/en.json +++ b/packages/core/admin/admin/src/translations/en.json @@ -362,6 +362,7 @@ "app.containers.Users.EditPage.roles-bloc-title": "Attributed roles", "app.containers.Users.ModalForm.footer.button-success": "Invite user", "app.links.configure-view": "Configure the view", + "app.page.not.found": "Oops! We can't seem to find the page you're looging for...", "app.static.links.cheatsheet": "CheatSheet", "app.utils.SelectOption.defaultMessage": " ", "app.utils.add-filter": "Add filter", From 0562ca0578c4fa4015e0a21fb46644db74e591e8 Mon Sep 17 00:00:00 2001 From: HichamELBSI Date: Tue, 18 Jan 2022 17:58:08 +0100 Subject: [PATCH 2/3] Fix button props Signed-off-by: HichamELBSI --- .../core/admin/admin/src/pages/InternalErrorPage/index.js | 2 +- .../admin/src/pages/InternalErrorPage/tests/index.test.js | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/core/admin/admin/src/pages/InternalErrorPage/index.js b/packages/core/admin/admin/src/pages/InternalErrorPage/index.js index e51c6ca941..be94f94e65 100644 --- a/packages/core/admin/admin/src/pages/InternalErrorPage/index.js +++ b/packages/core/admin/admin/src/pages/InternalErrorPage/index.js @@ -30,7 +30,7 @@ const InternalErrorPage = () => { } to="/"> + } to="/"> {formatMessage({ id: 'app.components.NotFoundPage.back', defaultMessage: 'Back to homepage', diff --git a/packages/core/admin/admin/src/pages/InternalErrorPage/tests/index.test.js b/packages/core/admin/admin/src/pages/InternalErrorPage/tests/index.test.js index c1897ef983..870faedaaf 100644 --- a/packages/core/admin/admin/src/pages/InternalErrorPage/tests/index.test.js +++ b/packages/core/admin/admin/src/pages/InternalErrorPage/tests/index.test.js @@ -84,8 +84,8 @@ describe('InternalErrorPage', () => { .c16 { font-weight: 600; color: #32324d; - font-size: 0.875rem; - line-height: 1.43; + font-size: 0.75rem; + line-height: 1.33; } .c18 { @@ -151,7 +151,7 @@ describe('InternalErrorPage', () => { } .c14 { - padding: 10px 16px; + padding: 8px 16px; background: #4945ff; border: none; border-radius: 4px; From 6bbdb976343a721fb48a48054e5a9c958e3c9219 Mon Sep 17 00:00:00 2001 From: HichamELBSI Date: Wed, 19 Jan 2022 14:23:04 +0100 Subject: [PATCH 3/3] Fix tests Signed-off-by: HichamELBSI --- .../src/pages/InternalErrorPage/tests/index.test.js | 11 ----------- .../admin/src/pages/NotFoundPage/tests/index.test.js | 11 ----------- 2 files changed, 22 deletions(-) diff --git a/packages/core/admin/admin/src/pages/InternalErrorPage/tests/index.test.js b/packages/core/admin/admin/src/pages/InternalErrorPage/tests/index.test.js index 870faedaaf..a5e600baaf 100644 --- a/packages/core/admin/admin/src/pages/InternalErrorPage/tests/index.test.js +++ b/packages/core/admin/admin/src/pages/InternalErrorPage/tests/index.test.js @@ -5,11 +5,6 @@ import { createMemoryHistory } from 'history'; import { IntlProvider } from 'react-intl'; import { ThemeProvider, lightTheme } from '@strapi/design-system'; import InternalErrorPage from '../index'; -import { useModels } from '../../../hooks'; - -jest.mock('../../../hooks', () => ({ - useModels: jest.fn(), -})); const history = createMemoryHistory(); @@ -24,12 +19,6 @@ const App = ( ); describe('InternalErrorPage', () => { - useModels.mockImplementation(() => ({ - isLoading: false, - collectionTypes: [], - singleTypes: [], - })); - it('renders and matches the snapshot', () => { const { container: { firstChild }, diff --git a/packages/core/admin/admin/src/pages/NotFoundPage/tests/index.test.js b/packages/core/admin/admin/src/pages/NotFoundPage/tests/index.test.js index 11aadf0e69..b3ead52062 100644 --- a/packages/core/admin/admin/src/pages/NotFoundPage/tests/index.test.js +++ b/packages/core/admin/admin/src/pages/NotFoundPage/tests/index.test.js @@ -5,11 +5,6 @@ import { createMemoryHistory } from 'history'; import { IntlProvider } from 'react-intl'; import { ThemeProvider, lightTheme } from '@strapi/design-system'; import NotFoundPage from '../index'; -import { useModels } from '../../../hooks'; - -jest.mock('../../../hooks', () => ({ - useModels: jest.fn(), -})); const history = createMemoryHistory(); @@ -24,12 +19,6 @@ const App = ( ); describe('NotFoundPage', () => { - useModels.mockImplementation(() => ({ - isLoading: false, - collectionTypes: [], - singleTypes: [], - })); - it('renders and matches the snapshot', () => { const { container: { firstChild },