Skip to content
Draft
Show file tree
Hide file tree
Changes from all 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
12 changes: 11 additions & 1 deletion assets/js/api-search/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
WPElement,
} from '@wordpress/element';
import { __, sprintf } from '@wordpress/i18n';
import { applyFilters } from '@wordpress/hooks';

/**
* Internal dependencies.
Expand Down Expand Up @@ -316,7 +317,16 @@ export const ApiSearchProvider = ({
return;
}

setResults(response);
/**
* Filter the search results response.
*
* @filter ep.InstantResults.response
* @since 5.3.0
*
* @param {object} response The search results response.
* @returns {object} Filtered search results response.
*/
setResults(applyFilters('ep.InstantResults.response', response));
} catch (e) {
const errorMessage = sprintf(
/* translators: Error message */
Expand Down
6 changes: 5 additions & 1 deletion assets/js/instant-results/components/common/result.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,18 @@ import Image from './image';
* @param {number} props.averageRating Average rating.
* @param {string} props.date Localized date.
* @param {string} props.excerpt Highlighted excerpt.
* @param {object} props.hit Elasticsearch hit.
* @param {number} props.id Post ID.
* @param {string} props.priceHtml Product price HTML.
* @param {object} props.thumbnail Thumbnail image attributes.
* @param {string} props.title Highlighted title.
* @param {string} props.type Type label.
* @param {string} props.url URL.
* @returns {WPElement} Component element.
*/
const Result = ({ averageRating = 0, date, excerpt, priceHtml, thumbnail, title, type, url }) => {
const Result = (props) => {
const { averageRating = 0, date, excerpt, priceHtml, thumbnail, title, type, url } = props;

return (
<article
className={`ep-search-result ${thumbnail ? 'ep-search-result--has-thumbnail' : null}`}
Expand Down
27 changes: 24 additions & 3 deletions assets/js/instant-results/components/facets/facet.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
* WordPress dependencies.
*/
import { WPElement } from '@wordpress/element';
import { applyFilters } from '@wordpress/hooks';

/**
* Internal dependencies.
Expand All @@ -24,16 +25,36 @@ import TaxonomyTermsFacet from './taxonomy-terms-facet';
export default ({ index, label, name, postTypes, type }) => {
const defaultIsOpen = index < 2;

/**
* Filter the filter label.
*
* @filter ep.InstantResults.filter.label
* @since 5.4.0
*
* @param {string} label Filter label.
* @param {string} name Filter name.
* @param {string} type Filter type.
* @param {string[]} postTypes Filter post types.
* @returns {string} Filtered filter label.
*/
const filteredLabel = applyFilters(
'ep.InstantResults.filter.label',
label,
name,
type,
postTypes,
);

switch (type) {
case 'post_type':
return <PostTypeFacet defaultIsOpen={defaultIsOpen} label={label} />;
return <PostTypeFacet defaultIsOpen={defaultIsOpen} label={filteredLabel} />;
case 'price_range':
return <PriceRangeFacet defaultIsOpen={defaultIsOpen} label={label} />;
return <PriceRangeFacet defaultIsOpen={defaultIsOpen} label={filteredLabel} />;
case 'taxonomy':
return (
<TaxonomyTermsFacet
defaultIsOpen={defaultIsOpen}
label={label}
label={filteredLabel}
name={name}
postTypes={postTypes}
/>
Expand Down
15 changes: 14 additions & 1 deletion assets/js/instant-results/components/facets/post-type-facet.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
*/
import { useCallback, useMemo, WPElement } from '@wordpress/element';
import { __ } from '@wordpress/i18n';
import { applyFilters } from '@wordpress/hooks';

/**
* Internal dependencies.
Expand Down Expand Up @@ -65,7 +66,19 @@ export default ({ defaultIsOpen, label }) => {
/**
* Reduce buckets to options.
*/
const options = useMemo(() => buckets.reduce(reduceOptions, []), [buckets, reduceOptions]);
const options = useMemo(() => {
const reducedOptions = buckets.reduce(reduceOptions, []);
/**
* Filter the post type filter options.
*
* @filter ep.InstantResults.filter.postType.options
* @since 5.4.0
*
* @param {object[]} options Post type filter options.
* @returns {object[]} Filtered post type filter options.
*/
return applyFilters('ep.InstantResults.filter.postType.options', reducedOptions);
}, [buckets, reduceOptions]);

/**
* Handle checkbox change event.
Expand Down
16 changes: 2 additions & 14 deletions assets/js/instant-results/components/layout.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,9 @@ import { useState, WPElement } from '@wordpress/element';
import { useApiSearch } from '../../api-search';
import { facets } from '../config';
import Facet from './facets/facet';
import SearchTermFacet from './facets/search-term-facet';
import Header from './layout/header';
import Results from './layout/results';
import Sidebar from './layout/sidebar';
import Toolbar from './layout/toolbar';
import ActiveConstraints from './tools/active-constraints';
import ClearConstraints from './tools/clear-constraints';
import SidebarToggle from './tools/sidebar-toggle';
import Sort from './tools/sort';

/**
Expand All @@ -39,15 +35,7 @@ export default () => {

return (
<div className={`ep-search-page ${isLoading ? 'is-loading' : ''}`}>
<div className="ep-search-page__header">
<SearchTermFacet />

<Toolbar>
<ActiveConstraints />
<ClearConstraints />
<SidebarToggle isOpen={isSidebarOpen} onClick={onClickSidebarToggle} />
</Toolbar>
</div>
<Header isSidebarOpen={isSidebarOpen} onClickSidebarToggle={onClickSidebarToggle} />

<div className="ep-search-page__body">
<Sidebar isOpen={isSidebarOpen}>
Expand Down
47 changes: 47 additions & 0 deletions assets/js/instant-results/components/layout/header.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/**
* WordPress dependencies.
*/
import { Component, FunctionComponent, WPElement } from '@wordpress/element';
import { applyFilters } from '@wordpress/hooks';

/**
* Internal dependencies.
*/
import SearchTermFacet from '../facets/search-term-facet';
import ActiveConstraints from '../tools/active-constraints';
import ClearConstraints from '../tools/clear-constraints';
import SidebarToggle from '../tools/sidebar-toggle';
import Toolbar from './toolbar';

/**
* Search page header: the search input and toolbar.
*
* @param {object} props Component props.
* @param {boolean} props.isSidebarOpen Whether the sidebar is open.
* @param {Function} props.onClickSidebarToggle Sidebar toggle click handler.
* @returns {WPElement} Component element.
*/
const Header = ({ isSidebarOpen, onClickSidebarToggle }) => {
return (
<div className="ep-search-page__header">
<SearchTermFacet />

<Toolbar>
<ActiveConstraints />
<ClearConstraints />
<SidebarToggle isOpen={isSidebarOpen} onClick={onClickSidebarToggle} />
</Toolbar>
</div>
);
};

/**
* Filter the Header component.
*
* @filter ep.InstantResults.Header
* @since 5.4.0
*
* @param {Component|FunctionComponent} Header Header component.
* @returns {Component|FunctionComponent} Header component.
*/
export default applyFilters('ep.InstantResults.Header', Header);
13 changes: 9 additions & 4 deletions assets/js/instant-results/components/layout/results.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { _n, sprintf, __ } from '@wordpress/i18n';
*/
import { useApiSearch } from '../../../api-search';
import Pagination from '../results/pagination';
import Result from '../results/result';
import ResultsList from '../results/results-list';
import Sort from '../tools/sort';
import DidYouMean from '../results/did-you-mean';

Expand All @@ -20,6 +20,7 @@ import DidYouMean from '../results/did-you-mean';
*/
export default () => {
const {
aggregations,
args: { offset, per_page, highlight },
nextPage,
previousPage,
Expand Down Expand Up @@ -106,9 +107,13 @@ export default () => {
suggestedTerms={suggestedTerms}
totalResults={totalResults}
/>
{searchResults.map((hit) => (
<Result key={hit._id} hit={hit} searchTerm={searchTerm} highlightTag={highlight} />
))}
<ResultsList
aggregations={aggregations}
highlightTag={highlight}
searchResults={searchResults}
searchTerm={searchTerm}
totalResults={totalResults}
/>

<Pagination
offset={offset}
Expand Down
15 changes: 14 additions & 1 deletion assets/js/instant-results/components/results/did-you-mean.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
*/
import { __, sprintf } from '@wordpress/i18n';
import { WPElement, createInterpolateElement } from '@wordpress/element';
import { applyFilters } from '@wordpress/hooks';

import { showSuggestions, suggestionsBehavior } from '../../config';

Expand All @@ -22,7 +23,7 @@ export default (props) => {
// Get other terms by excluding the first term from suggestedTerms
const otherTerms = suggestedTerms.slice(1);

return (
const didYouMean = (
<>
{showSuggestions && suggestedTerms && suggestedTerms?.[0]?.text && (
<div className="ep-search-suggestion">
Expand Down Expand Up @@ -67,4 +68,16 @@ export default (props) => {
)}
</>
);

/**
* Filter the did you mean component.
*
* @filter ep.InstantResults.component.didYouMean
* @since 5.4.0
*
* @param {WPElement} didYouMean Did you mean component.
* @param {object} props Props.
* @returns {WPElement} Did you mean component.
*/
return applyFilters('ep.InstantResults.component.didYouMean', didYouMean, props);
};
18 changes: 16 additions & 2 deletions assets/js/instant-results/components/results/pagination.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@ import { isNumberedPagination } from '../../config';
* @param {number} props.total Total number of items.
* @returns {WPElement} Element.
*/
const Pagination = ({ offset, onNext, onPage = {}, onPrevious, perPage, total }) => {
const Pagination = (props) => {
const { offset, onNext, onPage = {}, onPrevious, perPage, total } = props;

if (perPage <= 0) {
return null;
}
Expand Down Expand Up @@ -186,11 +188,23 @@ const Pagination = ({ offset, onNext, onPage = {}, onPrevious, perPage, total })
);
};

return (
const pagination = (
<nav className={`ep-search-pagination ${isNumbered ? 'is-numbered' : ''}`}>
{isNumbered ? renderNumberedNavigation() : renderButtonNavigation()}
</nav>
);

/**
* Filter the pagination component.
*
* @filter ep.InstantResults.component.pagination
* @since 5.4.0
*
* @param {WPElement} pagination Pagination component.
* @param {object} props Props.
* @returns {WPElement} Pagination component.
*/
return applyFilters('ep.InstantResults.component.pagination', pagination, props);
};

/**
Expand Down
49 changes: 49 additions & 0 deletions assets/js/instant-results/components/results/results-list.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/**
* WordPress dependencies.
*/
import { Component, FunctionComponent, WPElement } from '@wordpress/element';
import { applyFilters } from '@wordpress/hooks';

/**
* Internal dependencies.
*/
import Result from './result';

/**
* List of search results.
*
* @param {object} props Component props.
* @param {object} props.aggregations Elasticsearch aggregations for the current query.
* @param {string} props.highlightTag Selected highlight tag.
* @param {object[]} props.searchResults Elasticsearch hits.
* @param {string} props.searchTerm Search term from input search.
* @param {number} props.totalResults Total number of results across all pages.
* @returns {WPElement} Component element.
*/
const ResultsList = (props) => {
const { highlightTag, searchResults, searchTerm } = props;

return (
<>
{searchResults.map((hit) => (
<Result
key={hit._id}
hit={hit}
searchTerm={searchTerm}
highlightTag={highlightTag}
/>
))}
</>
);
};

/**
* Filter the ResultsList component.
*
* @filter ep.InstantResults.ResultsList
* @since 5.4.0
*
* @param {Component|FunctionComponent} ResultsList ResultsList component.
* @returns {Component|FunctionComponent} ResultsList component.
*/
export default applyFilters('ep.InstantResults.ResultsList', ResultsList);
25 changes: 24 additions & 1 deletion assets/js/instant-results/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,36 @@
* WordPress dependencies.
*/
import { createRoot, render } from '@wordpress/element';
import { doAction } from '@wordpress/hooks';

/**
* Internal dependencies.
*/
import { ApiSearchProvider } from '../api-search';
import { ApiSearchProvider, useApiSearch } from '../api-search';
import { apiEndpoint, apiHost, argsSchema, paramPrefix, requestIdBase } from './config';
import Modal from './apps/modal';
import SearchTermFacet from './components/facets/search-term-facet';
import Toolbar from './components/layout/toolbar';
import ActiveConstraints from './components/tools/active-constraints';
import ClearConstraints from './components/tools/clear-constraints';
import SidebarToggle from './components/tools/sidebar-toggle';

/**
* Expose the components and the useApiSearch hook.
*
* @action ep.InstantResults.ready
* @since 5.4.0
*/
doAction('ep.InstantResults.ready', {
components: {
ActiveConstraints,
ClearConstraints,
SearchTermFacet,
SidebarToggle,
Toolbar,
},
useApiSearch,
});

/**
* Initialize Instant Results.
Expand Down
Loading