Santhosh has uploaded a new change for review. https://gerrit.wikimedia.org/r/232000
Change subject: Refactor the dashboard and translationlist modules ...................................................................... Refactor the dashboard and translationlist modules Translation list module was handling the rendering and event handlers of translation status filter and language selectors. It was also rendering the new translation button. This commit removes all the above features to the dashboard module. Translation list is now just a widget to list the translations. This change is to initiate the listing of suggestion initiated by dashboard module and provide way for suggestion list to share the language filters. Functionality wise nothing changed. Change-Id: Ie5bbcb3a01dfa0b136ad8fa000ca1f52a7a98878 --- M extension.json M modules/dashboard/ext.cx.dashboard.js M modules/dashboard/ext.cx.translationlist.js M scripts/manage-lists.php 4 files changed, 269 insertions(+), 266 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/ContentTranslation refs/changes/00/232000/1 diff --git a/extension.json b/extension.json index abbb8d1..c1604cf 100644 --- a/extension.json +++ b/extension.json @@ -42,6 +42,7 @@ }, "APIListModules": { "contenttranslation": "ApiQueryContentTranslation", + "contenttranslationlist": "ApiQueryContentTranslationList", "contenttranslationstats": "ApiQueryContentTranslationStats", "contenttranslationlangtrend": "ApiQueryContentTranslationLanguageTrend", "cxpublishedtranslations": "ApiQueryPublishedTranslations" @@ -59,6 +60,7 @@ "ApiContentTranslationPublish": "api/ApiContentTranslationPublish.php", "ApiContentTranslationToken": "api/ApiContentTranslationToken.php", "ApiQueryContentTranslation": "api/ApiQueryContentTranslation.php", + "ApiQueryContentTranslationList": "api/ApiQueryContentTranslationList.php", "ApiQueryContentTranslationLanguageTrend": "api/ApiQueryContentTranslationLanguageTrend.php", "ApiQueryContentTranslationStats": "api/ApiQueryContentTranslationStats.php", "ApiQueryPublishedTranslations": "api/ApiQueryPublishedTranslations.php", @@ -193,6 +195,7 @@ "ext.cx.header", "ext.cx.model", "ext.cx.sitemapper", + "ext.cx.source.selector", "ext.cx.translationlist", "mediawiki.Uri", "mediawiki.ui.button" @@ -202,7 +205,13 @@ "cx-dashboard-sidebar-title", "cx-dashboard-sidebar-information", "cx-dashboard-sidebar-stats", - "cx-dashboard-sidebar-feedback" + "cx-dashboard-sidebar-feedback", + "cx-create-new-translation", + "cx-translation-filter-suggested-translations", + "cx-translation-filter-published-translations", + "cx-translation-filter-draft-translations", + "cx-translation-filter-from-any-language", + "cx-translation-filter-to-any-language" ] }, "ext.cx.magnuslink": { @@ -741,7 +750,6 @@ ], "dependencies": [ "ext.cx.progressbar", - "ext.cx.source.selector", "ext.cx.util", "ext.cx.widgets.overlay", "jquery.uls.data", @@ -749,12 +757,6 @@ ], "messages": [ "cx-dashboard-header", - "cx-create-new-translation", - "cx-translation-filter-suggested-translations", - "cx-translation-filter-published-translations", - "cx-translation-filter-draft-translations", - "cx-translation-filter-from-any-language", - "cx-translation-filter-to-any-language", "cx-discard-translation", "cx-translation-status-draft", "cx-translation-status-deleted", diff --git a/modules/dashboard/ext.cx.dashboard.js b/modules/dashboard/ext.cx.dashboard.js index 467da96..ac36202 100644 --- a/modules/dashboard/ext.cx.dashboard.js +++ b/modules/dashboard/ext.cx.dashboard.js @@ -20,23 +20,94 @@ this.siteMapper = siteMapper; this.$header = null; this.$sidebar = null; - this.$translationList = null; + this.translationList = null; + this.$translationListContainer = null; this.$newTranslationButton = null; + this.$filter = null; + this.$listHeader = null; + this.$sourceLanguageFilter = null; + this.$targetLanguageFilter = null; + this.$cta = null; this.init(); } CXDashboard.prototype.init = function () { this.render(); - this.initComponents(); + this.initLists(); this.listen(); mw.hook( 'mw.cx.dashboard.ready' ).fire(); }; /** + * Get all the translations of given user. + * + * @return {jQuery.Promise} + */ + CXDashboard.prototype.getTranslations = function () { + var api = new mw.Api(); + + return api.get( { + action: 'query', + list: 'contenttranslation', + format: 'json' + } ); + }; + + /** * Initialize the components */ - CXDashboard.prototype.initComponents = function () { - this.$translationList.cxTranslationList( this.siteMapper ); + CXDashboard.prototype.initLists = function () { + var self = this; + + this.getTranslations().done( function ( response ) { + self.renderTranslations( + response.query.contenttranslation.translations + ); + } ); + // TODO: Get suggestions + }; + + /** + * Populate the language filter + * + * @param {jQuery} $filter Source filter or target filter to fill + * @param {[String]} languages Array of languag codes + */ + CXDashboard.prototype.populateLanguageFilter = function ( $filter, languages ) { + var i; + + for ( i = 0; i < languages.length; i++ ) { + $filter.append( $( '<option>' ) + // Todo: use translated language name + .text( $.uls.data.getAutonym( languages[ i ] ) ) + .attr( 'value', languages[ i ] ) + ); + } + }; + /** + * Populates various UI components with data in the given translations. + */ + CXDashboard.prototype.renderTranslations = function ( translations ) { + var sourceLanguages, targetLanguages; + + // Remove unnecessary object wrapping to get plain list of objects + translations = $.map( translations, function ( e ) { + return e.translation; + } ); + + this.translations = translations; + this.translationList = new mw.cx.CXTranslationList( this.$translationListContainer, this.translations, this.siteMapper ); + this.translationList.init(); + sourceLanguages = $.map( translations, function ( e ) { + return e.sourceLanguage; + } ); + + this.populateLanguageFilter( this.$sourceLanguageFilter, mw.cx.unique( sourceLanguages ) ); + + targetLanguages = $.map( translations, function ( e ) { + return e.targetLanguage; + } ); + this.populateLanguageFilter( this.$targetLanguageFilter, mw.cx.unique( targetLanguages ) ); }; CXDashboard.prototype.getSidebarItems = function () { @@ -87,28 +158,183 @@ .append( $header, $links ); }; + /** + * Creates a jQuery select element from given options. + * @param {string} classes + * @param {Object} options + * @return {jQuery} + */ + function createSelect( classes, options ) { + var i, value, key, + keys = Object.keys( options ), + $select = $( '<select>' ).addClass( classes ); + + for ( i = 0; i < keys.length; i++ ) { + value = keys[ i ]; + key = options[ value ]; + + $select.append( $( '<option>' ).text( key ).attr( 'value', value ) ); + } + + return $select; + } + CXDashboard.prototype.render = function () { this.$header = $( '<div>' ) .addClass( 'cx-header--dashboard' ); this.$header.cxHeader( this.siteMapper, mw.msg( 'cx-dashboard-header' ) ); - this.$translationList = $( '<div>' ) - .addClass( 'cx-translationlist-container' ); + this.$translationListContainer = this.buildTranslationList(); this.$sidebar = $( '<div>' ) .addClass( 'cx-dashboard__sidebar' ) .append( this.buildSidebar() ); this.$dashboard = $( '<div>' ) .addClass( 'cx-dashboard' ) - .append( this.$translationList, this.$sidebar ); + .append( this.$translationListContainer, this.$sidebar ); this.$container.append( this.$header, this.$dashboard ); }; + CXDashboard.prototype.buildTranslationList = function () { + var $sourceLanguageContainer, $targetLanguageContainer; + + this.$listHeader = $( '<div>' ) + .addClass( 'translation-filter' ); + + this.$newTranslationButton = $( '<button>' ) + .addClass( 'cx-cta__new-translation mw-ui-button mw-ui-constructive' ) + .text( mw.msg( 'cx-create-new-translation' ) ); + this.$cta = $( '<div>' ) + .addClass( 'cx-cta' ) + .append( this.$newTranslationButton ); + + this.$filter = $( '<span>' ) + .addClass( 'cx-statusfilter' ) + .append( + $( '<span>' ) + .addClass( 'cx-status cx-status--draft cx-status--selected mw-ui-input' ) + .text( mw.msg( 'cx-translation-filter-draft-translations' ) ), + $( '<span>' ) + .addClass( 'cx-status cx-status--published mw-ui-input' ) + .text( mw.msg( 'cx-translation-filter-published-translations' ) ) + ); + + this.$sourceLanguageFilter = createSelect( + 'translation-source-language-filter', { + '': mw.msg( 'cx-translation-filter-from-any-language' ) + } + ); + + this.$targetLanguageFilter = createSelect( + 'translation-target-language-filter', { + '': mw.msg( 'cx-translation-filter-to-any-language' ) + } + ); + + $sourceLanguageContainer = $( '<div>' ) + .addClass( 'translation-language-source-container' ) + .append( + this.$sourceLanguageFilter, + $( '<div>' ) + .addClass( 'translation-language-select-content' ) + .text( mw.msg( 'cx-translation-filter-from-any-language' ) ), + $( '<div>' ) + .addClass( 'translation-language-select-arrow' ) + ); + + $targetLanguageContainer = $( '<div>' ) + .addClass( 'translation-language-target-container' ) + .append( + this.$targetLanguageFilter, + $( '<div>' ) + .addClass( 'translation-language-select-content' ) + .text( mw.msg( 'cx-translation-filter-to-any-language' ) ), + $( '<div>' ).addClass( 'translation-language-select-arrow' ) + ); + + this.$listHeader.append( + this.$filter, + $( '<div>' ).addClass( 'translation-language-filter' ).append( + $sourceLanguageContainer, + $( '<div>' ).addClass( 'translation-language-arrow' ), + $targetLanguageContainer + ), + this.$cta + ); + + return $( '<div>' ) + .addClass( 'cx-translationlist-container' ) + .append( this.$listHeader ); + }; + CXDashboard.prototype.listen = function () { + var setFilter, + self = this; + + setFilter = $.proxy( this.setFilter, this ); + + this.$filter.click( '.cx-status', function ( e ) { + var $filter = $( e.target ); + + self.$filter + .find( '.cx-status--selected' ) + .removeClass( 'cx-status--selected' ); + + $filter.addClass( 'cx-status--selected' ); + + if ( $filter.is( '.cx-status--draft' ) ) { + setFilter( 'status', 'draft' ); + } else if ( $filter.is( '.cx-status--published' ) ) { + setFilter( 'status', 'published' ); + } + } ); + + this.$sourceLanguageFilter.on( 'change', function () { + var code = $( this ).val(); + + setFilter( 'sourceLanguage', code ); + + self.$sourceLanguageFilter + .siblings( '.translation-language-select-content' ) + .text( $.uls.data.getAutonym( code ) ); + } ); + + this.$targetLanguageFilter.on( 'change', function () { + var code = $( this ).val(); + + setFilter( 'targetLanguage', code ); + self.$targetLanguageFilter + .siblings( '.translation-language-select-content' ) + .text( $.uls.data.getAutonym( code ) ); + } ); + + this.initSourceSelector(); + // Scroll handler $( window ).scroll( $.throttle( 250, $.proxy( this.scroll, this ) ) ); }; + CXDashboard.prototype.setFilter = function ( type, value ) { + this.translationList.filters[ type ] = value; + this.translationList.applyFilters( this.translationList.filters ); + }; + + CXDashboard.prototype.initSourceSelector = function () { + var query, + sourceSelectorOptions = {}; + + query = new mw.Uri().query; + sourceSelectorOptions.sourceLanguage = query.from; + sourceSelectorOptions.targetLanguage = query.to; + sourceSelectorOptions.sourceTitle = query.page; + sourceSelectorOptions.targetTitle = query.targettitle; + this.$newTranslationButton.cxSourceSelector( sourceSelectorOptions ); + + if ( query.campaign ) { + mw.hook( 'mw.cx.cta.accept' ).fire( query.campaign, query.from, query.to ); + } + }; + CXDashboard.prototype.scroll = function () { var scrollTop = $( window ).scrollTop(), offsetTop = this.$dashboard.offset().top; diff --git a/modules/dashboard/ext.cx.translationlist.js b/modules/dashboard/ext.cx.translationlist.js index 9ed86d1..d28e599 100644 --- a/modules/dashboard/ext.cx.translationlist.js +++ b/modules/dashboard/ext.cx.translationlist.js @@ -14,64 +14,29 @@ * * @class */ - function CXTranslationList( element, siteMapper ) { - this.$container = $( element ); + function CXTranslationList( $container, translations, siteMapper ) { + this.$container = $container; this.siteMapper = siteMapper; - this.translations = []; + this.translations = translations; this.filters = { status: null, sourceLanguage: null, targetLanguage: null }; - this.$statusFilter = null; this.$sourceLanguageFilter = null; this.$targetLanguageFilter = null; this.$header = null; this.$confirmationDialog = null; this.$overlay = null; - this.init(); - this.render(); this.listen(); } CXTranslationList.prototype.init = function () { - var translationList = this; - - this.getTranslations().done( function ( response ) { - translationList.getTranslationsCallback( - response.query.contenttranslation.translations - ); - } ); - }; - - /** - * Populates various UI components with data in the given translations. - */ - CXTranslationList.prototype.getTranslationsCallback = function ( translations ) { - var sourceLanguages, targetLanguages; - - // Remove unnecessary object wrapping to get plain list of objects - translations = $.map( translations, function ( e ) { - return e.translation; - } ); - - this.translations = translations; - this.$header.show(); - this.listTranslations( this.translations ); + this.listTranslations(); this.filters.status = 'draft'; - this.applyFilters( this.filters, translations ); - - sourceLanguages = $.map( translations, function ( e ) { - return e.sourceLanguage; - } ); - this.populateLanguageFilter( this.$sourceLanguageFilter, mw.cx.unique( sourceLanguages ) ); - - targetLanguages = $.map( translations, function ( e ) { - return e.targetLanguage; - } ); - this.populateLanguageFilter( this.$targetLanguageFilter, mw.cx.unique( targetLanguages ) ); + this.applyFilters( this.filters ); }; /** @@ -98,20 +63,6 @@ }; /** - * Get all the translations of given user. - * @return {jQuery.Promise} - */ - CXTranslationList.prototype.getTranslations = function () { - var api = new mw.Api(); - - return api.get( { - action: 'query', - list: 'contenttranslation', - format: 'json' - } ); - }; - - /** * Show a title image of the translation based on source title. * @param {Object} translation */ @@ -131,9 +82,8 @@ /** * List all translations. - * @param {Object[]} translations */ - CXTranslationList.prototype.listTranslations = function ( translations ) { + CXTranslationList.prototype.listTranslations = function () { var i, translation, progress, $translation, $lastUpdated, $imageBlock, $image, $progressbar, sourceDir, targetDir, @@ -143,8 +93,8 @@ $titleLanguageBlock, $translations = []; - for ( i = 0; i < translations.length; i++ ) { - translation = translations[ i ]; + for ( i = 0; i < this.translations.length; i++ ) { + translation = this.translations[ i ]; try { progress = JSON.parse( translation.progress ); @@ -208,12 +158,12 @@ $translationLink.append( $( '<span>' ).html( ' ' ), // nbsp to ensure separation between words $( '<span>' ) - .prop( { - lang: translation.targetLanguage, - dir: targetDir - } ) - .addClass( 'target-title' ) - .text( translation.targetTitle ) + .prop( { + lang: translation.targetLanguage, + dir: targetDir + } ) + .addClass( 'target-title' ) + .text( translation.targetTitle ) ); } @@ -285,141 +235,19 @@ .addClass( 'cx-translationlist-empty' ) .append( $( '<div>' ) - .addClass( 'cx-translationlist-empty__img' ), + .addClass( 'cx-translationlist-empty__img' ), $( '<div>' ) - .addClass( 'cx-translationlist-empty__title' ) - .text( mw.msg( 'cx-translationlist-empty-title' ) ), + .addClass( 'cx-translationlist-empty__title' ) + .text( mw.msg( 'cx-translationlist-empty-title' ) ), $( '<div>' ) - .addClass( 'cx-translationlist-empty__desc' ) - .text( mw.msg( 'cx-translationlist-empty-desc' ) ) + .addClass( 'cx-translationlist-empty__desc' ) + .text( mw.msg( 'cx-translationlist-empty-desc' ) ) ) ); } }; - CXTranslationList.prototype.populateLanguageFilter = function ( $filter, languages ) { - var i; - - for ( i = 0; i < languages.length; i++ ) { - $filter.append( $( '<option>' ) - // Todo: use translated language name - .text( $.uls.data.getAutonym( languages[ i ] ) ) - .attr( 'value', languages[ i ] ) - ); - } - }; - - CXTranslationList.prototype.render = function () { - var $sourceLanguageContainer, $targetLanguageContainer; - - this.$header = $( '<div>' ) - .addClass( 'translation-filter' ); - - this.$newTranslationButton = $( '<button>' ) - .addClass( 'cx-cta__new-translation mw-ui-button mw-ui-constructive' ) - .text( mw.msg( 'cx-create-new-translation' ) ); - this.$cta = $( '<div>' ) - .addClass( 'cx-cta' ) - .append( this.$newTranslationButton ); - - this.$statusFilter = $( '<span>' ) - .addClass( 'cx-statusfilter' ) - .append( - $( '<span>' ) - .addClass( 'cx-status cx-status--draft cx-status--selected mw-ui-input' ) - .text( mw.msg( 'cx-translation-filter-draft-translations' ) ), - $( '<span>' ) - .addClass( 'cx-status cx-status--published mw-ui-input' ) - .text( mw.msg( 'cx-translation-filter-published-translations' ) ) - ); - - this.$sourceLanguageFilter = createSelect( - 'translation-source-language-filter', { - '': mw.msg( 'cx-translation-filter-from-any-language' ) - } - ); - - this.$targetLanguageFilter = createSelect( - 'translation-target-language-filter', { - '': mw.msg( 'cx-translation-filter-to-any-language' ) - } - ); - - $sourceLanguageContainer = $( '<div>' ) - .addClass( 'translation-language-source-container' ) - .append( - this.$sourceLanguageFilter, - $( '<div>' ) - .addClass( 'translation-language-select-content' ) - .text( mw.msg( 'cx-translation-filter-from-any-language' ) ), - $( '<div>' ) - .addClass( 'translation-language-select-arrow' ) - ); - - $targetLanguageContainer = $( '<div>' ) - .addClass( 'translation-language-target-container' ) - .append( - this.$targetLanguageFilter, - $( '<div>' ) - .addClass( 'translation-language-select-content' ) - .text( mw.msg( 'cx-translation-filter-to-any-language' ) ), - $( '<div>' ).addClass( 'translation-language-select-arrow' ) - ); - - this.$header.append( - this.$statusFilter, - $( '<div>' ).addClass( 'translation-language-filter' ).append( - $sourceLanguageContainer, - $( '<div>' ).addClass( 'translation-language-arrow' ), - $targetLanguageContainer - ), - this.$cta - ); - - // Hide the filters till we see there are translations to list. - this.$header.hide(); - this.$container.append( this.$header ); - }; - CXTranslationList.prototype.listen = function () { - var setFilter, - translationList = this; - - setFilter = $.proxy( this.setFilter, this ); - - this.$statusFilter.click( '.cx-status', function ( e ) { - var $filter = $( e.target ); - - translationList.$statusFilter - .find( '.cx-status--selected' ) - .removeClass( 'cx-status--selected' ); - - $filter.addClass( 'cx-status--selected' ); - - if ( $filter.is( '.cx-status--draft' ) ) { - setFilter( 'status', 'draft' ); - } else if ( $filter.is( '.cx-status--published' ) ) { - setFilter( 'status', 'published' ); - } - } ); - - this.$sourceLanguageFilter.on( 'change', function () { - var code = $( this ).val(); - - setFilter( 'sourceLanguage', code ); - - translationList.$sourceLanguageFilter - .siblings( '.translation-language-select-content' ) - .text( $.uls.data.getAutonym( code ) ); - } ); - - this.$targetLanguageFilter.on( 'change', function () { - var code = $( this ).val(); - - setFilter( 'targetLanguage', code ); - translationList.$targetLanguageFilter - .siblings( '.translation-language-select-content' ) - .text( $.uls.data.getAutonym( code ) ); - } ); + var translationList = this; this.$container.on( 'click', '.cx-discard-translation', function ( e ) { var translation; @@ -453,25 +281,7 @@ location.href = $( this ).find( '.translation-link' ).attr( 'href' ); } ); - this.initSourceSelector(); - $( window ).scroll( $.throttle( 250, $.proxy( this.scroll, this ) ) ); - }; - - CXTranslationList.prototype.initSourceSelector = function () { - var query, - sourceSelectorOptions = {}; - - query = new mw.Uri().query; - sourceSelectorOptions.sourceLanguage = query.from; - sourceSelectorOptions.targetLanguage = query.to; - sourceSelectorOptions.sourceTitle = query.page; - sourceSelectorOptions.targetTitle = query.targettitle; - this.$newTranslationButton.cxSourceSelector( sourceSelectorOptions ); - - if ( query.campaign ) { - mw.hook( 'mw.cx.cta.accept' ).fire( query.campaign, query.from, query.to ); - } }; CXTranslationList.prototype.scroll = function () { @@ -577,17 +387,12 @@ return new mw.Api().postWithToken( 'edit', apiParams ); }; - CXTranslationList.prototype.setFilter = function ( type, value ) { - this.filters[ type ] = value; - this.applyFilters( this.filters, this.translations ); - }; - - CXTranslationList.prototype.applyFilters = function ( filters, translations ) { + CXTranslationList.prototype.applyFilters = function ( filters ) { var i, translation, visible, j, filterProp, filterValue, keys = Object.keys( filters ); - for ( i = 0; i < translations.length; i++ ) { - translation = translations[ i ]; + for ( i = 0; i < this.translations.length; i++ ) { + translation = this.translations[ i ]; visible = true; for ( j = 0; j < keys.length; j++ ) { @@ -609,35 +414,5 @@ } }; - /** - * Creates a jQuery select element from given options. - * @param {string} classes - * @param {Object} options - * @return {jQuery} - */ - function createSelect( classes, options ) { - var i, value, key, - keys = Object.keys( options ), - $select = $( '<select>' ).addClass( classes ); - - for ( i = 0; i < keys.length; i++ ) { - value = keys[ i ]; - key = options[ value ]; - - $select.append( $( '<option>' ).text( key ).attr( 'value', value ) ); - } - - return $select; - } - - $.fn.cxTranslationList = function ( siteMapper ) { - return this.each( function () { - var $this = $( this ), - data = $this.data( 'cxtranslationlist' ); - - if ( !data ) { - $this.data( 'cx', ( data = new CXTranslationList( this, siteMapper ) ) ); - } - } ); - }; + mw.cx.CXTranslationList = CXTranslationList; }( jQuery, mediaWiki ) ); diff --git a/scripts/manage-lists.php b/scripts/manage-lists.php index e4dd88e..4a6db94 100644 --- a/scripts/manage-lists.php +++ b/scripts/manage-lists.php @@ -91,8 +91,8 @@ $json = Http::get( $url ); $data = FormatJson::decode( $json, true ); if ( !isset( $data['query'] ) ) { - $this->output( "\t[FAIL]\n" ); - return; + $this->output( "\t[FAIL]\n" ); + return; } $pagesInCategory = $data['query']['pages']; foreach ( $pagesInCategory as $pageId => $page ) { -- To view, visit https://gerrit.wikimedia.org/r/232000 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: Ie5bbcb3a01dfa0b136ad8fa000ca1f52a7a98878 Gerrit-PatchSet: 1 Gerrit-Project: mediawiki/extensions/ContentTranslation Gerrit-Branch: master Gerrit-Owner: Santhosh <santhosh.thottin...@gmail.com> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits