Jforrester has uploaded a new change for review.
https://gerrit.wikimedia.org/r/247886
Change subject: mw.ForeignStructuredUpload: Provide category suggestions from
the right wiki
......................................................................
mw.ForeignStructuredUpload: Provide category suggestions from the right wiki
Also check for category existence on the right wiki, and generate
links pointing to the right wiki. Usually.
Bug: T116075
Change-Id: I85da301db4cb407b011277b0c00eb09a8bf3829f
(cherry picked from commit 86dedeea7f7cae5452acf5162672f34c32b593fd)
---
M resources/Resources.php
M resources/src/mediawiki.widgets/mw.widgets.CategoryCapsuleItemWidget.js
M resources/src/mediawiki.widgets/mw.widgets.CategorySelector.js
M resources/src/mediawiki/mediawiki.ForeignStructuredUpload.BookletLayout.js
4 files changed, 112 insertions(+), 41 deletions(-)
git pull ssh://gerrit.wikimedia.org:29418/mediawiki/core
refs/changes/86/247886/1
diff --git a/resources/Resources.php b/resources/Resources.php
index 0ec4b6b..ade5270 100644
--- a/resources/Resources.php
+++ b/resources/Resources.php
@@ -2037,6 +2037,8 @@
'dependencies' => array(
'oojs-ui',
'mediawiki.api',
+ 'mediawiki.ForeignApi',
+ 'mediawiki.Title',
),
'targets' => array( 'desktop', 'mobile' ),
),
diff --git
a/resources/src/mediawiki.widgets/mw.widgets.CategoryCapsuleItemWidget.js
b/resources/src/mediawiki.widgets/mw.widgets.CategoryCapsuleItemWidget.js
index f1c4f6f..24b0e72 100644
--- a/resources/src/mediawiki.widgets/mw.widgets.CategoryCapsuleItemWidget.js
+++ b/resources/src/mediawiki.widgets/mw.widgets.CategoryCapsuleItemWidget.js
@@ -7,42 +7,45 @@
( function ( $, mw ) {
/**
- * @class mw.widgets.CategoryCapsuleItemWidget
+ * @class mw.widgets.PageExistenceCache
+ * @private
+ * @param {mw.Api} [api]
*/
-
- var processExistenceCheckQueueDebounced,
- api = new mw.Api(),
- currentRequest = null,
- existenceCache = {},
- existenceCheckQueue = {};
-
- // The existence checking code really could be refactored into a
separate class.
+ function PageExistenceCache( api ) {
+ this.api = api || new mw.Api();
+ this.processExistenceCheckQueueDebounced = OO.ui.debounce(
this.processExistenceCheckQueue );
+ this.currentRequest = null;
+ this.existenceCache = {};
+ this.existenceCheckQueue = {};
+ }
/**
+ * Check for existence of pages in the queue.
+ *
* @private
*/
- function processExistenceCheckQueue() {
+ PageExistenceCache.prototype.processExistenceCheckQueue = function () {
var queue, titles;
- if ( currentRequest ) {
+ if ( this.currentRequest ) {
// Don't fire off a million requests at the same time
- currentRequest.always( function () {
- currentRequest = null;
- processExistenceCheckQueueDebounced();
- } );
+ this.currentRequest.always( function () {
+ this.currentRequest = null;
+ this.processExistenceCheckQueueDebounced();
+ }.bind( this ) );
return;
}
- queue = existenceCheckQueue;
- existenceCheckQueue = {};
+ queue = this.existenceCheckQueue;
+ this.existenceCheckQueue = {};
titles = Object.keys( queue ).filter( function ( title ) {
- if ( existenceCache.hasOwnProperty( title ) ) {
- queue[ title ].resolve( existenceCache[ title ]
);
+ if ( this.existenceCache.hasOwnProperty( title ) ) {
+ queue[ title ].resolve( this.existenceCache[
title ] );
}
- return !existenceCache.hasOwnProperty( title );
- } );
+ return !this.existenceCache.hasOwnProperty( title );
+ }.bind( this ) );
if ( !titles.length ) {
return;
}
- currentRequest = api.get( {
+ this.currentRequest = this.api.get( {
action: 'query',
prop: [ 'info' ],
titles: titles
@@ -50,14 +53,12 @@
var index, curr, title;
for ( index in response.query.pages ) {
curr = response.query.pages[ index ];
- title = mw.Title.newFromText( curr.title
).getPrefixedText();
- existenceCache[ title ] = curr.missing ===
undefined;
- queue[ title ].resolve( existenceCache[ title ]
);
+ title = new ForeignTitle( curr.title
).getPrefixedText();
+ this.existenceCache[ title ] = curr.missing ===
undefined;
+ queue[ title ].resolve( this.existenceCache[
title ] );
}
- } );
- }
-
- processExistenceCheckQueueDebounced = OO.ui.debounce(
processExistenceCheckQueue );
+ }.bind( this ) );
+ };
/**
* Register a request to check whether a page exists.
@@ -66,16 +67,35 @@
* @param {mw.Title} title
* @return {jQuery.Promise} Promise resolved with true if the page
exists or false otherwise
*/
- function checkPageExistence( title ) {
+ PageExistenceCache.prototype.checkPageExistence = function ( title ) {
var key = title.getPrefixedText();
- if ( !existenceCheckQueue[ key ] ) {
- existenceCheckQueue[ key ] = $.Deferred();
+ if ( !this.existenceCheckQueue[ key ] ) {
+ this.existenceCheckQueue[ key ] = $.Deferred();
}
- processExistenceCheckQueueDebounced();
- return existenceCheckQueue[ key ].promise();
- }
+ this.processExistenceCheckQueueDebounced();
+ return this.existenceCheckQueue[ key ].promise();
+ };
/**
+ * @class mw.widgets.ForeignTitle
+ * @private
+ * @extends mw.Title
+ *
+ * @constructor
+ * @inheritdoc
+ */
+ function ForeignTitle() {
+ ForeignTitle.parent.apply( this, arguments );
+ }
+ OO.inheritClass( ForeignTitle, mw.Title );
+ ForeignTitle.prototype.getNamespacePrefix = function () {
+ // We only need to handle categories here...
+ return 'Category:'; // HACK
+ };
+
+ /**
+ * @class mw.widgets.CategoryCapsuleItemWidget
+ *
* Category selector capsule item widget. Extends
OO.ui.CapsuleItemWidget with the ability to link
* to the given page, and to show its existence status (i.e., whether
it is a redlink).
*
@@ -85,6 +105,7 @@
* @constructor
* @param {Object} config Configuration options
* @cfg {mw.Title} title Page title to use (required)
+ * @cfg {string} [apiUrl] API URL, if not the current wiki's API
*/
mw.widgets.CategoryCapsuleItemWidget = function
MWWCategoryCapsuleItemWidget( config ) {
// Parent constructor
@@ -95,6 +116,7 @@
// Properties
this.title = config.title;
+ this.apiUrl = config.apiUrl || '';
this.$link = $( '<a>' )
.text( this.label )
.attr( 'target', '_blank' )
@@ -107,14 +129,38 @@
this.setMissing( false );
this.$label.replaceWith( this.$link );
this.setLabelElement( this.$link );
- checkPageExistence( this.title ).done( function ( exists ) {
- this.setMissing( !exists );
- }.bind( this ) );
+
+ /*jshint -W024*/
+ if ( !this.constructor.static.pageExistenceCaches[ this.apiUrl
] ) {
+ this.constructor.static.pageExistenceCaches[
this.apiUrl ] =
+ new PageExistenceCache( new mw.ForeignApi(
this.apiUrl ) );
+ }
+ this.constructor.static.pageExistenceCaches[ this.apiUrl ]
+ .checkPageExistence( new ForeignTitle(
this.title.getPrefixedText() ) )
+ .done( function ( exists ) {
+ this.setMissing( !exists );
+ }.bind( this ) );
+ /*jshint +W024*/
};
/* Setup */
OO.inheritClass( mw.widgets.CategoryCapsuleItemWidget,
OO.ui.CapsuleItemWidget );
+
+ /* Static Properties */
+
+ /*jshint -W024*/
+ /**
+ * Map of API URLs to PageExistenceCache objects.
+ *
+ * @static
+ * @inheritable
+ * @property {Object}
+ */
+ mw.widgets.CategoryCapsuleItemWidget.static.pageExistenceCaches = {
+ '': new PageExistenceCache()
+ };
+ /*jshint +W024*/
/* Methods */
@@ -125,13 +171,17 @@
* @param {boolean} missing Whether the page is missing (does not exist)
*/
mw.widgets.CategoryCapsuleItemWidget.prototype.setMissing = function (
missing ) {
+ var
+ title = new ForeignTitle( this.title.getPrefixedText()
), // HACK
+ prefix = this.apiUrl.replace( '/w/api.php', '' ); //
HACK
+
if ( !missing ) {
this.$link
- .attr( 'href', this.title.getUrl() )
+ .attr( 'href', prefix + title.getUrl() )
.removeClass( 'new' );
} else {
this.$link
- .attr( 'href', this.title.getUrl( { action:
'edit', redlink: 1 } ) )
+ .attr( 'href', prefix + title.getUrl( { action:
'edit', redlink: 1 } ) )
.addClass( 'new' );
}
};
diff --git a/resources/src/mediawiki.widgets/mw.widgets.CategorySelector.js
b/resources/src/mediawiki.widgets/mw.widgets.CategorySelector.js
index 89fcc0b..59f1d50 100644
--- a/resources/src/mediawiki.widgets/mw.widgets.CategorySelector.js
+++ b/resources/src/mediawiki.widgets/mw.widgets.CategorySelector.js
@@ -30,6 +30,7 @@
*
* @constructor
* @param {Object} [config] Configuration options
+ * @cfg {mw.Api} [api] Instance of mw.Api (or subclass thereof) to use
for queries
* @cfg {number} [limit=10] Maximum number of results to load
* @cfg {mw.widgets.CategorySelector.SearchType[]}
[searchTypes=[mw.widgets.CategorySelector.SearchType.OpenSearch]]
* Default search API to use when searching.
@@ -61,7 +62,7 @@
this.$input.on( 'change input cut paste', OO.ui.debounce(
this.updateMenuItems.bind( this ), 100 ) );
// Initialize
- this.api = new mw.Api();
+ this.api = config.api || new mw.Api();
}
/* Setup */
@@ -178,6 +179,7 @@
*/
CSP.createItemWidget = function ( data ) {
return new mw.widgets.CategoryCapsuleItemWidget( {
+ apiUrl: this.api.apiUrl || undefined,
title: mw.Title.newFromText( data, NS_CATEGORY )
} );
};
diff --git
a/resources/src/mediawiki/mediawiki.ForeignStructuredUpload.BookletLayout.js
b/resources/src/mediawiki/mediawiki.ForeignStructuredUpload.BookletLayout.js
index c8877fd..0cee580 100644
--- a/resources/src/mediawiki/mediawiki.ForeignStructuredUpload.BookletLayout.js
+++ b/resources/src/mediawiki/mediawiki.ForeignStructuredUpload.BookletLayout.js
@@ -36,6 +36,21 @@
/* Uploading */
/**
+ * @inheritdoc
+ */
+ mw.ForeignStructuredUpload.BookletLayout.prototype.initialize =
function () {
+
mw.ForeignStructuredUpload.BookletLayout.parent.prototype.initialize.call( this
);
+ // Point the CategorySelector to the right wiki as soon as we
know what the right wiki is
+ this.upload.apiPromise.done( function ( api ) {
+ // If this is a ForeignApi, it will have a apiUrl,
otherwise we don't need to do anything
+ if ( api.apiUrl ) {
+ // Can't reuse the same object,
CategorySelector calls #abort on its mw.Api instance
+ this.categoriesWidget.api = new mw.ForeignApi(
api.apiUrl );
+ }
+ }.bind( this ) );
+ };
+
+ /**
* Returns a {@link mw.ForeignStructuredUpload
mw.ForeignStructuredUpload}
* with the {@link #cfg-target target} specified in config.
*
@@ -150,6 +165,8 @@
mustBeBefore: moment().add( 1, 'day' ).locale( 'en'
).format( 'YYYY-MM-DD' ) // Tomorrow
} );
this.categoriesWidget = new mw.widgets.CategorySelector( {
+ // Can't be done here because we don't know the target
wiki yet... done in #initialize.
+ // api: new mw.ForeignApi( ... ),
$overlay: this.$overlay
} );
--
To view, visit https://gerrit.wikimedia.org/r/247886
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I85da301db4cb407b011277b0c00eb09a8bf3829f
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/core
Gerrit-Branch: wmf/1.27.0-wmf.3
Gerrit-Owner: Jforrester <[email protected]>
Gerrit-Reviewer: Bartosz DziewoĆski <[email protected]>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits