mirror of
https://gerrit.wikimedia.org/r/mediawiki/skins/Vector.git
synced 2024-11-24 07:43:47 +00:00
Merge "search: Optionally support load-more events"
This commit is contained in:
commit
eb9040b859
|
@ -13,7 +13,7 @@
|
|||
},
|
||||
{
|
||||
"resourceModule": "skins.vector.search",
|
||||
"maxSize": "3.1 kB"
|
||||
"maxSize": "3.3 kB"
|
||||
},
|
||||
{
|
||||
"resourceModule": "skins.vector.icons",
|
||||
|
|
|
@ -18,6 +18,8 @@
|
|||
:auto-expand-width="autoExpandWidth"
|
||||
:search-results="suggestions"
|
||||
:search-footer-url="searchFooterUrl"
|
||||
:visible-item-limit="visibleItemLimit"
|
||||
@load-more="onLoadMore"
|
||||
@input="onInput"
|
||||
@search-result-click="instrumentation.onSuggestionClick"
|
||||
@submit="onSubmit"
|
||||
|
@ -44,7 +46,7 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
/* global SearchSubmitEvent */
|
||||
/* global AbortableSearchFetch, SearchSubmitEvent */
|
||||
const { CdxTypeaheadSearch } = require( '@wikimedia/codex-search' ),
|
||||
{ defineComponent, nextTick } = require( 'vue' ),
|
||||
client = require( './restSearchClient.js' ),
|
||||
|
@ -153,6 +155,12 @@ module.exports = exports = defineComponent( {
|
|||
'vector-search-box-disable-transitions': this.disableTransitions,
|
||||
'vector-typeahead-search--active': this.isFocused
|
||||
};
|
||||
},
|
||||
visibleItemLimit() {
|
||||
// if the search client supports loading more results,
|
||||
// show 7 out of 10 results at first (arbitrary number),
|
||||
// so that scroll events are fired and trigger onLoadMore()
|
||||
return restClient.loadMore ? 7 : null;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
@ -172,15 +180,55 @@ module.exports = exports = defineComponent( {
|
|||
return;
|
||||
}
|
||||
|
||||
this.updateUIWithSearchClientResult(
|
||||
restClient.fetchByTitle( query, 10, this.showDescription ),
|
||||
true
|
||||
);
|
||||
},
|
||||
|
||||
/**
|
||||
* Fetch additional suggestions.
|
||||
*
|
||||
* This should only be called if visibleItemLimit is non-null,
|
||||
* i.e. if the search client supports loading more results.
|
||||
*/
|
||||
onLoadMore() {
|
||||
if ( !restClient.loadMore ) {
|
||||
mw.log.warn( 'onLoadMore() should not have been called for this search client' );
|
||||
return;
|
||||
}
|
||||
|
||||
this.updateUIWithSearchClientResult(
|
||||
restClient.loadMore(
|
||||
this.currentSearchQuery,
|
||||
this.suggestions.length,
|
||||
10,
|
||||
this.showDescription
|
||||
),
|
||||
false
|
||||
);
|
||||
},
|
||||
|
||||
/**
|
||||
* @param {AbortableSearchFetch} search
|
||||
* @param {boolean} replaceResults
|
||||
*/
|
||||
updateUIWithSearchClientResult( search, replaceResults ) {
|
||||
const query = this.currentSearchQuery;
|
||||
instrumentation.listeners.onFetchStart();
|
||||
|
||||
restClient.fetchByTitle( query, 10, this.showDescription ).fetch
|
||||
search.fetch
|
||||
.then( ( data ) => {
|
||||
// Only use these results if they're still relevant
|
||||
// If currentSearchQuery !== query, these results are for a previous search
|
||||
// and we shouldn't show them.
|
||||
if ( this.currentSearchQuery === query ) {
|
||||
this.suggestions = instrumentation.addWprovToSearchResultUrls( data.results );
|
||||
if ( replaceResults ) {
|
||||
this.suggestions = [];
|
||||
}
|
||||
this.suggestions.push(
|
||||
...instrumentation.addWprovToSearchResultUrls( data.results, this.suggestions.length )
|
||||
);
|
||||
this.searchFooterUrl = urlGenerator.generateUrl( query );
|
||||
}
|
||||
|
||||
|
|
|
@ -156,13 +156,14 @@ function generateUrl( suggestion, meta ) {
|
|||
* with the `wprov` parameter added to each result's url (if any).
|
||||
*
|
||||
* @param {SearchResultPartial[]} results Not modified.
|
||||
* @param {number} offset Offset to add to the index of each result.
|
||||
* @return {SearchResultPartial[]}
|
||||
*/
|
||||
function addWprovToSearchResultUrls( results ) {
|
||||
function addWprovToSearchResultUrls( results, offset ) {
|
||||
return results.map( ( result, index ) => {
|
||||
if ( result.url ) {
|
||||
const uri = new mw.Uri( result.url );
|
||||
uri.query.wprov = getWprovFromResultIndex( index );
|
||||
uri.query.wprov = getWprovFromResultIndex( index + offset );
|
||||
result = Object.assign( {}, result, { url: uri.toString() } );
|
||||
}
|
||||
return result;
|
||||
|
|
|
@ -71,9 +71,19 @@ function adaptApiResponse( config, query, restResponse, showDescription ) {
|
|||
* @return {AbortableSearchFetch}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @callback loadMore
|
||||
* @param {string} query The search term.
|
||||
* @param {number} offset The number of search results that were already loaded.
|
||||
* @param {number} [limit] How many further search results to load (at most).
|
||||
* @param {boolean} [showDescription] Whether descriptions should be added to the results.
|
||||
* @return {AbortableSearchFetch}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} SearchClient
|
||||
* @property {fetchByTitle} fetchByTitle
|
||||
* @property {loadMore} [loadMore]
|
||||
*/
|
||||
|
||||
/**
|
||||
|
|
|
@ -21,7 +21,7 @@ describe( 'instrumentation', () => {
|
|||
} );
|
||||
} );
|
||||
|
||||
test( 'addWprovToSearchResultUrls', () => {
|
||||
test( 'addWprovToSearchResultUrls without offset', () => {
|
||||
const url1 = 'https://host/?title=Special%3ASearch&search=Aa',
|
||||
url2Base = 'https://host/?title=Special%3ASearch&search=Ab',
|
||||
url3 = 'https://host/Ac';
|
||||
|
@ -43,7 +43,7 @@ describe( 'instrumentation', () => {
|
|||
}
|
||||
];
|
||||
|
||||
expect( instrumentation.addWprovToSearchResultUrls( results ) )
|
||||
expect( instrumentation.addWprovToSearchResultUrls( results, 0 ) )
|
||||
.toStrictEqual( [
|
||||
{
|
||||
title: 'Aa',
|
||||
|
@ -63,4 +63,31 @@ describe( 'instrumentation', () => {
|
|||
] );
|
||||
expect( results[ 0 ].url ).toStrictEqual( url1 );
|
||||
} );
|
||||
|
||||
test( 'addWprovToSearchResultUrls with offset', () => {
|
||||
const url1 = 'https://host/?title=Special%3ASearch&search=Ae',
|
||||
url2 = 'https://host/?title=Special%3ASearch&search=Af';
|
||||
const results = [
|
||||
{
|
||||
title: 'Ae',
|
||||
url: url1
|
||||
},
|
||||
{
|
||||
title: 'Af',
|
||||
url: url2
|
||||
}
|
||||
];
|
||||
|
||||
expect( instrumentation.addWprovToSearchResultUrls( results, 4 ) )
|
||||
.toStrictEqual( [
|
||||
{
|
||||
title: 'Ae',
|
||||
url: `${url1}&wprov=acrw1_4`
|
||||
},
|
||||
{
|
||||
title: 'Af',
|
||||
url: `${url2}&wprov=acrw1_5`
|
||||
}
|
||||
] );
|
||||
} );
|
||||
} );
|
||||
|
|
Loading…
Reference in a new issue