From c8f47d74a81ef7939b7181b34f118ed510a4075d Mon Sep 17 00:00:00 2001 From: ronronscelestes Date: Thu, 2 Sep 2021 17:37:38 +0200 Subject: [PATCH 1/4] delete a role added --- .../ee/admin/pages/Roles/ListPage/index.js | 52 +++++++++---------- 1 file changed, 24 insertions(+), 28 deletions(-) diff --git a/packages/core/admin/ee/admin/pages/Roles/ListPage/index.js b/packages/core/admin/ee/admin/pages/Roles/ListPage/index.js index 6900a5ad65..d633c98f7c 100644 --- a/packages/core/admin/ee/admin/pages/Roles/ListPage/index.js +++ b/packages/core/admin/ee/admin/pages/Roles/ListPage/index.js @@ -1,11 +1,11 @@ import { LoadingIndicatorPage, - PopUpWarning, SettingsPageTitle, request, useNotification, useQuery, useRBAC, + ConfirmDialog, } from '@strapi/helper-plugin'; import { AddIcon, DeleteIcon, Duplicate, EditIcon } from '@strapi/icons'; import { @@ -69,27 +69,17 @@ const useRoleActions = ({ getData, canCreate, canDelete, canUpdate, roles, sorte const toggleNotification = useNotification(); const [isWarningDeleteAllOpened, setIsWarningDeleteAllOpenend] = useState(false); const { push } = useHistory(); - const [ - { selectedRoles, showModalConfirmButtonLoading, shouldRefetchData }, - dispatch, - ] = useReducer(reducer, initialState); + const [{ selectedRoles, showModalConfirmButtonLoading }, dispatch] = useReducer( + reducer, + initialState + ); - const handleClosedModal = () => { - if (shouldRefetchData) { - getData(); - } - - // Empty the selected ids when the modal closes - dispatch({ - type: 'RESET_DATA_TO_DELETE', - }); - }; - - const handleConfirmDeleteData = async () => { + const handleDeleteData = async () => { try { dispatch({ type: 'ON_REMOVE_ROLES', }); + const filteredRoles = selectedRoles.filter(currentId => { const currentRole = roles.find(role => role.id === currentId); @@ -111,14 +101,13 @@ const useRoleActions = ({ getData, canCreate, canDelete, canUpdate, roles, sorte }, }); - // Empty the selectedRolesId and set the shouldRefetchData to true so the - // list is updated when closing the modal + await getData(); + dispatch({ - type: 'ON_REMOVE_ROLES_SUCCEEDED', + type: 'RESET_DATA_TO_DELETE', }); } } catch (err) { - console.error(err); const errorIds = get(err, ['response', 'payload', 'data', 'ids'], null); if (errorIds && Array.isArray(errorIds)) { @@ -133,9 +122,8 @@ const useRoleActions = ({ getData, canCreate, canDelete, canUpdate, roles, sorte message: { id: 'notification.error' }, }); } - } finally { - handleToggleModal(); } + handleToggleModal(); }; const onRoleDuplicate = useCallback( @@ -246,8 +234,8 @@ const useRoleActions = ({ getData, canCreate, canDelete, canUpdate, roles, sorte ); return { - handleClosedModal, - handleConfirmDeleteData, + // handleClosedModal, + // handleConfirmDeleteData, handleNewRoleClick, onRoleToggle, onAllRolesToggle, @@ -256,6 +244,7 @@ const useRoleActions = ({ getData, canCreate, canDelete, canUpdate, roles, sorte isWarningDeleteAllOpened, showModalConfirmButtonLoading, handleToggleModal, + handleDeleteData, }; }; @@ -275,8 +264,8 @@ const RoleListPage = () => { } = useSortedRoles(); const { - handleClosedModal, - handleConfirmDeleteData, + // handleClosedModal, + // handleConfirmDeleteData, handleNewRoleClick, onRoleToggle, onAllRolesToggle, @@ -285,6 +274,7 @@ const RoleListPage = () => { isWarningDeleteAllOpened, showModalConfirmButtonLoading, handleToggleModal, + handleDeleteData, } = useRoleActions({ getData, canCreate, canDelete, canUpdate, roles, sortedRoles }); // ! TODO - Show the search bar only if the user is allowed to read - add the search input @@ -409,12 +399,18 @@ const RoleListPage = () => { {!rowCount && !isLoading && } )} - */} + ); From 1ffa60a7795850349848cbdd065cc61fea7b6142 Mon Sep 17 00:00:00 2001 From: ronronscelestes Date: Thu, 2 Sep 2021 18:15:48 +0200 Subject: [PATCH 2/4] delete a role added --- .../src/components/Roles/RoleRow/index.js | 24 ++----------- .../ee/admin/pages/Roles/ListPage/index.js | 34 ------------------- 2 files changed, 2 insertions(+), 56 deletions(-) diff --git a/packages/core/admin/admin/src/components/Roles/RoleRow/index.js b/packages/core/admin/admin/src/components/Roles/RoleRow/index.js index 9bf509be55..d5044716f4 100644 --- a/packages/core/admin/admin/src/components/Roles/RoleRow/index.js +++ b/packages/core/admin/admin/src/components/Roles/RoleRow/index.js @@ -1,9 +1,9 @@ -import { Box, Row, Td, Text, Tr, IconButton, BaseCheckbox } from '@strapi/parts'; +import { Box, Row, Td, Text, Tr, IconButton } from '@strapi/parts'; import PropTypes from 'prop-types'; import React from 'react'; import { useIntl } from 'react-intl'; -const RoleRow = ({ onToggle, id, name, description, usersCount, isChecked, icons }) => { +const RoleRow = ({ id, name, description, usersCount, icons }) => { const { formatMessage } = useIntl(); const usersCountText = formatMessage( @@ -16,19 +16,6 @@ const RoleRow = ({ onToggle, id, name, description, usersCount, isChecked, icons return ( - {Boolean(onToggle) && ( - - onToggle(id)} - value={isChecked} - aria-label={formatMessage( - { id: `Roles.RoleRow.select-all`, defaultMessage: 'Select {name} for bulk actions' }, - { name } - )} - /> - - )} {name} @@ -53,19 +40,12 @@ const RoleRow = ({ onToggle, id, name, description, usersCount, isChecked, icons ); }; -RoleRow.defaultProps = { - onToggle: undefined, - isChecked: undefined, -}; - RoleRow.propTypes = { id: PropTypes.number.isRequired, name: PropTypes.string.isRequired, description: PropTypes.string.isRequired, usersCount: PropTypes.number.isRequired, icons: PropTypes.array.isRequired, - onToggle: PropTypes.func, - isChecked: PropTypes.bool, }; export default RoleRow; diff --git a/packages/core/admin/ee/admin/pages/Roles/ListPage/index.js b/packages/core/admin/ee/admin/pages/Roles/ListPage/index.js index d633c98f7c..2ae6a61af2 100644 --- a/packages/core/admin/ee/admin/pages/Roles/ListPage/index.js +++ b/packages/core/admin/ee/admin/pages/Roles/ListPage/index.js @@ -20,7 +20,6 @@ import { Tr, TableLabel, VisuallyHidden, - BaseCheckbox, Main, } from '@strapi/parts'; import { get } from 'lodash'; @@ -234,8 +233,6 @@ const useRoleActions = ({ getData, canCreate, canDelete, canUpdate, roles, sorte ); return { - // handleClosedModal, - // handleConfirmDeleteData, handleNewRoleClick, onRoleToggle, onAllRolesToggle, @@ -264,13 +261,8 @@ const RoleListPage = () => { } = useSortedRoles(); const { - // handleClosedModal, - // handleConfirmDeleteData, handleNewRoleClick, - onRoleToggle, - onAllRolesToggle, getIcons, - selectedRoles, isWarningDeleteAllOpened, showModalConfirmButtonLoading, handleToggleModal, @@ -283,11 +275,6 @@ const RoleListPage = () => { const rowCount = sortedRoles.length + 1; const colCount = 6; - const isAllEntriesIndeterminate = selectedRoles.length - ? selectedRoles.length !== rowCount - : false; - const isAllChecked = selectedRoles.length ? selectedRoles.length === rowCount : false; - if (isLoadingForPermissions) { return ; } @@ -335,16 +322,6 @@ const RoleListPage = () => { > - {!!onRoleToggle && ( - - - - )} {formatMessage({ @@ -384,10 +361,6 @@ const RoleListPage = () => { selectedRoleId === role.id) !== -1 - } name={role.name} description={role.description} usersCount={role.usersCount} @@ -399,13 +372,6 @@ const RoleListPage = () => { {!rowCount && !isLoading && } )} - {/* */} Date: Fri, 3 Sep 2021 11:38:16 +0200 Subject: [PATCH 3/4] Add search Signed-off-by: soupette --- .../admin/admin/src/pages/Users/ListPage/index.js | 4 ++-- .../core/admin/ee/admin/pages/Roles/ListPage/index.js | 11 +++++++---- .../lib/src/components}/Search/index.js | 4 ++-- packages/core/helper-plugin/lib/src/index.js | 1 + 4 files changed, 12 insertions(+), 8 deletions(-) rename packages/core/{admin/admin/src/pages/Users/ListPage => helper-plugin/lib/src/components}/Search/index.js (90%) diff --git a/packages/core/admin/admin/src/pages/Users/ListPage/index.js b/packages/core/admin/admin/src/pages/Users/ListPage/index.js index 29e6801671..547f1c4fac 100644 --- a/packages/core/admin/admin/src/pages/Users/ListPage/index.js +++ b/packages/core/admin/admin/src/pages/Users/ListPage/index.js @@ -1,8 +1,9 @@ import React from 'react'; import { CustomContentLayout, - useRBAC, + Search, SettingsPageTitle, + useRBAC, useNotification, useFocusWhenNavigate, } from '@strapi/helper-plugin'; @@ -15,7 +16,6 @@ import get from 'lodash/get'; import adminPermissions from '../../../permissions'; import DynamicTable from './DynamicTable'; import Filters from './Filters'; -import Search from './Search'; import PaginationFooter from './PaginationFooter'; import { deleteData, fetchData } from './utils/api'; import displayedFilters from './utils/displayedFilters'; diff --git a/packages/core/admin/ee/admin/pages/Roles/ListPage/index.js b/packages/core/admin/ee/admin/pages/Roles/ListPage/index.js index 2ae6a61af2..a22340cc83 100644 --- a/packages/core/admin/ee/admin/pages/Roles/ListPage/index.js +++ b/packages/core/admin/ee/admin/pages/Roles/ListPage/index.js @@ -1,11 +1,12 @@ import { + ConfirmDialog, LoadingIndicatorPage, + Search, SettingsPageTitle, request, useNotification, - useQuery, + useQueryParams, useRBAC, - ConfirmDialog, } from '@strapi/helper-plugin'; import { AddIcon, DeleteIcon, Duplicate, EditIcon } from '@strapi/icons'; import { @@ -21,6 +22,7 @@ import { TableLabel, VisuallyHidden, Main, + ActionLayout, } from '@strapi/parts'; import { get } from 'lodash'; import matchSorter from 'match-sorter'; @@ -39,8 +41,8 @@ const useSortedRoles = () => { } = useRBAC(adminPermissions.settings.roles); const { getData, roles, isLoading } = useRolesList(false); - const query = useQuery(); - const _q = decodeURIComponent(query.get('_q') || ''); + const [{ query }] = useQueryParams(); + const _q = query?._q || ''; const sortedRoles = matchSorter(roles, _q, { keys: ['name', 'description'] }); useEffect(() => { @@ -304,6 +306,7 @@ const RoleListPage = () => { })} as="h2" /> + {canRead && } />} {canRead && ( { const [isOpen, setIsOpen] = useState(false); const [{ query }, setQuery] = useQueryParams(); - const [value, setValue] = useState(query._q || ''); + const [value, setValue] = useState(query?._q || ''); useEffect(() => { const handler = setTimeout(() => { diff --git a/packages/core/helper-plugin/lib/src/index.js b/packages/core/helper-plugin/lib/src/index.js index 2a6e9c3076..8a57bc9f39 100644 --- a/packages/core/helper-plugin/lib/src/index.js +++ b/packages/core/helper-plugin/lib/src/index.js @@ -179,6 +179,7 @@ export { default as EmptyBodyTable } from './components/EmptyBodyTable'; export * from './components/InjectionZone'; export { default as LoadingIndicatorPage } from './components/LoadingIndicatorPage'; export { default as SettingsPageTitle } from './components/SettingsPageTitle'; +export { default as Search } from './components/Search'; export { default as Status } from './components/Status'; // New icons From 65e35431bd6948ef837b92947e79120ddfb81285 Mon Sep 17 00:00:00 2001 From: soupette Date: Fri, 3 Sep 2021 11:57:06 +0200 Subject: [PATCH 4/4] Add search and migrate to axios Signed-off-by: soupette --- .../admin/src/hooks/useRolesList/index.js | 9 ++- .../pages/Users/ListPage/tests/index.test.js | 80 +++++++++---------- .../ee/admin/pages/Roles/ListPage/index.js | 56 +++---------- .../ee/admin/pages/Roles/ListPage/reducer.js | 39 +-------- .../Roles/ListPage/tests/reducer.test.js | 68 ++-------------- 5 files changed, 67 insertions(+), 185 deletions(-) diff --git a/packages/core/admin/admin/src/hooks/useRolesList/index.js b/packages/core/admin/admin/src/hooks/useRolesList/index.js index 5ace36a7e8..a96cc913fd 100644 --- a/packages/core/admin/admin/src/hooks/useRolesList/index.js +++ b/packages/core/admin/admin/src/hooks/useRolesList/index.js @@ -1,6 +1,7 @@ import { useEffect, useReducer, useCallback } from 'react'; -import { request, useNotification } from '@strapi/helper-plugin'; -import { get } from 'lodash'; +import { useNotification } from '@strapi/helper-plugin'; +import get from 'lodash/get'; +import { axiosInstance } from '../../core/utils'; import init from './init'; import reducer, { initialState } from './reducer'; @@ -23,7 +24,9 @@ const useRolesList = (shouldFetchData = true) => { type: 'GET_DATA', }); - const { data } = await request('/admin/roles', { method: 'GET' }); + const { + data: { data }, + } = await axiosInstance.get('/admin/roles'); dispatch({ type: 'GET_DATA_SUCCEEDED', diff --git a/packages/core/admin/admin/src/pages/Users/ListPage/tests/index.test.js b/packages/core/admin/admin/src/pages/Users/ListPage/tests/index.test.js index 132fa139d4..a62b8723f6 100644 --- a/packages/core/admin/admin/src/pages/Users/ListPage/tests/index.test.js +++ b/packages/core/admin/admin/src/pages/Users/ListPage/tests/index.test.js @@ -699,46 +699,6 @@ describe('ADMIN | Pages | USERS | ListPage', () => { height: 0.25rem; } - .c13 { - padding-right: 56px; - padding-left: 56px; - } - - .c36 tr:last-of-type { - border-bottom: none; - } - - .c37 { - border-bottom: 1px solid #eaeaef; - } - - .c37 td, - .c37 th { - padding: 16px; - } - - .c37 td:first-of-type, - .c37 th:first-of-type { - padding: 0 4px; - } - - .c38 { - vertical-align: middle; - text-align: left; - color: #666687; - outline-offset: -4px; - } - - .c38 input { - vertical-align: sub; - } - - .c34 { - -webkit-transform: rotate(0deg); - -ms-transform: rotate(0deg); - transform: rotate(0deg); - } - .c15 { display: -webkit-box; display: -webkit-flex; @@ -788,6 +748,46 @@ describe('ADMIN | Pages | USERS | ListPage', () => { fill: #666687; } + .c13 { + padding-right: 56px; + padding-left: 56px; + } + + .c36 tr:last-of-type { + border-bottom: none; + } + + .c37 { + border-bottom: 1px solid #eaeaef; + } + + .c37 td, + .c37 th { + padding: 16px; + } + + .c37 td:first-of-type, + .c37 th:first-of-type { + padding: 0 4px; + } + + .c38 { + vertical-align: middle; + text-align: left; + color: #666687; + outline-offset: -4px; + } + + .c38 input { + vertical-align: sub; + } + + .c34 { + -webkit-transform: rotate(0deg); + -ms-transform: rotate(0deg); + transform: rotate(0deg); + } +
{ }; }; -const useRoleActions = ({ getData, canCreate, canDelete, canUpdate, roles, sortedRoles }) => { +const useRoleActions = ({ getData, canCreate, canDelete, canUpdate }) => { const { formatMessage } = useIntl(); const toggleNotification = useNotification(); const [isWarningDeleteAllOpened, setIsWarningDeleteAllOpenend] = useState(false); const { push } = useHistory(); - const [{ selectedRoles, showModalConfirmButtonLoading }, dispatch] = useReducer( + const [{ selectedRoles, showModalConfirmButtonLoading, roleToDelete }, dispatch] = useReducer( reducer, initialState ); @@ -81,33 +81,15 @@ const useRoleActions = ({ getData, canCreate, canDelete, canUpdate, roles, sorte type: 'ON_REMOVE_ROLES', }); - const filteredRoles = selectedRoles.filter(currentId => { - const currentRole = roles.find(role => role.id === currentId); - - return currentRole.usersCount === 0; + await axiosInstance.post('/admin/roles/batch-delete', { + ids: [roleToDelete], }); - if (selectedRoles.length !== filteredRoles.length) { - toggleNotification({ - type: 'info', - message: { id: 'Roles.ListPage.notification.delete-all-not-allowed' }, - }); - } + await getData(); - if (filteredRoles.length) { - await request('/admin/roles/batch-delete', { - method: 'POST', - body: { - ids: filteredRoles, - }, - }); - - await getData(); - - dispatch({ - type: 'RESET_DATA_TO_DELETE', - }); - } + dispatch({ + type: 'RESET_DATA_TO_DELETE', + }); } catch (err) { const errorIds = get(err, ['response', 'payload', 'data', 'ids'], null); @@ -145,19 +127,6 @@ const useRoleActions = ({ getData, canCreate, canDelete, canUpdate, roles, sorte handleToggleModal(); }, []); - const onRoleToggle = roleId => { - dispatch({ - type: 'ON_SELECTION', - id: roleId, - }); - }; - - const onAllRolesToggle = () => - dispatch({ - type: 'TOGGLE_ALL', - ids: sortedRoles.map(r => r.id), - }); - const handleToggleModal = () => setIsWarningDeleteAllOpenend(prev => !prev); const handleGoTo = useCallback( @@ -236,8 +205,6 @@ const useRoleActions = ({ getData, canCreate, canDelete, canUpdate, roles, sorte return { handleNewRoleClick, - onRoleToggle, - onAllRolesToggle, getIcons, selectedRoles, isWarningDeleteAllOpened, @@ -259,7 +226,6 @@ const RoleListPage = () => { isLoading, getData, sortedRoles, - roles, } = useSortedRoles(); const { @@ -269,7 +235,7 @@ const RoleListPage = () => { showModalConfirmButtonLoading, handleToggleModal, handleDeleteData, - } = useRoleActions({ getData, canCreate, canDelete, canUpdate, roles, sortedRoles }); + } = useRoleActions({ getData, canCreate, canDelete, canUpdate }); // ! TODO - Show the search bar only if the user is allowed to read - add the search input // canRead diff --git a/packages/core/admin/ee/admin/pages/Roles/ListPage/reducer.js b/packages/core/admin/ee/admin/pages/Roles/ListPage/reducer.js index 8b7e07b04c..5295d92757 100644 --- a/packages/core/admin/ee/admin/pages/Roles/ListPage/reducer.js +++ b/packages/core/admin/ee/admin/pages/Roles/ListPage/reducer.js @@ -2,7 +2,7 @@ import produce from 'immer'; export const initialState = { - selectedRoles: [], + roleToDelete: null, showModalConfirmButtonLoading: false, shouldRefetchData: false, }; @@ -10,57 +10,26 @@ export const initialState = { const reducer = (state, action) => produce(state, draftState => { switch (action.type) { - case 'ON_SELECTION': { - const { id } = action; - const roleIndex = state.selectedRoles.findIndex(roleId => roleId === id); - - if (roleIndex === -1) { - draftState.selectedRoles.push(id); - } else { - draftState.selectedRoles = state.selectedRoles.filter(roleId => roleId !== id); - } - break; - } - case 'TOGGLE_ALL': { - if (state.selectedRoles.length) { - draftState.selectedRoles = []; - } else { - const { ids } = action; - draftState.selectedRoles = ids; - } - break; - } case 'ON_REMOVE_ROLES': { draftState.showModalConfirmButtonLoading = true; break; } case 'ON_REMOVE_ROLES_SUCCEEDED': { draftState.shouldRefetchData = true; + draftState.roleToDelete = null; break; } case 'RESET_DATA_TO_DELETE': { draftState.shouldRefetchData = false; - draftState.selectedRoles = []; + draftState.roleToDelete = null; draftState.showModalConfirmButtonLoading = false; break; } case 'SET_ROLE_TO_DELETE': { - draftState.selectedRoles = [action.id]; + draftState.roleToDelete = action.id; break; } - // Leaving this code for the moment - // case 'ON_DUPLICATION': { - // const { id } = action; - // draftState.roles = state.roles.reduce((acc, c) => { - // if (c.id === id) { - // return acc.concat([c, { ...c, id: state.roles.length + 1 }]); - // } - - // return [...acc, c]; - // }, []); - // break; - // } default: return draftState; } diff --git a/packages/core/admin/ee/admin/pages/Roles/ListPage/tests/reducer.test.js b/packages/core/admin/ee/admin/pages/Roles/ListPage/tests/reducer.test.js index e72815f5ab..f16c8d422e 100644 --- a/packages/core/admin/ee/admin/pages/Roles/ListPage/tests/reducer.test.js +++ b/packages/core/admin/ee/admin/pages/Roles/ListPage/tests/reducer.test.js @@ -11,54 +11,18 @@ describe('ADMIN | ee | CONTAINERS | ROLES | ListPage | reducer', () => { }); }); - describe('ON_SELECTION', () => { - it('should add the selected role correctly', () => { - const action = { - type: 'ON_SELECTION', - id: 2, - }; - const initialState = { - selectedRoles: [], - shouldRefetchData: false, - }; - const expected = { - selectedRoles: [2], - shouldRefetchData: false, - }; - - expect(reducer(initialState, action)).toEqual(expected); - }); - - it('should remove the selected role correctly', () => { - const action = { - type: 'ON_SELECTION', - id: 2, - }; - const initialState = { - selectedRoles: [1, 2], - shouldRefetchData: false, - }; - const expected = { - selectedRoles: [1], - shouldRefetchData: false, - }; - - expect(reducer(initialState, action)).toEqual(expected); - }); - }); - describe('ON_REMOVE_ROLES', () => { it('should set the showModalConfirmButtonLoading to true', () => { const action = { type: 'ON_REMOVE_ROLES', }; const initialState = { - selectedRoles: [], + roleToDelete: 1, shouldRefetchData: false, showModalConfirmButtonLoading: false, }; const expected = { - selectedRoles: [], + roleToDelete: 1, shouldRefetchData: false, showModalConfirmButtonLoading: true, }; @@ -73,12 +37,12 @@ describe('ADMIN | ee | CONTAINERS | ROLES | ListPage | reducer', () => { type: 'ON_REMOVE_ROLES_SUCCEEDED', }; const initialState = { - selectedRoles: [], + roleToDelete: 1, shouldRefetchData: false, showModalConfirmButtonLoading: true, }; const expected = { - selectedRoles: [], + roleToDelete: null, shouldRefetchData: true, showModalConfirmButtonLoading: true, }; @@ -87,26 +51,6 @@ describe('ADMIN | ee | CONTAINERS | ROLES | ListPage | reducer', () => { }); }); - describe('RESET_DATA_TO_DELETE', () => { - it('should empty the selected role array and set the shouldRefetchData to false', () => { - const action = { - type: 'RESET_DATA_TO_DELETE', - }; - const initialState = { - selectedRoles: [1, 2, 4], - shouldRefetchData: true, - showModalConfirmButtonLoading: true, - }; - const expected = { - selectedRoles: [], - shouldRefetchData: false, - showModalConfirmButtonLoading: false, - }; - - expect(reducer(initialState, action)).toEqual(expected); - }); - }); - describe('SET_ROLE_TO_DELETE', () => { it('should set the selected roles property correctly', () => { const action = { @@ -114,11 +58,11 @@ describe('ADMIN | ee | CONTAINERS | ROLES | ListPage | reducer', () => { id: 6, }; const initialState = { - selectedRoles: [1, 2, 4], + roleToDelete: null, shouldRefetchData: false, }; const expected = { - selectedRoles: [6], + roleToDelete: 6, shouldRefetchData: false, };