Skip to content

Commit

Permalink
Merge branch 'master' into UIU-3302
Browse files Browse the repository at this point in the history
  • Loading branch information
UladzislauKutarkin authored Jan 13, 2025
2 parents a49d579 + c8acdcc commit 45d76e4
Show file tree
Hide file tree
Showing 19 changed files with 217 additions and 216 deletions.
10 changes: 9 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,22 @@
* Leverage API supported sorting of columns on pre-registrations records list. Refs UIU-3249.
* Fix issue with `Proxy borrower` field value. Refs UIU-3290.
* Remove duplicates from the keyboard shortcut modal. Refs UIU-3026.
* Create/Edit a Patron Block - HTML page title. Refs UIU-3302.
* React v19: refactor away from default props for functional components. Refs. UIU-3141.
* Hide Create block button for user without permission. Refs UIU-3300.
* Add HTML page title to add/edit patron block page. Refs UIU-3302.

## [11.0.10](https://github.com/folio-org/ui-users/tree/v11.0.10) (2025-01-10)
[Full Changelog](https://github.com/folio-org/ui-users/compare/v11.0.9...v11.0.10)

* Add sub permission `manual-block-templates.collection.get` to permission `Users: Can create, edit and remove patron blocks`. Refs UIU-3305.

## [11.0.9](https://github.com/folio-org/ui-users/tree/v11.0.9) (2024-12-13)
[Full Changelog](https://github.com/folio-org/ui-users/compare/v11.0.8...v11.0.9)

* Add permission to access users-keycloak delete method. Refs UIU-3282.
* Check if userId is present in withUserRoles HOC. Refs UIU-3273.
* Add missed permissions for endpoints used in withUserRoles HOC. UIU-3294.
* Add view/manage roles permissions. Refs UIU-3301.

## [11.0.8](https://github.com/folio-org/ui-users/tree/v11.0.8) (2024-12-10)
[Full Changelog](https://github.com/folio-org/ui-users/compare/v11.0.7...v11.0.8)
Expand Down
24 changes: 20 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -86,9 +86,7 @@
"departments.collection.get",
"departments.item.get",
"users.configurations.item.get",
"roles.users.collection.get",
"users-keycloak.auth-users.item.get",
"roles.collection.get"
"users-keycloak.auth-users.item.get"
],
"visible": true
},
Expand All @@ -106,7 +104,6 @@
"tags.item.post",
"circulation-storage.request-preferences.item.post",
"circulation-storage.request-preferences.item.put",
"roles.users.item.put",
"users-keycloak.auth-users.item.post"
],
"visible": true
Expand Down Expand Up @@ -173,6 +170,24 @@
],
"visible": true
},
{
"permissionName": "ui-users.roles.view",
"displayName": "Users: Can view user/role assignments",
"description": "Also includes basic permissions to view roles, users, patron groups",
"subPermissions": [
"ui-authorization-roles.users.settings.view"
],
"visible": true
},
{
"permissionName": "ui-users.roles.manage",
"displayName": "Users: Can manage user/role assignments",
"description": "",
"subPermissions": [
"ui-authorization-roles.users.settings.manage"
],
"visible": true
},
{
"permissionName": "ui-users.user-service-points.view",
"displayName": "Users: Can view service points assigned to users",
Expand Down Expand Up @@ -598,6 +613,7 @@
"replaces": ["ui-users.patron_blocks"],
"subPermissions": [
"manualblocks.collection.get",
"manual-block-templates.collection.get",
"manualblocks.item.delete",
"manualblocks.item.get",
"manualblocks.item.post",
Expand Down
12 changes: 3 additions & 9 deletions src/components/AffiliationsManager/AffiliationsManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ import { AffiliationsManagerModal } from './AffiliationsManagerModal';
import AffiliationsManagerTrigger from './AffiliationsManagerTrigger';

const AffiliationsManager = ({
disabled,
disabled = false,
onUpdateAffiliations,
renderTrigger,
renderTrigger = AffiliationsManagerTrigger,
userId,
withTrigger,
withTrigger = true,
}) => {
const [isModalOpen, toggleModal] = useToggle(!withTrigger);

Expand All @@ -36,10 +36,4 @@ AffiliationsManager.propTypes = {
withTrigger: PropTypes.bool,
};

AffiliationsManager.defaultProps = {
disabled: false,
renderTrigger: AffiliationsManagerTrigger,
withTrigger: true,
};

export default AffiliationsManager;
6 changes: 1 addition & 5 deletions src/components/AffiliationsSelect/AffiliationsSelect.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { Selection } from '@folio/stripes/components';
import { affiliationsShape } from '../../shapes';

const AffiliationsSelect = ({
id,
id = 'user-assigned',
affiliations,
value,
onChange,
Expand Down Expand Up @@ -53,10 +53,6 @@ const AffiliationsSelect = ({
);
};

AffiliationsSelect.defaultProps = {
id: 'user-assigned',
};

AffiliationsSelect.propTypes = {
affiliations: affiliationsShape,
onChange: PropTypes.func.isRequired,
Expand Down
11 changes: 6 additions & 5 deletions src/components/AssignedUsers/AssignedUsersContainer.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,12 @@ import AssignUsers from './AssignUsers';
import AssignedUsersList from './AssignedUsersList';
import { getUpdatedUsersList } from './utils';

const AssignedUsersContainer = ({ permissionSetId, expanded, onToggle, tenantId }) => {
const AssignedUsersContainer = ({
permissionSetId,
expanded = true,
onToggle,
tenantId
}) => {
const callout = useCallout();
const intl = useIntl();

Expand Down Expand Up @@ -123,8 +128,4 @@ AssignedUsersContainer.propTypes = {
tenantId: PropTypes.string,
};

AssignedUsersContainer.defaultProps = {
expanded: true,
};

export default AssignedUsersContainer;
7 changes: 1 addition & 6 deletions src/components/AssignedUsers/AssignedUsersList.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {
VISIBLE_COLUMNS,
} from './constants';

const AssignedUsersList = ({ users, isFetching }) => (
const AssignedUsersList = ({ users = [], isFetching = false }) => (
<Row
start="xs"
data-test-assigned-users
Expand All @@ -34,9 +34,4 @@ AssignedUsersList.propTypes = {
isFetching: PropTypes.bool,
};

AssignedUsersList.defaultProps = {
users: [],
isFetching: false,
};

export default AssignedUsersList;
7 changes: 1 addition & 6 deletions src/components/BulkRenewalDialog/BulkRenewedLoansList.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,11 @@ const propTypes = {
errorMessages: PropTypes.object.isRequired,
};

const defaultProps = {
height: 300,
};

const BulkRenewedLoansList = (props) => {
const {
failedRenewals,
successRenewals,
height,
height = 300,
errorMessages,
requestCounts,
loanPolicies,
Expand Down Expand Up @@ -126,7 +122,6 @@ const BulkRenewedLoansList = (props) => {
);
};

BulkRenewedLoansList.defaultProps = defaultProps;
BulkRenewedLoansList.propTypes = propTypes;

export default BulkRenewedLoansList;
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {

import { USER_TYPES } from '../../../../../constants';

const ChangeUserTypeModal = ({ onChange, initialUserType, open }) => {
const ChangeUserTypeModal = ({ onChange, initialUserType, open = false }) => {
const userTypeModalFooter = (
<ModalFooter>
<Button
Expand Down Expand Up @@ -47,8 +47,4 @@ ChangeUserTypeModal.propTypes = {
open: PropTypes.bool,
};

ChangeUserTypeModal.defaultProps = {
open: false,
};

export default ChangeUserTypeModal;
99 changes: 53 additions & 46 deletions src/components/EditSections/EditUserRoles/EditUserRoles.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import React, { useMemo, useState } from 'react';
import { Accordion, Headline, Badge, Row, Col, List, Button, Icon, ConfirmationModal } from '@folio/stripes/components';
import { useIntl, FormattedMessage } from 'react-intl';
import { withRouter } from 'react-router';
import PropTypes from 'prop-types';
import { isEmpty } from 'lodash';
import { FieldArray } from 'react-final-form-arrays';
import { OnChange } from 'react-final-form-listeners';
import { IfPermission } from '@folio/stripes/core';
import { Accordion, Headline, Badge, Row, Col, List, Button, Icon, ConfirmationModal } from '@folio/stripes/components';
import { useAllRolesData } from '../../../hooks';
import UserRolesModal from './components/UserRolesModal/UserRolesModal';
import { filtersConfig } from './helpers';
Expand Down Expand Up @@ -54,16 +55,18 @@ function EditUserRoles({ accordionId, form:{ change }, setAssignedRoleIds, assig
key={role.id}
>
{role.name}
<Button
buttonStyle="fieldControl"
align="end"
type="button"
id={`clickable-remove-user-role-${role.id}`}
aria-label={`${intl.formatMessage({ id:'ui-users.roles.deleteRole' })}: ${role.name}`}
onClick={() => fields.remove(index)}
>
<Icon icon="times-circle" />
</Button>
<IfPermission perm="ui-authorization-roles.users.settings.manage">
<Button
buttonStyle="fieldControl"
align="end"
type="button"
id={`clickable-remove-user-role-${role.id}`}
aria-label={`${intl.formatMessage({ id:'ui-users.roles.deleteRole' })}: ${role.name}`}
onClick={() => fields.remove(index)}
>
<Icon icon="times-circle" />
</Button>
</IfPermission>
</li>
);
};
Expand All @@ -90,41 +93,45 @@ function EditUserRoles({ accordionId, form:{ change }, setAssignedRoleIds, assig
}

return (
<div>
<Accordion
label={<Headline size="large" tag="h3"><FormattedMessage id="ui-users.roles.userRoles" /></Headline>}
id={accordionId}
displayWhenClosed={<Badge>{assignedRoleIds.length}</Badge>}
>
<Row>
{renderUserRoles()}
<Button data-testid="add-roles-button" onClick={() => setIsOpen(true)}><FormattedMessage id="ui-users.roles.addRoles" /></Button>
<Button data-testid="unassign-all-roles-button" disabled={isEmpty(listItemsData)} onClick={() => setUnassignModalOpen(true)}><FormattedMessage id="ui-users.roles.unassignAllRoles" /></Button>
</Row>
</Accordion>
<UserRolesModal
filtersConfig={filtersConfig}
isOpen={isOpen}
onClose={() => setIsOpen(false)}
initialRoleIds={assignedRoleIds}
changeUserRoles={changeUserRoles}
/>
<ConfirmationModal
open={unassignModalOpen}
heading={<FormattedMessage id="ui-users.roles.modal.unassignAll.header" />}
message={unassignAllMessage}
onConfirm={handleUnassignAllRoles}
onCancel={() => setUnassignModalOpen(false)}
cancelLabel={<FormattedMessage id="ui-users.no" />}
confirmLabel={<FormattedMessage id="ui-users.yes" />}
/>
<OnChange name="assignedRoleIds">
{(userAssignedRoleIds) => {
const userRoleIds = isEmpty(userAssignedRoleIds) ? [] : userAssignedRoleIds;
setAssignedRoleIds(userRoleIds);
}}
</OnChange>
</div>
<IfPermission perm="ui-authorization-roles.users.settings.view">
<div>
<Accordion
label={<Headline size="large" tag="h3"><FormattedMessage id="ui-users.roles.userRoles" /></Headline>}
id={accordionId}
displayWhenClosed={<Badge>{assignedRoleIds.length}</Badge>}
>
<Row>
{renderUserRoles()}
<IfPermission perm="ui-authorization-roles.users.settings.manage">
<Button data-testid="add-roles-button" onClick={() => setIsOpen(true)}><FormattedMessage id="ui-users.roles.addRoles" /></Button>
<Button data-testid="unassign-all-roles-button" disabled={isEmpty(listItemsData)} onClick={() => setUnassignModalOpen(true)}><FormattedMessage id="ui-users.roles.unassignAllRoles" /></Button>
</IfPermission>
</Row>
</Accordion>
<UserRolesModal
filtersConfig={filtersConfig}
isOpen={isOpen}
onClose={() => setIsOpen(false)}
initialRoleIds={assignedRoleIds}
changeUserRoles={changeUserRoles}
/>
<ConfirmationModal
open={unassignModalOpen}
heading={<FormattedMessage id="ui-users.roles.modal.unassignAll.header" />}
message={unassignAllMessage}
onConfirm={handleUnassignAllRoles}
onCancel={() => setUnassignModalOpen(false)}
cancelLabel={<FormattedMessage id="ui-users.no" />}
confirmLabel={<FormattedMessage id="ui-users.yes" />}
/>
<OnChange name="assignedRoleIds">
{(userAssignedRoleIds) => {
const userRoleIds = isEmpty(userAssignedRoleIds) ? [] : userAssignedRoleIds;
setAssignedRoleIds(userRoleIds);
}}
</OnChange>
</div>
</IfPermission>
);
}

Expand Down
19 changes: 19 additions & 0 deletions src/components/EditSections/EditUserRoles/EditUserRoles.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { cleanup, waitFor } from '@folio/jest-config-stripes/testing-library/rea
import userEvent from '@folio/jest-config-stripes/testing-library/user-event';
import renderWithRouter from 'helpers/renderWithRouter';
import {
IfPermission,
useStripes,
} from '@folio/stripes/core';
import { Form } from 'react-final-form';
Expand All @@ -19,6 +20,7 @@ jest.mock('../../../hooks', () => ({
jest.mock('@folio/stripes/core', () => ({
...jest.requireActual('@folio/stripes/core'),
useStripes: jest.fn(),
IfPermission: jest.fn()
}));

jest.unmock('@folio/stripes/components');
Expand Down Expand Up @@ -95,6 +97,7 @@ describe('EditUserRoles Component', () => {
beforeEach(() => {
useStripes.mockClear().mockReturnValue(STRIPES);
useAllRolesData.mockClear().mockReturnValue(mockAllRolesData);
IfPermission.mockImplementation(({ children }) => children);
});
afterEach(cleanup);

Expand All @@ -106,6 +109,22 @@ describe('EditUserRoles Component', () => {
expect(queryByText('simple role')).not.toBeInTheDocument();
});

it('hides the roles accordion when user doesn\'t have view roles permission', () => {
IfPermission.mockImplementation(({ perm, children }) => (perm !== 'ui-authorization-roles.users.settings.view' ? children : null));
const { queryByText } = renderEditRolesAccordion(propsData);

expect(queryByText('ui-users.roles.userRoles')).not.toBeInTheDocument();
});

it('hides the add role button when user doesn\'t have manage roles permission', () => {
IfPermission.mockImplementation(({ perm, children }) => (perm !== 'ui-authorization-roles.users.settings.manage' ? children : null));
const { getByText, queryByText } = renderEditRolesAccordion(propsData);

expect(getByText('test role')).toBeInTheDocument();
expect(getByText('admin role')).toBeInTheDocument();
expect(queryByText('ui-users.roles.addRoles')).not.toBeInTheDocument();
});

it('calls delete user role function', async () => {
const id = `clickable-remove-user-role-${mockAllRolesData.data.roles[0].id}`;
renderEditRolesAccordion(propsData);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ import css from './CheckboxColumn.css';
const CheckboxColumn = memo(props => {
const {
value,
checked,
checked = false,
roleName,
onChange,
onChange = noop,
} = props;

return (
Expand Down Expand Up @@ -39,9 +39,4 @@ CheckboxColumn.propTypes = {
onChange: PropTypes.func,
};

CheckboxColumn.defaultProps = {
checked: false,
onChange: noop,
};

export default CheckboxColumn;
Loading

0 comments on commit 45d76e4

Please sign in to comment.