diff --git a/CHANGELOG.md b/CHANGELOG.md index 6710907ec..c13a3de81 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ * Validate image url provided as external url for user profile picture. Refs UIU-3080. * Import and use ProfilePicture Component from stripes/smart-components. Refs UIU-3104. * Show Roles assigned to users. Refs UIU-3110. +* Add edit user roles accordion on edit role modal view. Refs UIU-3021. ## [10.1.0](https://github.com/folio-org/ui-users/tree/v10.1.0) (2024-03-20) [Full Changelog](https://github.com/folio-org/ui-users/compare/v10.0.4...v10.1.0) diff --git a/src/components/EditSections/EditUserRoles/ EditUserRoles.test.js b/src/components/EditSections/EditUserRoles/ EditUserRoles.test.js new file mode 100644 index 000000000..7be9f2748 --- /dev/null +++ b/src/components/EditSections/EditUserRoles/ EditUserRoles.test.js @@ -0,0 +1,58 @@ + +import React from 'react'; +import { cleanup } from '@folio/jest-config-stripes/testing-library/react'; +import renderWithRouter from 'helpers/renderWithRouter'; +import { + useStripes, +} from '@folio/stripes/core'; +import EditUserRoles from './EditUserRoles'; + +import { useUserTenantRoles } from '../../../hooks'; + +jest.mock('../../../hooks', () => ({ + ...jest.requireActual('../../../hooks'), + useUserTenantRoles: jest.fn(), +})); + +jest.mock('@folio/stripes/core', () => ({ + ...jest.requireActual('@folio/stripes/core'), + useStripes: jest.fn(), +})); + +jest.unmock('@folio/stripes/components'); + +const STRIPES = { + config: {}, + hasPerm: jest.fn().mockReturnValue(true), + okapi: { + tenant: 'diku', + }, + user: { + user: { + consortium: {}, + }, + }, +}; + + +const renderEditRolesAccordion = () => renderWithRouter(); + +describe('EditUserRoles Component', () => { + beforeEach(() => { + useStripes.mockClear().mockReturnValue(STRIPES); + useUserTenantRoles.mockClear().mockReturnValue({ + isFetching: false, + userRoles: [{ id: '1', name: 'test role' }, + { id: '2', name: 'admin role' } + ] + }); + }); + afterEach(cleanup); + + it('shows the list of user roles', () => { + const { getByText } = renderEditRolesAccordion(); + + expect(getByText('test role')).toBeInTheDocument(); + expect(getByText('admin role')).toBeInTheDocument(); + }); +}); diff --git a/src/components/EditSections/EditUserRoles/EditUserRoles.js b/src/components/EditSections/EditUserRoles/EditUserRoles.js new file mode 100644 index 000000000..0f2774293 --- /dev/null +++ b/src/components/EditSections/EditUserRoles/EditUserRoles.js @@ -0,0 +1,63 @@ +import React from 'react'; +import { Accordion, Headline, Badge, Row, Col, List, Button, Icon, Loading } from '@folio/stripes/components'; +import { useIntl, FormattedMessage } from 'react-intl'; +import { withRouter } from 'react-router'; +import PropTypes from 'prop-types'; +import { useStripes } from '@folio/stripes/core'; +import { useUserTenantRoles } from '../../../hooks'; + +function EditUserRoles({ match, accordionId }) { + const { okapi } = useStripes(); + const intl = useIntl(); + + const userId = match.params.id; + + const { userRoles, isLoading } = useUserTenantRoles({ userId, tenantId: okapi.tenant }); + + const renderRoles = (role) => { + return ( +
  • + {role.name} + +
  • + ); + }; + + return ( + } + id={accordionId} + displayWhenClosed={isLoading ? : {userRoles.length}} + > + + + } + /> + + + + + + ); +} + +EditUserRoles.propTypes = { + match: PropTypes.shape({ params: { id: PropTypes.string } }), + accordionId: PropTypes.string +}; + +export default withRouter(EditUserRoles); diff --git a/src/components/EditSections/EditUserRoles/EditUserRoles.test.js b/src/components/EditSections/EditUserRoles/EditUserRoles.test.js new file mode 100644 index 000000000..7be9f2748 --- /dev/null +++ b/src/components/EditSections/EditUserRoles/EditUserRoles.test.js @@ -0,0 +1,58 @@ + +import React from 'react'; +import { cleanup } from '@folio/jest-config-stripes/testing-library/react'; +import renderWithRouter from 'helpers/renderWithRouter'; +import { + useStripes, +} from '@folio/stripes/core'; +import EditUserRoles from './EditUserRoles'; + +import { useUserTenantRoles } from '../../../hooks'; + +jest.mock('../../../hooks', () => ({ + ...jest.requireActual('../../../hooks'), + useUserTenantRoles: jest.fn(), +})); + +jest.mock('@folio/stripes/core', () => ({ + ...jest.requireActual('@folio/stripes/core'), + useStripes: jest.fn(), +})); + +jest.unmock('@folio/stripes/components'); + +const STRIPES = { + config: {}, + hasPerm: jest.fn().mockReturnValue(true), + okapi: { + tenant: 'diku', + }, + user: { + user: { + consortium: {}, + }, + }, +}; + + +const renderEditRolesAccordion = () => renderWithRouter(); + +describe('EditUserRoles Component', () => { + beforeEach(() => { + useStripes.mockClear().mockReturnValue(STRIPES); + useUserTenantRoles.mockClear().mockReturnValue({ + isFetching: false, + userRoles: [{ id: '1', name: 'test role' }, + { id: '2', name: 'admin role' } + ] + }); + }); + afterEach(cleanup); + + it('shows the list of user roles', () => { + const { getByText } = renderEditRolesAccordion(); + + expect(getByText('test role')).toBeInTheDocument(); + expect(getByText('admin role')).toBeInTheDocument(); + }); +}); diff --git a/src/components/EditSections/EditUserRoles/index.js b/src/components/EditSections/EditUserRoles/index.js new file mode 100644 index 000000000..90e31fe29 --- /dev/null +++ b/src/components/EditSections/EditUserRoles/index.js @@ -0,0 +1 @@ +export { default } from './EditUserRoles'; diff --git a/src/components/EditSections/index.js b/src/components/EditSections/index.js index eab6ff9ec..b4dd720a5 100644 --- a/src/components/EditSections/index.js +++ b/src/components/EditSections/index.js @@ -3,3 +3,4 @@ export { default as EditExtendedInfo } from './EditExtendedInfo'; export { default as EditProxy } from './EditProxy'; export { default as EditUserInfo } from './EditUserInfo'; export { default as EditServicePoints } from './EditServicePoints'; +export { default as EditUserRoles } from './EditUserRoles'; diff --git a/src/views/UserEdit/UserForm.js b/src/views/UserEdit/UserForm.js index ddbb06083..beda27582 100644 --- a/src/views/UserEdit/UserForm.js +++ b/src/views/UserEdit/UserForm.js @@ -33,6 +33,7 @@ import { EditContactInfo, EditProxy, EditServicePoints, + EditUserRoles, } from '../../components/EditSections'; import { getFullName } from '../../components/util'; import RequestFeeFineBlockButtons from '../../components/RequestFeeFineBlockButtons'; @@ -380,6 +381,7 @@ class UserForm extends React.Component { permissions: false, servicePoints: false, customFields: true, + userRoles: false }} > + /> : }
    EditProxy accordion
    ), EditServicePoints: jest.fn(() =>
    EditServicePoints accordion
    ), EditUserInfo: jest.fn(() =>
    EditUserInfo accordion
    ), + EditUserRoles: jest.fn(() =>
    EditUserRoles accordion
    ) }) ); @@ -190,11 +191,17 @@ describe('UserForm', () => { expect(screen.getByText('TenantsPermissionsAccordion accordion')).toBeTruthy(); }); - it('omits permissions pane when "roles" interface is present', async () => { + it('shows permissions accordion when "roles" interface is NOT present', async () => { + renderWithRouter(); + + expect(screen.queryByText('TenantsPermissionsAccordion accordion')).toBeInTheDocument(); + }); + + it('show roles accordion when "roles" interface is present', async () => { props.stripes.hasInterface = () => true; renderWithRouter(); - expect(screen.queryByText('Permissions accordion')).toBeFalsy(); + expect(screen.queryByText('EditUserRoles accordion')).toBeInTheDocument(); }); }); diff --git a/translations/ui-users/en.json b/translations/ui-users/en.json index 1524fecda..0ac9b387f 100644 --- a/translations/ui-users/en.json +++ b/translations/ui-users/en.json @@ -1170,6 +1170,9 @@ "patronNoticePrintJobs.created": "Created", "patronNoticePrintJobs.errors.pdf": "'PDF generation failed", - "roles.userRoles": "Roles", - "roles.empty": "No roles found" + "roles.userRoles": "User roles", + "roles.empty": "No user roles found", + "roles.deleteRole": "Delete user role", + "roles.addRoles": "Add user roles", + "roles.unassignAllRoles": "Unassign all user roles" }