Skip to content
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@
*/
import { h, createRef, Component } from 'preact';
import strip from 'strip';

/**
* Internal dependencies
*/
import { getCheckedInputNames } from '../lib/dom';

export default class SearchFilterPostTypes extends Component {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@
*/
import { h, createRef, Component } from 'preact';
import strip from 'strip';

/**
* Internal dependencies
*/
import { getCheckedInputNames } from '../lib/dom';

export default class SearchFilterTaxonomies extends Component {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* External dependencies
*/
import { h, Component } from 'preact';
// NOTE: We only import the debounce package here for to reduced bundle size.
// NOTE: We only import the get package here for to reduced bundle size.
// Do not import the entire lodash library!
// eslint-disable-next-line lodash/import-scope
import get from 'lodash/get';
Expand Down
7 changes: 4 additions & 3 deletions modules/search/instant-search/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { h, render } from 'preact';
*/
import SearchWidget from './components/search-widget';
import { getSearchQuery, getFilterQuery, getSearchSort } from './lib/query-string';
import { SERVER_OBJECT_NAME } from './lib/constants';

const injectSearchWidget = grabFocus => {
render(
Expand All @@ -18,16 +19,16 @@ const injectSearchWidget = grabFocus => {
initialFilters={ getFilterQuery() }
initialSort={ getSearchSort() }
initialValue={ getSearchQuery() }
options={ window.JetpackInstantSearchOptions }
options={ window[ SERVER_OBJECT_NAME ] }
/>,
document.body
);
};

document.addEventListener( 'DOMContentLoaded', function() {
if (
!! window.JetpackInstantSearchOptions &&
'siteId' in window.JetpackInstantSearchOptions &&
!! window[ SERVER_OBJECT_NAME ] &&
'siteId' in window[ SERVER_OBJECT_NAME ] &&
document.body.classList.contains( 'search' )
) {
injectSearchWidget();
Expand Down
105 changes: 53 additions & 52 deletions modules/search/instant-search/lib/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@ import fetch from 'unfetch';
import { encode } from 'qss';
import { flatten } from 'q-flat';

/**
* Internal dependencies
*/
import { getFilterKeys } from './query-string';

const isLengthyArray = array => Array.isArray( array ) && array.length > 0;

export function buildFilterAggregations( widgets = [] ) {
Expand Down Expand Up @@ -40,10 +45,7 @@ export function buildFilterAggregations( widgets = [] ) {
}

const DATE_REGEX = /(\d{4})-(\d{2})-(\d{2})/;
function generateDateRange( query, type ) {
// NOTE: This only supports a single date query at this time
const input = Array.isArray( query ) && query[ 0 ];

function generateDateRangeFilter( fieldName, input, type ) {
let year, month;
if ( type === 'year' ) {
[ , year, , ] = input.match( DATE_REGEX );
Expand All @@ -52,67 +54,66 @@ function generateDateRange( query, type ) {
if ( type === 'month' ) {
[ , year, month ] = input.match( DATE_REGEX );
}

let startDate = '';
let endDate = '';
if ( month ) {
return { startDate: `${ year }-${ month }-01`, endDate: `${ year }-${ +month + 1 }-01` };
startDate = `${ year }-${ month }-01`;
endDate = `${ year }-${ +month + 1 }-01`;
}
if ( year ) {
return { startDate: `${ year }-01-01`, endDate: `${ +year + 1 }-01-01` };
startDate = `${ year }-01-01`;
endDate = `${ +year + 1 }-01-01`;
}
return { startDate: '', endDate: '' };

return { range: { [ fieldName ]: { gte: startDate, lt: endDate } } };
}

const filterKeyToEsFilter = new Map( [
// Post type
[ 'post_types', postType => ( { term: { post_type: postType } } ) ],

// Built-in taxonomies
[ 'category', category => ( { term: { 'category.slug': category } } ) ],
[ 'post_tag', tag => ( { term: { 'tag.slug': tag } } ) ],

// Dates
[ 'month_post_date', datestring => generateDateRangeFilter( 'date', datestring, 'month' ) ],
[
'month_post_date_gmt',
datestring => generateDateRangeFilter( 'date_gmt', datestring, 'month' ),
],
[ 'month_post_modified', datestring => generateDateRangeFilter( 'date', datestring, 'month' ) ],
[
'month_post_modified_gmt',
datestring => generateDateRangeFilter( 'date_gmt', datestring, 'month' ),
],
[ 'year_post_date', datestring => generateDateRangeFilter( 'date', datestring, 'year' ) ],
[ 'year_post_date_gmt', datestring => generateDateRangeFilter( 'date_gmt', datestring, 'year' ) ],
[ 'year_post_modified', datestring => generateDateRangeFilter( 'date', datestring, 'year' ) ],
[
'year_post_modified_gmt',
datestring => generateDateRangeFilter( 'date_gmt', datestring, 'year' ),
],
] );

function buildFilterObject( filterQuery ) {
if ( ! filterQuery ) {
return {};
}

const filter = { bool: { must: [] } };
if ( isLengthyArray( filterQuery.post_types ) ) {
filterQuery.post_types.forEach( postType => {
filter.bool.must.push( { term: { post_type: postType } } );
} );
}
if ( isLengthyArray( filterQuery.post_tag ) ) {
filterQuery.post_tag.forEach( tag => {
filter.bool.must.push( { term: { 'tag.slug': tag } } );
getFilterKeys()
.filter( key => isLengthyArray( filterQuery[ key ] ) )
.forEach( key => {
filterQuery[ key ].forEach( item => {
if ( filterKeyToEsFilter.has( key ) ) {
filter.bool.must.push( filterKeyToEsFilter.get( key )( item ) );
} else {
// If key is not in the standard map, assume to be a custom taxonomy
filter.bool.must.push( { term: { [ `taxonomy.${ key }.slug` ]: item } } );
}
} );
} );
}
if ( isLengthyArray( filterQuery.month_post_date ) ) {
const { startDate, endDate } = generateDateRange( filterQuery.month_post_date, 'month' );
filter.bool.must.push( { range: { date: { gte: startDate, lt: endDate } } } );
}
if ( isLengthyArray( filterQuery.month_post_date_gmt ) ) {
const { startDate, endDate } = generateDateRange( filterQuery.month_post_date_gmt, 'month' );
filter.bool.must.push( { range: { date_gmt: { gte: startDate, lt: endDate } } } );
}
if ( isLengthyArray( filterQuery.month_post_modified ) ) {
const { startDate, endDate } = generateDateRange( filterQuery.month_post_modified, 'month' );
filter.bool.must.push( { range: { modified: { gte: startDate, lt: endDate } } } );
}
if ( isLengthyArray( filterQuery.month_post_modified_gmt ) ) {
const { startDate, endDate } = generateDateRange(
filterQuery.month_post_modified_gmt,
'month'
);
filter.bool.must.push( { range: { modified_gmt: { gte: startDate, lt: endDate } } } );
}
if ( isLengthyArray( filterQuery.year_post_date ) ) {
const { startDate, endDate } = generateDateRange( filterQuery.year_post_date, 'year' );
filter.bool.must.push( { range: { date: { gte: startDate, lt: endDate } } } );
}
if ( isLengthyArray( filterQuery.year_post_date_gmt ) ) {
const { startDate, endDate } = generateDateRange( filterQuery.year_post_date_gmt, 'year' );
filter.bool.must.push( { range: { date_gmt: { gte: startDate, lt: endDate } } } );
}
if ( isLengthyArray( filterQuery.year_post_modified ) ) {
const { startDate, endDate } = generateDateRange( filterQuery.year_post_modified, 'year' );
filter.bool.must.push( { range: { modified: { gte: startDate, lt: endDate } } } );
}
if ( isLengthyArray( filterQuery.year_post_modified_gmt ) ) {
const { startDate, endDate } = generateDateRange( filterQuery.year_post_modified_gmt, 'year' );
filter.bool.must.push( { range: { modified_gmt: { gte: startDate, lt: endDate } } } );
}
return filter;
}

Expand Down
1 change: 1 addition & 0 deletions modules/search/instant-search/lib/constants.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const SERVER_OBJECT_NAME = 'JetpackInstantSearchOptions';
59 changes: 43 additions & 16 deletions modules/search/instant-search/lib/query-string.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,15 @@
* External dependencies
*/
import { decode, encode } from 'qss';
// NOTE: We only import the get package here for to reduced bundle size.
// Do not import the entire lodash library!
// eslint-disable-next-line lodash/import-scope
import get from 'lodash/get';

/**
* Internal dependencies
*/
import { SERVER_OBJECT_NAME } from './constants';

function getQuery() {
return decode( window.location.search.substring( 1 ) );
Expand Down Expand Up @@ -83,27 +92,45 @@ function getFilterQueryByKey( filterKey ) {
return query[ filterKey ];
}

export function getFilterKeys() {
const keys = [
// Post types
'post_types',
// Date filters
'month_post_date',
'month_post_date_gmt',
'month_post_modified',
'month_post_modified_gmt',
'year_post_date',
'year_post_date_gmt',
'year_post_modified',
'year_post_modified_gmt',
];

// Extract taxonomy names from server widget data
const widgetFilters = get( window[ SERVER_OBJECT_NAME ], 'widgets[0].filters' );
if ( widgetFilters ) {
return [
...keys,
...widgetFilters
.filter( filter => filter.type === 'taxonomy' )
.map( filter => filter.taxonomy ),
];
}
return [ ...keys, 'category', 'post_tag' ];
}

export function getFilterQuery( filterKey ) {
if ( filterKey ) {
return getFilterQueryByKey( filterKey );
}

return {
// Taxonomies
category: getFilterQueryByKey( 'category' ),
post_tag: getFilterQueryByKey( 'post_tag' ),
// Post types
post_types: getFilterQueryByKey( 'post_types' ),
// Date filters
month_post_date: getFilterQueryByKey( 'month_post_date' ),
month_post_date_gmt: getFilterQueryByKey( 'month_post_date_gmt' ),
month_post_modified: getFilterQueryByKey( 'month_post_modified' ),
month_post_modified_gmt: getFilterQueryByKey( 'month_post_modified_gmt' ),
year_post_date: getFilterQueryByKey( 'year_post_date' ),
year_post_date_gmt: getFilterQueryByKey( 'year_post_date_gmt' ),
year_post_modified: getFilterQueryByKey( 'year_post_modified' ),
year_post_modified_gmt: getFilterQueryByKey( 'year_post_modified_gmt' ),
};
return Object.assign(
{},
...getFilterKeys().map( key => ( {
[ key ]: getFilterQueryByKey( key ),
} ) )
);
}

export function setFilterQuery( filterKey, filterValue ) {
Expand Down