mirror of
https://gerrit.wikimedia.org/r/mediawiki/skins/Vector.git
synced 2024-09-25 03:09:24 +00:00
ce77018b7c
[Visual changes] This should result in 9 visual regression failures relating to increased height of search results and loading bar [More details about change] - Migrate search app from Vue 2 to Vue 3; update tests accordingly - Remove dependence on WVUI and use Codex instead, via the special `@wikimedia/codex-search` package - Update search app to use CdxTypeaheadSearch, which no longer takes in props related to the search client or fetch start/end instrumentation. Instead, directly use the restSearchClient and call fetch start/end events in the search app. - Handle hideDirection in the search app/API response formatting code, not within the TypeaheadSearch component - Handle showing/hiding the search button in the app - Move the WVUI URL generator into Vector - Update server-rendered search box styles to match design updates included with CdxTypeaheadSearch - Replace references to WVUI with references to Codex - Update values of various LESS variables to match Codex, and update searchBox styling to prevent jankiness when the searchBox is replaced with the Codex TypeaheadSearch component The VectorWvuiSearchOptions config variable has been maintained and will be updated to a code-agnostic name in a future patch. Bug: T300573 Bug: T302137 Bug: T303558 Bug: T309722 Bug: T310525 Co-Authored-By: Anne Tomasevich <atomasevich@wikimedia.org> Change-Id: I59fa3a006d988b14ebd8020cbd58e8d7bedbfe01
192 lines
4.5 KiB
Vue
192 lines
4.5 KiB
Vue
<template>
|
|
<cdx-typeahead-search
|
|
:id="id"
|
|
ref="searchForm"
|
|
:class="rootClasses"
|
|
:search-results-label="$i18n( 'searchresults' ).text()"
|
|
:accesskey="searchAccessKey"
|
|
:title="searchTitle"
|
|
:placeholder="searchPlaceholder"
|
|
:aria-label="searchPlaceholder"
|
|
:initial-input-value="searchQuery"
|
|
:button-label="$i18n( 'searchbutton' ).text()"
|
|
:form-action="action"
|
|
:show-thumbnail="showThumbnail"
|
|
:highlight-query="highlightQuery"
|
|
:auto-expand-width="autoExpandWidth"
|
|
:search-results="suggestions"
|
|
:search-footer-url="searchFooterUrl"
|
|
@input="onInput"
|
|
@search-result-click="instrumentation.onSuggestionClick"
|
|
@submit="onSubmit"
|
|
>
|
|
<template #default>
|
|
<input
|
|
type="hidden"
|
|
name="title"
|
|
:value="searchPageTitle"
|
|
>
|
|
<input
|
|
type="hidden"
|
|
name="wprov"
|
|
:value="wprov"
|
|
>
|
|
</template>
|
|
<!-- eslint-disable-next-line vue/no-template-shadow -->
|
|
<template #search-footer-text="{ searchQuery }">
|
|
<span v-i18n-html:vector-searchsuggest-containing="[ searchQuery ]"></span>
|
|
</template>
|
|
</cdx-typeahead-search>
|
|
</template>
|
|
|
|
<script>
|
|
/* global SearchSubmitEvent */
|
|
const { CdxTypeaheadSearch } = require( '@wikimedia/codex-search' ),
|
|
{ defineComponent, nextTick } = require( 'vue' ),
|
|
client = require( './restSearchClient.js' ),
|
|
restClient = client( mw.config ),
|
|
urlGenerator = require( './urlGenerator.js' )( mw.config ),
|
|
instrumentation = require( './instrumentation.js' );
|
|
|
|
// @vue/component
|
|
module.exports = exports = defineComponent( {
|
|
name: 'App',
|
|
components: { CdxTypeaheadSearch },
|
|
props: {
|
|
id: {
|
|
type: String,
|
|
required: true
|
|
},
|
|
searchPageTitle: {
|
|
type: String,
|
|
default: 'Special:Search'
|
|
},
|
|
autofocusInput: {
|
|
type: Boolean,
|
|
default: false
|
|
},
|
|
action: {
|
|
type: String,
|
|
default: ''
|
|
},
|
|
/** The keyboard shortcut to focus search. */
|
|
// eslint-disable-next-line vue/require-default-prop
|
|
searchAccessKey: {
|
|
type: String
|
|
},
|
|
/** The access key informational tip for search. */
|
|
// eslint-disable-next-line vue/require-default-prop
|
|
searchTitle: {
|
|
type: String
|
|
},
|
|
/** The ghost text shown when no search query is entered. */
|
|
// eslint-disable-next-line vue/require-default-prop
|
|
searchPlaceholder: {
|
|
type: String
|
|
},
|
|
/**
|
|
* The search query string taken from the server-side rendered input immediately before
|
|
* client render.
|
|
*/
|
|
// eslint-disable-next-line vue/require-default-prop
|
|
searchQuery: {
|
|
type: String
|
|
},
|
|
showThumbnail: {
|
|
type: Boolean,
|
|
// eslint-disable-next-line vue/no-boolean-default
|
|
default: true
|
|
},
|
|
showDescription: {
|
|
type: Boolean,
|
|
// eslint-disable-next-line vue/no-boolean-default
|
|
default: true
|
|
},
|
|
highlightQuery: {
|
|
type: Boolean,
|
|
// eslint-disable-next-line vue/no-boolean-default
|
|
default: true
|
|
},
|
|
autoExpandWidth: {
|
|
type: Boolean,
|
|
default: false
|
|
}
|
|
},
|
|
data() {
|
|
return {
|
|
// -1 here is the default "active suggestion index".
|
|
wprov: instrumentation.getWprovFromResultIndex( -1 ),
|
|
|
|
// Suggestions to be shown in the TypeaheadSearch menu.
|
|
suggestions: [],
|
|
|
|
// Link to the search page for the current search query.
|
|
searchFooterUrl: '',
|
|
|
|
// Whether to apply a CSS class that disables the CSS transitions on the text input
|
|
disableTransitions: this.autofocusInput,
|
|
|
|
instrumentation: instrumentation.listeners
|
|
};
|
|
},
|
|
computed: {
|
|
rootClasses() {
|
|
return {
|
|
'vector-search-box-disable-transitions': this.disableTransitions
|
|
};
|
|
}
|
|
},
|
|
methods: {
|
|
/**
|
|
* Fetch suggestions when new input is received.
|
|
*
|
|
* @param {string} value
|
|
*/
|
|
onInput: function ( value ) {
|
|
const domain = mw.config.get( 'wgVectorSearchHost', location.host ),
|
|
query = value.trim();
|
|
|
|
if ( query === '' ) {
|
|
this.suggestions = [];
|
|
this.searchFooterUrl = '';
|
|
return;
|
|
}
|
|
|
|
instrumentation.listeners.onFetchStart();
|
|
|
|
restClient.fetchByTitle( query, domain, 10, this.showDescription ).fetch
|
|
.then( ( data ) => {
|
|
this.suggestions = data.results;
|
|
this.searchFooterUrl = urlGenerator.generateUrl( query );
|
|
|
|
const event = {
|
|
numberOfResults: data.results.length,
|
|
query: query
|
|
};
|
|
instrumentation.listeners.onFetchEnd( event );
|
|
} )
|
|
.catch( () => {
|
|
// TODO: error handling
|
|
} );
|
|
},
|
|
|
|
/**
|
|
* @param {SearchSubmitEvent} event
|
|
*/
|
|
onSubmit( event ) {
|
|
this.wprov = instrumentation.getWprovFromResultIndex( event.index );
|
|
|
|
instrumentation.listeners.onSubmit( event );
|
|
}
|
|
},
|
|
mounted() {
|
|
if ( this.autofocusInput ) {
|
|
this.$refs.searchForm.focus();
|
|
nextTick( () => {
|
|
this.disableTransitions = false;
|
|
} );
|
|
}
|
|
}
|
|
} );
|
|
</script>
|