Skip to content

Commit

Permalink
UIU-3284-R-bugfix (#2812)
Browse files Browse the repository at this point in the history
* Show all patron notice print jobs, in correct order (#2806)

We now show the top 100 patron notice print jobs, not 10.

More importantly, they are now sorted correctly (reverse
chronological) on the server side, so even if the list grows past 100
and so is truncated in the UI at the first hundred, they will be the
_right_ (most recent) first hundred.

Fixes UIU-3269.

* UIU-3249 - Leverage API supported sorting of columns on pre-registrations records list. (#2808)

* UIU-3279 supply tenantId in all useUserTenantRoles queries (#2809)

Supply the `tenantId` argument in all queries. It was present in the
query for a user's roles, but missing from the follow-up join-query that
retrieved those roles' details, and thus returned an empty list unless
the selected-tenant matched that of the currently-authenticated user.

Refs UIU-3279

* Release v11.0.6

---------

Co-authored-by: Mike Taylor <mike@indexdata.com>
Co-authored-by: Zak Burke <zburke@ebsco.com>
  • Loading branch information
3 people authored Nov 29, 2024
1 parent dfa30c8 commit 373b887
Show file tree
Hide file tree
Showing 9 changed files with 40 additions and 114 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# Change history for ui-users

## [11.0.6](https://github.com/folio-org/ui-users/tree/v11.0.6) (2024-11-28)
[Full Changelog](https://github.com/folio-org/ui-users/compare/v11.0.5...v11.0.6)

* `useUserTenantRoles` supplies `tenantId` in all its queries. Refs UIU-3279.
* Leverage API supported sorting of columns on pre-registrations records list. Refs UIU-3249.
* Show all patron notice print jobs (not just ten random ones), in correct order. Fixes UIU-3269.

## [11.0.5](https://github.com/folio-org/ui-users/tree/v11.0.5) (2024-11-20)
[Full Changelog](https://github.com/folio-org/ui-users/compare/v11.0.3...v11.0.5)

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@folio/users",
"version": "11.0.5",
"version": "11.0.6",
"description": "User management",
"repository": "folio-org/ui-users",
"publishConfig": {
Expand Down
1 change: 1 addition & 0 deletions src/hooks/useUserTenantRoles/useUserTenantRoles.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ const useUserTenantRoles = (
ids,
queryEnabled: isSuccess,
reduceFunction: chunkedRolesReducer,
tenantId,
});

return {
Expand Down
80 changes: 9 additions & 71 deletions src/hooks/useUserTenantRoles/useUserTenantRoles.test.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { QueryClient, QueryClientProvider } from 'react-query';
import { act, renderHook } from '@folio/jest-config-stripes/testing-library/react';

import { renderHook } from '@folio/jest-config-stripes/testing-library/react';
import { act } from 'react';
import {
useChunkedCQLFetch,
useOkapiKy,
Expand Down Expand Up @@ -73,11 +73,17 @@ describe('useUserTenantRoles', () => {
});

it('fetches roles assigned to a user', async () => {
const { result } = renderHook(() => useUserTenantRoles({ userId: 'u', tenantId: 't' }), { wrapper });
const props = { userId: 'u', tenantId: 't' };
const { result } = renderHook(() => useUserTenantRoles(props), { wrapper });
await act(() => !result.current.isFetching);

expect(result.current.isLoading).toBe(false);
expect(result.current.userRoles).toEqual(roleData);
expect(useChunkedCQLFetch).toHaveBeenCalledWith(expect.objectContaining({
tenantId: props.tenantId,
ids: expect.any(Array),
reduceFunction: expect.any(Function),
}));
});
});

Expand All @@ -92,71 +98,3 @@ describe('chunkedRolesReducer', () => {
expect(result.length).toBe(6);
});
});



// import { renderHook, waitFor } from '@folio/jest-config-stripes/testing-library/react';
// import {
// QueryClient,
// QueryClientProvider,
// } from 'react-query';

// import { useOkapiKy, useStripes } from '@folio/stripes/core';

// import roles from 'fixtures/roles';
// import useUserTenantRoles from './useUserTenantRoles';

// const queryClient = new QueryClient();

// // eslint-disable-next-line react/prop-types
// const wrapper = ({ children }) => (
// <QueryClientProvider client={queryClient}>
// {children}
// </QueryClientProvider>
// );

// const response = {
// roles,
// totalRecords: roles.length,
// };

// describe('useUserTenantRoles', () => {
// const getMock = jest.fn(() => ({
// json: () => Promise.resolve(response),
// }));
// const setHeaderMock = jest.fn();
// const kyMock = {
// extend: jest.fn(({ hooks: { beforeRequest } }) => {
// beforeRequest.forEach(handler => handler({ headers: { set: setHeaderMock } }));

// return {
// get: getMock,
// };
// }),
// };

// beforeEach(() => {
// getMock.mockClear();

// useStripes.mockClear().mockReturnValue({
// okapi: {},
// config: {
// maxUnpagedResourceCount: 1000,
// }
// });
// useOkapiKy.mockClear().mockReturnValue(kyMock);
// });

// it('should fetch user roles for specified tenant', async () => {
// const options = {
// userId: 'userId',
// tenantId: 'tenantId',
// };
// const { result } = renderHook(() => useUserTenantRoles(options), { wrapper });

// await waitFor(() => !result.current.isLoading);

// expect(setHeaderMock).toHaveBeenCalledWith('X-Okapi-Tenant', options.tenantId);
// expect(getMock).toHaveBeenCalledWith('roles/users', expect.objectContaining({}));
// });
// });
4 changes: 2 additions & 2 deletions src/routes/PatronNoticePrintJobsContainer.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ PatronNoticePrintJobsContainer.manifest = {
type: 'okapi',
path: 'print/entries',
params: {
query: 'type="BATCH"',
sortby: 'created/sort.descending'
query: 'type="BATCH" sortby created/sort.descending',
limit: '100',
},
records: 'items',
throwErrors: false,
Expand Down
3 changes: 1 addition & 2 deletions src/views/PatronNoticePrintJobs/PatronNoticePrintJobs.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@

import { orderBy } from 'lodash';
import { Button, Pane, MenuSection, MultiColumnList, Checkbox, FormattedDate, FormattedTime, TextLink } from '@folio/stripes/components';
import { useEffect, useState } from 'react';
import PropTypes from 'prop-types';
Expand Down Expand Up @@ -72,7 +71,7 @@ const PatronNoticePrintJobs = (props) => {

useEffect(() => {
const updatedRecords =
orderBy(records, (item) => item.created, sortOrder === DESC ? 'desc' : 'asc')
records
.map(record => ({
...record,
selected: !!record.selected,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { useState, useEffect } from 'react';
import PropTypes from 'prop-types';
import { get, orderBy } from 'lodash';
import { get } from 'lodash';
import {
useIntl,
FormattedMessage,
Expand All @@ -18,34 +17,22 @@ import {
COLUMNS_NAME,
} from './constants';
import { useNewRecordHandler } from './hooks';
import { sortTypes } from '../../constants';

const PatronsPreRegistrationList = ({
data,
isEmptyMessage,
totalCount,
onNeedMoreData
onNeedMoreData,
onSort,
sortOrder,
}) => {
const intl = useIntl();
const sortInitialState = {
data: [],
order: '',
direction: sortTypes.ASC,
};
const [sortedRecordsDetails, setSortedRecordsDetails] = useState(sortInitialState);

const {
handle,
isLoading,
} = useNewRecordHandler();

useEffect(() => {
setSortedRecordsDetails(prev => ({
...prev,
data: orderBy(data, prev.order, prev.direction)
}));
}, [data]);

const renderActionColumn = (user) => (
<IfPermission perm="ui-users.patron-pre-registrations.execute">
<Button
Expand Down Expand Up @@ -84,29 +71,16 @@ const PatronsPreRegistrationList = ({
}
});

const onSort = (e, meta) => {
let newSortDirection = sortTypes.ASC;
if (sortedRecordsDetails.order === meta.name) {
newSortDirection = sortedRecordsDetails.direction === sortTypes.ASC ? sortTypes.DESC : sortTypes.ASC;
}
const sortedData = orderBy(sortedRecordsDetails.data, [meta.name], newSortDirection);
setSortedRecordsDetails({
data: sortedData,
order: meta.name,
direction: newSortDirection
});
};

return (
<MultiColumnList
id="PatronsPreRegistrationsList"
data-testid="PatronsPreRegistrationsList"
autosize
columnMapping={columnMapping}
contentData={sortedRecordsDetails.data}
hasMargin
fullWidth
columnMapping={columnMapping}
contentData={data}
formatter={preRegistrationsListFormatter()}
hasMargin
id="PatronsPreRegistrationsList"
data-testid="PatronsPreRegistrationsList"
isEmptyMessage={isEmptyMessage}
onNeedMoreData={onNeedMoreData}
pagingType="prev-next"
Expand All @@ -115,10 +89,9 @@ const PatronsPreRegistrationList = ({
visibleColumns={visibleColumns}
nonInteractiveHeaders={[COLUMNS_NAME.ACTION]}
showSortIndicator
sortOrder={sortedRecordsDetails.order}
sortDirection={`${sortedRecordsDetails.direction}ending`}
sortOrder={sortOrder.replace(/^-/, '').replace(/,.*/, '')}
sortDirection={sortOrder.startsWith('-') ? 'descending' : 'ascending'}
onHeaderClick={onSort}
virtualize
/>
);
};
Expand All @@ -128,6 +101,8 @@ PatronsPreRegistrationList.propTypes = {
totalCount: PropTypes.number.isRequired,
data: PropTypes.arrayOf(PropTypes.object).isRequired,
onNeedMoreData: PropTypes.func.isRequired,
sortOrder: PropTypes.string,
onSort: PropTypes.func.isRequired,
};

export default PatronsPreRegistrationList;
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ const defaultProps = {
isEmptyMessage: 'empty message',
totalCount: 0,
onNeedMoreData: jest.fn(),
onSort: jest.fn(),
sortOrder: '',
};

const handleDuplicationsCheck = jest.fn(() => ({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ const PatronsPreRegistrationListContainer = ({
const intl = useIntl();
const [isSearchPaneVisible, setIsSearchPaneVisible] = useState(true);
const query = queryGetter ? queryGetter() || {} : {};
const sortOrder = query.sort || '';
const count = source ? source.totalCount() : 0;
const emptyMessage = source
? <NoResultsMessage
Expand Down Expand Up @@ -79,6 +80,7 @@ const PatronsPreRegistrationListContainer = ({
getSearchHandlers,
onSubmitSearch,
searchValue,
onSort,
resetAll,
}) => {
const isResetButtonDisabled = !searchValue.query;
Expand Down Expand Up @@ -153,6 +155,8 @@ const PatronsPreRegistrationListContainer = ({
data={data}
isEmptyMessage={emptyMessage}
totalCount={count}
onSort={onSort}
sortOrder={sortOrder}
onNeedMoreData={onNeedMoreData}
/>
</Pane>
Expand Down

0 comments on commit 373b887

Please sign in to comment.