Jsahleen has uploaded a new change for review.
https://gerrit.wikimedia.org/r/166361
Change subject: Categories: Retrieve, adapt and manage categories
......................................................................
Categories: Retrieve, adapt and manage categories
Inital patch for category adaptation. Includes the following components:
* CXCategoryTool
Manages api requests
Adapts categories
Stores source, adapted and target categories
Initializes UI widgets
* CXCategoryCounter
UI widget for category count at top of column
* CXCategoryListing
UI widget for category listing at bottom of column
Handles removing and adding adapted categories
Change-Id: I93b6fc0282e087b29079f59d518ee0fb1c4f6408
---
M Resources.php
A modules/tools/ext.cx.tools.categories.js
A modules/tools/images/tag.png
A modules/tools/images/tag.svg
A modules/tools/styles/ext.cx.tools.categories.less
5 files changed, 710 insertions(+), 0 deletions(-)
git pull
ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/ContentTranslation
refs/changes/61/166361/1
diff --git a/Resources.php b/Resources.php
index 6227fe8..b3a43cd 100644
--- a/Resources.php
+++ b/Resources.php
@@ -189,6 +189,7 @@
'ext.cx.tools.mtabuse',
'ext.cx.tools.reference',
'ext.cx.tools.template',
+ 'ext.cx.tools.categories',
'ext.cx.util.selection',
'mediawiki.jqueryMsg',
),
@@ -350,6 +351,15 @@
),
) + $resourcePaths;
+$wgResourceModules['ext.cx.tools.categories'] = array(
+ 'scripts' => array(
+ 'tools/ext.cx.tools.categories.js',
+ ),
+ 'styles' => array(
+ 'tools/styles/ext.cx.tools.categories.less',
+ ),
+) + $resourcePaths;
+
$wgResourceModules['ext.cx.progressbar'] = array(
'scripts' => 'tools/ext.cx.progressbar.js',
'styles' => array(
diff --git a/modules/tools/ext.cx.tools.categories.js
b/modules/tools/ext.cx.tools.categories.js
new file mode 100644
index 0000000..e740932
--- /dev/null
+++ b/modules/tools/ext.cx.tools.categories.js
@@ -0,0 +1,556 @@
+/**
+ * ContentTranslation Tools
+ * A tool that allows editors to translate pages from one language
+ * to another with the help of machine translation and other translation tools
+ *
+ * @file
+ * @ingroup Extensions
+ * @copyright See AUTHORS.txt
+ * @license GPL-2.0+
+ */
+( function ( $, mw ) {
+ 'use strict';
+
+ function jump( e ) {
+ var id, url = location.href;
+ id = e.data.id;
+ location.href = '#' + id;
+ history.replaceState( null, null, url );
+
+ return false;
+ }
+
+ /**
+ * CXCategoryCounter Class
+ * @class
+ * @param {string} language, the language for the counter
+ * @param {CXCategoryTool} categoryTool, the CXCategoryTool
+ */
+ function CXCategoryCounter( language, categoryTool ) {
+ this.language = language;
+ this.categoryTool = categoryTool;
+ this.$view = null;
+ this.init();
+ }
+
+ /**
+ * Initializes the category counter
+ */
+ CXCategoryCounter.prototype.init = function () {
+ var count = 0;
+
+ this.$view = this.getView();
+ if ( this.language === mw.cx.sourceLanguage &&
+ this.categoryTool.categories.source !== null ) {
+ count = Object.keys(
this.categoryTool.categories.source ).length;
+ } else if ( this.language === mw.cx.targetLanguage &&
+ this.categoryTool.categories.target !== null ) {
+ count = Object.keys(
this.categoryTool.categories.target ).length;
+ }
+
+ this.update( count );
+ };
+
+ /**
+ * Retrieves the view for the category counter
+ * @return {jQuery}
+ */
+ CXCategoryCounter.prototype.getView = function () {
+ var $view, $anchor, $count;
+
+ $view = $( '<div>' )
+ .addClass( 'cx-category-widget')
+ .addClass( 'cx-category-widget-counter' );
+ $anchor = $( '<a>' )
+ .addClass( 'cx-category-anchor' );
+ if ( this.language === mw.cx.sourceLanguage ) {
+ $anchor.prop( 'id', 'cx-category-counter-source' );
+ $anchor.on( 'click', { id: 'cx-category-listing-source'
}, jump );
+ } else {
+ $anchor.prop( 'id', 'cx-category-counter-translation' );
+ $anchor.on( 'click', { id:
'cx-category-listing-translation' }, jump );
+ }
+
+ $anchor.attr( 'hidefocus', 'hidefocus');
+
+ $count = $( '<span>' )
+ .addClass( 'cx-category-count' );
+
+ $view.append( $anchor, $count );
+
+ return $view;
+ };
+
+ /**
+ * Updates the count shown in the category counter
+ * @param {integer} count, the category count
+ */
+ CXCategoryCounter.prototype.update = function ( count ) {
+ this.$view.find( 'span.cx-category-count' ).text( count );
+ };
+
+ /**
+ * CXCategoryListing Class
+ * @class
+ * @param {string} language, the language for the counter
+ * @param {CXCategoryTool} categoryTool, the CXCategoryTool
+ */
+ function CXCategoryListing( language, categoryTool ) {
+ this.language = language;
+ this.categoryTool = categoryTool;
+ this.$view = null;
+ this.init();
+ }
+
+ /**
+ * Initializes the category listing
+ */
+ CXCategoryListing.prototype.init = function () {
+ this.$view = this.getView();
+
+ if ( this.language === mw.cx.sourceLanguage &&
+ this.categoryTool.categories.source !== null &&
+ Object.keys( this.categoryTool.categories.source
).length > 0 ) {
+ this.addCategories( this.categoryTool.categories.source
);
+ } else if ( this.language === mw.cx.targetLanguage &&
+ this.categoryTool.categories.target !== null &&
+ Object.keys( this.categoryTool.categories.target
).length > 0 ) {
+ this.addCategories( this.categoryTool.categories.target
);
+ }
+ };
+
+ /**
+ * Handles click events on source list items
+ * @param {Event} e, the event object
+ */
+ function sourceClickHandler( e ) {
+ var $listItem, categoryId, categoryTool, title, count;
+
+ /*jshint validthis:true */
+ $listItem = $( this );
+ categoryId = $listItem.attr( 'cx-category-id' );
+ categoryTool = e.data.tool;
+
+ if ( categoryTool.categories.adapted.hasOwnProperty( categoryId
) &&
+ !categoryTool.categories.target.hasOwnProperty(
categoryId ) ) {
+
+ title = categoryTool.categories.adapted[ categoryId ];
+ categoryTool.categories.target[ categoryId ] = title;
+ count = Object.keys( categoryTool.categories.target
).length;
+ categoryTool.widgets.target.listing.addCategory(
categoryId, title );
+ $( '.cx-category-translation[cx-category-id="' +
categoryId + '"]' )
+ .addClass( 'cx-category-highlight' );
+ categoryTool.widgets.target.counter.update( count );
+ }
+ }
+
+ /**
+ * Handles click events on the remove link insisde target list items
+ * @param {Event} e, the event object
+ */
+ function targetClickHandler( e ) {
+ var $remove, $listItem, categoryId, categoryTool, count;
+
+ /*jshint validthis:true */
+ $remove = $( this );
+ $listItem = $remove.parent();
+ categoryId = $listItem.attr( 'cx-category-id' );
+ categoryTool = e.data.tool;
+
+ $listItem.remove();
+ delete categoryTool.categories.target[ categoryId ];
+ count = Object.keys( categoryTool.categories.target ).length;
+ $( '.cx-category-source[cx-category-id="' + categoryId + '"]' )
+ .removeClass( 'cx-category-highlight' );
+ categoryTool.widgets.target.counter.update( count );
+ }
+
+ /**
+ * Highlights the category and connected category list items
+ */
+ function highlightCategory() {
+ /*jshint validthis:true */
+ var categoryId = $( this ).attr( 'cx-category-id' );
+ $( '[cx-category-id="' + categoryId + '"]').addClass(
'cx-category-highlight' );
+ }
+
+ /**
+ * Remove the highlight on the category and connected category list
items
+ */
+ function removeCategoryHighlight() {
+ /*jshint validthis:true */
+ var categoryId = $( this ).attr( 'cx-category-id' );
+ $( '[cx-category-id="' + categoryId + '"]').removeClass(
'cx-category-highlight' );
+ }
+ /**
+ * Gets the view for the category listing
+ * @return {jQuery}
+ */
+ CXCategoryListing.prototype.getView = function () {
+ var categoryTool, $view, $anchor, $categoryList;
+
+ categoryTool = this.categoryTool;
+
+ $view = $( '<div>' )
+ .addClass( 'cx-category-widget' )
+ .addClass( 'cx-category-widget-listing');
+ $anchor = $( '<a>' )
+ .addClass( 'cx-category-anchor' );
+ $categoryList = $( '<ul>' )
+ .addClass( 'cx-categories' );
+
+ if ( this.language === mw.cx.sourceLanguage ) {
+ $anchor.prop( 'id', 'cx-category-listing-source' );
+ $anchor.on( 'click', { id: 'cx-category-counter-source'
}, jump );
+ $categoryList.on( 'click', '.cx-category-source', {
tool: categoryTool }, sourceClickHandler );
+ } else {
+ $anchor.prop( 'id', 'cx-category-listing-translation' );
+ $anchor.on( 'click', { id:
'cx-category-counter-translation' }, jump );
+ $categoryList.on( 'click', '.cx-category-remove', {
tool: categoryTool }, targetClickHandler );
+ }
+
+ $anchor.attr( 'hideFocus', 'hidefocus');
+
+ $categoryList.on( 'mouseover', '.cx-category',
highlightCategory );
+ $categoryList.on( 'mouseout', '.cx-category',
removeCategoryHighlight );
+
+ $view.append( $anchor, $categoryList );
+
+ return $view;
+ };
+
+ /**
+ * Adds categories to the category listing
+ *
+ * @param {object} categories, key value object with ids and titles
+ * @param {boolean} clear, flag to clear existing categories
+ */
+ CXCategoryListing.prototype.addCategories = function ( categories,
clear ) {
+ var category, $categoryList;
+
+ if ( !categories ) {
+ return;
+ }
+
+ clear = typeof clear !== 'boolean' ? false : clear;
+
+ $categoryList = this.$view.find( '.cx-categories' );
+ if ( clear ) {
+ $categoryList.empty();
+ }
+
+ for ( category in categories ) {
+ this.addCategory( category, categories[ category ] );
+ }
+ };
+
+ /**
+ * Creates a source category list item
+ *
+ * @param {string} id, the category id
+ * @param {string} title, the category title
+ * @return {jQuery}
+ */
+ function createSourceCategoryListItem( id, title ) {
+ var extract, $listItem;
+
+ extract = title.match( /^.*:(.*)$/ );
+ $listItem = $( '<li>' )
+ .addClass( 'cx-category' )
+ .addClass( 'cx-category-source' )
+ .attr( 'cx-category-id', id )
+ .text( extract[ 1 ] );
+
+ return $listItem;
+ }
+
+ /**
+ * Creates a target category list item
+ *
+ * @param {string} id, the category id
+ * @param {string} title, the category title
+ * @return {jQuery}
+ */
+ function createTargetCategoryListItem( id, title ) {
+ var extract, $listItem, $span;
+
+ extract = title.match( /^.*:(.*)$/ );
+ $listItem = $( '<li>' )
+ .addClass( 'cx-category' )
+ .addClass( 'cx-category-translation' )
+ .attr( 'cx-category-id', id )
+ .text( extract[ 1 ] );
+
+ $span = $( '<span>' )
+ .addClass( 'cx-category-remove' );
+
+ $listItem.append( $span );
+
+ return $listItem;
+ }
+
+ /**
+ * Ads a category to the category list
+ *
+ * @param {string} id, the category id
+ * @param {string} title, the category title
+ */
+ CXCategoryListing.prototype.addCategory = function ( id, title ) {
+ var $categoryList, $categoryListItem;
+
+ $categoryList = this.$view.find( '.cx-categories' );
+
+ if ( this.language === mw.cx.sourceLanguage ) {
+ $categoryListItem = createSourceCategoryListItem( id,
title );
+ } else {
+ $categoryListItem = createTargetCategoryListItem( id,
title );
+ }
+
+ $categoryList.append( $categoryListItem );
+ };
+
+ /**
+ * CX Category Tool Class
+ * @class
+ * @param {mw.cx.SiteMapper} siteMapper
+ */
+ function CXCategoryTool( siteMapper ) {
+ this.categories = { source: null, target: null, adapted: null };
+ this.widgets = {};
+ this.siteMapper = siteMapper;
+ }
+
+ /**
+ * Retrieves categories for the source article
+ *
+ * @param {string} title, the article title
+ * @param {string} language, the article language
+ * @return {jQuery.Promise}
+ */
+ CXCategoryTool.prototype.getArticleCategories = function ( title,
language ) {
+ var categoryTool, deferred = $.Deferred();
+
+ if ( this.categories.source !== null ) {
+ deferred.resolve( this.categories.source );
+ }
+
+ categoryTool = this;
+
+ this.siteMapper.getApi( language ).get( {
+ action: 'query',
+ prop: 'categories',
+ clshow: '!hidden',
+ indexpageids: true,
+ titles: title,
+ format: 'json'
+ }, {
+ dataType: 'jsonp',
+ cache: true
+ } ).done( function ( response ) {
+ var pageId, data, categories;
+
+ categories = {};
+
+ if ( response.query ) {
+ pageId = response.query.pageids[ 0 ];
+ data = response.query.pages[ pageId
].categories;
+ $.each( data, function ( index, value ) {
+ var key;
+ key = 'cx-category-' + index;
+ categories[ key ] = value.title;
+ });
+ }
+ categoryTool.categories.source = categories;
+ deferred.resolve( categories );
+ } ).fail( function ( error ) {
+ mw.log( '[CX] Error while retrieving source categories
' + error );
+ categoryTool.categories.source = {};
+ deferred.resolve( {} );
+ } );
+
+ return deferred.promise();
+ };
+
+ /**
+ * Adapts a set of categories
+ *
+ * @param {object} categories, key value listing of ids and titles
+ * @param {string} language, the language for adaptation
+ * @return {jQuery.Promise}
+ */
+ CXCategoryTool.prototype.adaptCategories = function ( categories,
language ) {
+ var categoryTool,
+ categoryId,
+ categoryTitles,
+ inverted,
+ deferred = $.Deferred();
+
+ if ( this.categories.adapted !== null ) {
+ deferred.resolve( this.categories.adapted );
+ }
+
+ categoryTool = this;
+
+ categoryTitles = [];
+ inverted = {};
+ for (categoryId in categories ) {
+ categoryTitles.push( categories[ categoryId ] );
+ if ( categories.hasOwnProperty( categoryId ) ) {
+ inverted[ categories[ categoryId ] ] =
categoryId;
+ }
+ }
+
+ this.siteMapper.getApi( mw.cx.sourceLanguage ).get( {
+ action: 'query',
+ titles: categoryTitles.join( '|' ),
+ prop: 'langlinks',
+ lllang: language,
+ redirects: true,
+ format: 'json'
+ }, {
+ dataType: 'jsonp',
+ cache: true
+ } ).done( function ( response ) {
+ var redirects,
+ adaptedCategories = {};
+
+ if ( response.query ) {
+ redirects = jQuery.extend( {},
response.query.redirects );
+
+ $.each( response.query.pages, function (
pageId, page ) {
+ var i, key, title;
+
+ for ( i in redirects ) {
+ if ( redirects[ i ].to ===
page.title ) {
+ key = redirects[ i
].from;
+ break;
+ }
+ }
+
+ if ( !key ) {
+ key = page.title;
+ }
+
+ title = mw.Title.newFromText( key );
+
+ if ( title ) {
+ adaptedCategories[ inverted[
title.getPrefixedDb() ] ] = page.langlinks &&
+ page.langlinks[ 0 ][
'*' ];
+ }
+ } );
+ }
+ categoryTool.categories.adapted = adaptedCategories;
+ if ( categoryTool.categories.target === null ) {
+ categoryTool.categories.target = $.extend( {},
adaptedCategories );
+ }
+ deferred.resolve( adaptedCategories );
+ } ).fail( function ( error ) {
+ mw.log( 'Error adapting categories ' + error );
+ categoryTool.categories.adapted = {};
+ deferred.resolve( {} );
+ } );
+
+ return deferred.promise();
+ };
+
+ /**
+ * Retrieves the specified set of categories
+ * Valid sets are 'source', 'target' and 'adapted'
+ * If no set is specified, returns all three sets
+ *
+ * @param {string} categorySet
+ * @return {jQuery.promis}
+ */
+ CXCategoryTool.prototype.getCategories = function ( categorySet ) {
+ var categoryTool = this,
+ deferred = $.Deferred();
+
+ switch ( categorySet ) {
+ case 'source':
+ this.getArticleCategories( mw.cx.sourceTitle,
mw.cx.sourceLanguage )
+ .done( function ( categories ) {
+ deferred.resolve( categories );
+ } );
+ break;
+ case 'adapted':
+ this.getArticleCategories( mw.cx.sourceTitle,
mw.cx.sourceLanguage )
+ .done( function ( categories ) {
+ categoryTool.adaptCategories(
categories, mw.cx.targetLanguage )
+ .done( function ( adaptedCategories ) {
+ deferred.resolve(
adaptedCategories );
+ } );
+ } );
+ break;
+ case 'target':
+ if ( this.categories.target !== null ) {
+ deferred.resolve(
this.categories.target );
+ } else {
+ this.getArticleCategories(
mw.cx.sourceTitle, mw.cx.sourceLanguage )
+ .done( function ( categories ) {
+ categoryTool.adaptCategories(
categories, mw.cx.targetLanguage )
+ .done( function (
adaptedCategories ) {
+ deferred.resolve(
adaptedCategories );
+ } );
+ } );
+ }
+ break;
+ default:
+ this.getArticleCategories( mw.cx.sourceTitle,
mw.cx.sourceLanguage )
+ .done( function ( categories ) {
+ categoryTool.adaptCategories(
categories, mw.cx.targetLanguage )
+ .done( function () {
+ deferred.resolve(
categoryTool.categories );
+ } );
+ } );
+ }
+
+ return deferred.promise();
+
+ };
+
+ /**
+ * Initalizes UI widgets and attaches them to DOM
+ */
+ CXCategoryTool.prototype.initializeWidgets = function () {
+ this.widgets.source = {};
+ this.widgets.source.counter = new CXCategoryCounter(
mw.cx.sourceLanguage, this );
+ this.widgets.source.listing = new CXCategoryListing(
mw.cx.sourceLanguage, this );
+ this.widgets.target = {};
+ this.widgets.target.counter = new CXCategoryCounter(
mw.cx.targetLanguage, this );
+ this.widgets.target.listing = new CXCategoryListing(
mw.cx.targetLanguage, this );
+ this.attachWidgets();
+ };
+
+ /**
+ * Attaches UI widgets to DOM
+ */
+ CXCategoryTool.prototype.attachWidgets = function () {
+ var categoryTool;
+
+ categoryTool = this;
+
+ // Load widgets for the source column
+ $( 'div.cx-column--source > div.cx-column__sub-heading' )
+ .after( categoryTool.widgets.source.counter.$view );
+ $( 'div.cx-column--source > div.cx-column__content' )
+ .after( categoryTool.widgets.source.listing.$view );
+
+ // Load widgets for the translation column
+ $( 'div.cx-column--translation > div.cx-column__sub-heading' )
+ .after( categoryTool.widgets.target.counter.$view );
+ $( 'div.cx-column--translation > div.cx-column__content' )
+ .after( categoryTool.widgets.target.listing.$view );
+ };
+
+ // Expose the CXCategoryTool (required by publishing)
+ mw.cx.categoryTool = new CXCategoryTool( mw.cx.siteMapper );
+
+ $( function () {
+ mw.hook( 'mw.cx.translation.ready' ).add( function () {
+ mw.cx.categoryTool.getCategories().done( function () {
+ mw.cx.categoryTool.initializeWidgets();
+ } );
+ } );
+ } );
+
+}( jQuery, mediaWiki ) );
diff --git a/modules/tools/images/tag.png b/modules/tools/images/tag.png
new file mode 100644
index 0000000..882d493
--- /dev/null
+++ b/modules/tools/images/tag.png
Binary files differ
diff --git a/modules/tools/images/tag.svg b/modules/tools/images/tag.svg
new file mode 100644
index 0000000..81dbb13
--- /dev/null
+++ b/modules/tools/images/tag.svg
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ version="1.1"
+ width="80"
+ height="80"
+ viewBox="0 0 80 80"
+ id="Layer_1"
+ xml:space="preserve"><metadata
+ id="metadata18"><rdf:RDF><cc:Work
+ rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage"
/><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
+ id="defs16">
+
+ <linearGradient
+ x1="326"
+ y1="-301.0737"
+ x2="326"
+ y2="-329.77579"
+ id="SVGID_1_"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,-1,-286,-294)">
+ <stop
+ id="stop6"
+ style="stop-color:#ffffff;stop-opacity:0.94999999"
+ offset="0" />
+ <stop
+ id="stop8"
+ style="stop-color:#ffffff;stop-opacity:1"
+ offset="0.78740001" />
+ </linearGradient>
+
+
+</defs>
+<path
+ d="m 67.171,46.794 3.663,-3.662 c 0.101,-0.083 0.189,-0.184 0.284,-0.278 l
0.053,-0.056 c 0.189,-0.19 0.354,-0.408 0.48,-0.639 0.888,-1.259 1.354,-2.717
1.354,-4.258 V 14.47 c 0,-1.991 -0.778,-3.874 -2.191,-5.288 C 69.405,7.781
67.528,6.999 65.53,6.999 H 42.104 c -1.661,0 -3.229,0.537 -4.552,1.562
-0.062,0.04 -0.12,0.092 -0.179,0.138 C 37.013,9 36.684,9.316 36.397,9.66 l
-2.885,2.882 c -0.251,0.206 -0.477,0.399 -0.685,0.604 L 21.24,24.746
10.974,35.01 8.477,37.508 c -1.979,1.975 -1.979,5.183 0,7.151 l 2.497,2.505
21.854,21.854 2.501,2.498 c 1.979,1.978 5.182,1.978 7.153,0 L 44.987,69.018
55.249,58.747 66.84,47.164 c 0.114,-0.11 0.215,-0.224 0.331,-0.37 z M
60.468,19.535 c 3.744,3.744 3.738,9.784 0,13.515 -3.729,3.74 -9.78,3.74
-13.518,0 -3.727,-3.729 -3.734,-9.785 0,-13.515 3.73,-3.732 9.796,-3.732
13.518,0 z"
+ id="path12"
+ style="fill:#929497" />
+</svg>
\ No newline at end of file
diff --git a/modules/tools/styles/ext.cx.tools.categories.less
b/modules/tools/styles/ext.cx.tools.categories.less
new file mode 100644
index 0000000..3534995
--- /dev/null
+++ b/modules/tools/styles/ext.cx.tools.categories.less
@@ -0,0 +1,100 @@
+@import "../../base/styles/grid/agora-grid";
+@import "mediawiki.mixins";
+
+@text-highlight-color: #FEFCE0;
+
+.cx-category-widget {
+ .mw-ui-item;
+ width: 100%;
+ clear: both;
+ padding: .2em;
+}
+
+.cx-category-widget-counter {
+ margin-bottom: 10px;
+ margin-top: -10px;
+}
+
+.cx-category-anchor {
+ cursor: pointer;
+ display: block;
+ min-width: 1.5em;
+ min-height: 1.5em;
+ width: 1.5em;
+ height: 1.5em;
+ float: left;
+ background-repeat: no-repeat;
+ background-position: center;
+ background-size: 1.5em 1.5em;
+ .background-image-svg( '../images/tag.svg', '../images/tag.png' );
+ text-decoration: none;
+}
+
+.cx-category-widget-counter .cx-category-anchor {
+ min-width: 1em;
+ min-height: 1em;
+ width: 1em;
+ height: 1em;
+ background-size: 1em 1em;
+}
+
+.cx-category-count {
+ margin-left: .5em;
+ margin-top: .5em;
+}
+
+.cx-category-widget-listing {
+ padding: .2em;
+ margin-top: 1em;
+ padding-top: .5em;
+ padding-bottom: .5em;
+ border: 1px solid #C9C9C9;
+ border-radius: 2px;
+ box-shadow: 0 1px 0 #C9C9C9;
+}
+
+ul.cx-categories {
+ list-display-type: none;
+ list-display-image: none;
+ padding: 0;
+ margin: 0;
+ margin-left: 2em;
+ cursor: pointer;
+}
+
+.cx-category {
+ border: 1px solid #C9C9C9;
+ border-radius: 2px;
+ box-shadow: 0 1px 0 #C9C9C9;
+ padding-left: .25em;
+ padding-right: .25em;
+ display: inline-block;
+ margin: 0;
+ margin-right: 1em;
+ margin-bottom: 1em;
+}
+
+.cx-category-source {
+ border: none;
+ box-shadow: none;
+}
+
+.cx-category-remove {
+ display: inline-block;
+ min-height: .75em;
+ min-width: .75em;
+ width: .75em;
+ height: .75em;
+ margin-left: .5em;
+ background-repeat: no-repeat;
+ background-position: center;
+ background-size: .75em .75em;
+ .background-image-svg( '../images/clear.svg', '../images/clear.png' );
+}
+
+.cx-category-highlight {
+ background-color: @text-highlight-color;
+ box-shadow: 0px 0px 0 2px @text-highlight-color;
+ border-radius: 2px;
+ transition: all 0.25s;
+}
--
To view, visit https://gerrit.wikimedia.org/r/166361
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I93b6fc0282e087b29079f59d518ee0fb1c4f6408
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/ContentTranslation
Gerrit-Branch: master
Gerrit-Owner: Jsahleen <[email protected]>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits