Skip to content

Commit

Permalink
Merge branch 'master' of github.com:folio-org/ui-users into feat/numb…
Browse files Browse the repository at this point in the history
…er_generator
  • Loading branch information
EthanFreestone committed Oct 23, 2023
2 parents aefd058 + 7149368 commit b8a6e03
Show file tree
Hide file tree
Showing 22 changed files with 2,369 additions and 1,908 deletions.
52 changes: 42 additions & 10 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,27 +1,36 @@
# Change history for ui-users

## 10.0.0 IN PROGRESS
## [10.1.0] IN PROGRESS
* Also support `feesfines` interface version `19.0`. Refs UIU-2960.
* Pass location.search parameter through history search. Refs UIU-2971.

## [10.0.1](https://github.com/folio-org/ui-users/tree/v10.0.1) (2023-10-18)
[Full Changelog](https://github.com/folio-org/ui-users/compare/v10.0.0...v10.0.1)

* Don't display affiliations of users with types `patron` or `dcb`. Refs UIU-2967.
* Make the `username` field required for users with the `staff` type in ECS mode. Refs UIU-2970.

## [10.0.0](https://github.com/folio-org/ui-users/tree/v10.0.0) (2023-10-13)
[Full Changelog](https://github.com/folio-org/ui-users/compare/v9.0.3...v10.0.0)

* Add STATUS FILTER to LOST ITEMS REQUIRING ACTUAL COST processing page. Refs UIU-2748.
* Correctly handle removing all permissions from given user. Fixes UIU-2822.
* Add "Status" filter to LOST ITEMS REQUIRING ACTUAL COST processing page. Refs UIU-2748.
* Fix problem with remaining amount (not shown correct value after filling the payment amount). Refs UIU-2812.
* Add "Status" column to LOST ITEMS REQUIRING ACTUAL COST processing page. Refs UIU-2772.
* Add "Lost items requiring actual cost" to Actions dropdown in User details record. Refs UIU-2810.
* Add "Fee/fine details" to LOST ITEMS REQUIRING ACTUAL COST processing page. Refs UIU-2773.
* Fix ability to remove all service points. Fixes UIU-2819.
* Add close button to "Lost items requiring actual cost" page. Refs UIU-2813.
* Fix permission error when viewing fees/fines for payment. Refs UIU-2824.
* Fix paths to `StripesContext`. Fixes UIU-2834.
* Support `feesfines` interface version `18.0`. Refs UIU-2825
* Support `feesfines` interface version `18.0`. Refs UIU-2825.
* View a users affiliations accordion in the details pane. refs UIU-2821.
* Update Jest from v26 to v29. Refs UIU-2820.
* A result is not displayed in list of permissions after clicking on the 'Search' button. Refs UIU-2835.
* Get rid of blinking list on lost items page. Refs UIU-2831.
* configure Jest to leverage multi-core CPUs in CI. Refs UIU-2842.
* Add actual cost details to lost items requiring actual cost processing page. Refs UIU-2774.
* Display `expirationDate` based on the current timezone. Refs UIU-2839.
* Assign/unassign users affiliations. Refs UIU-2801.
* View affiliation associated permissions. Refs UIU-2800.
* Confirmation modal for manual anonymization. Refs UIU-1631.
* Fix translations. Refs UIU-2854.
* Fixed bug with certain accordions not closing in edit view. Refs UIU-2811.
* Users: Implement search by middle name. Refs UIU-2860.
* Notify patron checkbox not checked correctly when fee/fine owner has default notice. Refs UIU-2823.
Expand All @@ -44,14 +53,15 @@
* Do not publish CI artifacts (e.g. test coverage) to NPM.
* Make Limit menu visible if user has "ui-users.settings.limits.all" permission. Refs UIU-2880.
* In loan history, older staff notes should NOT be marked as "SUPERSEDED". Fixes UIU-2891.
* Create Jest/RTL test for BlockTemplateForm.js. Refs UIU-2402.
* create Jest/RTL test for BlockTemplates.js. Refs UIU-2379.
* Users with view-only access to user permissions and access to edit user records get error message when saving a user record. Refs UIU-2885.
* Use new WSAPI for adding patron/staff notes to loans. Fixes UIU-2893. **Note.** The new requirement of the `add-info` interface is a breaking change.
* Modify add-patron/staff-info permission to use new subpermission. Fixes UIU-2895.
* Move view/assign affiliation permissions from `ui-users` to `ui-consortia-settings`. Refs UIU-2897.
* Handle sparse data in "Overdue loans report". Fixes UIU-2901.
* Update translations text for permission.settings.manual-charges.all. Fixes UIU-2908.
* Rename user setting permissions disaplay name and update their visibility. Refs UIU-2907.
* Convert primary search listing to use prev/next pagination vs load-more pagination. Refs UIU-2870.
* Cleanup User Settings permissions – Part 1. Refs UIU-2906
* Prevent editing of shared settings from outside "Consortium manager". Refs UIU-2914.
* User settings > Fee/fine section: Disable editing for users with "Setting (Users): View all settings" permission. Refs UIU-2904.
Expand All @@ -61,7 +71,10 @@
* Convert primary search listing to use prev/next pagination vs load-more pagination. Refs UIU-2870.
* Add permisson check to edit Patron block conditions in user settings. Refs UIU-2911.
* Add permissions check to edit Limits in user settings. Refs. UIU-2912.
* Restrict edit of Patron Block Templates in settings based on permissions check. UIU-2913.
* User settings > Comment required: Disable editing for users with "Setting (Users): View all settings" permission. Refs UIU-2905.
* Add permission checks to address types, patron groups pages to restrict edit. Refs. UIU-2902.
* Hebis: Modify "Overdue Loans Report" to include reminder fee information. Refs. UIU-2588.
* Display assigned users accordion on Permission set. Refs UIU-2872.
* Add support for `request-storage` version `6.0` for `<UserRequests>`. Refs UIU-2920.
* Add permisison checks to restrict edit on Manual charges settings page. Ref. UIU-2903.
Expand All @@ -74,7 +87,7 @@
* Update Node.js to v18 in GitHub Actions. Refs. UIU-2927.
* Add PULL_REQUEST_TEMPLATE.md file to the repository. Refs. UIU-2918.
* Adjust `loans.staffInfoDialogBody` translation. Refs. UIU-2922.
* *BREAKING* Upgrade React to v18. Refs-UIU-2912.
* *BREAKING* Upgrade React to v18. Refs-UIU-2921.
* ECS - Do not display shadow users in search results. Refs UIU-2933.
* User can't pay the fee/fine. Refs UIU-2930.
* Sort proxies and sponsors by user display name. Refs UIU-2799.
Expand All @@ -86,6 +99,26 @@
* Users App: Consume {{FormattedDate}} and {{FormattedTime}} via stripes-component. Refs UIU-1860.
* ECS - Prevent editing of specific shadow user data. Refs UIU-2951.
* Relabel "Users: Can create new user" to "Users: Can create and edit users". Refs UIU-2955.
* Assign/unassign a users affiliations adjustments. Refs UIU-2942.
* ECS - Prevent editing of specific shadow user data. Refs UIU-2951.
* Fix user can not renew the loan through the override. Refs UIU-2948.

## [9.0.3](https://github.com/folio-org/ui-users/tree/v9.0.3) (2023-03-31)
[Full Changelog](https://github.com/folio-org/ui-users/compare/v9.0.2...v9.0.3)

* A result is not displayed in list of permissions after clicking on the 'Search' button. Refs UIU-2835.

## [9.0.2](https://github.com/folio-org/ui-users/tree/v9.0.2) (2023-03-29)
[Full Changelog](https://github.com/folio-org/ui-users/compare/v9.0.1...v9.0.2)

* Fix permission error when viewing fees/fines for payment. Refs UIU-2824.

## [9.0.1](https://github.com/folio-org/ui-users/tree/v9.0.1) (2023-03-28)
[Full Changelog](https://github.com/folio-org/ui-users/compare/v9.0.0...v9.0.1)

* Fix problem with remaining amount (not shown correct value after filling the payment amount). Refs UIU-2812.
* Correctly handle removing all permissions from given user. Fixes UIU-2822.


## [9.0.0](https://github.com/folio-org/ui-users/tree/v9.0.0) (2023-02-20)
[Full Changelog](https://github.com/folio-org/ui-users/compare/v8.1.0...v9.0.0)
Expand Down Expand Up @@ -120,7 +153,6 @@
* Allow proxy/sponsor lists to be emptied completely. Refs UIU-2804.
* Show an error if the proxy record is corrupt, instead of an NPE. Refs UIU-2803.
* Create Jest/RTL test for LoanDetails.js. Refs UIU-2428.
* Add permission checks to address types, patron groups pages to restrict edit. Refs. UIU-2902.

## [8.2.0](https://github.com/folio-org/ui-users/tree/v8.2.0) (2022-10-24)
[Full Changelog](https://github.com/folio-org/ui-users/compare/v8.1.0...v8.2.0)
Expand Down
13 changes: 7 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@folio/users",
"version": "10.0.0",
"version": "10.1.0",
"description": "User management",
"repository": "folio-org/ui-users",
"publishConfig": {
Expand Down Expand Up @@ -30,19 +30,19 @@
],
"okapiInterfaces": {
"add-info": "0.1",
"users": "15.0 16.0",
"users": "16.0",
"configuration": "2.0",
"permissions": "5.5",
"login": "6.0 7.0",
"users-bl": "5.0 6.0",
"permissions": "5.6",
"login": "7.3",
"users-bl": "6.1",
"tags": "1.0"
},
"optionalOkapiInterfaces": {
"actual-cost-record-storage": "0.4",
"automated-patron-blocks": "0.1",
"circulation": "9.0 10.0 11.0 12.0 13.0 14.0",
"consortia": "1.0",
"feesfines": "16.1 17.0 18.0",
"feesfines": "16.1 17.0 18.0 19.0",
"loan-policy-storage": "1.0 2.0",
"loan-storage": "4.0 5.0 6.0 7.0",
"notes": "2.0 3.0",
Expand Down Expand Up @@ -1033,6 +1033,7 @@
"formatjs-compile": "formatjs compile-folder --ast --format simple ./translations/ui-users ./translations/ui-users/compiled"
},
"devDependencies": {
"@aashutoshrathi/word-wrap": "^1.2.6",
"@babel/core": "^7.21.4",
"@babel/eslint-parser": "^7.15.0",
"@babel/plugin-proposal-class-properties": "^7.13.0",
Expand Down
26 changes: 20 additions & 6 deletions src/components/AffiliationsManager/AffiliationsManager.test.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import userEvent from '@folio/jest-config-stripes/testing-library/user-event';
import { render, screen } from '@folio/jest-config-stripes/testing-library/react';
import { useStripes } from '@folio/stripes/core';

import '__mock__/currencyData.mock';

import affiliations from 'fixtures/affiliations';

import {
useConsortiumTenants,
useUserAffiliations,
Expand All @@ -13,6 +15,11 @@ import AffiliationsManager from './AffiliationsManager';
jest.unmock('@folio/stripes/components');
jest.unmock('@folio/stripes/util');

jest.mock('@folio/stripes/core', () => ({
...jest.requireActual('@folio/stripes/core'),
useStripes: jest.fn(),
}));

jest.mock('../../hooks', () => ({
...jest.requireActual('../../hooks'),
useConsortiumTenants: jest.fn(),
Expand All @@ -24,6 +31,12 @@ const defaultProps = {
userId: 'userId',
};

const tenants = affiliations.map(i => ({
id: i.tenantId,
name: i.tenantName,
primary: i.isPrimary,
}));

const renderAffiliationsManager = (props = {}) => render(
<AffiliationsManager
{...defaultProps}
Expand All @@ -42,6 +55,7 @@ describe('AffiliationsManager', () => {
useUserAffiliations
.mockClear()
.mockReturnValue({ isLoading: false, affiliations });
useStripes.mockClear().mockReturnValue({ user: { user: { tenants } } });
});

describe('Modal', () => {
Expand All @@ -68,7 +82,7 @@ describe('AffiliationsManager', () => {

describe('Filters', () => {
it('should filter results by search query', async () => {
expect(await screen.findAllByRole('row')).toHaveLength(affiliations.length + 1);
expect(await screen.findAllByRole('row')).toHaveLength(affiliations.length);

await userEvent.type(await screen.findByLabelText('ui-users.affiliations.manager.modal.aria.search'), affiliations[0].tenantName);
await userEvent.click(await screen.findByText('ui-users.search'));
Expand All @@ -77,7 +91,7 @@ describe('AffiliationsManager', () => {
});

it('should filter results by assignment status', async () => {
expect(await screen.findAllByRole('row')).toHaveLength(affiliations.length + 1);
expect(await screen.findAllByRole('row')).toHaveLength(affiliations.length);

const assignmentCheckboxes = await screen.findAllByLabelText('ui-users.affiliations.manager.modal.aria.assign');

Expand All @@ -86,18 +100,18 @@ describe('AffiliationsManager', () => {
await userEvent.click(assignmentCheckboxes[2]);
await userEvent.click(await screen.findByText('ui-users.affiliations.manager.filter.assignment.assigned'));

expect(await screen.findAllByRole('row')).toHaveLength((affiliations.length - 3) + 1);
expect(await screen.findAllByRole('row')).toHaveLength((affiliations.length - 3));

await userEvent.click(await screen.findByLabelText(/Clear selected filters for/));

expect(await screen.findAllByRole('row')).toHaveLength(affiliations.length + 1);
expect(await screen.findAllByRole('row')).toHaveLength(affiliations.length);
});

it('should reset search and filters when \'Reset all\' button was clicked', async () => {
await userEvent.click(await screen.findByLabelText('ui-users.affiliations.manager.modal.aria.assignAll'));
await userEvent.click(await screen.findByText('ui-users.affiliations.manager.filter.assignment.unassigned'));

expect(await screen.findAllByRole('row')).toHaveLength(affiliations.length + 1);
expect(await screen.findAllByRole('row')).toHaveLength(affiliations.length);

await userEvent.type(await screen.findByLabelText('ui-users.affiliations.manager.modal.aria.search'), 'Columbia');
await userEvent.click(await screen.findByText('ui-users.search'));
Expand All @@ -106,7 +120,7 @@ describe('AffiliationsManager', () => {

await userEvent.click(await screen.findByTestId('reset-all-affiliations-filters'));

expect(await screen.findAllByRole('row')).toHaveLength(affiliations.length + 1);
expect(await screen.findAllByRole('row')).toHaveLength(affiliations.length);
});
});
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
Modal,
Paneset,
} from '@folio/stripes/components';
import { useStripes } from '@folio/stripes/core';

import {
useConsortiumTenants,
Expand Down Expand Up @@ -43,6 +44,8 @@ const INITIAL_FILTERS = {};
const AffiliationManagerModal = ({ onClose, onSubmit, userId }) => {
const [isFiltersVisible, toggleFilters] = useToggle(true);
const [filters, dispatch] = useReducer(filtersReducer, INITIAL_FILTERS);
const stripes = useStripes();
const currentUserTenants = useMemo(() => stripes.user?.user?.tenants || [], [stripes]);

const {
sortOrder,
Expand All @@ -60,6 +63,15 @@ const AffiliationManagerModal = ({ onClose, onSubmit, userId }) => {
isLoading: isConsortiumTenantsLoading,
} = useConsortiumTenants();

const primaryAffiliation = useMemo(() => affiliations.find(({ isPrimary }) => isPrimary), [affiliations]);
const affiliationIds = useMemo(() => {
const excludePrimaryAffiliation = ({ id }) => {
return id !== primaryAffiliation?.tenantId;
};

return currentUserTenants.filter(excludePrimaryAffiliation).map(({ id }) => id);
}, [currentUserTenants, primaryAffiliation]);

const {
assignment,
isAllAssigned,
Expand All @@ -69,13 +81,16 @@ const AffiliationManagerModal = ({ onClose, onSubmit, userId }) => {
} = useAffiliationsAssignment({
affiliations,
tenants,
affiliationIds,
});

const isLoading = isConsortiumTenantsLoading || isUsersAffiliationsLoading;

const affiliationIds = useMemo(() => affiliations.map(({ tenantId }) => tenantId), [affiliations]);

const handleOnSubmit = useCallback(async () => {
const affiliationIdsToCompare = affiliations
.filter(({ isPrimary }) => !isPrimary)
.map(({ tenantId }) => tenantId);

const getAffiliationIds = (assigned) => (
Object
.entries(assignment)
Expand All @@ -84,13 +99,12 @@ const AffiliationManagerModal = ({ onClose, onSubmit, userId }) => {
);

const buildResult = (tenantIds) => tenantIds.map(tenantId => ({ tenantId, userId }));

const added = buildResult(difference(getAffiliationIds(true), affiliationIds));
const removed = buildResult(intersection(getAffiliationIds(false), affiliationIds));
const added = buildResult(difference(getAffiliationIds(true), affiliationIdsToCompare));
const removed = buildResult(intersection(getAffiliationIds(false), affiliationIdsToCompare));

await onSubmit({ added, removed });
onClose();
}, [affiliationIds, assignment, onClose, onSubmit, userId]);
}, [affiliations, assignment, onClose, onSubmit, userId]);

const modalFooter = (
<AffiliationsManagerModalFooter
Expand All @@ -115,12 +129,27 @@ const AffiliationManagerModal = ({ onClose, onSubmit, userId }) => {
orderBy(
filtersConfig
.reduce((filtered, config) => config.filter(filtered, activeFilters, assignment), tenants)
.filter(({ name }) => (searchQuery ? name.toLowerCase().includes(searchQuery.toLowerCase()) : true)),
.filter(({ name, isCentral, id }) => {
const isNotValid = isCentral || primaryAffiliation?.tenantId === id || !affiliationIds.includes(id);

if (isNotValid) return false;

return (searchQuery ? name.toLowerCase().includes(searchQuery.toLowerCase()) : true);
}),
sorters[sortOrder],
sortDirection.name,
)
);
}, [assignment, filters, sortDirection.name, sortOrder, sorters, tenants]);
}, [
affiliationIds,
assignment,
filters,
primaryAffiliation,
sortDirection.name,
sortOrder,
sorters,
tenants,
]);

return (
<Modal
Expand Down
12 changes: 7 additions & 5 deletions src/components/AffiliationsManager/useAffiliationsAssignment.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,22 @@ import {
useState,
} from 'react';

const useAffiliationsAssignment = ({ affiliations, tenants }) => {
const useAffiliationsAssignment = ({ affiliations, tenants, affiliationIds = [] }) => {
const [assignment, setAssignment] = useState({});

useEffect(() => {
setAssignment(() => {
const affiliationsMap = keyBy(affiliations, 'tenantId');

return tenants.reduce((acc, { id }) => {
acc[id] = Boolean(affiliationsMap[id]);
return tenants.reduce((acc, { id, isCentral }) => {
const isValidAffiliation = !isCentral && affiliationIds.includes(id);
if (isValidAffiliation) {
acc[id] = Boolean(affiliationsMap[id]);
}

return acc;
}, {});
});
}, [affiliations, tenants]);
}, [affiliationIds, affiliations, tenants]);

const isAllAssigned = useMemo(() => (
Object.values(assignment).every(value => Boolean(value))
Expand Down
Loading

0 comments on commit b8a6e03

Please sign in to comment.