Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

UIIN-2608: If Shared & Held by facets were selected in the Browse search, then retain them in the Search lookup after clicking the record. #2307

Merged
merged 6 commits into from
Oct 18, 2023
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# Change history for ui-inventory

## [10.0.1](IN PROGRESS)
* If Shared & Held by facets were selected in the Browse search, then retain them in the Search lookup after clicking the record. Refs UIIN-2608.

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

Expand Down
4 changes: 3 additions & 1 deletion src/components/BrowseResultsList/BrowseResultsList.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ const BrowseResultsList = ({
onNeedMoreData,
},
totalRecords,
filters,
}) => {
const data = useContext(DataContext);
const { search } = useLocation();
Expand All @@ -75,7 +76,7 @@ const BrowseResultsList = ({
id={listId}
totalCount={totalRecords}
contentData={browseData}
formatter={getBrowseResultsFormatter({ data, browseOption })}
formatter={getBrowseResultsFormatter({ data, browseOption, filters })}
visibleColumns={VISIBLE_COLUMNS_MAP[browseOption]}
isEmptyMessage={isEmptyMessage}
isSelected={isSelected}
Expand All @@ -101,6 +102,7 @@ const BrowseResultsList = ({

BrowseResultsList.propTypes = {
browseData: PropTypes.arrayOf(PropTypes.object),
filters: PropTypes.object.isRequired,
isEmptyMessage: PropTypes.node.isRequired,
isLoading: PropTypes.bool,
pagination: PropTypes.shape({
Expand Down
113 changes: 113 additions & 0 deletions src/components/BrowseResultsList/BrowseResultsList.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ import {
browseModeOptions,
BROWSE_INVENTORY_ROUTE,
INVENTORY_ROUTE,
browseCallNumberOptions,
FACETS,
} from '../../constants';
import { DataContext } from '../../contexts';
import BrowseResultsList from './BrowseResultsList';
Expand Down Expand Up @@ -59,14 +61,37 @@ const defaultProps = {
pageConfig: [0, null, null],
},
totalRecords: 1,
filters: {},
};

const mockContext = {
contributorNameTypes: [{
id: '2b94c631-fca9-4892-a730-03ee529ffe2a',
}],
contributorTypes: [{
id: '6e09d47d-95e2-4d8a-831b-f777b8ef6d81',
name: 'Author',
}],
};

const contributorsData = [
{
'name': 'Toth, Josh',
'contributorTypeId': [
'6e09d47d-95e2-4d8a-831b-f777b8ef6d81'
],
'contributorNameTypeId': '2b94c631-fca9-4892-a730-03ee529ffe2a',
'isAnchor': false,
'totalRecords': 1
},
];
const subjectsData = [
{
'value': 'Trivia and miscellanea',
'totalRecords': 8
},
];

const renderBrowseResultsList = (props = {}) => renderWithIntl(
<Router history={history}>
<DataContext.Provider value={mockContext}>
Expand Down Expand Up @@ -103,6 +128,94 @@ describe('BrowseResultsList', () => {
);
});

describe.each([
{ searchOption: browseCallNumberOptions.CALL_NUMBERS, shared: FACETS.SHARED, heldBy: FACETS.CALL_NUMBERS_HELD_BY },
{ searchOption: browseCallNumberOptions.DEWEY, shared: FACETS.SHARED, heldBy: FACETS.CALL_NUMBERS_HELD_BY },
{ searchOption: browseCallNumberOptions.LIBRARY_OF_CONGRESS, shared: FACETS.SHARED, heldBy: FACETS.CALL_NUMBERS_HELD_BY },
{ searchOption: browseCallNumberOptions.LOCAL, shared: FACETS.SHARED, heldBy: FACETS.CALL_NUMBERS_HELD_BY },
{ searchOption: browseCallNumberOptions.NATIONAL_LIBRARY_OF_MEDICINE, shared: FACETS.SHARED, heldBy: FACETS.CALL_NUMBERS_HELD_BY },
{ searchOption: browseCallNumberOptions.OTHER, shared: FACETS.SHARED, heldBy: FACETS.CALL_NUMBERS_HELD_BY },
{ searchOption: browseCallNumberOptions.SUPERINTENDENT, shared: FACETS.SHARED, heldBy: FACETS.CALL_NUMBERS_HELD_BY },
])('when the search option is $searchOption and the Shared and/or HeldBy facets are selected', ({ searchOption, shared, heldBy }) => {
describe('and the user clicks on a record in the list', () => {
it('should be navigated to the Search lookup with those filters', async () => {
history = createMemoryHistory({
initialEntries: [{
pathname: BROWSE_INVENTORY_ROUTE,
search: `${heldBy}=college&qindex=${searchOption}&query=a&${shared}=true&${shared}=false`,
}],
});

renderBrowseResultsList({
filters: {
qindex: searchOption,
query: 'a',
[shared]: ['true', 'false'],
[heldBy]: ['college'],
},
});

fireEvent.click(screen.getByText(defaultProps.browseData[2].fullCallNumber))

expect(history.location.search).toContain('?filters=shared.true%2Cshared.false%2CtenantId.college');
});
});
});

describe('when the search option is Contributors and the Shared and/or HeldBy facets are selected', () => {
describe('and the user clicks on a record in the list', () => {
it('should be navigated to the Search lookup with those filters', async () => {
history = createMemoryHistory({
initialEntries: [{
pathname: BROWSE_INVENTORY_ROUTE,
search: 'contributorsShared=true&contributorsShared=false&contributorsTenantId=college&qindex=contributors',
}],
});

renderBrowseResultsList({
filters: {
qindex: 'contributors',
contributorsShared: ['true', 'false'],
contributorsTenantId: ['college'],
},
browseData: contributorsData,
});

fireEvent.click(screen.getByText(contributorsData[0].name))

expect(history.location.search).toContain(
'?filters=searchContributors.2b94c631-fca9-4892-a730-03ee529ffe2a%2Cshared.true%2Cshared.false%2CtenantId.college'
);
});
});
});

describe('when the search option is Subjects and the Shared and/or HeldBy facets are selected', () => {
describe('and the user clicks on a record in the list', () => {
it('should be navigated to the Search lookup with those filters', async () => {
history = createMemoryHistory({
initialEntries: [{
pathname: BROWSE_INVENTORY_ROUTE,
search: 'qindex=browseSubjects&subjectsShared=true&subjectsShared=false&subjectsTenantId=college',
}],
});

renderBrowseResultsList({
filters: {
qindex: 'browseSubjects',
subjectsShared: ['true', 'false'],
subjectsTenantId: ['college'],
},
browseData: subjectsData,
});

fireEvent.click(screen.getByText(subjectsData[0].value))

expect(history.location.search).toContain('?filters=shared.true%2Cshared.false%2CtenantId.college');
});
});
});

describe('when Instance record is linked to an authority record', () => {
describe('by clicking on the icon of an authority app', () => {
const record = {
Expand Down
10 changes: 6 additions & 4 deletions src/components/BrowseResultsList/getBrowseResultsFormatter.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,10 @@ const getTargetRecord = (
item,
row,
browseOption,
filters,
) => {
const record = getFullMatchRecord(item, row.isAnchor);
const searchParams = getSearchParams(row, browseOption);
const searchParams = getSearchParams(row, browseOption, filters);
const isNotClickable = isRowPreventsClick(row, browseOption);

if (isNotClickable) return record;
Expand Down Expand Up @@ -98,12 +99,13 @@ const renderMarcAuthoritiesLink = (authorityId, content) => {
const getBrowseResultsFormatter = ({
data,
browseOption,
filters,
}) => {
return {
title: r => getFullMatchRecord(r.instance?.title, r.isAnchor),
subject: r => {
if (r?.totalRecords) {
const subject = getTargetRecord(r?.value, r, browseOption);
const subject = getTargetRecord(r?.value, r, browseOption, filters);
if (browseOption === browseModeOptions.SUBJECTS && r.authorityId) {
return renderMarcAuthoritiesLink(r.authorityId, subject);
}
Expand All @@ -114,13 +116,13 @@ const getBrowseResultsFormatter = ({
},
callNumber: r => {
if (r?.instance || r?.totalRecords) {
return getTargetRecord(r?.fullCallNumber, r, browseOption);
return getTargetRecord(r?.fullCallNumber, r, browseOption, filters);
}
return <MissedMatchItem query={r.fullCallNumber} />;
},
contributor: r => {
if (r?.totalRecords) {
const fullMatchRecord = getTargetRecord(r.name, r, browseOption);
const fullMatchRecord = getTargetRecord(r.name, r, browseOption, filters);

if (browseOption === browseModeOptions.CONTRIBUTORS && r.authorityId) {
return renderMarcAuthoritiesLink(r.authorityId, fullMatchRecord);
Expand Down
53 changes: 50 additions & 3 deletions src/components/BrowseResultsList/utils.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import omit from 'lodash/omit';

import {
browseCallNumberOptions,
browseModeOptions,
FACETS,
queryIndexes,
Expand All @@ -14,45 +17,89 @@ export const isRowPreventsClick = (row, browseOption) => {
);
};

export const getSearchParams = (row, qindex) => {
const facetsToString = (filters, facetNameInBrowse, facetNameInSearch) => {
return filters[facetNameInBrowse]?.map(value => `${facetNameInSearch}.${value}`).join(',');
};

const getExtraFilters = (row, qindex, allFilters) => {
const filtersOnly = omit(allFilters, 'qindex', 'query');
const extraFacets = [];

let sharedFacetName;
let heldByFacetName;

if (qindex === browseModeOptions.SUBJECTS) {
sharedFacetName = FACETS.SUBJECTS_SHARED;
heldByFacetName = FACETS.SUBJECTS_HELD_BY;

if (row.authorityId) {
extraFacets.push(`${FACETS.AUTHORITY_ID}.${row.authorityId}`);
}
} else if (qindex === browseModeOptions.CONTRIBUTORS) {
sharedFacetName = FACETS.CONTRIBUTORS_SHARED;
heldByFacetName = FACETS.CONTRIBUTORS_HELD_BY;

extraFacets.push(`${FACETS.SEARCH_CONTRIBUTORS}.${row.contributorNameTypeId}`);
} else if (Object.values(browseCallNumberOptions).includes(qindex)) {
sharedFacetName = FACETS.SHARED;
heldByFacetName = FACETS.CALL_NUMBERS_HELD_BY;
}

const sharedExtraFacets = facetsToString(filtersOnly, sharedFacetName, FACETS.SHARED);
const heldByExtraFacets = facetsToString(filtersOnly, heldByFacetName, FACETS.HELD_BY);
const extraFacetsString = [...extraFacets, sharedExtraFacets, heldByExtraFacets].filter(Boolean).join(',');

return extraFacetsString ? { filters: extraFacetsString } : {};
};

export const getSearchParams = (row, qindex, allFilters) => {
const filters = getExtraFilters(row, qindex, allFilters);

const optionsMap = {
[browseModeOptions.CALL_NUMBERS]: {
qindex: queryIndexes.CALL_NUMBER,
query: row.shelfKey,
...filters,
},
[browseModeOptions.DEWEY]: {
qindex: queryIndexes.CALL_NUMBER,
query: row.shelfKey,
...filters,
},
[browseModeOptions.LIBRARY_OF_CONGRESS]: {
qindex: queryIndexes.CALL_NUMBER,
query: row.shelfKey,
...filters,
},
[browseModeOptions.LOCAL]: {
qindex: queryIndexes.CALL_NUMBER,
query: row.shelfKey,
...filters,
},
[browseModeOptions.NATIONAL_LIBRARY_OF_MEDICINE]: {
qindex: queryIndexes.CALL_NUMBER,
query: row.shelfKey,
...filters,
},
[browseModeOptions.OTHER]: {
qindex: queryIndexes.CALL_NUMBER,
query: row.shelfKey,
...filters,
},
[browseModeOptions.SUPERINTENDENT]: {
qindex: queryIndexes.CALL_NUMBER,
query: row.shelfKey,
...filters,
},
[browseModeOptions.CONTRIBUTORS]: {
qindex: queryIndexes.CONTRIBUTOR,
query: row.name,
filters: `${FACETS.SEARCH_CONTRIBUTORS}.${row.contributorNameTypeId}`,
...filters,
},
[browseModeOptions.SUBJECTS]: {
qindex: queryIndexes.SUBJECT,
query: row.value,
...(row.authorityId && { filters: `${FACETS.AUTHORITY_ID}.${row.authorityId}` }),
...filters,
},
};

Expand Down
1 change: 1 addition & 0 deletions src/components/BrowseResultsPane/BrowseResultsPane.js
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ const BrowseResultsPane = ({
isLoading={isFetching}
pagination={pagination}
totalRecords={totalRecords}
filters={filters}
/>
</Pane>
);
Expand Down