Petar.petkovic has uploaded a new change for review. ( 
https://gerrit.wikimedia.org/r/376042 )

Change subject: Make CX dashboard responsive
......................................................................

Make CX dashboard responsive

- Make translation dashboard layout responsive
to adapt to small screens.
- Change ULS position calculations to avoid overflows.

Bug: T157212
Change-Id: I157182be03cf595ce2ecc82e54d1185b3685ef9c
---
M extension.json
M modules/dashboard/ext.cx.dashboard.js
M modules/dashboard/styles/ext.cx.dashboard.less
M modules/dashboard/styles/ext.cx.lists.common.less
M modules/dashboard/styles/ext.cx.suggestionlist.less
M modules/source/ext.cx.source.selector.js
M modules/widgets/common/ext.cx.common.less
M modules/widgets/translator/ext.cx.translator.less
M specials/SpecialContentTranslation.php
9 files changed, 128 insertions(+), 27 deletions(-)


  git pull 
ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/ContentTranslation 
refs/changes/42/376042/1

diff --git a/extension.json b/extension.json
index fc07c75..44d2294 100644
--- a/extension.json
+++ b/extension.json
@@ -282,7 +282,9 @@
                                "ext.uls.mediawiki",
                                "mediawiki.Uri",
                                "mediawiki.storage",
-                               "mediawiki.ui.button"
+                               "mediawiki.ui.button",
+                               "oojs-ui.styles.icons-editing-core",
+                               "oojs-ui.styles.icons-accessibility"
                        ],
                        "messages": [
                                "cx-create-new-translation",
diff --git a/modules/dashboard/ext.cx.dashboard.js 
b/modules/dashboard/ext.cx.dashboard.js
index a29dec0..33899f6 100644
--- a/modules/dashboard/ext.cx.dashboard.js
+++ b/modules/dashboard/ext.cx.dashboard.js
@@ -26,6 +26,9 @@
                this.$newTranslationButton = null;
                this.$listHeader = null;
                this.$sourceSelector = null;
+               this.narrowLimit = 700;
+               this.wideLimit = 1200;
+               this.isNarrowScreenSize = false;
        }
 
        CXDashboard.prototype.init = function () {
@@ -107,7 +110,9 @@
                var label;
 
                if ( selected ) {
-                       label = $.uls.data.getAutonym( selected );
+                       label = this.isNarrowScreenSize ?
+                               selected.toUpperCase() :
+                               $.uls.data.getAutonym( selected );
                } else if ( $filter.is( '.translation-source-language-filter' ) 
) {
                        label = mw.msg( 
'cx-translation-filter-from-any-language' );
                } else {
@@ -229,24 +234,35 @@
                var newTranslationButton,
                        filterButtons = [];
 
+               // document.documentElement.clientWidth performs faster than $( 
window ).width()
+               this.isNarrowScreenSize = document.documentElement.clientWidth 
< this.narrowLimit;
+
                if ( mw.config.get( 'wgContentTranslationEnableSuggestions' ) ) 
{
                        filterButtons.push( new OO.ui.ButtonOptionWidget( {
                                data: 'suggestions',
-                               label: mw.msg( 
'cx-translation-filter-suggested-translations' )
+                               label: !this.isNarrowScreenSize ?
+                                       mw.msg( 
'cx-translation-filter-suggested-translations' ) : undefined,
+                               icon: this.isNarrowScreenSize ? 'bright' : 
undefined
                        } ) );
                }
 
                filterButtons.push( new OO.ui.ButtonOptionWidget( {
                        data: 'draft',
-                       label: mw.msg( 
'cx-translation-filter-draft-translations' )
+                       label: !this.isNarrowScreenSize ?
+                               mw.msg( 
'cx-translation-filter-draft-translations' ) : undefined,
+                       icon: this.isNarrowScreenSize ? 'edit' : undefined
                } ) );
 
                filterButtons.push( new OO.ui.ButtonOptionWidget( {
                        data: 'published',
-                       label: mw.msg( 
'cx-translation-filter-published-translations' )
+                       label: !this.isNarrowScreenSize ?
+                               mw.msg( 
'cx-translation-filter-published-translations' ) : undefined,
+                       icon: this.isNarrowScreenSize ? 'check' : undefined
                } ) );
 
-               this.$listHeader = $( '<div>' ).addClass( 'translation-filter' 
);
+               this.filter = new OO.ui.ButtonSelectWidget( {
+                       items: filterButtons
+               } );
 
                newTranslationButton = new OO.ui.ButtonWidget( {
                        label: mw.msg( 'cx-create-new-translation' ),
@@ -258,10 +274,7 @@
                } );
                this.$newTranslationButton = newTranslationButton.$element;
 
-               this.filter = new OO.ui.ButtonSelectWidget( {
-                       items: filterButtons
-               } );
-
+               this.$listHeader = $( '<div>' ).addClass( 'translation-filter' 
);
                this.$listHeader.append(
                        this.$newTranslationButton,
                        this.filter.$element
@@ -353,6 +366,8 @@
                } );
                // Scroll handler
                $( window ).scroll( $.throttle( 250, this.scroll.bind( this ) ) 
);
+               // Resize handler
+               $( window ).resize( $.throttle( 250, this.resize.bind( this ) ) 
);
        };
 
        CXDashboard.prototype.setFilter = function ( type, value ) {
@@ -382,13 +397,54 @@
        CXDashboard.prototype.scroll = function () {
                var scrollTop = $( window ).scrollTop();
 
-               if ( scrollTop > 0 ) {
+               if ( document.documentElement.clientWidth > this.wideLimit && 
scrollTop > 0 ) {
                        this.$sidebar.addClass( 'sticky' );
                } else {
                        this.$sidebar.removeClass( 'sticky' );
                }
        };
 
+       CXDashboard.prototype.resize = function () {
+               var filterItems = this.filter.getItems(),
+                       narrowScreenSize = document.documentElement.clientWidth 
< this.narrowLimit,
+                       list = this.lists[ this.activeList ];
+
+               // Exit early if screen size stays above/under narrow screen 
size limit
+               if ( this.isNarrowScreenSize === narrowScreenSize ) {
+                       this.isNarrowScreenSize = narrowScreenSize;
+
+                       return;
+               }
+
+               // Change filter labels to icons and vice-versa
+               $.each( filterItems, function ( index, element ) {
+                       var label, icon,
+                               data = element.getData();
+
+                       if ( data === 'suggestions' ) {
+                               label = !narrowScreenSize ?
+                                       mw.msg( 
'cx-translation-filter-suggested-translations' ) : '';
+                               icon = narrowScreenSize ? 'bright' : '';
+                       } else if ( data === 'draft' ) {
+                               label = !narrowScreenSize ?
+                                       mw.msg( 
'cx-translation-filter-draft-translations' ) : '';
+                               icon = narrowScreenSize ? 'edit' : '';
+                       } else {
+                               label = !narrowScreenSize ?
+                                       mw.msg( 
'cx-translation-filter-published-translations' ) : '';
+                               icon = narrowScreenSize ? 'check' : '';
+                       }
+
+                       element.setIcon( icon );
+                       element.setLabel( label );
+               } );
+               this.isNarrowScreenSize = narrowScreenSize;
+
+               // Change language filter labels for active list
+               this.setLanguageFilterLabel( 
list.languageFilter.$sourceLanguageFilter, list.filters.sourceLanguage );
+               this.setLanguageFilterLabel( 
list.languageFilter.$targetLanguageFilter, list.filters.targetLanguage );
+       };
+
        $( function () {
                var dashboard;
 
diff --git a/modules/dashboard/styles/ext.cx.dashboard.less 
b/modules/dashboard/styles/ext.cx.dashboard.less
index e5f0f4f..5263150 100644
--- a/modules/dashboard/styles/ext.cx.dashboard.less
+++ b/modules/dashboard/styles/ext.cx.dashboard.less
@@ -32,6 +32,13 @@
        padding: 0 0 0 20px;
        line-height: 1;
 
+       @media only screen and ( max-width: @wide ) {
+               .mw-ui-one-whole;
+
+               margin-top: 48px;
+               padding: 0;
+       }
+
        &.sticky {
                position: fixed;
                top: @sticky-header-height;
@@ -68,7 +75,6 @@
                background-size: 16px;
                color: @colorProgressive;
                padding-left: 24px;
-
        }
 
        &__link {
@@ -89,9 +95,15 @@
                .mw-ui-one-whole;
 
                background-color: #fff;
+               margin-bottom: 48px;
                border-radius: @borderRadius;
                padding: 16px;
                font-size: 16px;
+
+               @media only screen and ( min-width: @narrow ) and ( max-width: 
@wide ) {
+                       width: 47.5%;
+                       margin-left: 5%;
+               }
 
                &-title {
                        color: @colorGray5;
@@ -121,6 +133,11 @@
 
        background-color: @colorGray14;
        padding: 0 @translationlist-container-padding-right 0 0;
+
+       @media only screen and ( max-width: @wide ) {
+               .mw-ui-one-whole;
+               padding: 0;
+       }
 }
 
 .translation-filter {
@@ -145,10 +162,15 @@
        padding: 10px 0; // Defines top and bottom padding. Left and right 
padding are defined separately for clarity
        padding-right: @sticky-sidebar-right-position + 
@translationlist-container-padding-right;
        padding-left: @dashboard-horizontal-padding;
+
+       @media only screen and ( max-width: @wide ) {
+               width: 100%;
+               padding: 10px @dashboard-horizontal-padding;
+       }
 }
 
 .cx-translationlist-container.sticky {
        // Occupy the place the place that would become empty when the header 
starts
        // floating when the page is scrolled. This prevents a jump of the 
content.
-       padding-top: 120px;
+       padding-top: @sticky-header-height;
 }
diff --git a/modules/dashboard/styles/ext.cx.lists.common.less 
b/modules/dashboard/styles/ext.cx.lists.common.less
index cb0a1bc..22a438d 100644
--- a/modules/dashboard/styles/ext.cx.lists.common.less
+++ b/modules/dashboard/styles/ext.cx.lists.common.less
@@ -27,8 +27,11 @@
 }
 
 .cx-tlitem:last-child {
-       margin-bottom: 48px;
        border-radius: 0 0 @borderRadius @borderRadius;
+
+       @media only screen and ( min-width: @wide ) {
+               margin-bottom: 48px;
+       }
 }
 
 .cx-suggestionlist__header,
@@ -84,8 +87,10 @@
                        font-size: 16px;
                        line-height: 1;
 
-                       overflow: hidden;
-                       text-overflow: ellipsis;
+                       @media only screen and ( min-width: @narrow ) {
+                               overflow: hidden;
+                               text-overflow: ellipsis;
+                       }
                        white-space: nowrap;
                }
 
diff --git a/modules/dashboard/styles/ext.cx.suggestionlist.less 
b/modules/dashboard/styles/ext.cx.suggestionlist.less
index 2e5c104..4fa689e 100644
--- a/modules/dashboard/styles/ext.cx.suggestionlist.less
+++ b/modules/dashboard/styles/ext.cx.suggestionlist.less
@@ -69,12 +69,16 @@
 
 .cx-suggestionlist__refresh {
        color: @colorProgressive;
-       margin: -10px 0 48px 0;
+       margin-top: -10px;
        border-width: 1px 0;
        border-radius: 0 0 @borderRadius @borderRadius;
        padding: 20px;
        font-weight: bold;
 
+       @media only screen and ( min-width: @wide ) {
+               margin-bottom: 48px;
+       }
+
        &:before {
                @iconSize: 16px;
 
diff --git a/modules/source/ext.cx.source.selector.js 
b/modules/source/ext.cx.source.selector.js
index fe55bc1..eac283c 100644
--- a/modules/source/ext.cx.source.selector.js
+++ b/modules/source/ext.cx.source.selector.js
@@ -66,14 +66,11 @@
         * @return {Object} autonyms indexed by language code.
         */
        function getAutonyms( languages ) {
-               var i,
-                       autonyms = {};
+               return languages.reduce( function ( prevObject, element ) {
+                       prevObject[ element ] = $.uls.data.getAutonym( element 
);
 
-               for ( i = 0; i < languages.length; i++ ) {
-                       autonyms[ languages[ i ] ] = $.uls.data.getAutonym( 
languages[ i ] );
-               }
-
-               return autonyms;
+                       return prevObject;
+               }, {} );
        }
 
        /**
@@ -94,10 +91,16 @@
         * Calculate position for ULS, depending on directionality
         */
        function calculateUlsPosition() {
-               if ( $( 'html' ).prop( 'dir' ) === 'rtl' ) {
-                       this.left = this.$element.offset().left + 
this.$element.parent().width() - this.$menu.width();
+               var isRtl = $( 'html' ).prop( 'dir' ) === 'rtl',
+                       left = this.$element.offset().left,
+                       right = left + this.$element.parent().width() - 
this.$menu.width(),
+                       isInRtlViewport = right > 0,
+                       isInLtrViewport = left + this.$menu.width() > $( window 
).width();
+
+               if ( ( isRtl && isInRtlViewport ) || ( !isRtl && 
isInLtrViewport ) ) {
+                       this.left = right;
                } else {
-                       this.left = this.$element.offset().left;
+                       this.left = left;
                }
 
                this.$menu.css( this.position() );
diff --git a/modules/widgets/common/ext.cx.common.less 
b/modules/widgets/common/ext.cx.common.less
index a6f56de..edd19f5 100644
--- a/modules/widgets/common/ext.cx.common.less
+++ b/modules/widgets/common/ext.cx.common.less
@@ -11,6 +11,9 @@
 @gray-lighter: #f8f9fa;
 @white: #fff;
 
+@narrow: 700px;
+@wide: 1200px;
+
 .cx-widget {
        .mw-ui-grid;
        color: @gray-darker;
diff --git a/modules/widgets/translator/ext.cx.translator.less 
b/modules/widgets/translator/ext.cx.translator.less
index d918223..254bed5 100644
--- a/modules/widgets/translator/ext.cx.translator.less
+++ b/modules/widgets/translator/ext.cx.translator.less
@@ -8,6 +8,11 @@
        margin-bottom: 1em;
        border-radius: @borderRadius;
        padding: 1em;
+
+       @media only screen and ( min-width: @narrow ) and ( max-width: @wide ) {
+               width: 47.5%;
+               margin-bottom: 3em;
+       }
 }
 
 .cx-translator__header {
diff --git a/specials/SpecialContentTranslation.php 
b/specials/SpecialContentTranslation.php
index 4e0d57d..1741ffa 100644
--- a/specials/SpecialContentTranslation.php
+++ b/specials/SpecialContentTranslation.php
@@ -164,6 +164,7 @@
                        }
                } else {
                        $out->addModules( 'ext.cx.dashboard' );
+                       $out->addMeta( 'viewport', 'width=device-width, 
initial-scale=1' );
                }
 
                $this->setHeaders();

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

Gerrit-MessageType: newchange
Gerrit-Change-Id: I157182be03cf595ce2ecc82e54d1185b3685ef9c
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/ContentTranslation
Gerrit-Branch: master
Gerrit-Owner: Petar.petkovic <ppetko...@wikimedia.org>

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

Reply via email to