jenkins-bot has submitted this change and it was merged.

Change subject: Remove uploads
......................................................................


Remove uploads

They are not getting the support they deserve. Given UploadWizard
is being rewritten by the new editing team it makes sense to support
efforts there instead.

Retain Special:Uploads due to link from special user profile. Only surface
it in menu if uploading is enabled.

Bug: T98874
Bug: T98402
Change-Id: I29ae18e2b8cd8e9b91d20c4f85d42c79dc70d6fd
---
M includes/MobileFrontend.hooks.php
M includes/Resources.php
M includes/skins/SkinMinerva.php
D javascripts/modules/uploads/LeadPhoto.js
D javascripts/modules/uploads/LeadPhotoUploaderButton.js
D javascripts/modules/uploads/PhotoApi.js
D javascripts/modules/uploads/PhotoUploadOverlay.js
D javascripts/modules/uploads/PhotoUploadProgress.js
D javascripts/modules/uploads/PhotoUploaderButton.js
D javascripts/modules/uploads/ProgressBar.js
D javascripts/modules/uploads/UploadTutorial.js
D javascripts/modules/uploads/init.js
D javascripts/modules/uploads/routes.js
M javascripts/specials/uploads.js
D less/modules/uploads/PhotoUploadOverlay.less
D less/modules/uploads/PhotoUploadProgress.less
D less/modules/uploads/PhotoUploaderButton.less
D less/modules/uploads/UploadTutorial.less
M less/pageactions.less
D resources/mobile.loggingSchemas/SchemaMobileWebUploads.js
M resources/mobile.startup/Page.js
M resources/skins.minerva.icons.images.legacy/icons.less
D templates/modules/uploads/LeadPhoto.hogan
D templates/modules/uploads/LeadPhotoUploaderButton.hogan
D templates/modules/uploads/PhotoUploadOverlay.hogan
D templates/modules/uploads/PhotoUploadProgress.hogan
D templates/modules/uploads/PhotoUploaderButton.hogan
D templates/modules/uploads/UploadTutorial.hogan
D templates/modules/uploads/commons-upload.hogan
D tests/browser/features/step_definitions/uploads_steps.rb
D tests/browser/features/uploads_copyvio.feature
D tests/browser/features/uploads_lead.feature
D tests/qunit/modules/uploads/test_PhotoApi.js
D tests/qunit/modules/uploads/test_ProgressBar.js
D tests/qunit/modules/uploads/test_UploadTutorial.js
D tests/qunit/modules/uploads/test_init.js
36 files changed, 2 insertions(+), 2,113 deletions(-)

Approvals:
  Florianschmidtwelzow: Looks good to me, approved
  jenkins-bot: Verified



diff --git a/includes/MobileFrontend.hooks.php 
b/includes/MobileFrontend.hooks.php
index 94d814a..c186f7a 100644
--- a/includes/MobileFrontend.hooks.php
+++ b/includes/MobileFrontend.hooks.php
@@ -965,7 +965,6 @@
 
                $scripts = array(
                        'resources/mobile.loggingSchemas/SchemaMobileWeb.js',
-                       
'resources/mobile.loggingSchemas/SchemaMobileWebUploads.js',
                        
'resources/mobile.loggingSchemas/SchemaMobileWebClickTracking.js',
                        
'resources/mobile.loggingSchemas/SchemaMobileWebEditing.js',
                        
'resources/mobile.loggingSchemas/SchemaMobileWebWatching.js',
diff --git a/includes/Resources.php b/includes/Resources.php
index 76b59ad..06a3e0f 100644
--- a/includes/Resources.php
+++ b/includes/Resources.php
@@ -473,19 +473,6 @@
                ),
        ),
 
-       'mobile.leadPhotoUploader' => $wgMFResourceFileModuleBoilerplate + 
array(
-               'dependencies' => array(
-                       'mobile.startup',
-                       'mobile.user',
-                       'mobile.upload.ui',
-               ),
-               'scripts' => array(
-                       'javascripts/modules/uploads/init.js',
-               ),
-               // This is a logged in user feature only.
-               'group' => 'user',
-       ),
-
        'mobile.editor' => $wgMFResourceParsedMessageModuleBoilerplate + array(
                'dependencies' => array(
                        'mobile.startup',
@@ -624,71 +611,6 @@
                ),
                'messages' => array(
                        'mobile-frontend-editor-viewing-source-page',
-               ),
-       ),
-
-       'mobile.uploads' => $wgMFResourceParsedMessageModuleBoilerplate + array(
-               'dependencies' => array(
-                       'mobile.startup',
-                       'mobile.editor.api',
-                       'mobile.contentOverlays',
-                       'mobile.foreignApi',
-                       'mobile.microAutoSize',
-                       'mobile.loggingSchemas',
-               ),
-               'scripts' => array(
-                       'javascripts/modules/uploads/PhotoApi.js',
-                       'javascripts/modules/uploads/LeadPhoto.js',
-                       'javascripts/modules/uploads/UploadTutorial.js',
-                       'javascripts/modules/uploads/PhotoUploadProgress.js',
-                       'javascripts/modules/uploads/PhotoUploadOverlay.js',
-                       'javascripts/externals/exif-js/binaryajax.js',
-                       'javascripts/externals/exif-js/exif.js',
-               ),
-               'styles' => array(
-                       'less/modules/uploads/UploadTutorial.less',
-                       'less/modules/uploads/PhotoUploadOverlay.less',
-                       'less/modules/uploads/PhotoUploadProgress.less',
-               ),
-               'templates' => array(
-                       'LeadPhoto.hogan' => 
'templates/modules/uploads/LeadPhoto.hogan',
-                       'UploadTutorial.hogan' => 
'templates/modules/uploads/UploadTutorial.hogan',
-                       'PhotoUploadOverlay.hogan' => 
'templates/modules/uploads/PhotoUploadOverlay.hogan',
-                       'PhotoUploadProgress.hogan' => 
'templates/modules/uploads/PhotoUploadProgress.hogan',
-               ),
-               'messages' => array(
-                       'mobile-frontend-photo-upload-success-article',
-                       'mobile-frontend-photo-upload-error',
-
-                       // PhotoApi.js
-                       'mobile-frontend-photo-article-edit-comment',
-                       'mobile-frontend-photo-article-donate-comment',
-                       'mobile-frontend-photo-upload-error-filename',
-                       'mobile-frontend-photo-upload-comment',
-
-                       // UploadTutorial.js
-                       'mobile-frontend-first-upload-wizard-new-page-1-header',
-                       'mobile-frontend-first-upload-wizard-new-page-1',
-                       'mobile-frontend-first-upload-wizard-new-page-2-header',
-                       'mobile-frontend-first-upload-wizard-new-page-2',
-                       'mobile-frontend-first-upload-wizard-new-page-3-header',
-                       'mobile-frontend-first-upload-wizard-new-page-3',
-                       'mobile-frontend-first-upload-wizard-new-page-3-ok',
-
-                       // PhotoUploadOverlay.js
-                       'mobile-frontend-image-heading-describe' => array( 
'parse' ),
-                       'mobile-frontend-photo-ownership',
-                       'mobile-frontend-photo-ownership-help',
-                       'mobile-frontend-photo-caption-placeholder',
-                       'mobile-frontend-photo-submit',
-                       'mobile-frontend-photo-upload-error-file-type',
-                       'mobile-frontend-photo-licensing',
-                       'mobile-frontend-photo-licensing-with-terms',
-                       'mobile-frontend-photo-upload-copyvio',
-
-                       // PhotoUploadProgress.js
-                       'mobile-frontend-image-uploading' => array( 'parse' ),
-                       'mobile-frontend-image-cancel-confirm' => array( 
'parse' ),
                ),
        ),
 
@@ -940,33 +862,6 @@
                ),
                'styles' => array(
                        'resources/mobile.toast/toast.less',
-               ),
-       ),
-
-       'mobile.upload.ui' => $wgMFResourceFileModuleBoilerplate + array(
-               'dependencies' => array(
-                       'mobile.startup',
-                       'mobile.ajax',
-                       'mobile.overlays',
-               ),
-               'templates' => array(
-                       // FIXME: This should not be a hogan template. Use a 
txt template.
-                       'template.hogan' => 
'templates/modules/uploads/commons-upload.hogan',
-                       // PhotoUploaderButton.js
-                       'LeadButton.hogan' => 
'templates/modules/uploads/LeadPhotoUploaderButton.hogan',
-                       // @todo FIXME: this should be in special.uploads (need 
to split
-                       // code in PhotoUploaderButton.js into separate files 
too)
-                       'Button.hogan' => 
'templates/modules/uploads/PhotoUploaderButton.hogan',
-               ),
-               'scripts' => array(
-                       'javascripts/modules/uploads/ProgressBar.js',
-                       'javascripts/modules/uploads/PhotoUploaderButton.js',
-                       
'javascripts/modules/uploads/LeadPhotoUploaderButton.js',
-                       'javascripts/modules/uploads/routes.js',
-               ),
-               'messages' => array(
-                       // LeadPhotoUploaderButton.js
-                       'mobile-frontend-photo-upload',
                ),
        ),
 
@@ -1671,7 +1566,6 @@
        'mobile.special.uploads.scripts' => $wgMFResourceFileModuleBoilerplate 
+ array(
                'dependencies' => array(
                        'mobile.gallery',
-                       'mobile.upload.ui',
                ),
                'messages' => array(
                        'mobile-frontend-photo-upload-generic',
@@ -1910,9 +1804,6 @@
        'mediawiki.skinning.content.parsoid' => array(),
        'mobile.special.userprofile.styles' => array(
                'less/specials/userprofile.less',
-       ),
-       'mobile.special.uploads.styles' => array(
-               'less/modules/uploads/PhotoUploaderButton.less',
        ),
        'mobile.special.history.styles' => array(),
 );
diff --git a/includes/skins/SkinMinerva.php b/includes/skins/SkinMinerva.php
index 1c8fba5..8a16858 100644
--- a/includes/skins/SkinMinerva.php
+++ b/includes/skins/SkinMinerva.php
@@ -828,17 +828,6 @@
                        );
                }
 
-               if (
-                       $this->isAllowedPageAction( 'upload' )
-                       && !$title->isMainPage()
-                       && $this->mobileContext->userCanUpload()
-               ) {
-                       $menu['photo'] = array( 'id' => 'ca-upload', 'text' => 
'',
-                               'itemtitle' => $this->msg( 
'mobile-frontend-pageaction-upload-tooltip' ),
-                               'class' => MobileUI::iconClass( 'addimage', 
'element', 'hidden' ),
-                       );
-               }
-
                if ( $this->isAllowedPageAction( 'watch' ) ) {
                        $watchTemplate = array(
                                'id' => 'ca-watch',
@@ -939,7 +928,6 @@
                // Get variables that are only needed in mobile mode
                if ( $this->isMobileMode ) {
                        $vars['wgImagesDisabled'] = 
$this->mobileContext->imagesDisabled();
-                       $vars['wgUserCanUpload'] = 
$this->mobileContext->userCanUpload();
                }
 
                return $vars;
@@ -956,14 +944,6 @@
                $action = $req->getVal( 'article_action' );
                $campaign = $req->getVal( 'campaign' );
                $title = $this->getTitle();
-
-               if (
-                       $this->isAllowedPageAction( 'upload' )
-                       && !$title->isMainPage()
-                       && $this->mobileContext->userCanUpload()
-               ) {
-                       $modules[] = 'mobile.leadPhotoUploader';
-               }
 
                if ( $user->isLoggedIn() ) {
                        // enable the user module
@@ -986,9 +966,6 @@
                        }
                }
 
-               if ( $this->mobileContext->userCanUpload() ) {
-                       $modules[] = 'mobile.upload.ui';
-               }
                return $modules;
        }
 
diff --git a/javascripts/modules/uploads/LeadPhoto.js 
b/javascripts/modules/uploads/LeadPhoto.js
deleted file mode 100644
index 1877aef..0000000
--- a/javascripts/modules/uploads/LeadPhoto.js
+++ /dev/null
@@ -1,17 +0,0 @@
-( function ( M ) {
-
-       var LeadPhoto,
-               View = M.require( 'View' );
-
-       /**
-        * Class for showing lead photo
-        * @class LeadPhoto
-        * @extends View
-        */
-       LeadPhoto = View.extend( {
-               template: mw.template.get( 'mobile.uploads', 'LeadPhoto.hogan' )
-       } );
-
-       M.define( 'modules/uploads/LeadPhoto', LeadPhoto );
-
-}( mw.mobileFrontend ) );
diff --git a/javascripts/modules/uploads/LeadPhotoUploaderButton.js 
b/javascripts/modules/uploads/LeadPhotoUploaderButton.js
deleted file mode 100644
index aa42c9c..0000000
--- a/javascripts/modules/uploads/LeadPhotoUploaderButton.js
+++ /dev/null
@@ -1,46 +0,0 @@
-( function ( M ) {
-       var
-               PhotoUploaderButton = M.require( 
'modules/uploads/PhotoUploaderButton' ),
-               Icon = M.require( 'Icon' ),
-               uploadIcon = new Icon( {
-                       name: 'addimage-enabled',
-                       additionalClassNames: 'enabled'
-               } ),
-               LeadPhotoUploaderButton;
-
-       /**
-        * Component for uploading lead photo
-        * @class LeadPhotoUploaderButton
-        * @extends PhotoUploaderButton
-        */
-       LeadPhotoUploaderButton = PhotoUploaderButton.extend( {
-               template: mw.template.get( 'mobile.upload.ui', 
'LeadButton.hogan' ),
-               className: uploadIcon.getClassName(),
-
-               /**
-                * @cfg {Object} defaults Default options hash.
-                * @cfg {String} defaults.buttonCaption Caption that is a call 
to action to add the
-                * first image.
-                * @cfg {Boolean} defaults.insertInPage If the image should be 
prepended to the wikitext
-                * of a page specified by options.pageTitle.
-                * @cfg {String} defaults.el CSS selector of the element in 
which the
-                * LeadPhotoUploaderButton is rendered.
-                */
-               defaults: {
-                       buttonCaption: mw.msg( 'mobile-frontend-photo-upload' ),
-                       insertInPage: true,
-                       el: '#ca-upload'
-               },
-
-               /** @inheritdoc */
-               initialize: function ( options ) {
-                       options.pageTitle = mw.config.get( 'wgPageName' );
-                       PhotoUploaderButton.prototype.initialize.apply( this, 
arguments );
-               }
-       } );
-
-       LeadPhotoUploaderButton.isSupported = PhotoUploaderButton.isSupported;
-
-       M.define( 'modules/uploads/LeadPhotoUploaderButton', 
LeadPhotoUploaderButton );
-
-}( mw.mobileFrontend ) );
diff --git a/javascripts/modules/uploads/PhotoApi.js 
b/javascripts/modules/uploads/PhotoApi.js
deleted file mode 100644
index 475a1c8..0000000
--- a/javascripts/modules/uploads/PhotoApi.js
+++ /dev/null
@@ -1,305 +0,0 @@
-( function ( M, $ ) {
-       var Api, PhotoApi,
-               user = M.require( 'user' ),
-               endpoint = mw.config.get( 'wgMFPhotoUploadEndpoint' );
-
-       if ( endpoint ) {
-               Api = M.require( 'modules/ForeignApi' );
-       } else {
-               Api = M.require( 'api' ).Api;
-       }
-
-       /**
-        * Originally written by Brion for WikiLovesMonuments app, trims a 
string
-        * to a certain number of bytes
-        *
-        * @param {String} str
-        * @param {Number} allowedLength in bytes
-        * @ignore
-        */
-       function trimUtf8String( str, allowedLength ) {
-               // Count UTF-8 bytes to see where we need to crop long names.
-               var codeUnit, len, i,
-                       bytes = 0,
-                       chars = 0;
-
-               for ( i = 0; i < str.length; i++ ) {
-                       // JavaScript strings are UTF-16.
-                       codeUnit = str.charCodeAt( i );
-
-                       // https://en.wikipedia.org/wiki/UTF-8#Description
-                       if ( codeUnit < 0x80 ) {
-                               len = 1;
-                       } else if ( codeUnit < 0x800 ) {
-                               len = 2;
-                       } else if ( codeUnit >= 0xd800 && codeUnit < 0xe000 ) {
-                               // 
https://en.wikipedia.org/wiki/UTF-16#Description
-                               // Code point is one half of a surrogate pair.
-                               // This and its partner combine to form a 
single 4 byte character in UTF-8.
-                               len = 4;
-                       } else {
-                               len = 3;
-                       }
-
-                       if ( bytes + len <= allowedLength ) {
-                               bytes += len;
-                               chars++;
-                               if ( len === 4 ) {
-                                       // Skip over second half of surrogate 
pair as a unit.
-                                       chars++;
-                                       i++;
-                               }
-                       } else {
-                               // Ran out of bytes.
-                               return str.substr( 0, chars );
-                       }
-               }
-
-               // We fit!
-               return str;
-       }
-
-       /**
-        * Generates a file name from a description and a date
-        * Removes illegal characters
-        * Respects maximum file name length (240 bytes)
-        *
-        * @param {String} description Data to be preprocessed and added to 
options
-        * @param {String} fileSuffix An optional file extension e.g. '.jpg' or 
'.gif'
-        * @param {Date} date An optional date (defaults to current date)
-        * @return {String} a legal filename
-        * @ignore
-        */
-       function generateFileName( description, fileSuffix, date ) {
-               // 240 bytes maximum enforced by MediaWiki - allow 10bytes 
margin of error
-               var allowedLength = 230,
-                       name, suffix;
-
-               fileSuffix = fileSuffix || '.jpg';
-               date = date || new Date();
-               name = description.replace( 
/[\x1B\n\x7f\.\[#<>\[\]\|\{\}\/:]/g, '-' );
-               // remove double spaces (bug 62241)
-               // also trim it in case it ends with a double space
-               name = $.trim( name ).replace( /  /g, ' ' );
-               // 
https://commons.wikimedia.org/wiki/MediaWiki:Titleblacklist-custom-double-apostrophe
-               name = name.replace( /''/g, '\'_' );
-
-               /**
-                * Pad single digit numbers with leading 0.
-                * @param {Number} number
-                * @ignore
-                * @returns {Number|String} representing number with at least 2 
digits
-                */
-               function pad( number ) {
-                       return number < 10 ? '0' + number : number;
-               }
-
-               suffix = ' ' + date.getUTCFullYear() + '-' +
-                       pad( date.getUTCMonth() + 1 ) + '-' + pad( 
date.getUTCDate() ) + ' ' +
-                       pad( date.getUTCHours() ) + '-' + pad( 
date.getUTCMinutes() ) + fileSuffix;
-
-               allowedLength -= suffix.length;
-               return trimUtf8String( name, allowedLength ) + suffix;
-       }
-
-       /**
-        * API to handle photo uploads
-        *
-        * @class PhotoApi
-        * @extends Api
-        */
-       PhotoApi = Api.extend( {
-               /** @inheritdoc */
-               apiUrl: endpoint || Api.prototype.apiUrl,
-
-               /**
-                * @inheritdoc
-                * @param {Object} options
-                *     [options.editorApi] EditorApi An API instance that will 
be used
-                *     [options.page] Page to upload to
-                * for inserting images in a page.
-                */
-               initialize: function ( options ) {
-                       Api.prototype.initialize.apply( this, arguments );
-                       options = options || {};
-                       this.page = options.page;
-                       this.editorApi = options.editorApi;
-               },
-
-               /**
-                * Applies special handling for uploads which fail due to a 
lack of filename.
-                * Scans the warnings and tries to construct a suitable error 
message.
-                * FIXME: See UploadBase::checkWarnings - why these are not 
errors only the MediaWiki Gods know See Bug 48261
-                * @private
-                * @param {jQuery.Deferred} result from an upload api request.
-                * @param {Object} warnings as found in the 
data.upload.warnings.
-                *  FIXME: This is part of the result and thus is an 
unnecessary parameter.
-                */
-               _handleWarnings: function ( result, warnings ) {
-                       var humanErrorMsg,
-                               err = {
-                                       stage: 'upload',
-                                       type: 'warning'
-                               };
-
-                       warnings = $.map( warnings, function ( value, code ) {
-                               return code + '/' + value;
-                       } );
-                       err.details = warnings[0] || 'unknown';
-
-                       if ( warnings.exists ) {
-                               humanErrorMsg = mw.msg( 
'mobile-frontend-photo-upload-error-filename' );
-                       }
-
-                       return result.reject( err, humanErrorMsg );
-               },
-
-               /**
-                * Upload an image and, optionally, add it to current page (if 
PhotoApi
-                * was initialized with `editorApi`).
-                *
-                * @param {Object} options
-                *     options.file File A file object obtained from a file 
input.
-                *     options.description String Image description.
-                * @return {jQuery.Deferred} On failure callback is passed an 
object with
-                * `stage`, `type` and `details` properties. `stage` is either 
"upload"
-                * or "edit" (inserting image in a page). `type` is a string 
describing
-                * the type of error, `details` can be any object (usually a 
string
-                * containing error message).
-                */
-               save: function ( options ) {
-                       var page = this.page,
-                               // FIXME: Use page.getId()
-                               isNewPage = mw.config.get( 'wgArticleId' ) === 
0,
-                               isNewFile = page.inNamespace( 'file' ) && 
isNewPage,
-                               self = this,
-                               result = $.Deferred();
-
-                       options.editSummaryMessage = options.insertInPage ?
-                               'mobile-frontend-photo-article-edit-comment' :
-                               'mobile-frontend-photo-article-donate-comment';
-
-                       /**
-                        * Performs upload
-                        *
-                        * @ignore
-                        */
-                       function doUpload() {
-                               var
-                                       ext = options.file.name.slice( 
options.file.name.lastIndexOf( '.' ) + 1 ),
-                                       request, data;
-
-                               if ( !isNewFile ) {
-                                       options.fileName = generateFileName( 
options.description, '.' + ext );
-                               } else {
-                                       options.fileName = mw.config.get( 
'wgTitle' );
-                               }
-
-                               data = {
-                                       action: 'upload',
-                                       filename: options.fileName,
-                                       comment: mw.msg( 
options.editSummaryMessage ),
-                                       file: options.file,
-                                       text: mw.template.get( 
'mobile.upload.ui', 'template.hogan' )
-                                               .render( {
-                                                       suffix: mw.config.get( 
'wgMFPhotoUploadAppendToDesc' ),
-                                                       text: 
options.description,
-                                                       username: user.getName()
-                                               } )
-                               };
-
-                               request = self.postWithToken( 'edit', data, {
-                                       contentType: 'multipart/form-data',
-                                       cache: false
-                               } ).done( function ( data ) {
-                                       var descriptionUrl = '',
-                                               warnings = data.upload ? 
data.upload.warnings : false,
-                                               err = {
-                                                       stage: 'upload',
-                                                       type: 'error'
-                                               };
-
-                                       if ( !data || !data.upload ) {
-                                               // error uploading image
-                                               if ( data.error ) {
-                                                       if ( data.error.code ) {
-                                                               err.details = 
data.error.code;
-                                                               if ( 
data.error.details && data.error.details[0] ) {
-                                                                       
err.details += '/' + data.error.details[0];
-                                                               }
-                                                       }
-                                               }
-                                               result.reject( err );
-                                               return;
-                                       }
-
-                                       options.fileName = data.upload.filename;
-
-                                       if ( !options.fileName ) {
-                                               // FIXME: Handle this case as 
an error in handleWarnings
-                                               if ( warnings && 
warnings.duplicate ) {
-                                                       options.fileName = 
warnings.duplicate[ '0' ];
-                                               } else if ( warnings ) {
-                                                       return 
self._handleWarnings( result, warnings );
-                                               } else {
-                                                       return result.reject( {
-                                                               stage: 'upload',
-                                                               type: 'unknown',
-                                                               details: 
'missing-filename'
-                                                       } );
-                                               }
-                                       }
-
-                                       // FIXME: API doesn't return this 
information on duplicate images...
-                                       if ( data.upload.imageinfo ) {
-                                               descriptionUrl = 
data.upload.imageinfo.descriptionurl;
-                                       }
-
-                                       if ( self.editorApi && !isNewFile ) {
-                                               self.editorApi.setPrependText( 
'[[File:' + options.fileName + '|thumbnail|' + options.description + ']]\n\n' );
-                                               self.editorApi.save( {
-                                                       summary: mw.msg( 
'mobile-frontend-photo-upload-comment' )
-                                               } )
-                                                       .done( function () {
-                                                               result.resolve( 
options.fileName, descriptionUrl );
-                                                       } )
-                                                       .fail( function ( err ) 
{
-                                                               err.stage = 
'edit';
-                                                               result.reject( 
err );
-                                                       } );
-                                       } else if ( isNewFile ) {
-                                               window.location.reload();
-                                       } else {
-                                               result.resolve( 
options.fileName, descriptionUrl );
-                                       }
-
-                               } ).fail( function () {
-                                       // error on the server side (abort 
happens when user cancels the upload)
-                                       if ( status !== 'abort' ) {
-                                               result.reject( {
-                                                       stage: 'upload',
-                                                       type: 'error',
-                                                       details: 'http'
-                                               } );
-                                       }
-                               } );
-
-                               self.on( 'progress', function ( req, progress ) 
{
-                                       if ( req === request ) {
-                                               self.emit( 'uploadProgress', 
progress );
-                                       }
-                               } );
-                       }
-                       doUpload();
-
-                       return result;
-               }
-       } );
-
-       M.define( 'modules/uploads/PhotoApi', PhotoApi );
-       M.define( 'modules/uploads/_photo', {
-               generateFileName: generateFileName,
-               trimUtf8String: trimUtf8String
-       } );
-
-}( mw.mobileFrontend, jQuery ) );
diff --git a/javascripts/modules/uploads/PhotoUploadOverlay.js 
b/javascripts/modules/uploads/PhotoUploadOverlay.js
deleted file mode 100644
index 9551501..0000000
--- a/javascripts/modules/uploads/PhotoUploadOverlay.js
+++ /dev/null
@@ -1,337 +0,0 @@
-/* global EXIF */
-( function ( M, $ ) {
-       var popup = M.require( 'toast' ),
-               user = M.require( 'user' ),
-               router = M.require( 'router' ),
-               Overlay = M.require( 'Overlay' ),
-               EditorApi = M.require( 'modules/editor/EditorApi' ),
-               PhotoApi = M.require( 'modules/uploads/PhotoApi' ),
-               PhotoUploadProgress = M.require( 
'modules/uploads/PhotoUploadProgress' ),
-               SchemaMobileWebUploads = M.require( 
'loggingSchemas/SchemaMobileWebUploads' ),
-               ownershipMessage = mw.msg( 'mobile-frontend-photo-ownership', 
user.getName(), user ),
-               PhotoUploadOverlay;
-
-       /**
-        * Overlay for photo upload
-        * @class PhotoUploadOverlay
-        * @uses PhotoApi
-        * @extends Overlay
-        */
-       PhotoUploadOverlay = Overlay.extend( {
-               /**
-                * @inheritdoc
-                * @cfg {Object} defaults Default options hash.
-                * @cfg {Page} defaults.page the page being uploaded to
-                * @cfg {String} defaults.descriptionPlaceholder Placeholder 
text prompting user to add
-                * a mandatory caption to an image.
-                * @cfg {String} defaults.help A link that allows the user to 
open more information
-                * about photo ownership.
-                * @cfg {String} defaults.ownerStatement A statement saying the 
user created the image.
-                * @cfg {String} defaults.heading A heading instructing the 
user to describe uploaded image.
-                * @cfg {String} defaults.headerButtonsListClassName Class name 
of the wrapper of the
-                * header buttons.
-                * @cfg {Array} defaults.headerButtons Objects that will be 
used as defaults to create
-                * header buttons. Defaults to the 'submit' button.
-                */
-               defaults: {
-                       page: undefined,
-                       descriptionPlaceholder: mw.msg( 
'mobile-frontend-photo-caption-placeholder' ),
-                       help: mw.msg( 'mobile-frontend-photo-ownership-help' ),
-                       ownerStatement: ownershipMessage,
-                       heading: mw.msg( 
'mobile-frontend-image-heading-describe' ),
-                       headerButtonsListClassName: 'overlay-action',
-                       headerButtons: [ {
-                               className: 'submit',
-                               msg: mw.msg( 'mobile-frontend-photo-submit' )
-                       } ]
-               },
-               /** @inheritdoc */
-               events: $.extend( {}, Overlay.prototype.events, {
-                       'click .submit': 'onSubmit',
-                       'keyup textarea': 'onDescriptionChange',
-                       // use input event too, Firefox doesn't fire keyup on 
many devices:
-                       // https://bugzilla.mozilla.org/show_bug.cgi?id=737658
-                       'input textarea': 'onDescriptionChange'
-               } ),
-
-               className: 'overlay photo-overlay',
-
-               templatePartials: {
-                       content: mw.template.get( 'mobile.uploads', 
'PhotoUploadOverlay.hogan' )
-               },
-
-               /** @inheritdoc */
-               initialize: function ( options ) {
-                       var fileReader = new FileReader(),
-                               self = this;
-
-                       this.schema = new SchemaMobileWebUploads( {
-                               funnel: options.funnel
-                       } );
-                       this.file = options.file;
-
-                       if ( this.file ) {
-                               fileReader.readAsDataURL( options.file );
-                               /**
-                                * onload event for FileReader
-                                * @ignore
-                                */
-                               fileReader.onload = function () {
-                                       var dataUri = fileReader.result;
-                                       // add mimetype if not present (some 
browsers need it, e.g. Android browser)
-                                       dataUri = dataUri.replace( 
/^data:base64/, 'data:image/jpeg;base64' );
-                                       self.schema.log( {
-                                               action: 'preview'
-                                       } );
-                                       self.setImageUrl( dataUri );
-                               };
-                       }
-
-                       if ( options.insertInPage ) {
-                               this.api = new PhotoApi( {
-                                       page: options.page,
-                                       editorApi: new EditorApi( {
-                                               // FIXME: Use options.page 
instead
-                                               title: options.pageTitle
-                                       } )
-                               } );
-                       } else {
-                               this.api = new PhotoApi( {
-                                       page: options.page
-                               } );
-                       }
-                       this.api.on( 'uploadProgress', function ( value ) {
-                               self.progressPopup.setValue( value );
-                       } );
-
-                       this.progressPopup = new PhotoUploadProgress().on( 
'cancel', function () {
-                               self.api.abort();
-                               self.schema.log( {
-                                       action: 'cancel'
-                               } );
-                       } ).on( 'submit', function () {
-                               // handle resubmitting after abusefilter message
-                               self._save();
-                       } );
-
-                       // If terms of use is enabled, include it in the 
licensing message
-                       if ( $( '#footer-places-terms-use' ).length > 0 ) {
-                               options.license = mw.msg(
-                                       
'mobile-frontend-photo-licensing-with-terms',
-                                       $( '#footer-places-terms-use' ).html(),
-                                       mw.config.get( 'wgMFUploadLicenseLink' )
-                               );
-                       } else {
-                               options.license = mw.msg(
-                                       'mobile-frontend-photo-licensing',
-                                       mw.config.get( 'wgMFUploadLicenseLink' )
-                               );
-                       }
-
-                       Overlay.prototype.initialize.apply( this, arguments );
-               },
-
-               /**
-                * Performs a file upload based on current state of 
PhotoUploadOverlay
-                * When succeeds either reloads page or emits a global event 
_file-upload
-                * If error occurs shows a toast
-                * @uses PhotoApi
-                * @private
-                */
-               _save: function () {
-                       var
-                               self = this,
-                               description = this.getDescription(),
-                               saveOptions = {
-                                       file: this.file,
-                                       description: description
-                               };
-
-                       this.api.save( saveOptions ).done( function ( fileName, 
descriptionUrl ) {
-                               self.progressPopup.hide( true );
-
-                               self.schema.log( {
-                                       action: 'success'
-                               } );
-                               if ( self.options.insertInPage ) {
-                                       popup.show( mw.msg( 
'mobile-frontend-photo-upload-success-article' ), 'toast' );
-
-                                       // reload the page
-                                       window.location.reload();
-                               } else {
-                                       /**
-                                        * @event _file-upload
-                                        * Emits global event _file-upload.
-                                        * FIXME: handle Special:Uploads case - 
find more generic way of doing this
-                                        */
-                                       M.emit( '_file-upload', {
-                                               fileName: fileName,
-                                               description: description,
-                                               descriptionUrl: descriptionUrl,
-                                               url: self.imageUrl
-                                       } );
-                               }
-                       } ).fail( function ( err, statusMessage, 
httpErrorThrown ) {
-                               var errMsg;
-
-                               if ( err.type === 'abusefilter' ) {
-                                       self.progressPopup.showAbuseFilter( 
err.details.type, err.details.message );
-                               } else {
-                                       self.progressPopup.hide( true );
-                                       popup.show( statusMessage || mw.msg( 
'mobile-frontend-photo-upload-error' ), 'toast error' );
-                                       // If there is error information in API 
response, report that in the log
-                                       if ( err.stage !== undefined || 
err.type !== undefined ) {
-                                               errMsg = err.stage + '/' + 
err.type;
-                                               if ( typeof err.details === 
'string' ) {
-                                                       errMsg += '/' + 
err.details;
-                                               }
-                                               // Otherwise, record the stage 
as 'unknown' and record the type as the
-                                               // status message ("timeout", 
"error", "abort", etc. ) and include any
-                                               // HTTP error that was thrown.
-                                       } else {
-                                               errMsg = 'unknown';
-                                               if ( statusMessage ) {
-                                                       errMsg += '/' + 
statusMessage;
-                                                       if ( httpErrorThrown ) {
-                                                               errMsg += '/' + 
httpErrorThrown;
-                                                       }
-                                               }
-                                       }
-                                       self.schema.log( {
-                                               action: 'error',
-                                               errorText: errMsg
-                                       } );
-                               }
-                       } );
-               },
-
-               /**
-                * Submits a photo for upload, reveals a progress bar and hides 
the overlay.
-                * Invokes _save method.
-                * @private
-                */
-               _submit: function () {
-                       this.hide( true );
-
-                       this.progressPopup.show();
-
-                       this._save();
-               },
-
-               /** @inheritdoc */
-               postRender: function () {
-                       var $submitButton,
-                               self = this;
-
-                       Overlay.prototype.postRender.apply( this );
-
-                       $submitButton = this.$( '.submit' )
-                               .prop( 'disabled', true );
-                       this.$description = this.$( 'textarea' )
-                               .microAutosize();
-
-                       // make license links open in separate tabs
-                       this.$( '.license a' ).attr( 'target', '_blank' );
-
-                       // Deal with case where user refreshes the page
-                       if ( !self.file ) {
-                               router.navigate( '#' );
-                       }
-               },
-
-               /** @inheritdoc */
-               show: function () {
-                       var self = this;
-
-                       Overlay.prototype.show.apply( this, arguments );
-
-                       if ( this.file ) {
-                               EXIF.getData( this.file, function () {
-                                       if ( $.isEmptyObject( this.exifdata ) ) 
{
-                                               if ( window.confirm( mw.msg( 
'mobile-frontend-photo-upload-copyvio' ) ) ) {
-                                                       self.schema.log( {
-                                                               action: 
'copyvioOk'
-                                                       } );
-                                               } else {
-                                                       self.schema.log( {
-                                                               action: 
'copyvioCancel'
-                                                       } );
-                                                       self.hide( true );
-                                               }
-                                       }
-                               } );
-                       }
-               },
-
-               /** @inheritdoc */
-               hide: function ( force ) {
-                       var _super = Overlay.prototype.hide;
-                       // In the case of a missing file force close
-                       if ( force || !this.file ) {
-                               return _super.apply( this, arguments );
-                       } else if ( window.confirm( mw.msg( 
'mobile-frontend-image-cancel-confirm' ) ) ) {
-                               this.emit( 'cancel' );
-                               this.schema.log( {
-                                       action: 'previewCancel'
-                               } );
-                               return _super.apply( this, arguments );
-                       } else {
-                               return false;
-                       }
-               },
-
-               /**
-                * Gets the user inputted description
-                * @returns {String} of current value of description according 
to view
-                */
-               getDescription: function () {
-                       return this.$description.val();
-               },
-
-               /**
-                * Set the url of the image in the preview.
-                * Throws toast if for some reason image cannot render e.g. bad 
file type.
-                * @param {String} url usually a data uri
-                */
-               setImageUrl: function ( url ) {
-                       var self = this,
-                               $preview = this.$( '.preview' );
-
-                       this.imageUrl = url;
-                       this.$( '.spinner' ).hide();
-                       this.$( '.help' ).on( 'click', function () {
-                               self.schema.log( {
-                                       action: 'whatDoesThisMean'
-                               } );
-                       } );
-                       $( '<img>' )
-                               .attr( 'src', url )
-                               .appendTo( $preview )
-                               .on( 'error', function () {
-                                       // When using a bad filetype close the 
overlay
-                                       popup.show( mw.msg( 
'mobile-frontend-photo-upload-error-file-type' ), 'toast error' );
-                                       self.hide( true );
-                               } );
-               },
-
-               /**
-                * event handler to submit
-                */
-               onSubmit: function () {
-                       this.schema.log( {
-                               action: 'previewSubmit'
-                       } );
-                       this._submit();
-               },
-
-               /**
-                * event handler for changing description of property
-                */
-               onDescriptionChange: function () {
-                       this.$( '.submit' ).prop( 'disabled', this.$( 
'textarea' ).val() === '' );
-               }
-       } );
-
-       M.define( 'modules/uploads/PhotoUploadOverlay', PhotoUploadOverlay );
-
-}( mw.mobileFrontend, jQuery ) );
diff --git a/javascripts/modules/uploads/PhotoUploadProgress.js 
b/javascripts/modules/uploads/PhotoUploadProgress.js
deleted file mode 100644
index 360d64e..0000000
--- a/javascripts/modules/uploads/PhotoUploadProgress.js
+++ /dev/null
@@ -1,94 +0,0 @@
-( function ( M, $ ) {
-       var Overlay = M.require( 'Overlay' ),
-               ProgressBar = M.require( 'modules/uploads/ProgressBar' ),
-               AbuseFilterPanel = M.require( 'modules/editor/AbuseFilterPanel' 
),
-               PhotoUploadProgress;
-
-       /**
-        * Overlay displaying photo upload progress bar.
-        ** Appears at top of the page does not cover display.
-        * @class PhotoUploadProgress
-        * @extends Overlay
-        * @uses ProgressBar
-        * @uses AbuseFilterPanel
-        */
-       PhotoUploadProgress = Overlay.extend( {
-               /**
-                * @inheritdoc
-                * @cfg {Object} defaults Default options hash. Extends 
{Overlay} defaults.
-                * @cfg {String} defaults.uploadingMsg A message telling the 
user that an image is being
-                * uploaded.
-                */
-               defaults: $.extend( {}, Overlay.prototype.defaults, {
-                       uploadingMsg: mw.msg( 'mobile-frontend-image-uploading' 
)
-               } ),
-               /** @inheritdoc */
-               events: $.extend( {}, Overlay.prototype.events, {
-                       'click .submit': 'onSubmit'
-               } ),
-               template: mw.template.get( 'mobile.uploads', 
'PhotoUploadProgress.hogan' ),
-               fullScreen: false,
-
-               /** @inheritdoc */
-               initialize: function () {
-                       Overlay.prototype.initialize.apply( this, arguments );
-                       this.progressBar = new ProgressBar();
-               },
-
-               /** @inheritdoc */
-               postRender: function () {
-                       Overlay.prototype.postRender.apply( this );
-               },
-
-               /**
-                * Show abuse filter
-                * @method
-                * @param {String} type The type of alert, e.g. 'warning' or 
'disallow'
-                * @param {String} message Message to show in the AbuseFilter 
overlay
-                */
-               showAbuseFilter: function ( type, message ) {
-                       new AbuseFilterPanel().appendTo( this.$( 
'.overlay-header-container' ) )
-                               .show( type, message );
-                       this.showHidden( '.save-header' );
-               },
-
-               /** @inheritdoc */
-               hide: function ( force ) {
-                       var _super = Overlay.prototype.hide;
-                       if ( force ) {
-                               return _super.apply( this, arguments );
-                       } else if ( window.confirm( mw.msg( 
'mobile-frontend-image-cancel-confirm' ) ) ) {
-                               this.emit( 'cancel' );
-                               return _super.apply( this, arguments );
-                       } else {
-                               return false;
-                       }
-               },
-
-               /**
-                * Set the value of the progress bar in percentages
-                * @method
-                * @param {Number} value of the progress bar
-                */
-               setValue: function ( value ) {
-                       var $uploading = this.$( '.uploading' );
-                       // only add progress bar if we're getting progress 
events
-                       if ( $uploading.length && $uploading.text() !== '' ) {
-                               $uploading.text( '' );
-                               this.progressBar.appendTo( $uploading );
-                               this.$( '.right' ).remove();
-                       }
-                       this.progressBar.setValue( value );
-               },
-
-               /**
-                * event handler to submit
-                */
-               onSubmit: function () {
-                       this.emit( 'submit' );
-               }
-       } );
-
-       M.define( 'modules/uploads/PhotoUploadProgress', PhotoUploadProgress );
-
-}( mw.mobileFrontend, jQuery ) );
diff --git a/javascripts/modules/uploads/PhotoUploaderButton.js 
b/javascripts/modules/uploads/PhotoUploaderButton.js
deleted file mode 100644
index fb08955..0000000
--- a/javascripts/modules/uploads/PhotoUploaderButton.js
+++ /dev/null
@@ -1,79 +0,0 @@
-( function ( M, $ ) {
-       var browser = M.require( 'browser' ),
-               View = M.require( 'View' ),
-               Icon = M.require( 'Icon' ),
-               photoIcon = new Icon( {
-                       name: 'photo',
-                       hasText: true,
-                       additionalClassNames: 'mw-ui-progressive mw-ui-button 
button'
-               } ),
-               router = M.require( 'router' ),
-               PhotoUploaderButton;
-
-       /**
-        * @class PhotoUploaderButton
-        * @extends View
-        * @uses Icon
-        * PhotoUploaderButton is a component for uploading images to the wiki.
-        *
-        *     @example
-        *     <code>
-        *     var photoUploaderButton = new PhotoUploaderButton( {
-        *         buttonCaption: 'Add a photo',
-        *     } );
-        *     photoUploaderButton.
-        *         insertAfter( 'h1' ).
-        *         on( 'upload', function ( fileName, url ) {
-        *             $( '.someImage' ).attr( 'src', url );
-        *         } );
-        *     </code>
-        *
-        * @param {Object} options Uploader options.
-        * @param {String} options.buttonCaption Caption for the upload button.
-        * @param {Boolean} options.insertInPage If the image should be 
prepended
-        * to the wikitext of a page specified by options.pageTitle.
-        * @param {String} options.pageTitle Title of the page to which the 
image
-        * belongs (image name will be based on this) and to which it should be
-        * prepended (if options.insertInPage is true).
-        * @param {String} options.funnel Funnel for EventLogging.
-        */
-       PhotoUploaderButton = View.extend( {
-               template: mw.template.get( 'mobile.upload.ui', 'Button.hogan' ),
-               className: photoIcon.getClassName(),
-               events: {
-                       'change input': 'onFileSelected'
-               },
-
-               /**
-                * Event handler, called when a file is selected in the input
-                * @param {jQuery.Event} ev
-                */
-               onFileSelected: function ( ev ) {
-                       var $input = $( ev.target );
-                       this.handleFile( $input[0].files[0] );
-                       // clear so that change event is fired again when user 
selects the same file
-                       $input.val( '' );
-               },
-
-               /**
-                * Handle a selected file for upload, emit event and route to 
the
-                * appropiate url
-                * @param {File} file associated with file upload input
-                */
-               handleFile: function ( file ) {
-                       // FIXME: this is hacky but it would be hard to pass a 
file in a route
-                       M.emit( '_upload-preview', file );
-                       router.navigate( '#/upload-preview/' + 
this.options.funnel );
-               },
-
-               /** @inheritdoc */
-               postRender: function () {
-                       this.$el.removeClass( 'hidden' );
-               }
-       } );
-
-       PhotoUploaderButton.isSupported = browser.supportsFileUploads();
-
-       M.define( 'modules/uploads/PhotoUploaderButton', PhotoUploaderButton );
-
-}( mw.mobileFrontend, jQuery ) );
diff --git a/javascripts/modules/uploads/ProgressBar.js 
b/javascripts/modules/uploads/ProgressBar.js
deleted file mode 100644
index 6915ab0..0000000
--- a/javascripts/modules/uploads/ProgressBar.js
+++ /dev/null
@@ -1,28 +0,0 @@
-( function ( M ) {
-
-       var ProgressBar,
-               View = M.require( 'View' );
-
-       /**
-        * Progress bar
-        * @class ProgressBar
-        * @extends View
-        */
-       ProgressBar = View.extend( {
-               className: 'progress-bar',
-
-               template: mw.template.compile( '<div class="value"></div>', 
'hogan' ),
-
-               /**
-                * Set the value of the progress bar in percentages
-                * @method
-                * @param {Number} value of the progress bar
-                */
-               setValue: function ( value ) {
-                       this.$( '.value' ).css( 'width', value * 100 + '%' );
-               }
-       } );
-
-       M.define( 'modules/uploads/ProgressBar', ProgressBar );
-
-}( mw.mobileFrontend ) );
diff --git a/javascripts/modules/uploads/UploadTutorial.js 
b/javascripts/modules/uploads/UploadTutorial.js
deleted file mode 100644
index 3591093..0000000
--- a/javascripts/modules/uploads/UploadTutorial.js
+++ /dev/null
@@ -1,126 +0,0 @@
-( function ( M, $ ) {
-
-       var context = M.require( 'context' ),
-               Overlay = M.require( 'Overlay' ),
-               Icon = M.require( 'Icon' ),
-               LeadPhotoUploaderButton = M.require( 
'modules/uploads/PhotoUploaderButton' ),
-               buttonMsg = mw.msg( 
'mobile-frontend-first-upload-wizard-new-page-3-ok' ),
-               UploadTutorial;
-
-       /**
-        * Overlay for displaying upload tutorial
-        * @class UploadTutorial
-        * @extends Overlay
-        * @uses Icon
-        * @uses LeadPhotoUploaderButton
-        */
-       UploadTutorial = Overlay.extend( {
-               template: mw.template.get( 'mobile.uploads', 
'UploadTutorial.hogan' ),
-               className: 'overlay carousel tutorial content-overlay 
tutorial-overlay',
-
-               /** @inheritdoc */
-               events: $.extend( {}, Overlay.prototype.events, {
-                       'click .prev': 'onPreviousClick',
-                       'click .next': 'onNextClick',
-                       'click .button': 'onClickUploadButton'
-               } ),
-               /**
-                * @inheritdoc
-                * @cfg {Object} defaults Default options hash.
-                * @cfg {String} defaults.slideLeftButton HTML of the slide 
left button.
-                * @cfg {String} defaults.slideRightButton HTML of the slide 
right button.
-                * @cfg {Boolean} defaults.inBeta Whether the user is a beta 
group member.
-                * @cfg {Array} defaults.pages Array of {Object}s that will be 
used as options to
-                * create pages. Defaults to the following pages:
-                *  * Informative statement about where images come from.
-                *  * Guidance on avoiding copyright materials shown to first 
time users on
-                *    [[Special:Uploads]].
-                *  * Question asking user if they understood the tutorial.
-                */
-               defaults: {
-                       slideLeftButton: new Icon( {
-                               name: 'previous-invert'
-                       } ).toHtmlString(),
-                       slideRightButton: new Icon( {
-                               name: 'next-invert'
-                       } ).toHtmlString(),
-                       inBeta: context.isBetaGroupMember(),
-                       pages: [
-                               {
-                                       caption: mw.msg( 
'mobile-frontend-first-upload-wizard-new-page-1-header' ),
-                                       text: mw.msg( 
'mobile-frontend-first-upload-wizard-new-page-1' )
-                               },
-                               {
-                                       caption: mw.msg( 
'mobile-frontend-first-upload-wizard-new-page-2-header' ),
-                                       text: mw.msg( 
'mobile-frontend-first-upload-wizard-new-page-2' )
-                               },
-                               {
-                                       caption: mw.msg( 
'mobile-frontend-first-upload-wizard-new-page-3-header' ),
-                                       button: buttonMsg
-                               }
-                       ]
-               },
-
-               /** @inheritdoc */
-               postRender: function () {
-                       var $button = this.$( '.button' ),
-                               photoUploaderButton;
-
-                       if ( this.options.funnel ) {
-                               photoUploaderButton = new 
LeadPhotoUploaderButton( {
-                                       el: $button,
-                                       buttonCaption: buttonMsg,
-                                       funnel: this.options.funnel
-                               } );
-                       }
-
-                       this.page = 0;
-                       this.totalPages = this.options.pages.length;
-                       this._showCurrentPage();
-                       Overlay.prototype.postRender.apply( this );
-               },
-
-               /**
-                * Show current page inside the upload tutorial
-                * @method
-                * @private
-                */
-               _showCurrentPage: function () {
-                       this.$( '.slide' ).removeClass( 'active' ).eq( 
this.page ).addClass( 'active' );
-                       this.$( '.prev' ).toggle( this.page > 0 );
-                       this.$( '.next' ).toggle( this.page < this.totalPages - 
1 );
-               },
-
-               /**
-                * Event that is fired when clicking the final button at the 
end of the tutorial.
-                * @method
-                */
-               onClickUploadButton: function () {
-                       this.emit( 'hide' );
-                       // FIXME: this is a hack. Not sure why this is needed 
but without it
-                       // when escaping the upload interface you will still 
see it.
-                       this.$el.hide();
-               },
-
-               /**
-                * Show next page of the tutorial
-                * @method
-                */
-               onNextClick: function () {
-                       this.page += 1;
-                       this._showCurrentPage();
-               },
-
-               /**
-                * Show previous page of the tutorial
-                * @method
-                */
-               onPreviousClick: function () {
-                       this.page -= 1;
-                       this._showCurrentPage();
-               }
-       } );
-
-       M.define( 'modules/uploads/UploadTutorial', UploadTutorial );
-
-}( mw.mobileFrontend, jQuery ) );
diff --git a/javascripts/modules/uploads/init.js 
b/javascripts/modules/uploads/init.js
deleted file mode 100644
index 75d964a..0000000
--- a/javascripts/modules/uploads/init.js
+++ /dev/null
@@ -1,75 +0,0 @@
-( function ( M, $ ) {
-
-       var
-               funnel = $.cookie( 'mwUploadsFunnel' ) || 'article',
-               LeadPhotoUploaderButton = M.require( 
'modules/uploads/LeadPhotoUploaderButton' ),
-               user = M.require( 'user' ),
-               skin = M.require( 'skin' ),
-               isSupported = LeadPhotoUploaderButton.isSupported;
-
-       /**
-        * Checks whether there is no suitable image in the container.
-        * Judges this based on selector in wgMFLeadPhotoUploadCssSelector
-        *
-        * @param {jQuery.Object} $container
-        * @return {Boolean}
-        * @ignore
-        */
-       function needsPhoto( $container ) {
-               return $container.find( mw.config.get( 
'wgMFLeadPhotoUploadCssSelector' ) ).length === 0;
-       }
-
-       // reset the funnel cookie as it is no longer valid
-       if ( funnel ) {
-               $.cookie( 'mwUploadsFunnel', null );
-       }
-
-       /**
-        * Initialise interface would uploading an image to the top of the 
current page.
-        *
-        * @ignore
-        */
-       function initialize() {
-               var
-                       page = M.getCurrentPage(),
-                       $lead = page.getLeadSectionElement(),
-                       inFileNamespace = page.inNamespace( 'file' ),
-                       validNamespace = ( page.inNamespace( '' ) || 
page.inNamespace( 'user' ) || inFileNamespace );
-
-               // Only show upload page action in File namespace if page 
doesn't already exist.
-               if ( inFileNamespace ) {
-                       if ( mw.config.get( 'wgArticleId' ) ) {
-                               $( '#ca-upload' ).remove();
-                       }
-               } else {
-                       if ( !page.isEditable( user ) || !validNamespace ||
-                                       // FIXME: Anonymous users cannot upload 
but really this should also check rights of user via getRights
-                                       // (without triggering an additional 
HTTP request)
-                                       user.isAnon() ||
-                                       mw.util.getParamValue( 'action' ) || 
!needsPhoto( $lead ) || mw.config.get( 'wgIsMainPage' ) ) {
-                               $( '#ca-upload' ).remove();
-                       }
-               }
-
-               new LeadPhotoUploaderButton( {
-                       funnel: funnel
-               } );
-               skin.emit( 'changed' );
-       }
-
-       if ( isSupported ) {
-               $( initialize );
-       } else {
-               // FIXME: We want to enable it to these users however we must 
first deal with what to show
-               // to users who haven't uploaded anything to make the page 
useful.
-               $( function () {
-                       // FIXME: Move to MainMenu.js
-                       $( 'nav li.menu-item-upload' ).remove();
-               } );
-       }
-
-       M.define( 'modules/uploads/_leadphoto', {
-               needsPhoto: needsPhoto
-       } );
-
-}( mw.mobileFrontend, jQuery ) );
diff --git a/javascripts/modules/uploads/routes.js 
b/javascripts/modules/uploads/routes.js
deleted file mode 100644
index ef40b36..0000000
--- a/javascripts/modules/uploads/routes.js
+++ /dev/null
@@ -1,42 +0,0 @@
-/* Defines all possible routes in MobileFrontend and where to find the code to 
provide them. */
-( function ( M, $ ) {
-       var lastFile,
-               overlayManager = M.require( 'overlayManager' ),
-               loader = M.require( 'loader' );
-
-       // FIXME: this is hacky but it would be hard to pass a file in a route
-       M.on( '_upload-preview', function ( file ) {
-               lastFile = file;
-       } );
-
-       // Upload Tutorial
-       overlayManager.add( /^\/upload-tutorial\/?(.*)$/, function ( funnel ) {
-               var result = $.Deferred();
-               loader.loadModule( 'mobile.uploads' ).done( function () {
-                       var UploadTutorialNew = M.require( 
'modules/uploads/UploadTutorial' );
-                       result.resolve( new UploadTutorialNew( {
-                               funnel: funnel || null
-                       } ) );
-               } );
-               return result;
-       } );
-
-       // Upload Preview
-       overlayManager.add( /^\/upload-preview\/?(.*)$/, function ( funnel ) {
-               var result = $.Deferred();
-               loader.loadModule( 'mobile.uploads' ).done( function () {
-                       var PhotoUploadOverlay = M.require( 
'modules/uploads/PhotoUploadOverlay' );
-                       result.resolve( new PhotoUploadOverlay( {
-                               page: M.getCurrentPage(),
-                               // FIXME: Remove this and use page option 
instead
-                               pageTitle: mw.config.get( 'wgTitle' ),
-                               file: lastFile,
-                               funnel: funnel,
-                               // When the funnel is uploads you are on 
Special:Uploads
-                               insertInPage: funnel === 'uploads' ? false : 
true
-                       } ) );
-               } );
-               return result;
-       } );
-
-} )( mw.mobileFrontend, jQuery );
diff --git a/javascripts/specials/uploads.js b/javascripts/specials/uploads.js
index 4dbbf06..33ee225 100644
--- a/javascripts/specials/uploads.js
+++ b/javascripts/specials/uploads.js
@@ -1,86 +1,19 @@
 ( function ( M, $ ) {
        var
-               PhotoUploaderButton = M.require( 
'modules/uploads/PhotoUploaderButton' ),
                user = M.require( 'user' ),
-               popup = M.require( 'toast' ),
-               Button = M.require( 'Button' ),
-               Icon = M.require( 'Icon' ),
                PhotoList = M.require( 'modules/gallery/PhotoList' ),
                pageParams = mw.config.get( 'wgPageName' ).split( '/' ),
                currentUserName = user.getName(),
                userName = pageParams[1] ? pageParams[1] : currentUserName;
 
        /**
-        * Create a {PhotoUploaderButton} with an uploads funnel.
-        * @param {jQuery.Object} $container to append new button to.
-        * @ignore
-        */
-       function createButton( $container ) {
-               var btn = new PhotoUploaderButton( {
-                       buttonCaption: mw.msg( 
'mobile-frontend-photo-upload-generic' ),
-                       pageTitle: mw.config.get( 'wgTitle' ),
-                       funnel: 'uploads'
-               } );
-
-               btn.appendTo( $container );
-       }
-
-       /**
         * Initialise a photo upload button at the top of the page.
         * @ignore
         */
        function init() {
-               var userGallery,
-                       $btnContainer = $( '.ctaUploadPhoto' ),
-                       $content = $( '.content' );
-
-               // Don't attempt to display the gallery if PHP displayed an 
error
-               if ( $( '.error' ).length ) {
-                       return;
-               }
-
-               userGallery = new PhotoList( {
+               new PhotoList( {
                        username: userName
-               } ).appendTo( $content );
-
-               if ( PhotoUploaderButton.isSupported && currentUserName === 
userName && mw.config.get( 'wgUserCanUpload' ) ) {
-                       if ( $btnContainer.length ) {
-                               if ( user.getEditCount() === 0 ) {
-                                       new Button( {
-                                               href: 
'#/upload-tutorial/uploads',
-                                               progressive: true,
-                                               label: mw.msg( 
'mobile-frontend-photo-upload-generic' ),
-                                               additionalClassNames: new Icon( 
{
-                                                       name: 'photo',
-                                                       additionalClassNames: 
'button',
-                                                       hasText: true
-                                               } ).getClassName()
-                                       } ).appendTo( $btnContainer );
-                               } else {
-                                       createButton( $btnContainer );
-                               }
-                       }
-
-                       // FIXME: Please find a way to do this without a global 
event.
-                       M.on( '_file-upload', function ( image ) {
-                               var newCount, msgKey,
-                                       $counter = $btnContainer.find( 'h2' 
).show().find( 'span' );
-
-                               if ( userGallery.isEmpty() ) {
-                                       msgKey = 
'mobile-frontend-donate-photo-first-upload-success';
-                               } else {
-                                       msgKey = 
'mobile-frontend-donate-photo-upload-success';
-                               }
-                               popup.show( mw.msg( msgKey ), 'toast' );
-
-                               userGallery.prependPhoto( image );
-
-                               if ( $counter.length ) {
-                                       newCount = parseInt( $counter.text(), 
10 ) + 1;
-                                       $counter.parent().html( mw.msg( 
'mobile-frontend-photo-upload-user-count', newCount ) ).show();
-                               }
-                       } );
-               }
+               } ).appendTo( '.content' );
        }
 
        if ( userName && mw.config.get( 'wgCanonicalSpecialPageName' ) === 
'Uploads' ) {
diff --git a/less/modules/uploads/PhotoUploadOverlay.less 
b/less/modules/uploads/PhotoUploadOverlay.less
deleted file mode 100644
index 6678110..0000000
--- a/less/modules/uploads/PhotoUploadOverlay.less
+++ /dev/null
@@ -1,25 +0,0 @@
-@import "minerva.variables";
-@import "minerva.mixins";
-
-.photo-overlay {
-       @height: 90px;
-
-       .help {
-               display: block;
-       }
-
-       .preview {
-               height: @height;
-               min-width: 50px;
-               float: left;
-               margin: 0 8px 8px 0;
-       }
-
-       img {
-               height: @height !important;
-       }
-
-       textarea {
-               height: 3em;
-       }
-}
diff --git a/less/modules/uploads/PhotoUploadProgress.less 
b/less/modules/uploads/PhotoUploadProgress.less
deleted file mode 100644
index a87e242..0000000
--- a/less/modules/uploads/PhotoUploadProgress.less
+++ /dev/null
@@ -1,21 +0,0 @@
-@import "mediawiki.mixins";
-@import "minerva.variables";
-@import "minerva.mixins";
-
-.drawer {
-       .progress-bar {
-               margin: .9em 0 0;
-       }
-}
-
-.progress-bar {
-       width: 100%;
-       height: .9em;
-       border: 1px solid @colorGray12;
-
-       .value {
-               width: 0;
-               height: 100%;
-               background: @colorProgressive;
-       }
-}
\ No newline at end of file
diff --git a/less/modules/uploads/PhotoUploaderButton.less 
b/less/modules/uploads/PhotoUploaderButton.less
deleted file mode 100644
index 8ee59a5..0000000
--- a/less/modules/uploads/PhotoUploaderButton.less
+++ /dev/null
@@ -1,28 +0,0 @@
-@import "mediawiki.mixins";
-@import "minerva.variables";
-@import "minerva.mixins";
-
-.ctaUploadPhoto {
-       // Ensure entire button is clickable
-       .button {
-               position: relative;
-               display: table;
-               position: relative;
-               margin: 0 auto;
-
-               input {
-                       opacity: 0;
-                       z-index: @z-indexContent;
-               }
-
-               input, div {
-                       cursor: pointer;
-                       position: absolute;
-                       top: 0;
-                       left: 0;
-                       width: 100%;
-                       height: 100%;
-               }
-       }
-}
-
diff --git a/less/modules/uploads/UploadTutorial.less 
b/less/modules/uploads/UploadTutorial.less
deleted file mode 100644
index a8ab2f6..0000000
--- a/less/modules/uploads/UploadTutorial.less
+++ /dev/null
@@ -1,83 +0,0 @@
-@import "minerva.variables";
-@import "minerva.mixins";
-
-.carousel {
-       @buttonWidth: 40px;
-       overflow: hidden;
-
-       .slide {
-               @imageHeight: 180px;
-
-               position: absolute;
-               left: 0;
-               right: 0;
-               background: 50% 0 no-repeat;
-               .background-size(auto, @imageHeight);
-               display: none;
-               padding: 0 @buttonWidth;
-
-               &.active {
-                       display: block;
-               }
-
-               strong {
-                       display: block;
-                       font-size: 1.1em;
-                       margin: 0 0 1em;
-               }
-
-               &.slide-image {
-                       padding-top: @imageHeight;
-               }
-
-               &:nth-child(1) {
-                       .background-image('../images/uploads/page1.png');
-               }
-
-               &:nth-child(2) {
-                       .background-image('../images/uploads/page2.png');
-               }
-
-               &:nth-child(3) {
-                       .background-image('../images/uploads/page3.png');
-               }
-       }
-}
-
-.animations {
-       .carousel {
-               .slide {
-                       display: block;
-                       .transform( translate3d(-100%, 0, 0) );
-                       .transition-transform( .5s );
-
-                       &.active {
-                               .transform( none );
-                       }
-
-                       &.active ~ .slide {
-                               .transform( translate3d(100%, 0, 0) );
-                       }
-               }
-       }
-}
-
-html[dir="rtl"] .carousel > button {
-       .transform(rotate(180deg));
-}
-
-html[dir="rtl"].animations {
-       .carousel {
-               .slide {
-                       .transform( translate3d(100%, 0, 0) );
-
-                       &.active {
-                               .transform( none );
-                       }
-
-                       &.active ~ .slide {
-                               .transform( translate3d(-100%, 0, 0) );
-                       }
-               }
-       }
-}
diff --git a/less/pageactions.less b/less/pageactions.less
index a70ff20..dd2ed52 100644
--- a/less/pageactions.less
+++ b/less/pageactions.less
@@ -9,7 +9,6 @@
 // hide menu items when not possible to use
 .client-nojs #ca-watch,
 .client-nojs #ca-edit,
-.client-nojs #ca-upload,
 #ca-talk.selected {
        display: none;
 }
@@ -70,19 +69,3 @@
        }
 }
 
-#ca-upload {
-       input {
-               display: none;
-       }
-       &.enabled {
-               input {
-                       display: block;
-                       // this rule has to be here (and not combined with the 
webkit rule below) for it to work on firefox
-                       cursor: pointer;
-               }
-               // webkit-file-upload-button for pointer cursor in chrome.
-               ::-webkit-file-upload-button {
-                       cursor: pointer;
-               }
-       }
-}
diff --git a/resources/mobile.loggingSchemas/SchemaMobileWebUploads.js 
b/resources/mobile.loggingSchemas/SchemaMobileWebUploads.js
deleted file mode 100644
index 3ab1eb7..0000000
--- a/resources/mobile.loggingSchemas/SchemaMobileWebUploads.js
+++ /dev/null
@@ -1,39 +0,0 @@
-( function ( M, $ ) {
-       var SchemaMobileWebUploads,
-               user = M.require( 'user' ),
-               page = M.getCurrentPage(),
-               SchemaMobileWeb = M.require( 'loggingSchemas/SchemaMobileWeb' );
-
-       /**
-        * @class SchemaMobileWebUploads
-        * @extends Schema
-        */
-       SchemaMobileWebUploads = SchemaMobileWeb.extend( {
-               /** @inheritdoc **/
-               name: 'MobileWebUploads',
-               /**
-                * @inheritdoc
-                *
-                * @cfg {Object} defaults Default options hash.
-                * @cfg {Number} defaults.pageId The value of the wgArticleId 
config variable
-                * @cfg {String} defaults.token Unique session ID for the user
-                * @cfg {String} defaults.funnel Identifier for the upload 
funnel
-                * @cfg {String|undefined} defaults.username Username if the 
user is logged in, otherwise -
-                * undefined. Assigning undefined will make event logger omit 
this property when sending
-                * the data to a server. According to the schema username is 
optional.
-                * @cfg {Boolean} defaults.isLoggedIn Whether the user is 
logged in
-                * @cfg {Boolean} defaults.isEditable True, if the user is able 
to edit the current page, false otherwise
-                */
-               defaults: $.extend( {}, SchemaMobileWeb.prototype.defaults, {
-                       pageId: mw.config.get( 'wgArticleId' ),
-                       token: user.getSessionId(),
-                       funnel: 'unknown',
-                       // FIXME: Introduce a SchemaWithUser class and rethink 
the data recorded that follows
-                       username: user.getName() || undefined,
-                       isEditable: page.isEditable( user )
-               } )
-       } );
-
-       M.define( 'loggingSchemas/SchemaMobileWebUploads', 
SchemaMobileWebUploads );
-
-}( mw.mobileFrontend, jQuery ) );
diff --git a/resources/mobile.startup/Page.js b/resources/mobile.startup/Page.js
index c58c65f..36bddce 100644
--- a/resources/mobile.startup/Page.js
+++ b/resources/mobile.startup/Page.js
@@ -26,7 +26,6 @@
                 * e.g. [{ edit: ['*'] }]
                 * @cfg {Array} defaults.sections Array of {Section} objects.
                 * @cfg {Boolean} defaults.isMainPage Whether the page is the 
Main Page.
-                * @cfg {Boolean} defaults.userCanUpload Whether the current 
user can upload.
                 * @cfg {String} defaults.hash Window location hash.
                 */
                defaults: {
@@ -39,7 +38,6 @@
                        },
                        sections: [],
                        isMainPage: false,
-                       userCanUpload: mw.config.get( 'wgUserCanUpload' ),
                        hash: window.location.hash
                },
 
diff --git a/resources/skins.minerva.icons.images.legacy/icons.less 
b/resources/skins.minerva.icons.images.legacy/icons.less
index d9a4d5a..b35e6b4 100644
--- a/resources/skins.minerva.icons.images.legacy/icons.less
+++ b/resources/skins.minerva.icons.images.legacy/icons.less
@@ -17,11 +17,6 @@
        .m-background-image('clear.png');
 }
 
-// Uploads set
-.mw-ui-icon-photo {
-       .m-background-image('camera.png');
-}
-
 .mw-ui-icon-back {
        .m-background-image('back-ltr.png');
 }
diff --git a/templates/modules/uploads/LeadPhoto.hogan 
b/templates/modules/uploads/LeadPhoto.hogan
deleted file mode 100644
index 0d214c7..0000000
--- a/templates/modules/uploads/LeadPhoto.hogan
+++ /dev/null
@@ -1,8 +0,0 @@
-<div class="thumb tright">
-       <div class="thumbinner" style="width:222px;">
-               <a href="{{pageUrl}}" class="image">
-                       <img alt="{{caption}}" src="{{url}}" class="thumbimage">
-               </a>
-               <div class="thumbcaption">{{caption}}</div>
-       </div>
-</div>
diff --git a/templates/modules/uploads/LeadPhotoUploaderButton.hogan 
b/templates/modules/uploads/LeadPhotoUploaderButton.hogan
deleted file mode 100644
index 5ff5936..0000000
--- a/templates/modules/uploads/LeadPhotoUploaderButton.hogan
+++ /dev/null
@@ -1 +0,0 @@
-<input name="file" type="file" accept="image/*" 
class="cloaked-element">{{buttonCaption}}
diff --git a/templates/modules/uploads/PhotoUploadOverlay.hogan 
b/templates/modules/uploads/PhotoUploadOverlay.hogan
deleted file mode 100644
index a739908..0000000
--- a/templates/modules/uploads/PhotoUploadOverlay.hogan
+++ /dev/null
@@ -1,7 +0,0 @@
-<div class="content">
-       {{{spinner}}}
-       <div class="preview"></div>
-       <p>{{ownerStatement}} <a href="#/upload-tutorial" class="help 
inline">{{help}}</a></p>
-       <textarea class="mw-ui-input" name="description" 
placeholder="{{descriptionPlaceholder}}"></textarea>
-       <p class="license">{{{license}}}</p>
-</div>
diff --git a/templates/modules/uploads/PhotoUploadProgress.hogan 
b/templates/modules/uploads/PhotoUploadProgress.hogan
deleted file mode 100644
index ceeaadc..0000000
--- a/templates/modules/uploads/PhotoUploadProgress.hogan
+++ /dev/null
@@ -1,21 +0,0 @@
-<div class="overlay-header-container visible position-fixed">
-       <div class="overlay-header progress-header hideable">
-               <ul>
-                       <li>{{{cancelButton}}}</li>
-               </ul>
-               <div>
-                       <h2 class="uploading">{{{uploadingMsg}}}</h2>
-               </div>
-               <ul class="{{headerButtonsListClassName}}">
-                       <li><button class="loading 
icon">{{{uploadingMsg}}}</button></li>
-               </ul>
-       </div>
-       <div class="overlay-header save-header hideable hidden">
-               <ul>
-                       <li><button class="cancel 
icon">{{closeMsg}}</button></li>
-               </ul>
-               <div>
-               </div>
-               <div class="overlay-action"><button 
class="submit">{{saveMsg}}</button></div>
-       </div>
-</div>
diff --git a/templates/modules/uploads/PhotoUploaderButton.hogan 
b/templates/modules/uploads/PhotoUploaderButton.hogan
deleted file mode 100644
index aa9b4bf..0000000
--- a/templates/modules/uploads/PhotoUploaderButton.hogan
+++ /dev/null
@@ -1,2 +0,0 @@
-{{buttonCaption}}
-<input name="file" type="file" class="cloaked-element">
diff --git a/templates/modules/uploads/UploadTutorial.hogan 
b/templates/modules/uploads/UploadTutorial.hogan
deleted file mode 100644
index dcb8d63..0000000
--- a/templates/modules/uploads/UploadTutorial.hogan
+++ /dev/null
@@ -1,22 +0,0 @@
-<div class="prev slider-button">
-       {{{slideLeftButton}}}
-</div>
-<ul>
-       {{#pages}}
-       <li class="slide slide-image">
-               <strong>{{caption}}</strong>
-               <p>{{text}}</p>
-               {{#button}}
-               {{#funnel}}
-               <div class="mw-ui-button button"></div>
-               {{/funnel}}
-               {{^funnel}}
-               <button class="cancel button mw-ui-button">{{button}}</button>
-               {{/funnel}}
-               {{/button}}
-       </li>
-       {{/pages}}
-</ul>
-<div class="next slider-button">
-{{{slideRightButton}}}
-</div>
diff --git a/templates/modules/uploads/commons-upload.hogan 
b/templates/modules/uploads/commons-upload.hogan
deleted file mode 100644
index a480324..0000000
--- a/templates/modules/uploads/commons-upload.hogan
+++ /dev/null
@@ -1,10 +0,0 @@
-{{=<% %>=}}
-== {{int:filedesc}} ==
-{{Information
-|description=<%text%>
-|source={{own}}
-|author=[[User:<%username%>]]
-}}<%suffix%>
-
-== {{int:license-header}} ==
-{{self|cc-by-sa-3.0}}
diff --git a/tests/browser/features/step_definitions/uploads_steps.rb 
b/tests/browser/features/step_definitions/uploads_steps.rb
deleted file mode 100644
index 92efc3c..0000000
--- a/tests/browser/features/step_definitions/uploads_steps.rb
+++ /dev/null
@@ -1,56 +0,0 @@
-Given(/^I can see the uploads interface$/) do
-  on(UploadPage).contribute_image_element.when_present
-end
-
-Given(/^I click on the lead photo upload button$/) do
-  on(ArticlePage).upload_page_action_element.when_present.click
-end
-
-When(/^I click Upload$/) do
-  on(UploadPage).upload_button_element.when_present.click
-end
-
-When(/^I click the upload preview overlay close button$/) do
-  on(ArticlePage).photo_overlay_close_button_element.when_present.click
-end
-
-When(/^I go to uploads page$/) do
-  visit(UploadPage)
-end
-
-When(/^I type a description$/) do
-  on(UploadPage).photo_description_element.when_present.send_keys("Describing 
with #{@random_string}")
-end
-
-When(/^I upload file "(.*?)"$/) do |file_name|
-  on(UploadPage).select_file = File.join(Dir.pwd, 'features', 'support', 
file_name)
-end
-
-Then(/^I should be able to enter a description for my file upload$/) do
-  expect(on(ArticlePage).photo_description_element.when_present).to be_visible
-end
-
-Then(/^I should not see the upload preview$/) do
-  expect(on(ArticlePage).photo_overlay_element).not_to be_visible
-end
-
-Then(/^I should see an upload progress bar$/) do
-  expect(on(ArticlePage).progress_header_element).to be_visible
-end
-
-Then(/^I should see the upload preview$/) do
-  expect(on(ArticlePage).photo_overlay_element.when_present).to be_visible
-end
-
-Then(/^my image should be on the Uploads page$/) do
-  on(UploadPage) do |page|
-    page.wait_until(10) do
-      page.text.include? "#{@random_string}" # Chrome needs this, FF does not
-    end
-    expect(page.uploaded_image_link_element.when_present.attribute('alt')).to 
match "#{@random_string}"
-  end
-end
-
-Then(/^the Contribute an image button should be visible$/) do
-  expect(on(UploadPage).contribute_image_element).to be_visible
-end
diff --git a/tests/browser/features/uploads_copyvio.feature 
b/tests/browser/features/uploads_copyvio.feature
deleted file mode 100644
index 2ed27f8..0000000
--- a/tests/browser/features/uploads_copyvio.feature
+++ /dev/null
@@ -1,23 +0,0 @@
-# FIXME: Get this working on Chrome (bug 64397)
-@firefox @login @vagrant
-Feature: Image uploads copyvio notice
-
-  Background:
-    Given I am using the mobile site
-      And I am logged in as a user with a > 0 edit count
-      And I am on the "Nonexistent_page_abc" page
-      And I click on the lead photo upload button
-
-  Scenario: Opening upload preview and confirming (image without EXIF)
-    When upload file image.png
-      And I say OK in the confirm dialog
-    Then I should see the upload preview
-
-  Scenario: Opening upload preview and cancelling (image without EXIF)
-    When upload file image.png
-      And I say Cancel in the confirm dialog
-    Then I should not see the upload preview
-
-  Scenario: Opening upload preview (image with EXIF)
-    When I upload file "exif.jpg"
-    Then I should see the upload preview
diff --git a/tests/browser/features/uploads_lead.feature 
b/tests/browser/features/uploads_lead.feature
deleted file mode 100644
index 578db63..0000000
--- a/tests/browser/features/uploads_lead.feature
+++ /dev/null
@@ -1,23 +0,0 @@
-@firefox @login @vagrant
-Feature: Lead image uploads
-
-  Background:
-    Given I am using the mobile site
-      And I am logged in as a user with a > 0 edit count
-      And I am on the "Nonexistent_page_abc" page
-      And I click on the lead photo upload button
-      And I upload file "exif.jpg"
-
-  Scenario: Opening upload preview
-    Then I should see the upload preview
-      And I should be able to enter a description for my file upload
-
-  Scenario: Closing upload preview (overlay button)
-    When I click the upload preview overlay close button
-      And I say OK in the confirm dialog
-    Then I should not see the upload preview
-
-  Scenario: Closing upload preview (browser button)
-    When I click the browser back button
-      And I say OK in the confirm dialog
-    Then I should not see the upload preview
diff --git a/tests/qunit/modules/uploads/test_PhotoApi.js 
b/tests/qunit/modules/uploads/test_PhotoApi.js
deleted file mode 100644
index 6bb753e..0000000
--- a/tests/qunit/modules/uploads/test_PhotoApi.js
+++ /dev/null
@@ -1,269 +0,0 @@
-( function ( $, M ) {
-
-       var photo = M.require( 'modules/uploads/_photo' ),
-               PhotoApi = M.require( 'modules/uploads/PhotoApi' ),
-               Page = M.require( 'Page' ),
-               EditorApi = M.require( 'modules/editor/EditorApi' ),
-               editorApi, photoApi;
-
-       QUnit.module( 'MobileFrontend modules/uploads/PhotoApi', {
-               setup: function () {
-                       var resp = {
-                               warnings: {
-                                       main: {
-                                               '*': 'Unrecognized parameters: 
"useformat", "r"'
-                                       }
-                               },
-                               upload: {
-                                       result: 'Success',
-                                       filename: 'z_2013-05-13_09-45.jpg',
-                                       imageinfo: {
-                                               timestamp: 
'2013-05-13T16:45:53Z',
-                                               user: 'Jdlrobson',
-                                               userid: 825,
-                                               size: 182912,
-                                               width: 960,
-                                               height: 578,
-                                               parsedcomment: 'Added photo for 
use on page',
-                                               comment: 'Added photo for use 
on page',
-                                               url: 
'http://upload.beta.wmflabs.org/wikipedia/en/b/b3/Tulip_test_2013-05-13_09-45.jpg',
-                                               descriptionurl: 
'http://en.wikipedia.beta.wmflabs.org/wiki/File:Tulip_test_2013-05-13_09-45.jpg',
-                                               sha1: 
'7e56537b1929d7d4d211bded2d46ba01ddbbe30f',
-                                               metadata: [ {
-                                                       name: 'JPEGFileComment',
-                                                       value: [ {
-                                                               name: 0,
-                                                               value: '*'
-                                                       } ]
-                                               }, {
-                                                       name: 
'MEDIAWIKI_EXIF_VERSION',
-                                                       value: 2
-                                               } ],
-                                               mime: 'image/jpeg',
-                                               mediatype: 'BITMAP',
-                                               bitdepth: 8
-                                       }
-                               }
-                       };
-
-                       editorApi = new EditorApi( {} );
-                       photoApi = new PhotoApi( {
-                               page: new Page( {
-                                       title: 'Foo',
-                                       namespaceNumber: 0
-                               } ),
-                               editorApi: editorApi
-                       } );
-                       // Saves to edits will use getToken
-                       this.sandbox.stub( editorApi, 'getToken' ).returns( 
$.Deferred().resolve( 'foo' ) );
-                       this.sandbox.stub( editorApi, 'post' ).returns( 
$.Deferred().resolve( {
-                               edit: {
-                                       result: 'Success'
-                               }
-                       } ) );
-                       this.sandbox.stub( photoApi, 'postWithToken' ).returns( 
$.Deferred().resolve( resp ) );
-               }
-       } );
-
-       QUnit.test( '#save, upload with missing filename', 1, function ( assert 
) {
-               var resp = {
-                               upload: {
-                                       result: 'Warning',
-                                       warnings: {
-                                               badfilename: '::.JPG'
-                                       },
-                                       filekey: '1s.1.jpg',
-                                       sessionkey: 'z1.jpg'
-                               }
-                       },
-                       spy = this.sandbox.spy();
-
-               photoApi.postWithToken.returns( $.Deferred().resolve( resp ) );
-
-               photoApi.save( {
-                       file: {
-                               name: '::'
-                       },
-                       description: 'yo:: yo ::'
-               } ).fail( spy );
-
-               assert.ok( spy.calledWith( {
-                       stage: 'upload',
-                       type: 'warning',
-                       details: 'badfilename/::.JPG'
-               } ), 'The request caused a bad file name error' );
-       } );
-
-       QUnit.test( '#save, successful upload', 2, function ( assert ) {
-               var spy = this.sandbox.spy();
-               this.sandbox.spy( editorApi, 'setPrependText' );
-
-               photoApi.save( {
-                       file: {
-                               name: 'z.jpg'
-                       },
-                       description: 'hello world'
-               } ).done( spy );
-
-               assert.ok( spy.calledOnce, 'call done' );
-               assert.ok( editorApi.setPrependText.calledWith( 
'[[File:z_2013-05-13_09-45.jpg|thumbnail|hello world]]\n\n' ), 'prepend text' );
-       } );
-
-       QUnit.test( '#save, error uploading, AbuseFilter', 2, function ( assert 
) {
-               var doneSpy = this.sandbox.spy(),
-                       failSpy = this.sandbox.spy();
-
-               photoApi.postWithToken.returns( $.Deferred().resolve( {
-                               error: {
-                                       code: 'verification-error',
-                                       info: 'This file did not pass file 
verification',
-                                       details: [ 'abusefilter-warning', 
'test', 1 ]
-                               }
-                       } ) );
-
-               photoApi.save( {
-                       insertInPage: true,
-                       file: {
-                               name: 'z.jpg'
-                       },
-                       description: 'hello world'
-               } ).done( doneSpy ).fail( failSpy );
-
-               assert.ok( !doneSpy.called, 'don\'t call done' );
-               assert.ok( failSpy.calledWith( {
-                       stage: 'upload',
-                       type: 'error',
-                       details: 'verification-error/abusefilter-warning'
-               } ), 'call fail' );
-       } );
-
-       QUnit.test( '#save. error inserting in page, captcha', 2, function ( 
assert ) {
-               var doneSpy = this.sandbox.spy(),
-                       failSpy = this.sandbox.spy(),
-                       captcha = {
-                               type: 'image',
-                               mime: 'image/png',
-                               id: '1852528679',
-                               url: 
'/w/index.php?title=Especial:Captcha/image&wpCaptchaId=1852528679'
-                       };
-
-               editorApi.post
-                       .returns( $.Deferred().resolve( {
-                               edit: {
-                                       captcha: captcha,
-                                       result: 'Failure'
-                               }
-                       } ) );
-
-               photoApi.save( {
-                       insertInPage: true,
-                       file: {
-                               name: 'z.jpg'
-                       },
-                       description: 'hello world'
-               } ).done( doneSpy ).fail( failSpy );
-
-               assert.ok( !doneSpy.called, 'don\'t call done' );
-               assert.ok( failSpy.calledWith( {
-                       stage: 'edit',
-                       type: 'captcha',
-                       details: captcha
-               } ), 'call fail' );
-       } );
-
-       QUnit.test( '#save, error inserting in page, AbuseFilter', 2, function 
( assert ) {
-               var doneSpy = this.sandbox.spy(),
-                       failSpy = this.sandbox.spy();
-
-               editorApi.post.returns( $.Deferred().resolve( {
-                       edit: {
-                               code: 'abusefilter-warning-usuwanie-tekstu',
-                               info: 'Hit AbuseFilter: Usuwanie du\u017cej 
ilo\u015bci tekstu',
-                               warning: 'horrible desktop-formatted message',
-                               result: 'Failure'
-                       }
-               } ) );
-
-               photoApi.save( {
-                       insertInPage: true,
-                       file: {
-                               name: 'z.jpg'
-                       },
-                       description: 'hello world'
-               } ).done( doneSpy ).fail( failSpy );
-
-               assert.ok( !doneSpy.called, 'don\'t call done' );
-               assert.ok( failSpy.calledWith( {
-                       stage: 'edit',
-                       type: 'abusefilter',
-                       details: {
-                               type: 'warning',
-                               message: 'horrible desktop-formatted message'
-                       }
-               } ), 'call fail' );
-       } );
-
-       QUnit.module( 'MobileFrontend photo: filenames' );
-
-       QUnit.test( 'generateFileName', 1, function ( assert ) {
-               var date = new Date( Date.UTC( 2010, 9, 15, 12, 9 ) ),
-                       name = photo.generateFileName( 'Jon eating bacon next 
to an armadillo', '.jpg', date );
-               assert.strictEqual( name, 'Jon eating bacon next to an 
armadillo 2010-10-15 12-09.jpg',
-                       'Check file name is description with appended date' );
-       } );
-
-       QUnit.test( 'generateFileName with double apostrophes', 1, function ( 
assert ) {
-               var date = new Date( Date.UTC( 2010, 9, 15, 12, 9 ) ),
-                       name = photo.generateFileName( 'Image of \'\' the 
double apostrophe', '.jpg', date );
-               assert.strictEqual( name, 'Image of \'_ the double apostrophe 
2010-10-15 12-09.jpg',
-                       'Check double apostrophe stripped out' );
-       } );
-
-       QUnit.test( 'generateFileName test padding', 1, function ( assert ) {
-               var date = new Date( Date.UTC( 2013, 2, 1, 12, 51 ) ), // note 
0 = january
-                       name = photo.generateFileName( 'Tomasz eating bacon 
next to a dinosaur', '.jpg', date );
-               assert.strictEqual( name, 'Tomasz eating bacon next to a 
dinosaur 2013-03-01 12-51.jpg',
-                       'Check file name is description with appended date and 
numbers were padded' );
-       } );
-
-       QUnit.test( 'generateFileName double spaces', 1, function ( assert ) {
-               var longDescription = 'double space  woop woop  ',
-                       date = new Date( Date.UTC( 2013, 2, 1, 12, 51 ) ),
-                       name;
-
-               name = photo.generateFileName( longDescription, '.jpg', date );
-               assert.strictEqual( name, 'double space woop woop 2013-03-01 
12-51.jpg' );
-       } );
-
-       QUnit.test( 'generateFileName long line', 2, function ( assert ) {
-               var i,
-                       longDescription = '',
-                       date = new Date( Date.UTC( 2013, 2, 1, 12, 51 ) ),
-                       name;
-
-               for ( i = 0; i < 240; i++ ) {
-                       longDescription += 'a';
-               }
-               name = photo.generateFileName( longDescription, '.jpg', date );
-               assert.strictEqual( name.length, 230, 'Check file name was 
shortened to the minimum length' );
-               assert.strictEqual( name.substr( 223, 7 ), '-51.jpg', 'ends 
with date' );
-       } );
-
-       QUnit.test( 'generateFileName with new lines', 1, function ( assert ) {
-               var
-                       description = 'One\nTwo\nThree',
-                       date = new Date( Date.UTC( 2013, 2, 1, 12, 51 ) ),
-                       name;
-
-               name = photo.generateFileName( description, '.jpg', date );
-               assert.strictEqual( name, 'One-Two-Three 2013-03-01 12-51.jpg', 
'New lines converted' );
-       } );
-
-       QUnit.test( 'trimUtf8String', 4, function ( assert ) {
-               assert.strictEqual( photo.trimUtf8String( 'Just a string', 20 
), 'Just a string', 'ascii string fits' );
-               assert.strictEqual( photo.trimUtf8String( 'Just a string', 10 
), 'Just a str', 'ascii string truncated' );
-               assert.strictEqual( photo.trimUtf8String( 'Júst á stríng', 10 
), 'Júst á s', 'latin1 string truncated' );
-               assert.strictEqual( photo.trimUtf8String( 'こんにちは', 10 ), 'こんに', 
'CJK string truncated' );
-       } );
-
-}( jQuery, mw.mobileFrontend ) );
diff --git a/tests/qunit/modules/uploads/test_ProgressBar.js 
b/tests/qunit/modules/uploads/test_ProgressBar.js
deleted file mode 100644
index e5ec597..0000000
--- a/tests/qunit/modules/uploads/test_ProgressBar.js
+++ /dev/null
@@ -1,13 +0,0 @@
-( function ( M ) {
-
-       var ProgressBar = M.require( 'modules/uploads/ProgressBar' );
-
-       QUnit.module( 'MobileFrontend ProgressBar' );
-
-       QUnit.test( '#setValue', 1, function ( assert ) {
-               var progressBar = new ProgressBar();
-               progressBar.setValue( 0.35 );
-               assert.strictEqual( progressBar.$( '.value' ).css( 'width' ), 
'35%', 'set width to reflect value' );
-       } );
-
-}( mw.mobileFrontend ) );
diff --git a/tests/qunit/modules/uploads/test_UploadTutorial.js 
b/tests/qunit/modules/uploads/test_UploadTutorial.js
deleted file mode 100644
index 62f01e2..0000000
--- a/tests/qunit/modules/uploads/test_UploadTutorial.js
+++ /dev/null
@@ -1,39 +0,0 @@
-( function ( M ) {
-
-       var UploadTutorial = M.require( 'modules/uploads/UploadTutorial' ),
-               uploadTutorial;
-
-       QUnit.module( 'MobileFrontend UploadTutorial', {
-               setup: function () {
-                       uploadTutorial = new UploadTutorial();
-               }
-       } );
-
-       QUnit.test( '#initialize, with cancel button', 2, function ( assert ) {
-               assert.ok( uploadTutorial.$( '.cancel' ).length, 'Has cancel 
button' );
-               assert.ok( !uploadTutorial.$( 'input' ).length, 'Has no file 
button' );
-       } );
-
-       QUnit.test( '#initialize, with file button', 2, function ( assert ) {
-               uploadTutorial = new UploadTutorial( {
-                       funnel: 'article'
-               } );
-               assert.ok( uploadTutorial.$( 'div.button' ).length, 'Has file 
button' );
-               assert.ok( !uploadTutorial.$( '.cancel' ).length, 'Has no 
cancel button' );
-       } );
-
-       QUnit.test( '#onNextClick', 3, function ( assert ) {
-               assert.ok( uploadTutorial.$( '.slide' ).eq( 0 ).hasClass( 
'active' ), 'Initialises to page 0' );
-               uploadTutorial.onNextClick();
-               assert.ok( !uploadTutorial.$( '.slide' ).eq( 0 ).hasClass( 
'active' ), 'Deactivates page 0' );
-               assert.ok( uploadTutorial.$( '.slide' ).eq( 1 ).hasClass( 
'active' ), 'Progresses to page 1' );
-       } );
-
-       QUnit.test( '#onPreviousClick', 2, function ( assert ) {
-               uploadTutorial.onNextClick();
-               uploadTutorial.onPreviousClick();
-               assert.ok( !uploadTutorial.$( '.slide' ).eq( 1 ).hasClass( 
'active' ), 'Deactivates page 1' );
-               assert.ok( uploadTutorial.$( '.slide' ).eq( 0 ).hasClass( 
'active' ), 'Back to page 1' );
-       } );
-
-}( mw.mobileFrontend ) );
diff --git a/tests/qunit/modules/uploads/test_init.js 
b/tests/qunit/modules/uploads/test_init.js
deleted file mode 100644
index 03f4c48..0000000
--- a/tests/qunit/modules/uploads/test_init.js
+++ /dev/null
@@ -1,48 +0,0 @@
-( function ( $, M ) {
-
-       var photo = M.require( 'modules/uploads/_leadphoto' ),
-               _wgMFLeadPhotoUploadCssSelector,
-               articles = [
-                       // blank #content_0
-                       [ $( '<div><div id="content_0"></div></div>' ), true ],
-                       // infobox in #content_1
-                       [ $( '<div><div id="content_1"><table 
class="infobox"></div>' ), false ],
-                       // infobox in #content_0
-                       [ $( '<div><div id="content_0"><table 
class="infobox"></div></div>' ), false ],
-                       // navbox in #content_0
-                       [ $( '<div><table class="navbox"></table></div>' ), 
false ],
-                       // navbox in #content_0
-                       [ $( '<div><div id="content_0"><table 
class="navbox"></div></div>' ), false ],
-                       // thumbnail in #content_0
-                       [ $( '<div><div id="content_0"><div 
class="thumb"><img></div></div></div>' ), false ],
-                       // no #content_0 and no thumbnail, infobox or navbox
-                       [ $( '<div><p></p><div>' ), true ],
-                       // no #content_0 and a thumbnail
-                       [ $( '<div><div class="thumb"><img></div><div>' ), 
false ],
-                       // no #content_0 and an infobox
-                       [ $( '<div><table class="infobox"><div>' ), false ],
-                       // no #content_0 and a navbox
-                       [ $( '<div><table class="navbox"><div>' ), false ],
-                       // no #content_0, image not in .thumb (happens on main 
pages)
-                       [ $( '<div><img><div>' ), false ]
-               ];
-
-       QUnit.module( 'MobileFrontend photo', {
-               setup: function () {
-                       _wgMFLeadPhotoUploadCssSelector = mw.config.get( 
'wgMFLeadPhotoUploadCssSelector' );
-                       mw.config.set( 'wgMFLeadPhotoUploadCssSelector', 'img, 
.navbox, .infobox' );
-               },
-               teardown: function () {
-                       mw.config.set( 'wgMFLeadPhotoUploadCssSelector', 
_wgMFLeadPhotoUploadCssSelector );
-               }
-       } );
-
-       QUnit.test( '#needsPhoto', function ( assert ) {
-               QUnit.expect( articles.length );
-               var i;
-               for ( i = 0; i < articles.length; i++ ) {
-                       assert.strictEqual( photo.needsPhoto( articles[ i ][ 0 
] ), articles[ i ][ 1 ], 'article ' + i );
-               }
-       } );
-
-}( jQuery, mw.mobileFrontend ) );

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

Gerrit-MessageType: merged
Gerrit-Change-Id: I29ae18e2b8cd8e9b91d20c4f85d42c79dc70d6fd
Gerrit-PatchSet: 10
Gerrit-Project: mediawiki/extensions/MobileFrontend
Gerrit-Branch: master
Gerrit-Owner: Jdlrobson <[email protected]>
Gerrit-Reviewer: Florianschmidtwelzow <[email protected]>
Gerrit-Reviewer: Jdlrobson <[email protected]>
Gerrit-Reviewer: jenkins-bot <>

_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to