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

Instant Search: fix many theme incompatibilities #13602

Merged
merged 10 commits into from
Oct 8, 2019
7 changes: 7 additions & 0 deletions modules/search/instant-search/components/gridicon/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@ class Gridicon extends Component {
return <title>{ __( 'Has multiple images' ) }</title>;
case 'gridicons-image':
return <title>{ __( 'Has an image' ) }</title>;
case 'gridicons-jetpack-search':
case 'gridicons-search':
return <title>{ __( 'Search' ) }</title>;
case 'gridicons-tag':
Expand Down Expand Up @@ -324,6 +325,12 @@ class Gridicon extends Component {
<path d="M21 19l-5.154-5.154C16.574 12.742 17 11.42 17 10c0-3.866-3.134-7-7-7s-7 3.134-7 7 3.134 7 7 7c1.42 0 2.742-.426 3.846-1.154L19 21l2-2zM5 10c0-2.757 2.243-5 5-5s5 2.243 5 5-2.243 5-5 5-5-2.243-5-5z" />
</g>
);
case 'gridicons-jetpack-search':
gibrown marked this conversation as resolved.
Show resolved Hide resolved
return (
<g>
<path d="M12.85 10.85a7 7 0 1 0-2 2L16 18l2-2zm-2-5l-3.49 6.76V5.83zM6.64 1.39v6.78H3.15z" />
</g>
);
case 'gridicons-star-outline':
return (
<g>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import debounce from 'lodash/debounce';
import SearchResults from './search-results';
import SearchFiltersWidget from './search-filters-widget';
import SearchSortWidget from './search-sort-widget';
import SearchBox from './search-box';
import { search, buildFilterAggregations } from '../lib/api';
import {
setSearchQuery,
Expand All @@ -24,7 +25,7 @@ import {
setSortQuery,
getSortQuery,
} from '../lib/query-string';
import { removeChildren, hideSearchHeader } from '../lib/dom';
import { removeChildren, hideElements } from '../lib/dom';

class SearchApp extends Component {
constructor() {
Expand All @@ -38,8 +39,9 @@ class SearchApp extends Component {
query: this.props.initialValue,
sort: this.props.initialSort,
results: {},
loading: false,
};
this.getResults = debounce( this.getResults, 500 );
this.getResults = debounce( this.getResults, 200 );
this.getResults( this.state.query, getFilterQuery(), this.state.sort );
}

Expand All @@ -48,11 +50,15 @@ class SearchApp extends Component {
this.input.current.focus();
}

hideSearchHeader();
removeChildren( document.querySelector( 'main' ) );
hideElements( this.props.themeOptions.elem_selectors );
removeChildren( document.querySelector( this.props.themeOptions.results_selector ) );
this.props.widgets.forEach( function( widget ) {
removeChildren( document.getElementById( widget.widget_id ) );
} );
const searchForms = document.querySelectorAll( this.props.themeOptions.search_form_selector );
searchForms.forEach( function( elem ) {
removeChildren( elem );
} );
}

onChangeQuery = event => {
Expand All @@ -77,6 +83,9 @@ class SearchApp extends Component {
this.requestId++;
const requestId = this.requestId;

this.setState( {
loading: true,
} );
search( {
aggregations: this.props.aggregations,
filter,
Expand All @@ -86,36 +95,36 @@ class SearchApp extends Component {
sort,
} ).then( results => {
if ( this.requestId === requestId ) {
this.setState( { results } );
this.setState( {
results,
loading: false,
} );
}
} );
} else {
this.setState( { results: [] } );
this.setState( {
results: [],
loading: false,
} );
}
};

render() {
const { query, results } = this.state;
const searchForms = Array.from(
document.querySelectorAll( this.props.themeOptions.search_form_selector )
);
return (
<Preact.Fragment>
{ this.props.widgets.map( ( widget, index ) => (
{ this.props.widgets.map( widget => (
<Portal into={ `#${ widget.widget_id }` }>
<div id={ `${ widget.widget_id }-wrapper` }>
<div className="search-form">
{ /* TODO: Add support for preserving label text */ }
<input
className="search-field"
onInput={ this.onChangeQuery }
ref={ index === 0 ? this.input : null }
type="search"
value={ query }
<SearchBox
onChangeQuery={ this.onChangeQuery }
appRef={ this.input }
gibrown marked this conversation as resolved.
Show resolved Hide resolved
query={ query }
/>
<button type="submit" className="search-submit">
<svg className="icon icon-search" aria-hidden="true" role="img">
<use href="#icon-search" />
</svg>
<span className="screen-reader-text">Search</span>
</button>
</div>
<div className="jetpack-search-sort-wrapper">
<SearchSortWidget
Expand All @@ -126,6 +135,7 @@ class SearchApp extends Component {
<SearchFiltersWidget
initialValues={ this.props.initialFilters }
onChange={ this.onChangeFilter }
loading={ this.state.loading }
postTypes={ this.props.options.postTypes }
results={ this.state.results }
widget={ widget }
Expand All @@ -134,9 +144,21 @@ class SearchApp extends Component {
</Portal>
) ) }

<Portal into="main">
{ searchForms &&
searchForms.map( elem => (
<Portal into={ elem }>
<SearchBox
onChangeQuery={ this.onChangeQuery }
appRef={ this.input }
query={ query }
/>
</Portal>
) ) }

<Portal into={ this.props.themeOptions.results_selector }>
<SearchResults
query={ query }
loading={ this.state.loading }
{ ...results }
result_format={ this.props.options.resultFormat }
/>
Expand Down
30 changes: 30 additions & 0 deletions modules/search/instant-search/components/search-box.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/** @jsx h */

/**
* External dependencies
*/
import { h, Component } from 'preact';
import { __ } from '@wordpress/i18n';

class SearchBox extends Component {
render() {
const { query, onChangeQuery, appRef } = this.props;

return (
<div className={ 'jp-instant-search__box' }>
{ /* TODO: Add support for preserving label text */ }
<span className="screen-reader-text">{ __( 'Search', 'jetpack' ) }</span>
<input
className="search-field jp-instant-search__box-input"
onInput={ onChangeQuery }
ref={ appRef }
placeholder={ __( 'Search…', 'jetpack' ) }
type="search"
value={ query }
/>
</div>
);
}
}

export default SearchBox;
8 changes: 8 additions & 0 deletions modules/search/instant-search/components/search-box.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/* apply to all the inputs to try and pick up any theme styling */
.jp-instant-search__box input {
border-radius: 2px;
font-size: 14px;
height: 26px;
width: 100%;
line-height: 1.2em;
}
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,13 @@ export default class SearchFiltersWidget extends Component {

render() {
const aggregations = get( this.props.results, 'aggregations' );
const cls =
this.props.loading === true
? 'jetpack-instant-search__filters-widget jetpack-instant-search__is-loading'
: 'jetpack-instant-search__filters-widget';

return (
<div className="jetpack-instant-search__filters-widget">
<div className={ cls }>
{ get( this.props.widget, 'filters' )
.map( configuration =>
aggregations
Expand Down
26 changes: 16 additions & 10 deletions modules/search/instant-search/components/search-results.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
/**
* External dependencies
*/
import { __, sprintf } from '@wordpress/i18n';
import { __, _n, sprintf } from '@wordpress/i18n';
import { h, Component } from 'preact';

/**
Expand All @@ -23,33 +23,39 @@ class SearchResults extends Component {
}

render() {
const { results = [], query, total = 0, corrected_query = false } = this.props;
const { results = [], query, total = 0, corrected_query = false, loading = false } = this.props;
if ( query === '' ) {
return <div className="jetpack-instant-search__search-results" />;
}
if ( total === 0 ) {
return (
<div className="jetpack-instant-search__search-results">
<div>
<h3>{ sprintf( __( 'No Results.' ), query ) }</h3>
<h3>{ sprintf( __( 'No Results.', 'jetpack' ), query ) }</h3>
</div>
</div>
);
}
const num = new Intl.NumberFormat().format( total );
jsnmoon marked this conversation as resolved.
Show resolved Hide resolved
const cls =
loading === true
? 'jetpack-instant-search__search-results jetpack-instant-search__is-loading'
: 'jetpack-instant-search__search-results';

return (
<div className="jetpack-instant-search__search-results">
<span className="jetpack-instant-search__search-results-count">
{ sprintf( __( '%d Results' ), total ) }
</span>
<div className={ cls }>
<p className="jetpack-instant-search__search-results-real-query">
{ corrected_query !== false
? sprintf( __( 'Showing results for "%s"' ), corrected_query )
: sprintf( __( 'Results for "%s"' ), query ) }
? sprintf(
_n( 'Showing %s result for "%s"', 'Showing %s results for "%s"', total ),
num,
corrected_query
)
: sprintf( _n( '%s results for "%s"', '%s results for "%s"', total ), num, query ) }
</p>
{ corrected_query !== false && (
<p className="jetpack-instant-search__search-results-unused-query">
{ sprintf( __( 'No results for "%s"' ), query ) }
{ sprintf( __( 'No results for "%s"', 'jetpack' ), query ) }
</p>
) }
{ results.map( result => this.render_result( result ) ) }
Expand Down
11 changes: 3 additions & 8 deletions modules/search/instant-search/components/search-results.scss
Original file line number Diff line number Diff line change
@@ -1,13 +1,8 @@
.jetpack-instant-search__search-results {
padding: 0.125em 0;
margin: 1em 0;
padding: 0.125em 2em;
margin: 1em auto;
position: relative;
}

.jetpack-instant-search__search-results-count {
float: right;
margin-left: 0.5em;
display: block;
max-width: 1080px;
}

.jetpack-instant-search__search-results-real-query {
Expand Down
10 changes: 6 additions & 4 deletions modules/search/instant-search/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,20 @@ import { h, render } from 'preact';
/**
* Internal dependencies
*/
import SearchWidget from './components/search-widget';
import SearchApp from './components/search-app';
import { getSearchQuery, getFilterQuery, getSortQuery } from './lib/query-string';
import { getThemeOptions } from './lib/dom';
import { SERVER_OBJECT_NAME } from './lib/constants';

const injectSearchWidget = grabFocus => {
const injectSearchApp = grabFocus => {
render(
<SearchWidget
<SearchApp
grabFocus={ grabFocus }
initialFilters={ getFilterQuery() }
initialSort={ getSortQuery() }
initialValue={ getSearchQuery() }
options={ window[ SERVER_OBJECT_NAME ] }
themeOptions={ getThemeOptions( window[ SERVER_OBJECT_NAME ] ) }
/>,
document.body
);
Expand All @@ -31,6 +33,6 @@ document.addEventListener( 'DOMContentLoaded', function() {
'siteId' in window[ SERVER_OBJECT_NAME ] &&
document.body.classList.contains( 'search' )
) {
injectSearchWidget();
injectSearchApp();
}
} );
5 changes: 5 additions & 0 deletions modules/search/instant-search/instant-search.scss
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,10 @@
@import './components/search-filters-widget.scss';
@import './components/search-sort-widget.scss';
@import './components/search-result-minimal.scss';
@import './components/search-box.scss';
//@import './components/search-result-engagement.scss';
//@import './components/search-result-product.scss';

.jetpack-instant-search__is-loading {
opacity: 0.2;
}
Loading