MarkAHershberger has uploaded a new change for review.

  https://gerrit.wikimedia.org/r/210831

Change subject: WIP Show recent uploads in MWMediaSearchWidget
......................................................................

WIP Show recent uploads in MWMediaSearchWidget

Initially show the user's recent uploads.  Using the search makes them
in-accessible.  This should really be done with a toggle.

A kind of, sort of update of I79d283318585fb677423e607e0851157459b1108
Bug: 60398

Change-Id: I0a1a88933efa9003a75373c61f194f56bb083219
---
M VisualEditor.php
M extension.json
M modules/ve-mw/dm/models/ve.dm.MWMediaResourceProvider.js
M modules/ve-mw/dm/models/ve.dm.MWMediaResourceQueue.js
A modules/ve-mw/dm/models/ve.dm.MWRecentUploadsProvider.js
M modules/ve-mw/i18n/en.json
M modules/ve-mw/i18n/qqq.json
M modules/ve-mw/ui/widgets/ve.ui.MWMediaSearchWidget.js
8 files changed, 368 insertions(+), 35 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/VisualEditor 
refs/changes/31/210831/1

diff --git a/VisualEditor.php b/VisualEditor.php
index efd4a3b..01f3e96 100644
--- a/VisualEditor.php
+++ b/VisualEditor.php
@@ -1037,6 +1037,7 @@
                'scripts' => array(
                        'modules/ve-mw/dm/models/ve.dm.MWImageModel.js',
                        
'modules/ve-mw/dm/models/ve.dm.MWMediaResourceProvider.js',
+                       
'modules/ve-mw/dm/models/ve.dm.MWRecentUploadsProvider.js',
                        'modules/ve-mw/dm/models/ve.dm.MWMediaResourceQueue.js',
 
                        'modules/ve-mw/ui/widgets/ve.ui.MWMediaSearchWidget.js',
diff --git a/extension.json b/extension.json
index 7b9623e..3180458 100644
--- a/extension.json
+++ b/extension.json
@@ -1070,6 +1070,7 @@
                        "scripts": [
                                "modules/ve-mw/dm/models/ve.dm.MWImageModel.js",
                                
"modules/ve-mw/dm/models/ve.dm.MWMediaResourceProvider.js",
+                               
"modules/ve-mw/dm/models/ve.dm.MWRecentUploadsProvider.js",
                                
"modules/ve-mw/dm/models/ve.dm.MWMediaResourceQueue.js",
                                
"modules/ve-mw/ui/widgets/ve.ui.MWMediaSearchWidget.js",
                                
"modules/ve-mw/ui/widgets/ve.ui.MWMediaResultWidget.js",
diff --git a/modules/ve-mw/dm/models/ve.dm.MWMediaResourceProvider.js 
b/modules/ve-mw/dm/models/ve.dm.MWMediaResourceProvider.js
index bef33e3..a40067a 100644
--- a/modules/ve-mw/dm/models/ve.dm.MWMediaResourceProvider.js
+++ b/modules/ve-mw/dm/models/ve.dm.MWMediaResourceProvider.js
@@ -98,7 +98,7 @@
                provider = this;
 
        return this.loadSiteInfo()
-               .then( function () {
+       .then( function () {
                        if ( aborted ) {
                                return $.Deferred().reject();
                        }
@@ -106,7 +106,7 @@
                        return xhr;
                } )
                .then(
-                       function ( results ) {
+                   function ( results ) {
                                if ( !results || results.length === 0 ) {
                                        provider.toggleDepleted( true );
                                        return [];
diff --git a/modules/ve-mw/dm/models/ve.dm.MWMediaResourceQueue.js 
b/modules/ve-mw/dm/models/ve.dm.MWMediaResourceQueue.js
index 7c073ff..4bfe282 100644
--- a/modules/ve-mw/dm/models/ve.dm.MWMediaResourceQueue.js
+++ b/modules/ve-mw/dm/models/ve.dm.MWMediaResourceQueue.js
@@ -17,12 +17,12 @@
  *  search call to the API.
  */
 ve.dm.MWMediaResourceQueue = function VeDmMWMediaResourceQueue( config ) {
-       config = config || {};
+    config = config || {};
 
-       // Parent constructor
-       ve.dm.MWMediaResourceQueue.super.call( this, config );
-       this.searchQuery = '';
-       this.maxHeight = config.maxHeight || 200;
+    // Parent constructor
+    ve.dm.MWMediaResourceQueue.super.call( this, config );
+    this.searchQuery = '';
+    this.maxHeight = config.maxHeight || 200;
 };
 
 /* Inheritance */
@@ -35,36 +35,57 @@
  * @return {jQuery.Promise} Promise that resolves when the resources are set up
  */
 ve.dm.MWMediaResourceQueue.prototype.setup = function () {
-       var i, len,
-               queue = this;
+    var i, len,
+       queue = this;
 
-       return this.getFileRepos().then( function ( sources ) {
-               if ( queue.providers.length === 0 ) {
-                       // Set up the providers
-                       for ( i = 0, len = sources.length; i < len; i++ ) {
-                               queue.providers.push( new 
ve.dm.MWMediaResourceProvider(
-                                       sources[i].apiurl,
-                                       {
-                                               name: sources[i].name,
-                                               local: sources[i].local,
-                                               scriptDirUrl: 
sources[i].scriptDirUrl,
-                                               userParams: {
-                                                       gsrsearch: 
queue.getSearchQuery()
-                                               },
-                                               staticParams: {
-                                                       action: 'query',
-                                                       iiurlheight: 
queue.getMaxHeight(),
-                                                       generator: 'search',
-                                                       gsrnamespace: 6,
-                                                       continue: '',
-                                                       iiprop: 
'dimensions|url|mediatype|extmetadata|timestamp',
-                                                       prop: 'imageinfo'
-                                               }
-                                       } )
-                               );
+    return this.getFileRepos().then( function ( sources ) {
+       if ( queue.providers.length === 0 ) {
+           // Set up the providers
+           for ( i = 0, len = sources.length; i < len; i++ ) {
+               if ( !mw.user.isAnon() ) {
+                   // This appears to result in a second call to 
MWMRP.loadSiteInfo()
+                   queue.providers.push( new ve.dm.MWRecentUploadsProvider(
+                       sources[i].apiurl,
+                       {
+                           name: sources[i].name,
+                           local: sources[i].local,
+                           scriptDirUrl: sources[i].scriptDirUrl,
+                           userParams: {
+                               grcuser: mw.user.getName()
+                           },
+                           staticParams: {
+                               action: 'query',
+                               generator: 'recentchanges',
+                               grcnamespace: 6,
+                               continue: '',
+                               prop: 'imageinfo'
+                           }
                        }
+                   ) );
                }
-       } );
+                   queue.providers.push( new ve.dm.MWMediaResourceProvider(
+                       sources[i].apiurl,
+                       {
+                           name: sources[i].name,
+                           local: sources[i].local,
+                           scriptDirUrl: sources[i].scriptDirUrl,
+                           userParams: {
+                               gsrsearch: queue.getSearchQuery()
+                           },
+                           staticParams: {
+                               action: 'query',
+                               iiurlheight: queue.getMaxHeight(),
+                               generator: 'search',
+                               gsrnamespace: 6,
+                               continue: '',
+                               iiprop: 
'dimensions|url|mediatype|extmetadata|timestamp',
+                               prop: 'imageinfo'
+                           }
+                       } )
+                                       );
+           }
+       }
+    } );
 };
 
 /**
diff --git a/modules/ve-mw/dm/models/ve.dm.MWRecentUploadsProvider.js 
b/modules/ve-mw/dm/models/ve.dm.MWRecentUploadsProvider.js
new file mode 100644
index 0000000..dcb343e
--- /dev/null
+++ b/modules/ve-mw/dm/models/ve.dm.MWRecentUploadsProvider.js
@@ -0,0 +1,306 @@
+/*!
+ * VisualEditor DataModel MWRecentUploadsProvider class.
+ *
+ * @copyright 2011-2015 VisualEditor Team and others; see AUTHORS.txt
+ * @license The MIT License (MIT); see LICENSE.txt
+ */
+
+/**
+ * MediaWiki media resource provider.
+ *
+ * @class
+ * @extends ve.dm.APIResultsProvider
+ *
+ * @constructor
+ * @param {string} apiurl The API url
+ * @param {Object} [config] Configuration options
+ * @cfg {string} [scriptDirUrl] The url of the API script
+ */
+ve.dm.MWRecentUploadsProvider = function VeDmMWRecentUploadsProvider( apiurl, 
config ) {
+       config = config || {};
+
+       // Parent constructor
+       ve.dm.MWRecentUploadsProvider.super.call( this, apiurl, config );
+
+       // Fetching configuration
+       this.scriptDirUrl = config.scriptDirUrl;
+       this.isLocal = config.local;
+
+       if ( config.local ) {
+               this.setAjaxSettings( {
+                       url: mw.util.wikiScript( 'api' ),
+                       // If the url is local use json
+                       dataType: 'json'
+               } );
+       } else {
+               this.setAjaxSettings( {
+                       // If 'apiurl' is set, use that. Otherwise, build the 
url
+                       // from scriptDirUrl and /api.php suffix
+                       url: this.getAPIurl() || ( this.scriptDirUrl + 
'/api.php' ),
+                       // If the url is not the same origin use jsonp
+                       dataType: 'jsonp',
+                       // JSON-P requests are not cached by default and get a 
&_=random trail.
+                       // While setting cache=true will still bypass cache in 
most case due to the
+                       // callback parameter, at least drop the &_=random 
trail which triggers
+                       // an API warning (invalid parameter).
+                       cache: true
+               } );
+       }
+       this.siteInfoPromise = null;
+       this.thumbSizes = [];
+       this.imageSizes = [];
+};
+
+/* Inheritance */
+OO.inheritClass( ve.dm.MWRecentUploadsProvider, ve.dm.APIResultsProvider );
+
+/* Methods */
+
+/**
+ * Initialize the source and get the site info.
+ *
+ * Connect to the api url and retrieve the siteinfo parameters
+ * that are required for fetching results.
+ *
+ * @return {jQuery.Promise} Promise that resolves when the class
+ * properties are set.
+ */
+ve.dm.MWRecentUploadsProvider.prototype.loadSiteInfo = function () {
+       var provider = this;
+
+       if ( !this.siteInfoPromise ) {
+               this.siteInfoPromise = new mw.Api().get( {
+                       action: 'query',
+                       meta: 'siteinfo'
+               } )
+                       .then( function ( data ) {
+                               provider.setImageSizes( 
data.query.general.imagelimits || [] );
+                               provider.setThumbSizes( 
data.query.general.thumblimits || [] );
+                               provider.setUserParams( {
+                                       // Standard width per resource
+                                       iiurlwidth: provider.getStandardWidth()
+                               } );
+                       } );
+       }
+       return this.siteInfoPromise;
+};
+
+/**
+ * Override parent method and get results from the source
+ *
+ * @param {number} [howMany] The number of items to pull from the API
+ * @returns {jQuery.Promise} Promise that is resolved into an array
+ * of available results, or is rejected if no results are available.
+ */
+ve.dm.MWRecentUploadsProvider.prototype.getResults = function ( howMany ) {
+       var xhr,
+               aborted = false,
+               provider = this;
+
+       return this.loadSiteInfo()
+       .then( function () {
+            console.log("loadSiteInfo");
+                       if ( aborted ) {
+            console.log("loadSiteInfo reject");
+                               return $.Deferred().reject();
+                       }
+            console.log("fetching " + howMany + " api results");
+                       xhr = provider.fetchAPIresults( howMany );
+                       return xhr;
+               } )
+               .then(
+                   function ( results ) {
+                               if ( !results || results.length === 0 ) {
+                                       provider.toggleDepleted( true );
+                                       return [];
+                               }
+                               return results;
+                       },
+                       // Process failed, return an empty promise
+                       function () {
+                               provider.toggleDepleted( true );
+                               return $.Deferred().resolve( [] );
+                       }
+               )
+               .promise( { abort: function () {
+                       aborted = true;
+                       if ( xhr ) {
+                               xhr.abort();
+                       }
+               } } );
+};
+
+/**
+ * Call the API for search results.
+ *
+ * @param {number} howMany The number of results to retrieve
+ * @return {jQuery.Promise} Promise that resolves with an array of objects 
that contain
+ *  the fetched data.
+ */
+ve.dm.MWRecentUploadsProvider.prototype.fetchAPIresults = function ( howMany ) 
{
+    console.log( "fetching..." );
+       var xhr,
+               ajaxOptions = {},
+               provider = this,
+               apiCallConfig = $.extend(
+                       {},
+                       this.getUserParams(),
+                       {
+                           grcstart: this.getOffset(),
+                            iiprop: 'size|url|extmetadata'
+//                             iiextmetadatalanguage: provider.getLang()
+                       } );
+
+       // Number of images
+       apiCallConfig.grclimit = howMany || this.getDefaultFetchLimit();
+
+       if ( !this.isValid() ) {
+    console.log( "aborting, not valid" );
+               return $.Deferred().reject().promise( { abort: $.noop } );
+       }
+
+       ajaxOptions = this.getAjaxSettings();
+
+    console.log( "Actually getting." );
+       xhr = new mw.Api().get( $.extend( this.getStaticParams(), apiCallConfig 
), ajaxOptions );
+       return xhr
+               .then( function ( data ) {
+                       var page, newObj, raw,
+                               results = [];
+
+                       if ( data.error ) {
+                               provider.toggleDepleted( true );
+                               return [];
+                       }
+
+                    // Do we ever want to continue? probably not.
+                   if ( data[ 'continue' ][ 'continue'] !== "||") {
+                        console.debug(data['continue']);
+                               // Update the offset for next time
+                               provider.setOffset( data[ 'continue' ].grcstart 
);
+                       } else {
+                               // This is the last available set of results. 
Mark as depleted!
+                               provider.toggleDepleted( true );
+                       }
+
+                       // If the source returned no results, it will not have a
+                       // query property
+                   if ( data.query ) {
+                               raw = data.query.pages;
+                               if ( raw ) {
+                                       // Strip away the page ids
+                                       for ( page in raw ) {
+                                            console.debug("yah!");
+                                            console.debug(raw[page]);
+                                            console.debug(raw[page]);
+                                               newObj = raw[page].imageinfo[0];
+                                               newObj.title = raw[page].title;
+                                               results.push( newObj );
+                                       }
+                               }
+                       }
+                       return results;
+               } )
+               .promise( { abort: xhr.abort } );
+};
+
+/**
+ * Set name
+ *
+ * @param {string} name
+ */
+ve.dm.MWRecentUploadsProvider.prototype.setName = function ( name ) {
+       this.name = name;
+};
+
+/**
+ * Get name
+ *
+ * @returns {string} name
+ */
+ve.dm.MWRecentUploadsProvider.prototype.getName = function () {
+       return this.name;
+};
+
+/**
+ * Get standard width, based on the provider source's thumb sizes.
+ *
+ * @return {number|undefined} fetchWidth
+ */
+ve.dm.MWRecentUploadsProvider.prototype.getStandardWidth = function () {
+       return ( this.thumbSizes && this.thumbSizes[ this.thumbSizes.length - 1 
] ) ||
+               ( this.imageSizes && this.imageSizes[ 0 ] ) ||
+               // Fall back on a number
+               300;
+};
+
+/**
+ * Get prop
+ *
+ * @return {string} prop
+ */
+ve.dm.MWRecentUploadsProvider.prototype.getFetchProp = function () {
+       return this.fetchProp;
+};
+
+/**
+ * Set prop
+ *
+ * @param {string} prop
+ */
+ve.dm.MWRecentUploadsProvider.prototype.setFetchProp = function ( prop ) {
+       this.fetchProp = prop;
+};
+
+/**
+ * Set thumb sizes
+ *
+ * @param {number[]} sizes Available thumbnail sizes
+ */
+ve.dm.MWRecentUploadsProvider.prototype.setThumbSizes = function ( sizes ) {
+       this.thumbSizes = sizes;
+};
+
+/**
+ * Set image sizes
+ *
+ * @param {number[]} sizes Available image sizes
+ */
+ve.dm.MWRecentUploadsProvider.prototype.setImageSizes = function ( sizes ) {
+       this.imageSizes = sizes;
+};
+
+/**
+ * Get thumb sizes
+ *
+ * @returns {number[]} sizes Available thumbnail sizes
+ */
+ve.dm.MWRecentUploadsProvider.prototype.getThumbSizes = function () {
+       return this.thumbSizes;
+};
+
+/**
+ * Get image sizes
+ *
+ * @returns {number[]} sizes Available image sizes
+ */
+ve.dm.MWRecentUploadsProvider.prototype.getImageSizes = function () {
+       return this.imageSizes;
+};
+
+/**
+ * Check if this source is valid and ready for search.
+ * @return {boolean} Source is valid
+ */
+ve.dm.MWRecentUploadsProvider.prototype.isValid = function () {
+    var params = this.getUserParams();
+    console.log("Valid?");
+       return params.grcuser &&
+               (
+                       this.isLocal ||
+                       // If we don't have either 'apiurl' or 'scriptDirUrl'
+                       // the source is invalid, and we will skip it
+                       this.apiurl !== undefined ||
+                       this.scriptDirUrl !== undefined
+               );
+};
diff --git a/modules/ve-mw/i18n/en.json b/modules/ve-mw/i18n/en.json
index 6a60d38..1b37118 100644
--- a/modules/ve-mw/i18n/en.json
+++ b/modules/ve-mw/i18n/en.json
@@ -250,6 +250,7 @@
        "visualeditor-loadwarning-token": "Error loading edit token from 
server: $1. Would you like to retry?",
        "visualeditor-mainnamespacepagelink": "Project:Main namespace",
        "visualeditor-media-input-placeholder": "Search for media",
+       "visualeditor-media-input-recent-uploads": "Your recent uploads",
        "visualeditor-meta-tool": "Options",
        "visualeditor-mweditmodesource-title": "Switch to source editing?",
        "visualeditor-mweditmodesource-tool": "Switch to source editing",
diff --git a/modules/ve-mw/i18n/qqq.json b/modules/ve-mw/i18n/qqq.json
index 96001a6..2604c52 100644
--- a/modules/ve-mw/i18n/qqq.json
+++ b/modules/ve-mw/i18n/qqq.json
@@ -259,6 +259,7 @@
        "visualeditor-loadwarning-token": "Text (JavaScript confirm()) shown 
when the editor fails to load properly.\n\nParameters:\n* $1 - the error 
message from the server.",
        "visualeditor-mainnamespacepagelink": "Name of a page describing the 
main namespace (NS0) in this project.\n{{doc-important|Do not translate 
\"Project\"; it is automatically converted to the wiki's project namespace.}}",
        "visualeditor-media-input-placeholder": "Place holder text for media 
search input",
+       "visualeditor-media-input-recent-uploads": "Heading for section showing 
a user's recent uploads",
        "visualeditor-meta-tool": "Text of tool in the toolbar the lets users 
set categories, language links and other page settings.\n{{Identical|Options}}",
        "visualeditor-mweditmodesource-title": "Title of dialog to confirm 
switching to source mode.",
        "visualeditor-mweditmodesource-tool": "Label for tool that changes edit 
mode to source editing.",
diff --git a/modules/ve-mw/ui/widgets/ve.ui.MWMediaSearchWidget.js 
b/modules/ve-mw/ui/widgets/ve.ui.MWMediaSearchWidget.js
index d497a7c..f2a135c 100644
--- a/modules/ve-mw/ui/widgets/ve.ui.MWMediaSearchWidget.js
+++ b/modules/ve-mw/ui/widgets/ve.ui.MWMediaSearchWidget.js
@@ -128,7 +128,9 @@
        var search = this,
                value = this.query.getValue();
 
-       if ( value === '' ) {
+       // It would be nice to be able to use something from the
+       // ResourceQueue object here.
+       if ( value === '' && mw.user.isAnon() ) {
                return;
        }
 

-- 
To view, visit https://gerrit.wikimedia.org/r/210831
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I0a1a88933efa9003a75373c61f194f56bb083219
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/VisualEditor
Gerrit-Branch: master
Gerrit-Owner: MarkAHershberger <m...@nichework.com>

_______________________________________________
MediaWiki-commits mailing list
MediaWiki-commits@lists.wikimedia.org
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to