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

Change subject: Convert to use OOUI
......................................................................


Convert to use OOUI

On the backend, we now use a simplified OOUIHTMLForm. The frontend was
mostly re-written to use OOUI.

Co-Authored-By: Prateek Saxena <[email protected]>
Change-Id: Icecc027206484feaf08dc5247f82356eb7d45469
---
A .gitignore
A .jscsrc
A .jshintignore
M .jshintrc
A Gruntfile.js
M SpecialUrlShortener.php
M UrlShortener.php
D js/ext.urlShortener.special.js
D less/ext.urlShortener.special.less
A modules/ext.urlShortener.special.js
A package.json
11 files changed, 238 insertions(+), 282 deletions(-)

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



diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..c2658d7
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+node_modules/
diff --git a/.jscsrc b/.jscsrc
new file mode 100644
index 0000000..9d22e3f
--- /dev/null
+++ b/.jscsrc
@@ -0,0 +1,3 @@
+{
+       "preset": "wikimedia"
+}
diff --git a/.jshintignore b/.jshintignore
new file mode 100644
index 0000000..3c3629e
--- /dev/null
+++ b/.jshintignore
@@ -0,0 +1 @@
+node_modules
diff --git a/.jshintrc b/.jshintrc
index ca284e1..66e3d48 100644
--- a/.jshintrc
+++ b/.jshintrc
@@ -1,18 +1,24 @@
 {
-       "globals": {
-               "console": true,
-               "require": true,
-               "module": true,
-               "marshaller": true
-       },
-
-       "browser": true,
-       "curly": true,
+       // Enforcing
+       "bitwise": true,
        "eqeqeq": true,
-       "forin": false,
-       "onevar": false,
-       "trailing": true,
-       "undef" : true,
+       "freeze": true,
+       "latedef": true,
+       "noarg": true,
+       "nonew": true,
+       "undef": true,
        "unused": true,
-       "supernew": true
+       "strict": false,
+
+       // Relaxing
+       "es5": false,
+
+       // Environment
+       "browser": true,
+       "jquery": true,
+
+       "globals": {
+               "mediaWiki": false,
+               "OO": false
+       }
 }
diff --git a/Gruntfile.js b/Gruntfile.js
new file mode 100644
index 0000000..c2a64cc
--- /dev/null
+++ b/Gruntfile.js
@@ -0,0 +1,44 @@
+/*jshint node:true */
+module.exports = function ( grunt ) {
+       grunt.loadNpmTasks( 'grunt-contrib-jshint' );
+       grunt.loadNpmTasks( 'grunt-jsonlint' );
+       grunt.loadNpmTasks( 'grunt-banana-checker' );
+       grunt.loadNpmTasks( 'grunt-jscs' );
+       grunt.loadNpmTasks( 'grunt-tyops' );
+
+       grunt.initConfig( {
+               tyops: {
+                       options: {
+                               typos: 'build/typos.json'
+                       },
+                       src: [
+                               '**/*',
+                               '!{node_modules,vendor}/**',
+                               '!build/typos.json'
+                       ]
+               },
+               jshint: {
+                       options: {
+                               jshintrc: true
+                       },
+                       all: [
+                               'modules/**/*.js'
+                       ]
+               },
+               jscs: {
+                       src: '<%= jshint.all %>'
+               },
+               banana: {
+                       all: [ 'i18n/' ]
+               },
+               jsonlint: {
+                       all: [
+                               '**/*.json',
+                               '!node_modules/**'
+                       ]
+               }
+       } );
+
+       grunt.registerTask( 'test', [ 'tyops', 'jshint', 'jscs', 'jsonlint', 
'banana' ] );
+       grunt.registerTask( 'default', 'test' );
+};
diff --git a/SpecialUrlShortener.php b/SpecialUrlShortener.php
index d12c699..ea1ef28 100644
--- a/SpecialUrlShortener.php
+++ b/SpecialUrlShortener.php
@@ -20,42 +20,22 @@
                parent::__construct( 'UrlShortener' );
        }
 
+       protected function getDisplayFormat() {
+               return 'ooui';
+       }
+
        /**
-        * Remove the legend wrapper and also use the agora styles.
         * @param HTMLForm $form
         */
        protected function alterForm( HTMLForm $form ) {
-               $form->setWrapperLegend( false );
-               $form->setDisplayFormat( 'raw' );
-               $form->suppressDefaultSubmit( true );
-               $form->addHeaderText(
-                       Html::element( "span", array( "id" => 
"mwe-urlshortener-form-header" ),
-                               $this->msg( 'urlshortener-form-header' )->text()
-                       )
-               );
-               $form->addFooterText(
-                       Html::rawElement( 'div', array( 'id' => 
'mwe-urlshortener-form-footer' ),
-                               Html::element( 'span', array( 'id' => 
'mwe-urlshortener-shortened-url-label' ),
-                                       $this->msg( 
'urlshortener-shortened-url-label')->text()
-                               ) .
-                               Html::rawElement( 'div', array(
-                                               // Using a div instead of an 
<input> so we don't have to worry about sizing the
-                                               // input to match the length of 
the shortened URL
-                                               'id' => 
'mwe-urlshortener-shorturl-display',
-                                       )
-                               )
-                       ) .
-                       Html::rawElement( 'div', array( 'id' => 
'mwe-urlshortener-form-error' ) )
-               );
+               $form->setMethod( 'GET' );
+               $form->setSubmitID( 'mw-urlshortener-submit' );
+               $form->setSubmitTextMsg( 'urlshortener-url-input-submit' );
 
                $this->getOutput()->addModules( 'ext.urlShortener.special' );
                $this->getOutput()->addJsConfigVars( array(
                        'wgUrlShortenerDomainsWhitelist' => 
UrlShortenerUtils::getWhitelistRegex(),
                ) );
-               $this->getOutput()->addModuleStyles( 'mediawiki.ui' );
-               // Send Styles anyway, even without JS
-               $this->getOutput()->addModuleStyles( 
'ext.urlShortener.special.styles' );
-
        }
 
 
@@ -67,6 +47,10 @@
         * @return bool|string true if url is valid, error message otherwise
         */
        public function validateURL( $url, $allData ) {
+               if ( $url === null ) {
+                       // No input
+                       return true;
+               }
                $validity_check =  UrlShortenerUtils::validateUrl( $url );
                if ( $validity_check === true ) {
                        return true;
@@ -82,29 +66,16 @@
        protected function getFormFields() {
                return array(
                        'url' => array(
-                               'class' => 'HTMLTextField',
-                               'cssclass' => 'mw-ui-input',
                                'validation-callback' => array( $this, 
'validateURL' ),
                                'required' => true,
                                'type' => 'url',
-                               'id' => 'mwe-urlshortener-url-input',
+                               'name' => 'url',
+                               'label-message' => 'urlshortener-form-header',
+                               'autofocus' => true,
+                               'id' => 'mw-urlshortener-url-input',
                                'placeholder' => $this->msg( 
'urlshortener-url-input-label' )->text()
                        ),
-                       'submit' => array(
-                               'class' => 'HTMLSubmitField',
-                               'default' => $this->msg( 
'urlshortener-url-input-submit' )->text(),
-                               'cssclass' => 'mw-ui-button mw-ui-progressive',
-                               'id' => 'mwe-urlshortener-url-submit'
-                       )
                );
-       }
-
-       /**
-        * Stub to make this compatible with MW1.21, since this was
-        * abstract in that version.
-        */
-       public function onSuccess() {
-               parent::onSuccess();
        }
 
        /**
@@ -117,14 +88,15 @@
         */
        public function onSubmit( array $data ) {
                $out = $this->getOutput();
-               $out->addModuleStyles( 'ext.urlShortener.special.styles' );
+               $out->enableOOUI();
+               if ( $data['url'] === null ) {
+                       return false;
+               }
 
-               $html = Html::element( 'input', array(
-                       'type' => 'text',
-                       'readonly' => true,
-                       'id' => 'mwe-urlshortener-shorturl-display',
-                       'value' => UrlShortenerUtils::makeUrl( 
UrlShortenerUtils::getShortCode( $data['url']  ) )
-               ));
+               $html = new OOUI\TextInputWidget( array(
+                       'value' => UrlShortenerUtils::makeUrl( 
UrlShortenerUtils::getShortCode( $data['url']  ) ),
+                       'readOnly' => true,
+               ) );
                $out->addHTML( $html );
                return true;
        }
diff --git a/UrlShortener.php b/UrlShortener.php
index f1b5182..9033bad 100644
--- a/UrlShortener.php
+++ b/UrlShortener.php
@@ -101,35 +101,23 @@
 
 $wgAPIModules['shortenurl'] = 'ApiShortenUrl';
 
-// Served both to JS and non-JS clients
-$wgResourceModules['ext.urlShortener.special.styles'] = array(
-       'styles' => 'less/ext.urlShortener.special.less',
-       'targets' => array ( 'desktop', 'mobile' ),
-       'position' => 'top',
-       'dependencies' => array(
-               'mediawiki.ui',
-       ),
-       'localBasePath' => __DIR__,
-       'remoteExtPath' => 'UrlShortener',
-);
-
 // Served only to JS clients
 $wgResourceModules['ext.urlShortener.special'] = array(
        'scripts' => array(
-               'js/ext.urlShortener.special.js',
+               'modules/ext.urlShortener.special.js',
        ),
        'messages' => array(
                'urlshortener-error-malformed-url',
                'urlshortener-error-disallowed-url',
                'urlshortener-url-input-submit',
                'urlshortener-url-input-submitting',
+               'urlshortener-shortened-url-label',
        ),
        'localBasePath' => __DIR__,
        'remoteExtPath' => 'UrlShortener',
        'dependencies' => array(
+               'oojs-ui',
                'mediawiki.api',
                'mediawiki.Uri',
-               'jquery.tipsy',
        ),
-       "position" => "top"
 );
diff --git a/js/ext.urlShortener.special.js b/js/ext.urlShortener.special.js
deleted file mode 100644
index f1e53fd..0000000
--- a/js/ext.urlShortener.special.js
+++ /dev/null
@@ -1,138 +0,0 @@
-(function ( mw, $ ) {
-       function UrlShortener() {
-       }
-
-       /**
-        * Initialize the UrlShortener!
-        *
-        * Primarily sets up event handlers
-        */
-       UrlShortener.prototype.init = function () {
-               $( '#mwe-urlshortener-url-submit' ).click( $.proxy( 
this.onSubmit, this ) );
-               $( '#mwe-urlshortener-shorturl-display' ).click( function () {
-                       selectElement( this );
-               } );
-               $( '#mwe-urlshortener-url-input' ).tipsy( {
-                       gravity: 'n',
-                       fade: true,
-                       tigger: 'manual',
-                       className: 'mwe-urlshortener-tipsy'
-               } );
-               this.api = new mw.Api();
-       };
-
-       /**
-        * Event Handler for the 'shorten' button
-        */
-       UrlShortener.prototype.onSubmit = function () {
-               $( "#mwe-urlshortener-form-footer" ).hide( 'blind' );
-               $( '#mwe-urlshortener-url-submit' ).val( mw.message( 
'urlshortener-url-input-submitting' ).text() );
-               this.shortenUrl(
-                       this.getLongUrl()
-               ).done( function ( shorturl ) {
-                               $( '#mwe-urlshortener-url-submit' ).val( 
mw.message( 'urlshortener-url-input-submit' ).text() );
-                               $( "#mwe-urlshortener-form-footer" ).show( 
'blind' );
-                               // The selectElement() call makes the text 
selected, so the user can just ctrl-C it
-                               $( '#mwe-urlshortener-url-input' )
-                                       .attr( 'title', '' )
-                                       .attr( 'original-title', '' );
-                               selectElement( $( 
"#mwe-urlshortener-shorturl-display" ).text( shorturl )[0] );
-                       } ).fail( function ( err ) {
-                               $( '#mwe-urlshortener-url-submit' ).val( 
mw.message( 'urlshortener-url-input-submit' ).text() );
-                               $( '#mwe-urlshortener-form-footer' ).hide();
-                               $( '#mwe-urlshortener-url-input' )
-                                       .attr( 'title', err.info )
-                                       .tipsy( 'show' );
-                       } );
-               return false;
-       };
-
-       /**
-        * Returns the current user specified long url that we need to shorten
-        *
-        * @returns String The long URL that the user has specified
-        */
-       UrlShortener.prototype.getLongUrl = function () {
-               return $( '#mwe-urlshortener-url-input' ).val();
-       };
-
-       /**
-        * Shorten a given url by making an API request
-        *
-        * @param url Url to shorten
-        * @returns jQuery.Promise A deferred object that resolves
-        *                         with the short url on success or
-        *                         fails with an error object on failure
-        */
-       UrlShortener.prototype.shortenUrl = function ( url ) {
-               var validate = this.validateInput( url );
-               if ( validate !== true ) {
-                       return $.Deferred().reject( validate ).promise();
-               }
-               return this.api.get( {
-                               action: 'shortenurl',
-                               url: url
-                       } ).then( function ( data ) {
-                               return data.shortenurl.shorturl;
-                       }, function ( errCode, data ) {
-                               return data.error;
-                       } );
-       };
-
-       /**
-        * Validate the input URL clientside. Note that this is not the
-        * only check - they are checked serverside too.
-        *
-        * Checks for both URL validity and whitelist matching.
-        *
-        * @param input String the URL that is to be shortened
-        * @returns Boolean|Object true if object is validated, an object 
matching what is
-        *                         returned by the API in case of error.
-        */
-       UrlShortener.prototype.validateInput = function( input ) {
-               var parsed;
-               try {
-                       parsed = new mw.Uri( input );
-               } catch ( e ) {
-                       return {
-                               code: 'urlshortener-error-malformed-url',
-                               info: mw.msg( 
'urlshortener-error-malformed-url' )
-                       };
-               }
-               if ( parsed.host.match( new RegExp( mw.config.get( 
'wgUrlShortenerDomainsWhitelist' ) ) ) ) {
-                       return true;
-               } else {
-                       return {
-                               code: 'urlshortener-error-disallowed-url',
-                               info: mw.msg( 
'urlshortener-error-disallowed-url', parsed.host )
-                       };
-               }
-       };
-
-       /**
-        * Method to 'select' an element, which is equivalent to the user
-        * clicking and dragging over it.
-        *
-        * Contains code from http://stackoverflow.com/a/987376
-        * @param element Element the element to select
-        */
-       function selectElement( element ) {
-               var range, selection;
-               if ( document.body.createTextRange ) { //ms
-                       range = document.body.createTextRange();
-                       range.moveToElementText( element );
-                       range.select();
-               } else if ( window.getSelection ) { //all others
-                       selection = window.getSelection();
-                       range = document.createRange();
-                       range.selectNodeContents( element );
-                       selection.removeAllRanges();
-                       selection.addRange( range );
-               }
-       }
-
-       $( function () {
-               var us = new UrlShortener();
-               us.init();
-       } )
-})( mediaWiki, jQuery );
diff --git a/less/ext.urlShortener.special.less 
b/less/ext.urlShortener.special.less
deleted file mode 100644
index 88a0270..0000000
--- a/less/ext.urlShortener.special.less
+++ /dev/null
@@ -1,64 +0,0 @@
-#firstHeading, #mwe-urlshortener-shortened-url-label {
-       font: 16px sans-serif !important;
-       font-weight: bold !important;
-       color: #444;
-       border: none;
-       margin-bottom: 0;
-}
-
-#mwe-urlshortener-url-textbox {
-       font-size: 1em;
-       line-height: 1.4em;
-       min-width: 40%;
-}
-
-#mwe-urlshortener-form-header {
-       display: block;
-       font: 14px sans-serif;
-       margin-bottom: 8px;
-}
-
-#mwe-urlshortener-form-footer {
-       display: none;
-       margin-top: 1em;
-       padding: 10px;
-       border: 1px solid #ddd;
-       border-bototm: 3px solid #e1e1e1;
-       background: #eee;
-       width: 430px;
-       box-radius: 2px;
-}
-
-#mwe-urlshortener-shorturl-display {
-       font: 1.5em monospace;
-       line-height: 1.6em;
-}
-
-#mwe-urlshortener-form-error {
-       display: none;
-       color: #FF9494;
-}
-
-.mwe-urlshortener-tipsy {
-       .tipsy-inner {
-               background: #d11d13;
-               border: none;
-               border-bottom: 3px solid #b51700;
-               border-radius: 0;
-               color: #fff;
-               font-weight: bold;
-               padding: 10px;
-       }
-
-       .tipsy-arrow {
-               width: 0 !important;
-               height: 5px !important;
-               border-left: 5px solid transparent;
-               border-right: 5px solid transparent;
-               border-top: 5px solid #d11d13;
-               background-image: none;
-               -webkit-transform: rotate( 180deg );
-               margin-top: -5px;
-       }
-
-}
\ No newline at end of file
diff --git a/modules/ext.urlShortener.special.js 
b/modules/ext.urlShortener.special.js
new file mode 100644
index 0000000..914642a
--- /dev/null
+++ b/modules/ext.urlShortener.special.js
@@ -0,0 +1,129 @@
+( function ( mw, $, OO ) {
+
+       mw.urlshortener = {
+               /**
+                * @var {mw.Api)
+                */
+               api: new mw.Api(),
+
+               /**
+                * @var {RegExp}
+                */
+               regex: new RegExp( mw.config.get( 
'wgUrlShortenerDomainsWhitelist' ) ),
+
+               /**
+                * @var {OO.ui.TextInputWidget}
+                */
+               shortened: null,
+
+               /**
+                * @var {OO.ui.TextInputWidget}
+                */
+               input: null,
+               /**
+                * @var {OO.ui.ButtonInputWidget}
+                */
+               submit: null,
+
+               /**
+                * Validate the input URL clientside. Note that this is not the
+                * only check - they are checked serverside too.
+                *
+                * Checks for both URL validity and whitelist matching.
+                *
+                * @param {string} input the URL that is to be shortened
+                * @return {boolean|Object} true if object is validated, an 
object matching what is
+                *                         returned by the API in case of error.
+                */
+               validateInput: function ( input ) {
+                       var parsed, error, self = mw.urlshortener;
+                       try {
+                               parsed = new mw.Uri( input );
+                               if ( parsed.host.match( self.regex ) ) {
+                                       this.setLabel( null );
+                                       return true;
+                               } else {
+                                       error = mw.msg( 
'urlshortener-error-disallowed-url', parsed.host );
+                               }
+                       } catch ( e ) {
+                               error = mw.msg( 
'urlshortener-error-malformed-url' );
+                       }
+
+                       this.setLabel( error );
+                       return false;
+               },
+
+               /**
+                * Click handler for the submit button
+                */
+               onSubmit: function () {
+                       var self = mw.urlshortener;
+                       self.input.pushPending().setReadOnly( true );
+                       self.setSubmit( 'submitting' );
+                       self.input.isValid().done( function () {
+                               self.shortenUrl(
+                                       self.input.getValue()
+                               ).done( function ( shorturl ) {
+                                               self.setSubmit( 'submit' );
+                                               
self.input.popPending().setReadOnly( false );
+
+                                               if ( !self.shortened ) {
+                                                       self.shortened = new 
OO.ui.TextInputWidget( {
+                                                               value: shorturl,
+                                                               readOnly: true
+                                                       } );
+                                                       // Wrap in a 
FieldLayout so we get the label
+                                                       
self.input.$element.after( new OO.ui.FieldLayout( self.shortened, {
+                                                               align: 'top',
+                                                               label: mw.msg( 
'urlshortener-shortened-url-label' )
+                                                       } ).$element );
+                                               } else {
+                                                       
self.shortened.setValue( shorturl );
+                                               }
+                                               self.shortened.select();
+                                       } ).fail( function ( err ) {
+                                               self.setSubmit( 'submit' );
+                                               
self.input.popPending().setReadOnly( false );
+                                               self.input.setLabel( err.info );
+                                       } );
+                       } );
+               },
+
+               init: function () {
+                       this.input = OO.ui.infuse( 'mw-urlshortener-url-input' 
);
+                       this.input.focus(); // FIXME not staying focused due to 
T106313
+                       this.input.setValidation( this.validateInput );
+                       this.submit = OO.ui.infuse( 'mw-urlshortener-submit' );
+                       this.submit.on( 'click', this.onSubmit );
+               },
+
+               /**
+                * @param {string} status either 'submitting' or 'submit'
+                */
+               setSubmit: function ( status ) {
+                       // urlshortener-url-input-submitting, 
urlshortener-url-input-submit
+                       this.submit.setLabel( mw.message( 
'urlshortener-url-input-' + status ).text() );
+               },
+
+               /**
+                * Shorten the provided url
+                *
+                * @param {string} url
+                * @return {jQuery.Promise}
+                */
+               shortenUrl: function ( url ) {
+                       return this.api.get( {
+                               action: 'shortenurl',
+                               url: url
+                       } ).then( function ( data ) {
+                               return data.shortenurl.shorturl;
+                       }, function ( errCode, data ) {
+                               return data.error;
+                       } );
+               }
+       };
+
+       $( function () {
+               mw.urlshortener.init();
+       } );
+} )( mediaWiki, jQuery, OO );
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..63d5896
--- /dev/null
+++ b/package.json
@@ -0,0 +1,14 @@
+{
+  "scripts": {
+    "test": "grunt test"
+  },
+  "devDependencies": {
+    "grunt": "0.4.5",
+    "grunt-cli": "0.1.13",
+    "grunt-contrib-jshint": "0.11.2",
+    "grunt-banana-checker": "0.2.2",
+    "grunt-jscs": "1.8.0",
+    "grunt-jsonlint": "1.0.4",
+    "grunt-tyops": "0.1.0"
+  }
+}

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

Gerrit-MessageType: merged
Gerrit-Change-Id: Icecc027206484feaf08dc5247f82356eb7d45469
Gerrit-PatchSet: 12
Gerrit-Project: mediawiki/extensions/UrlShortener
Gerrit-Branch: master
Gerrit-Owner: Legoktm <[email protected]>
Gerrit-Reviewer: Bartosz DziewoƄski <[email protected]>
Gerrit-Reviewer: Legoktm <[email protected]>
Gerrit-Reviewer: Prtksxna <[email protected]>
Gerrit-Reviewer: Yuvipanda <[email protected]>
Gerrit-Reviewer: jenkins-bot <>

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

Reply via email to