@plone/volto
Version:
Volto
157 lines (139 loc) • 5.11 kB
JSX
import React, { useRef } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import hoistNonReactStatics from 'hoist-non-react-statics';
import useDeepCompareEffect from 'use-deep-compare-effect';
import { getContent } from '@plone/volto/actions/content/content';
import { getQueryStringResults } from '@plone/volto/actions/querystringsearch/querystringsearch';
import { usePagination } from '@plone/volto/helpers/Utils/usePagination';
import { getBaseUrl } from '@plone/volto/helpers/Url/Url';
import config from '@plone/volto/registry';
function getDisplayName(WrappedComponent) {
return WrappedComponent.displayName || WrappedComponent.name || 'Component';
}
export default function withQuerystringResults(WrappedComponent) {
function WithQuerystringResults(props) {
const {
data = {},
id = data.block,
properties: content,
path,
variation,
} = props;
const { settings } = config;
const querystring = data.querystring || data; // For backwards compat with data saved before Blocks schema. Note, this is also how the Search block passes data to ListingBody
const subrequestID = content?.UID ? `${content?.UID}-${id}` : id;
const { b_size = settings.defaultPageSize } = querystring; // batchsize
// save the path so it won't trigger dispatch on eager router location change
const [initialPath] = React.useState(getBaseUrl(path));
const copyFields = ['limit', 'query', 'sort_on', 'sort_order', 'depth'];
const { currentPage, setCurrentPage } = usePagination(id, 1);
const adaptedQuery = Object.assign(
variation?.fullobjects ? { fullobjects: 1 } : { metadata_fields: '_all' },
{
b_size: b_size,
},
...copyFields.map((name) =>
Object.keys(querystring).includes(name)
? { [name]: querystring[name] }
: {},
),
);
const adaptedQueryRef = useRef(adaptedQuery);
const currentPageRef = useRef(currentPage);
const querystringResults = useSelector(
(state) => state.querystringsearch.subrequests,
);
const dispatch = useDispatch();
const folderItems = content?.is_folderish ? content.items : [];
const hasQuery = querystring?.query?.length > 0;
const hasLoaded = hasQuery
? querystringResults?.[subrequestID]?.loaded
: true;
const listingItems = hasQuery
? querystringResults?.[subrequestID]?.items || []
: folderItems;
const showAsFolderListing = !hasQuery && content?.items_total > b_size;
const showAsQueryListing =
hasQuery && querystringResults?.[subrequestID]?.total > b_size;
const totalPages = showAsFolderListing
? Math.ceil(content.items_total / b_size)
: showAsQueryListing
? Math.ceil(querystringResults[subrequestID].total / b_size)
: 0;
const prevBatch = showAsFolderListing
? content.batching?.prev
: showAsQueryListing
? querystringResults[subrequestID].batching?.prev
: null;
const nextBatch = showAsFolderListing
? content.batching?.next
: showAsQueryListing
? querystringResults[subrequestID].batching?.next
: null;
const isImageGallery =
(!data.variation && data.template === 'imageGallery') ||
data.variation === 'imageGallery';
useDeepCompareEffect(() => {
if (hasQuery) {
dispatch(
getQueryStringResults(
initialPath,
adaptedQuery,
subrequestID,
currentPage,
),
);
} else if (isImageGallery && !hasQuery) {
// when used as image gallery, it doesn't need a query to list children
dispatch(
getQueryStringResults(
initialPath,
{
...adaptedQuery,
b_size: 10000000000,
query: [
{
i: 'path',
o: 'plone.app.querystring.operation.string.relativePath',
v: '',
},
],
},
subrequestID,
),
);
} else {
dispatch(getContent(initialPath, null, null, currentPage));
}
adaptedQueryRef.current = adaptedQuery;
currentPageRef.current = currentPage;
}, [
subrequestID,
isImageGallery,
adaptedQuery,
hasQuery,
initialPath,
dispatch,
currentPage,
]);
return (
<WrappedComponent
{...props}
onPaginationChange={(e, { activePage }) => setCurrentPage(activePage)}
total={querystringResults?.[subrequestID]?.total}
batch_size={b_size}
currentPage={currentPage}
totalPages={totalPages}
prevBatch={prevBatch}
nextBatch={nextBatch}
listingItems={listingItems}
hasLoaded={hasLoaded}
isFolderContentsListing={showAsFolderListing}
/>
);
}
WithQuerystringResults.displayName = `WithQuerystringResults(${getDisplayName(
WrappedComponent,
)})`;
return hoistNonReactStatics(WithQuerystringResults, WrappedComponent);
}