diff --git a/jest.config.front.js b/jest.config.front.js index e8b1825ef1..e34535337d 100644 --- a/jest.config.front.js +++ b/jest.config.front.js @@ -64,6 +64,7 @@ module.exports = { testPathIgnorePatterns: [ '/node_modules/', '/examples/getstarted/', + '/examples/kitchensink/', '/packages/strapi-helper-plugin/dist/', '/OLD/', '__tests__', diff --git a/jsconfig.json b/jsconfig.json index bc6d4bd653..a3c94b00a9 100644 --- a/jsconfig.json +++ b/jsconfig.json @@ -14,6 +14,7 @@ "**/build/*", "**/*.test.js", "**/*.test.e2e.js", - "**/examples/getstarted/*" + "**/examples/getstarted/*", + "**/examples/kitchensink/*" ] } diff --git a/packages/core/admin/admin/src/content-manager/pages/App/index.js b/packages/core/admin/admin/src/content-manager/pages/App/index.js index 02ab2e247d..c22871f451 100644 --- a/packages/core/admin/admin/src/content-manager/pages/App/index.js +++ b/packages/core/admin/admin/src/content-manager/pages/App/index.js @@ -1,9 +1,12 @@ import React from 'react'; import { Switch, Route, useRouteMatch, Redirect, useLocation } from 'react-router-dom'; import { CheckPagePermissions, LoadingIndicatorPage, NotFound } from '@strapi/helper-plugin'; -import { Layout } from '@strapi/parts/Layout'; +import { Layout, HeaderLayout } from '@strapi/parts/Layout'; +import { Main } from '@strapi/parts'; +import { useIntl } from 'react-intl'; import sortBy from 'lodash/sortBy'; import permissions from '../../../permissions'; +import getTrad from '../../utils/getTrad'; import DragLayer from '../../components/DragLayer'; import ModelsContext from '../../contexts/ModelsContext'; import CollectionTypeRecursivePath from '../CollectionTypeRecursivePath'; @@ -20,9 +23,22 @@ const App = () => { const { status, collectionTypeLinks, singleTypeLinks, models, refetchData } = useModels(); const authorisedModels = sortBy([...collectionTypeLinks, ...singleTypeLinks], 'title'); const { pathname } = useLocation(); + const { formatMessage } = useIntl(); + // Check with @mfrachet if ok with a11y if (status === 'loading') { - return ; + return ( +
+ + +
+ ); } // Redirect the user to the 403 page diff --git a/packages/core/admin/admin/src/content-manager/pages/App/useModels.js b/packages/core/admin/admin/src/content-manager/pages/App/useModels.js index 63ca52e51a..90bb281452 100644 --- a/packages/core/admin/admin/src/content-manager/pages/App/useModels.js +++ b/packages/core/admin/admin/src/content-manager/pages/App/useModels.js @@ -1,10 +1,12 @@ import { useNotification, useRBACProvider, useStrapiApp } from '@strapi/helper-plugin'; import { useEffect, useRef } from 'react'; import { useDispatch, useSelector } from 'react-redux'; +import { useNotifyAT } from '@strapi/parts/LiveRegions'; import axios from 'axios'; +import { useIntl } from 'react-intl'; import { axiosInstance } from '../../../core/utils'; import { MUTATE_COLLECTION_TYPES_LINKS, MUTATE_SINGLE_TYPES_LINKS } from '../../../exposedHooks'; -import { getRequestUrl } from '../../utils'; +import { getRequestUrl, getTrad } from '../../utils'; import { getData, resetProps, setContentTypeLinks } from './actions'; import { selectAppDomain } from './selectors'; import getContentTypeLinks from './utils/getContentTypeLinks'; @@ -18,6 +20,8 @@ const useModels = () => { const { runHookWaterfall } = useStrapiApp(); const CancelToken = axios.CancelToken; const source = CancelToken.source(); + const { notifyStatus } = useNotifyAT(); + const { formatMessage } = useIntl(); const fetchData = async () => { dispatch(getData()); @@ -36,6 +40,13 @@ const useModels = () => { ) ); + notifyStatus( + formatMessage({ + id: getTrad('App.schemas.data-loaded'), + defaultMessage: 'The schemas have been successfully loaded.', + }) + ); + const { authorizedCtLinks, authorizedStLinks } = await getContentTypeLinks( models, allPermissions, diff --git a/packages/core/admin/admin/src/content-manager/pages/NoContentType/index.js b/packages/core/admin/admin/src/content-manager/pages/NoContentType/index.js index 029b2fbe16..94169a3701 100644 --- a/packages/core/admin/admin/src/content-manager/pages/NoContentType/index.js +++ b/packages/core/admin/admin/src/content-manager/pages/NoContentType/index.js @@ -1,68 +1,51 @@ import React from 'react'; -import { Button, Padded, Text } from '@buffetjs/core'; -import { useHistory } from 'react-router'; -import { BaselineAlignment, CheckPermissions } from '@strapi/helper-plugin'; +import { useFocusWhenNavigate } from '@strapi/helper-plugin'; +import { Main } from '@strapi/parts'; +import { LinkButton } from '@strapi/parts/LinkButton'; +import { ContentLayout, HeaderLayout } from '@strapi/parts/Layout'; +import { EmptyStateLayout } from '@strapi/parts/EmptyStateLayout'; +import { AddIcon, EmptyStateDocument } from '@strapi/icons'; import { useIntl } from 'react-intl'; -import styled from 'styled-components'; import { getTrad } from '../../utils'; -import Container from '../../components/Container'; -// TODO change pic when DS ready -import Oops from './oops.png'; - -const Block = styled.div` - padding: 48px 10px 50px 10px; - background: #ffffff; - border-radius: 2px; - box-shadow: 0 2px 4px #e3e9f3; - margin-bottom: 17px; - text-align: center; -`; - -const Img = styled.img` - max-height: 77px; -`; const NoContentType = () => { const { formatMessage } = useIntl(); - const { push } = useHistory(); - - const handleClick = () => { - // TODO change url when CTB ready - push( - '/plugins/content-type-builder/content-types/plugin::users-permissions.user?modalType=contentType&kind=collectionType&actionType=create&settingType=base&forTarget=contentType&headerId=content-type-builder.modalForm.contentType.header-create&header_icon_isCustom_1=false&header_icon_name_1=contentType&header_label_1=null' - ); - }; + useFocusWhenNavigate(); return ( - - - -
- - - +
+ + + } + to="/plugins/content-type-builder/content-types/plugin::users-permissions.user?modalType=contentType&kind=collectionType&actionType=create&settingType=base&forTarget=contentType&headerId=content-type-builder.modalForm.contentType.header-create&header_icon_isCustom_1=false&header_icon_name_1=contentType&header_label_1=null" + > {formatMessage({ - id: getTrad('pages.NoContentType.text'), - defaultMessage: - "You don't have any content yet, we recommend you to create your first Content-Type.", + id: 'app.components.HomePage.create', + defaultMessage: 'Create your first Content-type', })} - - - - - - - -
-
-
+ + } + content={formatMessage({ + id: 'content-manager.pages.NoContentType.text', + defaultMessage: + "You don't have any content yet, we recommend you to create your first Content-Type.", + })} + hasRadius + icon={} + shadow="tableShadow" + /> + + ); }; diff --git a/packages/core/admin/admin/src/content-manager/pages/NoContentType/oops.png b/packages/core/admin/admin/src/content-manager/pages/NoContentType/oops.png deleted file mode 100644 index b469309255..0000000000 Binary files a/packages/core/admin/admin/src/content-manager/pages/NoContentType/oops.png and /dev/null differ diff --git a/packages/core/admin/admin/src/content-manager/pages/NoContentType/tests/index.test.js b/packages/core/admin/admin/src/content-manager/pages/NoContentType/tests/index.test.js new file mode 100644 index 0000000000..4a9e19ce9e --- /dev/null +++ b/packages/core/admin/admin/src/content-manager/pages/NoContentType/tests/index.test.js @@ -0,0 +1,399 @@ +import React from 'react'; +import { render } from '@testing-library/react'; +import { IntlProvider } from 'react-intl'; +import { Router } from 'react-router-dom'; +import { createMemoryHistory } from 'history'; +import Theme from '../../../../components/Theme'; +import NoContentType from '../index'; + +jest.mock('@strapi/helper-plugin', () => ({ + useFocusWhenNavigate: jest.fn(), +})); + +describe('CONTENT MANAGER | pages | NoContentType', () => { + it('renders and matches the snapshot', () => { + const { + container: { firstChild }, + } = render( + + + + + + + + ); + + expect(firstChild).toMatchInlineSnapshot(` + .c0 { + outline: none; + } + + .c19 { + font-weight: 500; + font-size: 0.75rem; + line-height: 1.33; + color: #32324d; + } + + .c17 { + padding-right: 8px; + } + + .c14 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + cursor: pointer; + padding: 8px; + border-radius: 4px; + background: #ffffff; + border: 1px solid #dcdce4; + } + + .c14 svg { + height: 12px; + width: 12px; + } + + .c14 svg > g, + .c14 svg path { + fill: #ffffff; + } + + .c14[aria-disabled='true'] { + pointer-events: none; + } + + .c15 { + 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; + } + + .c15 .c16 { + 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; + } + + .c15 .c18 { + color: #ffffff; + } + + .c15[aria-disabled='true'] { + border: 1px solid #dcdce4; + background: #eaeaef; + } + + .c15[aria-disabled='true'] .c18 { + color: #666687; + } + + .c15[aria-disabled='true'] svg > g, + .c15[aria-disabled='true'] svg path { + fill: #666687; + } + + .c15[aria-disabled='true']:active { + border: 1px solid #dcdce4; + background: #eaeaef; + } + + .c15[aria-disabled='true']:active .c18 { + color: #666687; + } + + .c15[aria-disabled='true']:active svg > g, + .c15[aria-disabled='true']:active svg path { + fill: #666687; + } + + .c15:hover { + background-color: #ffffff; + } + + .c15:active { + background-color: #ffffff; + border: 1px solid #4945ff; + } + + .c15:active .c18 { + color: #4945ff; + } + + .c15:active svg > g, + .c15:active svg path { + fill: #4945ff; + } + + .c15 .c18 { + color: #271fe0; + } + + .c15 svg > g, + .c15 svg path { + fill: #271fe0; + } + + .c1 { + background: #f6f6f9; + padding-top: 56px; + padding-right: 56px; + padding-bottom: 56px; + padding-left: 56px; + } + + .c7 { + 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 { + font-weight: 600; + font-size: 2rem; + line-height: 1.25; + color: #32324d; + } + + .c5 { + font-weight: 400; + font-size: 0.875rem; + line-height: 1.43; + color: #666687; + } + + .c6 { + font-size: 1rem; + line-height: 1.5; + } + + .c13 { + font-weight: 500; + font-size: 1rem; + line-height: 1.25; + color: #666687; + } + + .c8 { + background: #ffffff; + padding: 64px; + border-radius: 4px; + box-shadow: 0px 1px 4px rgba(33,33,52,0.1); + } + + .c10 { + padding-bottom: 24px; + } + + .c12 { + padding-bottom: 16px; + } + + .c9 { + 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; + } + + .c11 svg { + height: 5.5rem; + } + +
+
+
+
+
+

+ Content +

+
+
+

+

+
+
+
+ +
+

+ You don't have any content yet, we recommend you to create your first Content-Type. +

+
+ + + + Create your first Content-type + + +
+
+
+ `); + }); +}); diff --git a/packages/core/admin/admin/src/translations/en.json b/packages/core/admin/admin/src/translations/en.json index 87d8cf7001..8a94367f8f 100644 --- a/packages/core/admin/admin/src/translations/en.json +++ b/packages/core/admin/admin/src/translations/en.json @@ -405,6 +405,7 @@ "content-manager.EditRelations.title": "Relational data", "content-manager.api.id": "API ID", "content-manager.header.name": "Content", + "content-manager.App.schemas.data-loaded": "The schemas have been successfully loaded", "content-manager.components.AddFilterCTA.add": "Filters", "content-manager.components.AddFilterCTA.hide": "Filters", "content-manager.components.DraggableAttr.edit": "Click to edit",