From 1389a447c2d1b93c9774134b46d4279c60f4eb05 Mon Sep 17 00:00:00 2001 From: Mark Kaylor Date: Mon, 6 Sep 2021 15:36:56 +0200 Subject: [PATCH 1/2] migrate roles page header --- .../users-permissions/admin/src/index.js | 30 +- .../admin/src/pages/Roles/ListPage/index.js | 214 +++---------- .../pages/Roles/ListPage/tests/index.test.js | 284 ++++++++++++++++++ 3 files changed, 338 insertions(+), 190 deletions(-) create mode 100644 packages/plugins/users-permissions/admin/src/pages/Roles/ListPage/tests/index.test.js diff --git a/packages/plugins/users-permissions/admin/src/index.js b/packages/plugins/users-permissions/admin/src/index.js index c2b62a2786..be4c3ff22a 100644 --- a/packages/plugins/users-permissions/admin/src/index.js +++ b/packages/plugins/users-permissions/admin/src/index.js @@ -27,22 +27,22 @@ export default { }, }, [ - // { - // intlLabel: { - // id: getTrad('HeaderNav.link.roles'), - // defaultMessage: 'Roles', - // }, - // id: 'roles', - // to: `/settings/${pluginId}/roles`, - // Component: async () => { - // const component = await import( - // /* webpackChunkName: "users-roles-settings-page" */ './pages/Roles' - // ); + { + intlLabel: { + id: getTrad('HeaderNav.link.roles'), + defaultMessage: 'Roles', + }, + id: 'roles', + to: `/settings/${pluginId}/roles`, + Component: async () => { + const component = await import( + /* webpackChunkName: "users-roles-settings-page" */ './pages/Roles' + ); - // return component; - // }, - // permissions: pluginPermissions.accessRoles, - // }, + return component; + }, + permissions: pluginPermissions.accessRoles, + }, { intlLabel: { id: getTrad('HeaderNav.link.providers'), diff --git a/packages/plugins/users-permissions/admin/src/pages/Roles/ListPage/index.js b/packages/plugins/users-permissions/admin/src/pages/Roles/ListPage/index.js index a88f5170a5..cc9a84d766 100644 --- a/packages/plugins/users-permissions/admin/src/pages/Roles/ListPage/index.js +++ b/packages/plugins/users-permissions/admin/src/pages/Roles/ListPage/index.js @@ -1,195 +1,59 @@ -import React, { useCallback, useMemo, useState } from 'react'; -import { List, Header } from '@buffetjs/custom'; -import { Helmet } from 'react-helmet'; +import React from 'react'; +import { Button, HeaderLayout, Layout, Main } from '@strapi/parts'; +import { AddIcon } from '@strapi/icons'; import { useIntl } from 'react-intl'; +import { useTracking, SettingsPageTitle } from '@strapi/helper-plugin'; import { useHistory } from 'react-router-dom'; -import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { - useRBAC, - PopUpWarning, - request, - useTracking, - useNotification, - useOverlayBlocker, -} from '@strapi/helper-plugin'; -import permissions from '../../../permissions'; -import { EmptyRole, RoleListWrapper, RoleRow } from '../../../components/Roles'; -import { useRolesList } from '../../../hooks'; -import BaselineAlignment from './BaselineAlignment'; -import pluginId from '../../../pluginId'; import { getTrad } from '../../../utils'; +import pluginId from '../../../pluginId'; const RoleListPage = () => { - const { formatMessage } = useIntl(); const { trackUsage } = useTracking(); + const { formatMessage } = useIntl(); const { push } = useHistory(); - const toggleNotification = useNotification(); - const { lockApp, unlockApp } = useOverlayBlocker(); - const [modalToDelete, setModalDelete] = useState(); - const [shouldRefetchData, setShouldRefetchData] = useState(false); - const [showModalConfirmButtonLoading, setModalButtonLoading] = useState(false); - - const updatePermissions = useMemo(() => { - return { - update: permissions.updateRole, - create: permissions.createRole, - delete: permissions.deleteRole, - read: permissions.readRoles, - }; - }, []); - const { - isLoading: isLoadingForPermissions, - allowedActions: { canCreate, canUpdate, canDelete, canRead }, - } = useRBAC(updatePermissions); - const shouldFetchData = !isLoadingForPermissions && canRead; - - const { roles, getData, isLoading } = useRolesList(shouldFetchData); - - const handleGoTo = id => { - if (canUpdate) { - push(`/settings/${pluginId}/roles/${id}`); - } - }; - - const handleDelete = () => { - lockApp(); - - setModalButtonLoading(true); - - Promise.resolve( - request(`/${pluginId}/roles/${modalToDelete}`, { - method: 'DELETE', - }) - ) - .then(() => { - setShouldRefetchData(true); - toggleNotification({ - type: 'success', - message: { id: getTrad('Settings.roles.deleted') }, - }); - }) - .catch(err => { - console.error(err); - toggleNotification({ - type: 'warning', - message: { id: 'notification.error' }, - }); - }) - .finally(() => { - setModalDelete(null); - unlockApp(); - }); - }; - - const handleClosedModalDelete = () => { - if (shouldRefetchData) { - getData(); - } - setModalButtonLoading(false); - setShouldRefetchData(false); - }; const handleNewRoleClick = () => { trackUsage('willCreateRole'); push(`/settings/${pluginId}/roles/new`); }; - /* eslint-disable indent */ - const headerActions = canCreate - ? [ - { - label: formatMessage({ - id: getTrad('List.button.roles'), - defaultMessage: 'Add new role', - }), - onClick: handleNewRoleClick, - color: 'primary', - type: 'button', - icon: true, - }, - ] - : []; - /* eslint-enable indent */ - - const checkCanDeleteRole = useCallback( - role => { - return canDelete && !['public', 'authenticated'].includes(role.type); - }, - [canDelete] - ); - - const getLinks = role => { - const links = []; - - if (canUpdate) { - links.push({ - icon: , - onClick: () => handleGoTo(role.id), - }); - } - if (checkCanDeleteRole(role)) { - links.push({ - icon: , - onClick: e => { - e.preventDefault(); - setModalDelete(role.id); - e.stopPropagation(); - }, - }); - } - - return links; - }; + const pageTitle = formatMessage({ + id: getTrad('HeaderNav.link.roles'), + defaultMessage: 'Roles', + }); return ( - <> - - -
+ +
- - - {canRead && ( - - 1 ? '.plural' : '.singular'}`, - }, - { number: roles.length } - )} - items={roles} - isLoading={isLoading || isLoadingForPermissions} - customRowComponent={role => ( - handleGoTo(role.id)} links={getLinks(role)} role={role} /> - )} - /> - {!roles && !isLoading && !isLoadingForPermissions && } - setModalDelete(null)} - isConfirmButtonLoading={showModalConfirmButtonLoading} - /> - - )} - + > + }> + {formatMessage({ + id: getTrad('List.button.roles'), + defaultMessage: 'Add new role', + })} + + } + /> +
+ ); }; diff --git a/packages/plugins/users-permissions/admin/src/pages/Roles/ListPage/tests/index.test.js b/packages/plugins/users-permissions/admin/src/pages/Roles/ListPage/tests/index.test.js new file mode 100644 index 0000000000..50b7c8d1b8 --- /dev/null +++ b/packages/plugins/users-permissions/admin/src/pages/Roles/ListPage/tests/index.test.js @@ -0,0 +1,284 @@ +import React from 'react'; +import { render } from '@testing-library/react'; +import { IntlProvider } from 'react-intl'; +import { ThemeProvider, lightTheme } from '@strapi/parts'; + +import RoleListPage from '../index'; + +jest.mock('@strapi/helper-plugin', () => ({ + ...jest.requireActual('@strapi/helper-plugin'), + useTracking: jest.fn(() => ({ trackUsage: jest.fn() })), + useNotification: jest.fn(), +})); + +jest.mock('react-router-dom', () => ({ + ...jest.requireActual('react-router-dom'), + useHistory: () => ({ + push: jest.fn(), + }), +})); + +const App = ( + + + + + +); + +describe('Admin | containers | RoleListPage', () => { + it('renders and matches the snapshot', () => { + const { + container: { firstChild }, + } = render(App); + + expect(firstChild).toMatchInlineSnapshot(` + .c8 { + font-weight: 600; + font-size: 2rem; + line-height: 1.25; + color: #32324d; + } + + .c13 { + font-weight: 500; + font-size: 0.75rem; + line-height: 1.33; + color: #32324d; + } + + .c14 { + font-weight: 400; + font-size: 0.875rem; + line-height: 1.43; + color: #666687; + } + + .c15 { + font-size: 1rem; + line-height: 1.5; + } + + .c2 { + padding-bottom: 56px; + } + + .c5 { + background: #f6f6f9; + padding-top: 56px; + padding-right: 56px; + padding-bottom: 56px; + padding-left: 56px; + } + + .c11 { + padding-right: 8px; + } + + .c6 { + 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; + } + + .c7 { + 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; + } + + .c9 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + cursor: pointer; + padding: 8px; + border-radius: 4px; + background: #ffffff; + border: 1px solid #dcdce4; + } + + .c9 svg { + height: 12px; + width: 12px; + } + + .c9 svg > g, + .c9 svg path { + fill: #ffffff; + } + + .c9[aria-disabled='true'] { + pointer-events: none; + } + + .c10 { + padding: 8px 16px; + background: #4945ff; + border: none; + border: 1px solid #4945ff; + background: #4945ff; + } + + .c10 .c0 { + 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; + } + + .c10 .c12 { + color: #ffffff; + } + + .c10[aria-disabled='true'] { + border: 1px solid #dcdce4; + background: #eaeaef; + } + + .c10[aria-disabled='true'] .c12 { + color: #666687; + } + + .c10[aria-disabled='true'] svg > g, + .c10[aria-disabled='true'] svg path { + fill: #666687; + } + + .c10[aria-disabled='true']:active { + border: 1px solid #dcdce4; + background: #eaeaef; + } + + .c10[aria-disabled='true']:active .c12 { + color: #666687; + } + + .c10[aria-disabled='true']:active svg > g, + .c10[aria-disabled='true']:active svg path { + fill: #666687; + } + + .c10:hover { + border: 1px solid #7b79ff; + background: #7b79ff; + } + + .c10:active { + border: 1px solid #4945ff; + background: #4945ff; + } + + .c1 { + display: grid; + grid-template-columns: 1fr; + } + + .c3 { + overflow-x: hidden; + } + + .c4 { + outline: none; + } + +
+
+
+
+
+
+
+

+ Roles +

+
+ +
+

+ List of roles +

+
+
+
+
+
+ `); + }); +}); From 8891295614bdced5d6d00e726a02d0b163dac0f2 Mon Sep 17 00:00:00 2001 From: Mark Kaylor Date: Tue, 7 Sep 2021 10:12:37 +0200 Subject: [PATCH 2/2] add check permissions --- .../admin/src/pages/Roles/ListPage/index.js | 17 +- .../pages/Roles/ListPage/tests/index.test.js | 166 +++--------------- 2 files changed, 31 insertions(+), 152 deletions(-) diff --git a/packages/plugins/users-permissions/admin/src/pages/Roles/ListPage/index.js b/packages/plugins/users-permissions/admin/src/pages/Roles/ListPage/index.js index cc9a84d766..89c9f591b1 100644 --- a/packages/plugins/users-permissions/admin/src/pages/Roles/ListPage/index.js +++ b/packages/plugins/users-permissions/admin/src/pages/Roles/ListPage/index.js @@ -2,11 +2,12 @@ import React from 'react'; import { Button, HeaderLayout, Layout, Main } from '@strapi/parts'; import { AddIcon } from '@strapi/icons'; import { useIntl } from 'react-intl'; -import { useTracking, SettingsPageTitle } from '@strapi/helper-plugin'; +import { useTracking, SettingsPageTitle, CheckPermissions } from '@strapi/helper-plugin'; import { useHistory } from 'react-router-dom'; import { getTrad } from '../../../utils'; import pluginId from '../../../pluginId'; +import permissions from '../../../permissions'; const RoleListPage = () => { const { trackUsage } = useTracking(); @@ -44,12 +45,14 @@ const RoleListPage = () => { defaultMessage: 'List of roles', })} primaryAction={ - + + + } /> diff --git a/packages/plugins/users-permissions/admin/src/pages/Roles/ListPage/tests/index.test.js b/packages/plugins/users-permissions/admin/src/pages/Roles/ListPage/tests/index.test.js index 50b7c8d1b8..580b2cdf49 100644 --- a/packages/plugins/users-permissions/admin/src/pages/Roles/ListPage/tests/index.test.js +++ b/packages/plugins/users-permissions/admin/src/pages/Roles/ListPage/tests/index.test.js @@ -9,6 +9,7 @@ jest.mock('@strapi/helper-plugin', () => ({ ...jest.requireActual('@strapi/helper-plugin'), useTracking: jest.fn(() => ({ trackUsage: jest.fn() })), useNotification: jest.fn(), + CheckPermissions: jest.fn(() =>
), })); jest.mock('react-router-dom', () => ({ @@ -33,37 +34,30 @@ describe('Admin | containers | RoleListPage', () => { } = render(App); expect(firstChild).toMatchInlineSnapshot(` - .c8 { + .c7 { font-weight: 600; font-size: 2rem; line-height: 1.25; color: #32324d; } - .c13 { - font-weight: 500; - font-size: 0.75rem; - line-height: 1.33; - color: #32324d; - } - - .c14 { + .c8 { font-weight: 400; font-size: 0.875rem; line-height: 1.43; color: #666687; } - .c15 { + .c9 { font-size: 1rem; line-height: 1.5; } - .c2 { + .c1 { padding-bottom: 56px; } - .c5 { + .c4 { background: #f6f6f9; padding-top: 56px; padding-right: 56px; @@ -71,11 +65,7 @@ describe('Admin | containers | RoleListPage', () => { padding-left: 56px; } - .c11 { - padding-right: 8px; - } - - .c6 { + .c5 { display: -webkit-box; display: -webkit-flex; display: -ms-flexbox; @@ -93,7 +83,7 @@ describe('Admin | containers | RoleListPage', () => { align-items: center; } - .c7 { + .c6 { display: -webkit-box; display: -webkit-flex; display: -ms-flexbox; @@ -107,170 +97,56 @@ describe('Admin | containers | RoleListPage', () => { align-items: center; } - .c9 { - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - cursor: pointer; - padding: 8px; - border-radius: 4px; - background: #ffffff; - border: 1px solid #dcdce4; - } - - .c9 svg { - height: 12px; - width: 12px; - } - - .c9 svg > g, - .c9 svg path { - fill: #ffffff; - } - - .c9[aria-disabled='true'] { - pointer-events: none; - } - - .c10 { - padding: 8px 16px; - background: #4945ff; - border: none; - border: 1px solid #4945ff; - background: #4945ff; - } - - .c10 .c0 { - 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; - } - - .c10 .c12 { - color: #ffffff; - } - - .c10[aria-disabled='true'] { - border: 1px solid #dcdce4; - background: #eaeaef; - } - - .c10[aria-disabled='true'] .c12 { - color: #666687; - } - - .c10[aria-disabled='true'] svg > g, - .c10[aria-disabled='true'] svg path { - fill: #666687; - } - - .c10[aria-disabled='true']:active { - border: 1px solid #dcdce4; - background: #eaeaef; - } - - .c10[aria-disabled='true']:active .c12 { - color: #666687; - } - - .c10[aria-disabled='true']:active svg > g, - .c10[aria-disabled='true']:active svg path { - fill: #666687; - } - - .c10:hover { - border: 1px solid #7b79ff; - background: #7b79ff; - } - - .c10:active { - border: 1px solid #4945ff; - background: #4945ff; - } - - .c1 { + .c0 { display: grid; grid-template-columns: 1fr; } - .c3 { + .c2 { overflow-x: hidden; } - .c4 { + .c3 { outline: none; }

Roles

- +

List of roles