Implement wikidata entity selector

The current wikidata entity selector requires WikibaseRepo to be enabled on the client wiki, which is only the case for very small installations.

We implement our custom entity selector that
* displays the item label and
* uses the description as tool-tip.

The implementation was inspired by
mw.widgets.TitleInputWidget.

Bug: T229939
Change-Id: I35d6cc317cf2984d9de6e062f79030f5c31c0811
This commit is contained in:
Moritz Schubotz (physikerwelt) 2020-11-02 13:38:51 +01:00
parent 31aa824cc9
commit ba19b3e1cd
5 changed files with 134 additions and 25 deletions

View file

@ -40,7 +40,8 @@
"MathWikibaseInfo": "src/MathWikibaseInfo.php"
},
"AutoloadNamespaces": {
"MediaWiki\\Extension\\Math\\InputCheck\\": "src/InputCheck"
"MediaWiki\\Extension\\Math\\InputCheck\\": "src/InputCheck",
"MediaWiki\\Extension\\Math\\Widget\\": "src/Widget"
},
"TestAutoloadClasses": {
"MathMLHttpRequestTester": "tests/phpunit/MathMLHttpRequestTester.php",
@ -167,10 +168,15 @@
"ext.math.scripts": {
"scripts": "ext.math.js"
},
"ext.math.wikibase.scripts": {
"scripts": "ext.math.wikibase.js",
"mw.widgets.MathWbEntitySelector": {
"scripts": "mw.widgets.MathWbEntitySelector.js",
"dependencies": [
"jquery.wikibase.entityselector"
"oojs-ui-core",
"oojs-ui-windows",
"oojs-ui-widgets",
"mw.config.values.wbRepo",
"mediawiki.ForeignApi",
"mediawiki.widgets"
]
},
"ext.math.visualEditor": {

View file

@ -1,17 +0,0 @@
( function () {
'use strict';
var serverUrl = mw.config.get( 'wgServer' ),
scriptPath = mw.config.get( 'wgScriptPath' ),
repoApiUrl = serverUrl + scriptPath + '/api.php',
contLang = mw.config.get( 'wgContentLanguage' );
// eslint-disable-next-line no-jquery/no-global-selector
$( '.mwe-math-wikibase-entityselector-input input' ).entityselector( {
url: repoApiUrl,
language: contLang,
type: 'item'
} ).on( 'entityselectorselected', function ( event, entityId ) {
this.value = entityId;
} );
}() );

View file

@ -0,0 +1,102 @@
( function () {
'use strict';
/**
* Creates an mw.widgets.MathWbEntitySelector object. This class was inspired by
* mw.widgets.TitleInputWidget.
*
* @class
* @extends OO.ui.TextInputWidget
* @mixins mw.widgets.TitleWidget
* @mixins OO.ui.mixin.LookupElement
*
* @constructor
* @param {Object} [config] Configuration options
* @cfg {mw.Api} [api] API object to use, creates a mw.ForeignApi instance if not specified
*/
mw.widgets.MathWbEntitySelector = function ( config ) {
config = config || {};
this.api = config.api;
if ( !this.api ) {
// eslint-disable-next-line vars-on-top
var repoConfig = mw.config.get( 'wbRepo' ), url = repoConfig.url + repoConfig.scriptPath + '/api.php';
this.api = new mw.ForeignApi( url );
}
OO.ui.TextInputWidget.call( this, config );
OO.ui.mixin.LookupElement.call( this, config );
this.$element.addClass( 'mw-widget-MathWbEntitySelector' );
};
OO.inheritClass( mw.widgets.MathWbEntitySelector, OO.ui.TextInputWidget );
OO.mixinClass( mw.widgets.MathWbEntitySelector, OO.ui.mixin.LookupElement );
/**
* Get the API object for wikibase requests
*
* @return {mw.Api} MediaWiki API
*/
mw.widgets.MathWbEntitySelector.prototype.getApi = function () {
return this.api;
};
/**
* Get the current value of the search query
*
* @abstract
* @return {string} Search query
*/
mw.widgets.MathWbEntitySelector.prototype.getQueryValue = function () {
return this.getValue();
};
/**
* @inheritdoc OO.ui.mixin.LookupElement
*/
mw.widgets.MathWbEntitySelector.prototype.getLookupCacheDataFromResponse = function ( response ) {
return response.search || {};
};
/**
* @inheritdoc OO.ui.mixin.LookupElement
*/
mw.widgets.MathWbEntitySelector.prototype.getLookupMenuOptionsFromData = function ( response ) {
return response.map( function ( res ) {
return new OO.ui.MenuOptionWidget( { data: res.id, label: res.label, title: res.description } );
} );
};
/**
* Get API params for a given query
*
* @param {string} query User query
* @return {Object} API params
*/
mw.widgets.MathWbEntitySelector.prototype.getApiParams = function ( query ) {
return {
action: 'wbsearchentities',
search: query,
format: 'json',
errorformat: 'plaintext',
language: mw.config.get( 'wgContentLanguage' ),
uselang: mw.config.get( 'wgContentLanguage' )
};
};
/**
* @inheritdoc
*/
mw.widgets.MathWbEntitySelector.prototype.getLookupRequest = function () {
var req,
api = this.getApi(),
query = this.getQueryValue(),
widget = this,
promiseAbortObject = {
abort: function () {
// Do nothing. This is just so OOUI doesn't break due to abort being undefined.
// see also mw.widgets.TitleWidget.prototype.getSuggestionsPromise
}
};
req = api.get( widget.getApiParams( query ) );
promiseAbortObject.abort = req.abort.bind( req );
return req.promise( promiseAbortObject );
};
// eslint-disable-next-line no-jquery/no-global-selector,vars-on-top
var $wbEntitySelector = $( '#wbEntitySelector' );
if ( $wbEntitySelector.length ) {
OO.ui.infuse( $wbEntitySelector );
}
}() );

View file

@ -1,5 +1,6 @@
<?php
use MediaWiki\Extension\Math\Widget\WikibaseEntitySelector;
use MediaWiki\Logger\LoggerFactory;
class SpecialMathWikibase extends SpecialPage {
@ -53,7 +54,7 @@ class SpecialMathWikibase extends SpecialPage {
$output->enableOOUI();
$this->setHeaders();
$output->addModules( [ 'ext.math.wikibase.scripts' ] );
$output->addModules( [ 'mw.widgets.MathWbEntitySelector' ] );
$output->setPageTitle(
$this->getPlainText( 'math-wikibase-header' )
@ -82,12 +83,12 @@ class SpecialMathWikibase extends SpecialPage {
*/
private function showForm() {
$actionField = new \OOUI\ActionFieldLayout(
new \OOUI\TextInputWidget( [
new WikibaseEntitySelector( [
'name' => self::PARAMETER,
'placeholder' => $this->getPlainText( 'math-wikibase-special-form-placeholder' ),
'required' => true,
'autocomplete' => false,
'classes' => [ 'mwe-math-wikibase-entityselector-input' ]
'infusable' => true,
'id' => 'wbEntitySelector'
] ),
new OOUI\ButtonInputWidget( [
'name' => 'request-qid',

View file

@ -0,0 +1,17 @@
<?php
namespace MediaWiki\Extension\Math\Widget;
use OOUI\SearchInputWidget;
class WikibaseEntitySelector extends SearchInputWidget {
public function __construct( array $config = [] ) {
parent::__construct( $config );
$this->addClasses( [ 'mw-math-widget-wb-entity-selector' ] );
}
protected function getJavaScriptClassName() {
return 'mw.widgets.MathWbEntitySelector';
}
}