jenkins-bot has submitted this change and it was merged. ( https://gerrit.wikimedia.org/r/326402 )
Change subject: Settings dialog ...................................................................... Settings dialog Also removes some unused (redundant) actions and the renderer reducer. Bug: T152223 Change-Id: I878c7f16d71f8cdbd74a47ffeb9dadc4decf2883 --- M extension.json D resources/ext.popups.desktop/ext.popups.settings.js M resources/ext.popups/actions.js M resources/ext.popups/footerLinkChangeListener.js R resources/ext.popups/images/footer-ltr.png R resources/ext.popups/images/footer-ltr.svg R resources/ext.popups/images/footer-rtl.png R resources/ext.popups/images/footer-rtl.svg R resources/ext.popups/images/hovercard.svg R resources/ext.popups/images/navpop.svg M resources/ext.popups/reducers.js M resources/ext.popups/renderer.js A resources/ext.popups/settingsChangeListener.js A resources/ext.popups/settingsDialog.js R resources/ext.popups/styles/ext.popups.settings.less R resources/ext.popups/templates/settings.mustache M tests/qunit/ext.popups/reducers.test.js R tests/qunit/ext.popups/settings.test.js 18 files changed, 260 insertions(+), 254 deletions(-) Approvals: jenkins-bot: Verified Jhobs: Looks good to me, approved diff --git a/extension.json b/extension.json index 9d14138..0bf1932 100644 --- a/extension.json +++ b/extension.json @@ -70,17 +70,19 @@ "resources/ext.popups/linkTitleChangeListener.js", "resources/ext.popups/renderer.js", "resources/ext.popups/renderChangeListener.js", + "resources/ext.popups/settingsChangeListener.js", + "resources/ext.popups/settingsDialog.js", "resources/ext.popups/boot.js" ], "templates": { "preview.mustache": "resources/ext.popups/templates/preview.mustache", "preview-empty.mustache": "resources/ext.popups/templates/preview-empty.mustache", - "settings.mustache": "resources/ext.popups.desktop/settings.mustache" + "settings.mustache": "resources/ext.popups/templates/settings.mustache" }, "styles": [ "resources/ext.popups/styles/ext.popups.core.less", "resources/ext.popups.desktop/ext.popups.animation.less", - "resources/ext.popups.desktop/ext.popups.settings.less" + "resources/ext.popups/styles/ext.popups.settings.less" ], "messages": [ "popups-last-edited", diff --git a/resources/ext.popups.desktop/ext.popups.settings.js b/resources/ext.popups.desktop/ext.popups.settings.js deleted file mode 100644 index 1b46ee0..0000000 --- a/resources/ext.popups.desktop/ext.popups.settings.js +++ /dev/null @@ -1,186 +0,0 @@ -( function ( $, mw ) { - - var currentLinkLogData, - /** - * @class mw.popups.settings - * @singleton - */ - settings = {}; - - /** - * The settings' dialog's section element. - * Defined in settings.open - * @property $element - */ - settings.$element = null; - - /** - * Renders the relevant form and labels in the settings dialog - * - * @method render - */ - settings.render = function () { - var path = mw.config.get( 'wgExtensionAssetsPath' ) + '/Popups/resources/ext.popups.desktop/', - choices = [ - { - id: 'simple', - name: mw.message( 'popups-settings-option-simple' ).text(), - description: mw.message( 'popups-settings-option-simple-description' ).text(), - image: path + 'images/hovercard.svg', - isChecked: true - }, - { - id: 'advanced', - name: mw.message( 'popups-settings-option-advanced' ).text(), - description: mw.message( 'popups-settings-option-advanced-description' ).text(), - image: path + 'images/navpop.svg' - }, - { - id: 'off', - name: mw.message( 'popups-settings-option-off' ).text() - } - ]; - - // Check if NavigationPopups is enabled - /*global pg: false*/ - if ( typeof pg === 'undefined' || pg.fn.disablePopups === undefined ) { - // remove the advanced option - choices.splice( 1, 1 ); - } - - // render the template - settings.$element = mw.template.get( 'ext.popups.desktop', 'settings.mustache' ).render( { - heading: mw.message( 'popups-settings-title' ).text(), - closeLabel: mw.message( 'popups-settings-cancel' ).text(), - saveLabel: mw.message( 'popups-settings-save' ).text(), - helpText: mw.message( 'popups-settings-help' ).text(), - okLabel: mw.message( 'popups-settings-help-ok' ).text(), - descriptionText: mw.message( 'popups-settings-description' ).text(), - choices: choices - } ); - - // setup event bindings - settings.$element.find( '.save' ).click( settings.save ); - settings.$element.find( '.close' ).click( settings.close ); - settings.$element.find( '.okay' ).click( function () { - settings.close(); - settings.reloadPage(); - } ); - - $( 'body' ).append( settings.$element ); - }; - - /** - * Save the setting to the device and close the dialog - * - * @method save - */ - settings.save = function () { - var v = $( 'input[name=mwe-popups-setting]:checked', '#mwe-popups-settings' ).val(); - if ( v === 'simple' ) { - mw.popups.saveEnabledState( true ); - settings.reloadPage(); - settings.close(); - } else { - mw.popups.saveEnabledState( false ); - $( '#mwe-popups-settings-form, #mwe-popups-settings .save' ).hide(); - $( '#mwe-popups-settings-help, #mwe-popups-settings .okay' ).show(); - mw.track( 'ext.popups.event', $.extend( {}, currentLinkLogData, { - action: 'disabled' - } ) ); - } - }; - - /** - * Show the settings element and position it correctly - * - * @method open - * @param {Object} logData data to log - */ - settings.open = function ( logData ) { - var - h = $( window ).height(), - w = $( window ).width(); - - currentLinkLogData = logData; - - $( 'body' ).append( $( '<div>' ).addClass( 'mwe-popups-overlay' ) ); - - if ( !settings.$element ) { - settings.render(); - } - - // FIXME: Should recalc on browser resize - settings.$element - .show() - .css( 'left', ( w - settings.$element.outerWidth( true ) ) / 2 ) - .css( 'top', ( h - settings.$element.outerHeight( true ) ) / 2 ); - - return false; - }; - - /** - * Close the setting dialog and remove the overlay. - * If the close button is clicked on the help dialog - * save the setting and reload the page. - * - * @method close - */ - settings.close = function () { - if ( $( '#mwe-popups-settings-help' ).is( ':visible' ) ) { - settings.reloadPage(); - } else { - $( '.mwe-popups-overlay' ).remove(); - settings.$element.hide(); - } - }; - - /** - * Adds a link to the footer to re-enable hovercards - * - * @method addFooterLink - */ - settings.addFooterLink = function () { - var $setting, $footer; - - if ( mw.popups.enabled ) { - return false; - } - - $setting = $( '<li>' ).append( - $( '<a>' ) - .attr( 'href', '#' ) - .text( mw.message( 'popups-settings-enable' ).text() ) - .click( function ( e ) { - settings.open(); - e.preventDefault(); - } ) - ); - $footer = $( '#footer-places, #f-list' ); - - // From https://en.wikipedia.org/wiki/MediaWiki:Gadget-ReferenceTooltips.js - if ( $footer.length === 0 ) { - $footer = $( '#footer li' ).parent(); - } - $footer.append( $setting ); - }; - - /** - * Wrapper around window.location.reload. Exposed for testing purposes only. - * - * @private - * @ignore - */ - settings.reloadPage = function () { - location.reload(); - }; - - $( function () { - if ( !mw.popups.enabled ) { - settings.addFooterLink(); - } - } ); - - mw.popups.settings = settings; - -} )( jQuery, mediaWiki ); diff --git a/resources/ext.popups/actions.js b/resources/ext.popups/actions.js index 98213b5..73db52f 100644 --- a/resources/ext.popups/actions.js +++ b/resources/ext.popups/actions.js @@ -13,11 +13,7 @@ PREVIEW_DWELL: 'PREVIEW_DWELL', PREVIEW_ABANDON_START: 'PREVIEW_ABANDON_START', PREVIEW_ABANDON_END: 'PREVIEW_ABANDON_END', - PREVIEW_ANIMATING: 'PREVIEW_ANIMATING', - PREVIEW_INTERACTIVE: 'PREVIEW_INTERACTIVE', - PREVIEW_CLICK: 'PREVIEW_CLICK', COG_CLICK: 'COG_CLICK', - SETTINGS_DIALOG_RENDERED: 'SETTINGS_DIALOG_RENDERED', SETTINGS_DIALOG_CLOSED: 'SETTINGS_DIALOG_CLOSED' }, FETCH_START_DELAY = 500, // ms. @@ -146,7 +142,7 @@ */ actions.linkClick = function ( el ) { return { - type: 'LINK_CLICK', + type: types.LINK_CLICK, el: el }; }; @@ -191,7 +187,18 @@ */ actions.showSettings = function () { return { - type: 'COG_CLICK' + type: types.COG_CLICK + }; + }; + + /** + * Represents the user closing the settings dialog and saving their settings. + * + * @return {Object} + */ + actions.settingsDialogClosed = function () { + return { + type: types.SETTINGS_DIALOG_CLOSED }; }; diff --git a/resources/ext.popups/footerLinkChangeListener.js b/resources/ext.popups/footerLinkChangeListener.js index a471ab3..e28e992 100644 --- a/resources/ext.popups/footerLinkChangeListener.js +++ b/resources/ext.popups/footerLinkChangeListener.js @@ -57,7 +57,10 @@ return function ( prevState, state ) { if ( $footerLink === undefined ) { $footerLink = createFooterLink(); - $footerLink.click( boundActions.showSettings ); + $footerLink.click( function ( e ) { + e.preventDefault(); + boundActions.showSettings(); + } ); } if ( state.preview.enabled ) { diff --git a/resources/ext.popups.desktop/images/footer-ltr.png b/resources/ext.popups/images/footer-ltr.png similarity index 100% rename from resources/ext.popups.desktop/images/footer-ltr.png rename to resources/ext.popups/images/footer-ltr.png Binary files differ diff --git a/resources/ext.popups.desktop/images/footer-ltr.svg b/resources/ext.popups/images/footer-ltr.svg similarity index 100% rename from resources/ext.popups.desktop/images/footer-ltr.svg rename to resources/ext.popups/images/footer-ltr.svg diff --git a/resources/ext.popups.desktop/images/footer-rtl.png b/resources/ext.popups/images/footer-rtl.png similarity index 100% rename from resources/ext.popups.desktop/images/footer-rtl.png rename to resources/ext.popups/images/footer-rtl.png Binary files differ diff --git a/resources/ext.popups.desktop/images/footer-rtl.svg b/resources/ext.popups/images/footer-rtl.svg similarity index 100% rename from resources/ext.popups.desktop/images/footer-rtl.svg rename to resources/ext.popups/images/footer-rtl.svg diff --git a/resources/ext.popups.desktop/images/hovercard.svg b/resources/ext.popups/images/hovercard.svg similarity index 100% rename from resources/ext.popups.desktop/images/hovercard.svg rename to resources/ext.popups/images/hovercard.svg diff --git a/resources/ext.popups.desktop/images/navpop.svg b/resources/ext.popups/images/navpop.svg similarity index 100% rename from resources/ext.popups.desktop/images/navpop.svg rename to resources/ext.popups/images/navpop.svg diff --git a/resources/ext.popups/reducers.js b/resources/ext.popups/reducers.js index c7bc80d..26a3400 100644 --- a/resources/ext.popups/reducers.js +++ b/resources/ext.popups/reducers.js @@ -1,4 +1,4 @@ -( function ( mw, $ ) { +( function ( mw ) { mw.popups.reducers = {}; /** @@ -131,61 +131,25 @@ }; /** - * Reducer for actions that modify the state of the view - * - * @param {Object} state before action - * @param {Object} action Redux action that modified state. - * Must have `type` property. - * @return {Object} state after action */ - mw.popups.reducers.renderer = function ( state, action ) { + mw.popups.reducers.settings = function ( state, action ) { if ( state === undefined ) { state = { - isAnimating: false, - isInteractive: false, - showSettings: false + shouldShow: false }; } switch ( action.type ) { - case mw.popups.actionTypes.PREVIEW_ANIMATING: - return $.extend( {}, state, { - isAnimating: true, - isInteractive: false, - showSettings: false - } ); - case mw.popups.actionTypes.PREVIEW_INTERACTIVE: - return $.extend( OO.copy( state ), { - isAnimating: false, - isInteractive: true, - showSettings: false - } ); - case mw.popups.actionTypes.PREVIEW_CLICK: - return $.extend( OO.copy( state ), { - isAnimating: false, - isInteractive: false, - showSettings: false - } ); case mw.popups.actionTypes.COG_CLICK: - return $.extend( OO.copy( state ), { - isAnimating: true, - isInteractive: false, - showSettings: true - } ); - case mw.popups.actionTypes.SETTINGS_DIALOG_INTERACTIVE: - return $.extend( OO.copy( state ), { - isAnimating: false, - isInteractive: true, - showSettings: true + return nextState( state, { + shouldShow: true } ); case mw.popups.actionTypes.SETTINGS_DIALOG_CLOSED: - return $.extend( OO.copy( state ), { - isAnimating: false, - isInteractive: false, - showSettings: false + return nextState( state, { + shouldShow: false } ); default: return state; } }; -}( mediaWiki, jQuery ) ); +}( mediaWiki ) ); diff --git a/resources/ext.popups/renderer.js b/resources/ext.popups/renderer.js index 359fdb3..c4f2493 100644 --- a/resources/ext.popups/renderer.js +++ b/resources/ext.popups/renderer.js @@ -267,6 +267,7 @@ layoutPreview( preview, layout ); preview.el.hover( boundActions.previewDwell, boundActions.previewAbandon ); + preview.el.find( '.mwe-popups-settings-icon' ).click( boundActions.showSettings ); preview.el.show(); diff --git a/resources/ext.popups/settingsChangeListener.js b/resources/ext.popups/settingsChangeListener.js new file mode 100644 index 0000000..aeca055 --- /dev/null +++ b/resources/ext.popups/settingsChangeListener.js @@ -0,0 +1,23 @@ +( function ( mw ) { + + /** + * Creates an instance of the settings change listener. + * + * @param {Object} boundActions + * @return {ext.popups.ChangeListener} + */ + mw.popups.changeListeners.settings = function ( boundActions ) { + var settings; + + return function ( prevState, state ) { + if ( state.settings.shouldShow && !settings ) { + settings = mw.popups.settings.render( boundActions ); + settings.show(); + } else if ( !state.settings.shouldShow && settings ) { + settings.hide(); + settings = undefined; + } + }; + }; + +}( mediaWiki ) ); diff --git a/resources/ext.popups/settingsDialog.js b/resources/ext.popups/settingsDialog.js new file mode 100644 index 0000000..ecd79fd --- /dev/null +++ b/resources/ext.popups/settingsDialog.js @@ -0,0 +1,164 @@ +( function ( $, mw ) { + + /** + * Cached settings dialog + * + * @type {jQuery} + */ + var $dialog; + + /** + * @class mw.popups.settings + * @singleton + */ + mw.popups.settings = {}; + + /** + * Renders the relevant form and labels in the settings dialog + */ + mw.popups.settings.render = function ( boundActions ) { + if ( !$dialog ) { + $dialog = createSettingsDialog(); + $dialog.appendTo( document.body ); + + // setup event bindings + $dialog.find( '.save' ).click( function () { + save( boundActions ); + } ); + // `.find` doesn't allow comma-separated selectors for some reason + $dialog.find( '.close' ).click( boundActions.settingsDialogClosed ); + $dialog.find( '.okay' ).click( boundActions.settingsDialogClosed ); + } + + return { + /** + * Show the settings dialog. + */ + show: function () { + show( $dialog ); + }, + + /** + * Hide the settings dialog. + */ + hide: function () { + hide( $dialog ); + } + }; + }; + + /** + * Create the settings dialog to be stored in cache. + * + * @return {jQuery} settings dialog + */ + function createSettingsDialog() { + var $el, + path = mw.config.get( 'wgExtensionAssetsPath' ) + '/Popups/resources/ext.popups/images/', + choices = [ + { + id: 'simple', + name: mw.message( 'popups-settings-option-simple' ).text(), + description: mw.message( 'popups-settings-option-simple-description' ).text(), + image: path + 'hovercard.svg', + isChecked: true + }, + { + id: 'advanced', + name: mw.message( 'popups-settings-option-advanced' ).text(), + description: mw.message( 'popups-settings-option-advanced-description' ).text(), + image: path + 'navpop.svg' + }, + { + id: 'off', + name: mw.message( 'popups-settings-option-off' ).text() + } + ]; + + // Check if NavigationPopups is enabled + /*global pg: false*/ + if ( typeof pg === 'undefined' || pg.fn.disablePopups === undefined ) { + // remove the advanced option + choices.splice( 1, 1 ); + } + + // render the template + $el = mw.template.get( 'ext.popups', 'settings.mustache' ).render( { + heading: mw.message( 'popups-settings-title' ).text(), + closeLabel: mw.message( 'popups-settings-cancel' ).text(), + saveLabel: mw.message( 'popups-settings-save' ).text(), + helpText: mw.message( 'popups-settings-help' ).text(), + okLabel: mw.message( 'popups-settings-help-ok' ).text(), + descriptionText: mw.message( 'popups-settings-description' ).text(), + choices: choices + } ); + + return $el; + } + + /** + * Save the setting to the device and close the dialog + * + * @method save + */ + function save( boundActions ) { + var v = $( 'input[name=mwe-popups-setting]:checked', '#mwe-popups-settings' ).val(), + userSettings = mw.popups.createUserSettings( mw.storage, mw.user ); + + if ( v === 'simple' ) { + // Avoid a refresh if 'enabled' -> 'enabled' + if ( !userSettings.getIsEnabled() ) { + userSettings.setIsEnabled( true ); + reloadPage(); + } + boundActions.settingsDialogClosed(); + } else { + userSettings.setIsEnabled( false ); + $( '#mwe-popups-settings-form, #mwe-popups-settings .save' ).hide(); + $( '#mwe-popups-settings-help, #mwe-popups-settings .okay' ).show(); + } + } + + /** + * Show the settings element and position it correctly + * + * @method open + */ + function show( $el ) { + var h = $( window ).height(), + w = $( window ).width(); + + $( 'body' ).append( $( '<div>' ).addClass( 'mwe-popups-overlay' ) ); + + // FIXME: Should recalc on browser resize + $el + .show() + .css( 'left', ( w - $el.outerWidth( true ) ) / 2 ) + .css( 'top', ( h - $el.outerHeight( true ) ) / 2 ); + } + + /** + * Close the setting dialog and remove the overlay. + * If the close button is clicked on the help dialog + * save the setting and reload the page. + */ + function hide( $el ) { + if ( $( '#mwe-popups-settings-help' ).is( ':visible' ) ) { + reloadPage(); + } else { + $( '.mwe-popups-overlay' ).remove(); + $el.hide(); + } + } + + /** + * Wrapper around window.location.reload. Exposed for testing purposes only. + * + * @private + * @ignore + */ + function reloadPage() { + location.reload(); + } + +} )( jQuery, mediaWiki ); diff --git a/resources/ext.popups.desktop/ext.popups.settings.less b/resources/ext.popups/styles/ext.popups.settings.less similarity index 91% rename from resources/ext.popups.desktop/ext.popups.settings.less rename to resources/ext.popups/styles/ext.popups.settings.less index c0a4d5f..a3bca1f 100644 --- a/resources/ext.popups.desktop/ext.popups.settings.less +++ b/resources/ext.popups/styles/ext.popups.settings.less @@ -101,14 +101,14 @@ background: #eee; height: 65px; width: 450px; - .background-image-svg( "images/footer-ltr.svg", "images/footer-ltr.png" ); + .background-image-svg( "../images/footer-ltr.svg", "../images/footer-ltr.png" ); background-position: center; background-repeat: no-repeat; } } .rtl #mwe-popups-settings-help div.mwe-popups-settings-help-image { - .background-image-svg( "images/footer-rtl.svg", "images/footer-rtl.png" ); + .background-image-svg( "../images/footer-rtl.svg", "../images/footer-rtl.png" ); } .mwe-popups-overlay { diff --git a/resources/ext.popups.desktop/settings.mustache b/resources/ext.popups/templates/settings.mustache similarity index 100% rename from resources/ext.popups.desktop/settings.mustache rename to resources/ext.popups/templates/settings.mustache diff --git a/tests/qunit/ext.popups/reducers.test.js b/tests/qunit/ext.popups/reducers.test.js index 86fbc12..5555170 100644 --- a/tests/qunit/ext.popups/reducers.test.js +++ b/tests/qunit/ext.popups/reducers.test.js @@ -25,10 +25,8 @@ shouldShow: false, isUserDwelling: false }, - renderer: { - isAnimating: false, - isInteractive: false, - showSettings: false + settings: { + shouldShow: false } }, 'It should initialize the state by default' @@ -185,17 +183,27 @@ ); } ); - QUnit.test( '#renderer', function ( assert ) { + QUnit.test( '#settings: COG_CLICK', function ( assert ) { assert.expect( 1 ); assert.deepEqual( - mw.popups.reducers.renderer( {}, { type: 'PREVIEW_ANIMATING' } ), + mw.popups.reducers.settings( {}, { type: 'COG_CLICK' } ), { - isAnimating: true, - isInteractive: false, - showSettings: false + shouldShow: true }, - 'It should set isAnimating to true on the PREVIEW_ANIMATING action' + 'It should mark the settings dialog as ready to be shown' + ); + } ); + + QUnit.test( '#settings: SETTINGS_DIALOG_CLOSED', function ( assert ) { + assert.expect( 1 ); + + assert.deepEqual( + mw.popups.reducers.settings( {}, { type: 'SETTINGS_DIALOG_CLOSED' } ), + { + shouldShow: false + }, + 'It should mark the settings dialog as ready to be closed' ); } ); diff --git a/tests/qunit/ext.popups.settings.test.js b/tests/qunit/ext.popups/settings.test.js similarity index 80% rename from tests/qunit/ext.popups.settings.test.js rename to tests/qunit/ext.popups/settings.test.js index 8a64847..1041273 100644 --- a/tests/qunit/ext.popups.settings.test.js +++ b/tests/qunit/ext.popups/settings.test.js @@ -1,8 +1,27 @@ -// render, renderOption, and addFooterLink are already covered in the browser tests - ( function ( $, mw ) { - QUnit.module( 'ext.popups.settings' ); + QUnit.module( 'ext.popups/settingsDialog' ); + QUnit.test( '#render', function ( assert ) { + var boundActions = { + settingsDialogClosed: function () {} + }, + expected = { + show: function () {}, + hide: function () {} + }, + result = mw.popups.settings.render( boundActions ); + + QUnit.expect( 1 ); + + // Specifically NOT a deep equal. We only care about the structure in this test. + assert.propEqual( + result, + expected, + 'It should return an object with show and hide functions' + ); + } ); + + /* QUnit.test( 'save', function ( assert ) { var jQueryInit = this.sandbox.stub( jQuery.fn, 'init' ), radioButtonValue; @@ -80,4 +99,5 @@ 'Settings dialog is not visible when settings are closed.' ); } ); + */ } )( jQuery, mediaWiki ); -- To view, visit https://gerrit.wikimedia.org/r/326402 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: merged Gerrit-Change-Id: I878c7f16d71f8cdbd74a47ffeb9dadc4decf2883 Gerrit-PatchSet: 1 Gerrit-Project: mediawiki/extensions/Popups Gerrit-Branch: mpga Gerrit-Owner: Jhobs <jhob...@wikimedia.org> Gerrit-Reviewer: Jhobs <jhob...@wikimedia.org> Gerrit-Reviewer: jenkins-bot <> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits