UNPKG

design-comuni-plone-theme

Version:
312 lines (276 loc) 10 kB
/* CUSTOMIZATIONS: - get content from state.content.data and not from data.properties.content, - added listingRef to scroll to start of listing, and not to start of page - added additional filters - added additional fields to pass to @querystring-search (config.settings.querystringAdditionalFields) - usedeepCompareEffect and integrate custom logic for searchBlock to make it work with our implementation - used [subrequestID] instead [id] of block, as id of subrequest to avoid block unload on duplicate contents with blocks with same id's. Volto's pr: https://github.com/plone/volto/pull/5071 */ import React, { createRef, useEffect } from 'react'; import hoistNonReactStatics from 'hoist-non-react-statics'; import { getContent, getQueryStringResults } from '@plone/volto/actions'; import { useDispatch, useSelector } from 'react-redux'; import useDeepCompareEffect from 'use-deep-compare-effect'; import { flattenToAppURL, getBaseUrl } from '@plone/volto/helpers'; import config from '@plone/volto/registry'; import { setOriginalQuery } from 'design-comuni-plone-theme/actions'; function getDisplayName(WrappedComponent) { return WrappedComponent.displayName || WrappedComponent.name || 'Component'; } const getVariationSettings = (variation) => { return config?.blocks?.blocksConfig?.listing?.variations?.find( (v) => v.id === variation, ); }; const getAdaptedQuery = (querystring, b_size, variation) => { const copyFields = [ 'limit', 'query', 'sort_on', 'sort_order', 'depth', ...(config.settings.querystringAdditionalFields ?? []), ]; const variationSettings = getVariationSettings(variation) ?? {}; return Object.assign( variationSettings?.fullobjects ? { fullobjects: 1 } : { metadata_fields: '_all' }, { b_size: b_size, }, ...copyFields.map((name) => Object.keys(querystring).includes(name) ? { [name]: querystring[name] } : {}, ), ); }; export default function withQuerystringResults(WrappedComponent) { function WithQuerystringResults(props) { const { data = {}, id = data.block, //properties: content, properties, path, //variation, isEditMode, } = props; const content = useSelector((state) => state.content.data); const { settings } = config; const querystring = data.querystring || data; // For backwards compat with data saved before Blocks schema const subrequestID = content?.UID + '-' + id; const { b_size = settings.defaultPageSize } = querystring; const [firstLoading, setFirstLoading] = React.useState(true); // save the path so it won't trigger dispatch on eager router location change const [initialPath] = React.useState(getBaseUrl(path)); const [currentPage, setCurrentPage] = React.useState(1); const querystringResults = useSelector( (state) => state.querystringsearch.subrequests, ); const subrequestResult = querystringResults[subrequestID]; const dispatch = useDispatch(); const listingRef = createRef(); const [additionalFilters, setAdditionalFilters] = React.useState([]); const originalQuery = useSelector((state) => { if (props?.variation?.['@type'] === 'search') { return state.originalQuery?.[path]?.[subrequestID]; } return state.originalQuery?.[properties['@id']]?.[ subrequestID ]?.toArray?.(); }); const folderItems = content?.is_folderish ? content.items : []; const hasQuery = querystring?.query?.length > 0; const hasLoaded = hasQuery ? querystringResults?.[subrequestID]?.loaded : true; const loadingQuery = hasQuery && (querystringResults?.[subrequestID]?.loading || !querystringResults?.[subrequestID]?.loaded); const listingItems = hasQuery ? querystringResults?.[subrequestID]?.items || [] : folderItems; const showAsFolderListing = !hasQuery && content?.items_total > b_size; const showAsQueryListing = hasQuery && querystringResults?.[subrequestID]?.total > b_size; const itemsTotal = showAsFolderListing ? content.items_total : querystringResults?.[subrequestID]?.total; 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; function handleContentPaginationChange(e, { activePage }) { !isEditMode && listingRef.current.scrollIntoView({ behavior: 'smooth' }); const current = activePage?.children ?? 1; setCurrentPage(current); dispatch(getContent(initialPath, null, null, current)); } function handleQueryPaginationChange(e, { activePage }) { !isEditMode && listingRef.current.scrollIntoView({ behavior: 'smooth' }); const current = activePage?.children ?? 1; setCurrentPage(current); doSearch(data, current); } // const isImageGallery = // (!data.variation && data.template === 'imageGallery') || // data.variation === 'imageGallery'; //set original query on loading component useEffect(() => { let path = properties?.['@id']; if (props?.variation?.['@type'] === 'search') { path = flattenToAppURL(props?.path); } if ( !originalQuery && path && data.block && querystring.query?.length > 0 ) { dispatch( setOriginalQuery( path, data.block, JSON.parse(JSON.stringify(querystring.query)), ), ); } // eslint-disable-next-line react-hooks/exhaustive-deps }, []); useEffect(() => { if (firstLoading && subrequestResult && !loadingQuery) { setFirstLoading(false); } }, [firstLoading, loadingQuery, subrequestResult]); useDeepCompareEffect(() => { if ( (hasQuery && (isEditMode || (!isEditMode && !querystringResults[subrequestID]?.loaded))) || (hasQuery && props.variation?.['@type'] === 'search') ) { doSearch(data); } /* eslint-disable react-hooks/exhaustive-deps */ }, [data, content]); const doSearch = (data = { querystring: { query: [] } }, page = 1) => { let _dataQuerystring = data?.querystring ?? data; //Backward compatibility before blockSchema //additional fields to pass to @querystring-search if (config.settings.querystringAdditionalFields?.length > 0) { config.settings.querystringAdditionalFields.forEach((f) => { if (data[f] != null) { _dataQuerystring[f] = data[f]; } }); } if (_dataQuerystring?.query?.length > 0 || additionalFilters.length > 0) { let query = [ ...(originalQuery && additionalFilters.length > 0 ? JSON.parse(JSON.stringify(originalQuery)) : _dataQuerystring.query), ]; //faccio l'override dei filtri di default additionalFilters.forEach((filter) => { let replaced = false; query.forEach((f) => { if (f.i === filter.i && f.o === filter.o) { replaced = true; f.v = filter.v; } }); if (!replaced) { query.push(filter); } }); let _querystring = { ..._dataQuerystring, query: query }; if (page !== currentPage) { setCurrentPage(page); } dispatch( getQueryStringResults( path, getAdaptedQuery(_querystring, b_size, data.variation), subrequestID, page, ), ); } else if ( ((!data.variation && data.template === 'imageGallery') || data.variation === 'imageGallery') && _dataQuerystring?.query?.length === 0 ) { dispatch( getQueryStringResults( path, { ...getAdaptedQuery(_dataQuerystring, b_size, data.variation), b_size: 10000000000, query: [ { i: 'path', o: 'plone.app.querystring.operation.string.relativePath', v: '', }, ], }, subrequestID, ), ); } }; useDeepCompareEffect(() => { if (!firstLoading && !loadingQuery) { doSearch(data); } }, [additionalFilters]); const addFilters = (filters = []) => { setCurrentPage(1); setAdditionalFilters(filters); }; return ( <WrappedComponent {...props} onPaginationChange={(e, { activePage }) => { showAsFolderListing ? handleContentPaginationChange(e, { activePage }) : handleQueryPaginationChange(e, { activePage }); }} total={querystringResults?.[subrequestID]?.total} batch_size={b_size} currentPage={currentPage} totalPages={totalPages} itemsTotal={itemsTotal} prevBatch={prevBatch} nextBatch={nextBatch} listingItems={listingItems} hasLoaded={hasLoaded} isFolderContentsListing={showAsFolderListing} addFilters={addFilters} firstLoading={firstLoading} loadingQuery={loadingQuery} listingRef={listingRef} hasQuery={hasQuery} additionalFilters={additionalFilters} /> ); } WithQuerystringResults.displayName = `WithQuerystringResults(${getDisplayName( WrappedComponent, )})`; return hoistNonReactStatics(WithQuerystringResults, WrappedComponent); }